Skip to contentSkip to conversation

*hacky* basic support for Nvidia Tegra K1/Jetson board (probably ignore)

PATCH In review Ian Campbell 1 participant 12 messages Mar 10, 2015 Tegra architecture support

lore
Share & tools
lore
#0 lore raw

cover *hacky* basic support for Nvidia Tegra K1/Jetson board (probably ignore)

There is a lot of hacky and WIP stuff here, including a serial driver issue (FIFO depth? Interrupts?) which I haven't gotten to the bottom of yet. But with these hacks and sync_console I can boot on the platform and run guests etc.

Actually only up to and including patch #7 "HACK: xen: arm: trying to figure out ns16550 vs. Tegra issue" are needed for a functioning system.

I'm not sure when I'll be able to dig in properly into the issues so I'm sending it out now. Nothing here is to be applied, except possibly "xen:
arm: Add debug keyhandler to dump the physical GIC stat" but even that needs more cleanup I think (in particular only handles GICv2).

I've deliberately not CC-d anyone on the patches themselves so as not to spam you with half complete rubbish.

The following changes since commit f0ffd6032f679ec4b9a39d526cdbcdaf692e2f03:

netif.h: describe request/response structures in terms of binary layout (2015-03-03 11:26:24 +0000)

are available in the git repository at:

git://xenbits.xen.org/people/ianc/xen.git tegra-tk1-jetson-v1

for you to fetch changes up to c78d51660446d33dac4bb07c3c17e1d14d62ebc2:

Tegra hacking. (2015-03-10 08:55:00 +0000)

----------------------------------------------------------------
Ian Campbell (10):
xen: arm: Add debug keyhandler to dump the physical GIC state.
xen: arm: earlyprintk support for Nvidia Jetson
xen: arm: add platform hook for routing IRQ to guests
WIP: xen: ns16550: Add nvidia,tegra20-uart to DT compatible list
WIP: xen: arm: intial platform support for Nvidia TK1
HACK: xen: arm: Map other regions to dom0 after one fails
HACK: xen: arm: trying to figure out ns16550 vs. Tegra issue
HACK: xen: arm: Add mask, unmask and eoi platform hooks.
HACK: xen: arm: stop recursing with dom0 mappings once we've hit a ranges. Tegra hacking.

 docs/misc/arm/early-printk.txt  |   1 +
 xen/arch/arm/Rules.mk           |   5 +++
 xen/arch/arm/domain.c           |   2 +-
 xen/arch/arm/domain_build.c     |  23 +++++++---
 xen/arch/arm/gic-v2.c           |  69 +++++++++++++++++++++++++++++-
 xen/arch/arm/gic-v3.c           |   5 ++-
 xen/arch/arm/gic.c              |  25 ++++++++++-
 xen/arch/arm/irq.c              |   4 ++
 xen/arch/arm/platform.c         |  22 ++++++++++
 xen/arch/arm/platforms/Makefile |   1 +
 xen/arch/arm/platforms/tegra.c  | 461 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 xen/drivers/char/ns16550.c      |  17 +++++++-
 xen/include/asm-arm/gic.h       |   6 ++-
 xen/include/asm-arm/platform.h  |  13 ++++++
 14 files changed, 639 insertions(+), 15 deletions(-)
 create mode 100644 xen/arch/arm/platforms/tegra.c

Ian.

#1 lore raw

PATCH 1/10 xen: arm: Add debug keyhandler to dump the physical GIC state.

Rename the existing gic_dump_info to gic_dump_info_guest reduce confusion.

---
v2: s/gic_dump_info/gic_dump_info_guest/

---
 xen/arch/arm/domain.c     |  2 +-
 xen/arch/arm/gic-v2.c     | 66 ++++++++++++++++++++++++++++++++++++++++++++++-
 xen/arch/arm/gic-v3.c     |  5 ++--
 xen/arch/arm/gic.c        | 25 ++++++++++++++++--
 xen/include/asm-arm/gic.h |  6 +++--
 5 files changed, 96 insertions(+), 8 deletions(-)
xen/arch/arm/domain.c +1 -1
index fdba081..bec1082 100644
@@ -803,7 +803,7 @@ long arch_do_vcpu_op(int cmd, struct vcpu *v, XEN_GUEST_HANDLE_PARAM(void) arg)
 
 void arch_dump_vcpu_info(struct vcpu *v)
 {
-    gic_dump_info(v);
+    gic_dump_info_guest(v);
 }
 
 void vcpu_mark_events_pending(struct vcpu *v)
xen/arch/arm/gic-v2.c +65 -1

90 lines not on this page · raw message

xen/arch/arm/gic-v3.c +3 -2
index ab80670..4516304 100644
@@ -394,7 +394,7 @@ static void gicv3_restore_state(const struct vcpu *v)
     dsb(sy);
 }
 
-static void gicv3_dump_state(const struct vcpu *v)
+static void gicv3_dump_state_guest(const struct vcpu *v)
 {
     int i;
 
@@ -1177,7 +1177,8 @@ static const struct gic_hw_operations gicv3_ops = {
     .info                = &gicv3_info,
     .save_state          = gicv3_save_state,
     .restore_state       = gicv3_restore_state,
-    .dump_state          = gicv3_dump_state,
+    .dump_state          = NULL,
+    .dump_state_guest    = gicv3_dump_state_guest,
     .gicv_setup          = gicv_v3_init,
     .gic_host_irq_type   = &gicv3_host_irq_type,
     .gic_guest_irq_type  = &gicv3_guest_irq_type,
xen/arch/arm/gic.c +23 -2
index 390c8b0..6c5581b 100644
@@ -27,6 +27,7 @@
 #include <xen/softirq.h>
 #include <xen/list.h>
 #include <xen/device_tree.h>
+#include <xen/keyhandler.h>
 #include <asm/p2m.h>
 #include <asm/domain.h>
 #include <asm/platform.h>
@@ -163,6 +164,24 @@ int gic_irq_xlate(const u32 *intspec, unsigned int intsize,
     return 0;
 }
 
+
+static void do_dump_gic(unsigned char key)
+{
+    if ( gic_hw_ops->dump_state )
+    {
+        printk("'%c' pressed -> dumping GIC state\n", key);
+        gic_hw_ops->dump_state();
+    }
+    else
+        printk("'%c' pressed -> no GIC dump state handler\n", key);
+}
+
+static struct keyhandler dump_gic_keyhandler = {
+    .irq_callback = 0,
+    .u.fn = do_dump_gic,
+    .desc = "dump GIC state"
+};
+
 /* Set up the GIC */
 void __init gic_init(void)
 {
@@ -191,6 +210,8 @@ void __init gic_init(void)
 
     /* Clear LR mask for cpu0 */
     clear_cpu_lr_mask();
+
+    register_keyhandler('G', &dump_gic_keyhandler);
 }
 
 void send_SGI_mask(const cpumask_t *cpumask, enum gic_sgi sgi)
@@ -609,12 +630,12 @@ static void maintenance_interrupt(int irq, void *dev_id, struct cpu_user_regs *r
     perfc_incr(maintenance_irqs);
 }
 
-void gic_dump_info(struct vcpu *v)
+void gic_dump_info_guest(struct vcpu *v)
 {
     struct pending_irq *p;
 
     printk("GICH_LRs (vcpu %d) mask=%"PRIx64"\n", v->vcpu_id, v->arch.lr_mask);
-    gic_hw_ops->dump_state(v);
+    gic_hw_ops->dump_state_guest(v);
 
     list_for_each_entry ( p, &v->arch.vgic.inflight_irqs, inflight )
     {
xen/include/asm-arm/gic.h +4 -2
index 6f5767f..65a379c 100644
@@ -263,7 +263,7 @@ extern void send_SGI_self(enum gic_sgi sgi);
 extern void send_SGI_allbutself(enum gic_sgi sgi);
 
 /* print useful debug info */
-extern void gic_dump_info(struct vcpu *v);
+extern void gic_dump_info_guest(struct vcpu *v);
 
 /* Number of interrupt lines */
 extern unsigned int gic_number_lines(void);
@@ -291,8 +291,10 @@ struct gic_hw_operations {
     void (*save_state)(struct vcpu *);
     /* Restore GIC registers */
     void (*restore_state)(const struct vcpu *);
+    /* Dump GIC host register information */
+    void (*dump_state)(void);
     /* Dump GIC LR register information */
-    void (*dump_state)(const struct vcpu *);
+    void (*dump_state_guest)(const struct vcpu *);
     /* Map MMIO region of GIC */
     int (*gicv_setup)(struct domain *);
 
Signature · 1 line
2.1.4
#2 lore raw

PATCH 2/10 xen: arm: earlyprintk support for Nvidia Jetson

In reply to Ian Campbell
---
 docs/misc/arm/early-printk.txt | 1 +
 xen/arch/arm/Rules.mk          | 5 +++++
 2 files changed, 6 insertions(+)
docs/misc/arm/early-printk.txt +1 -0
index 1ca2a55..4354e2d 100644
@@ -13,6 +13,7 @@ where mach is the name of the machine:
   - exynos5250: printk with the second UART
   - midway: printk with the pl011 on Calxeda Midway processors
   - fastmodel: printk on ARM Fastmodel software emulators
+  - jetson: printk on Nvidia Jetson TK1
   - omap5432: printk with UART3 on TI OMAP5432 processors
   - sun6i: printk with 8250 on Allwinner A31 processors
   - sun7i: printk with 8250 on Allwinner A20 processors
xen/arch/arm/Rules.mk +5 -0
index c7bd227..3fc8065 100644
@@ -105,6 +105,11 @@ EARLY_PRINTK_INC := 8250
 EARLY_UART_BASE_ADDRESS := 0xE4007000
 EARLY_UART_REG_SHIFT := 2
 endif
+ifeq ($(CONFIG_EARLY_PRINTK), jetson)
+EARLY_PRINTK_INC := 8250
+EARLY_UART_BASE_ADDRESS := 0x70006300
+EARLY_UART_REG_SHIFT := 2
+endif
 ifeq ($(CONFIG_EARLY_PRINTK), seattle)
 EARLY_PRINTK_INC := pl011
 EARLY_UART_BASE_ADDRESS := 0xe1010000
Signature · 1 line
2.1.4
#3 lore raw

PATCH 3/10 xen: arm: add platform hook for routing IRQ to guests

In reply to Ian Campbell

Tegra contains a secondary set of IRQ registers which dom0 wants to poke at, we will use this for that.

---
 xen/arch/arm/irq.c             | 4 ++++
 xen/arch/arm/platform.c        | 6 ++++++
 xen/include/asm-arm/platform.h | 5 +++++
 3 files changed, 15 insertions(+)
xen/arch/arm/irq.c +4 -0
index cb9c99b..c574b92 100644
@@ -27,6 +27,7 @@
 
 #include <asm/gic.h>
 #include <asm/vgic.h>
+#include <asm/platform.h>
 
 static unsigned int local_irqs_type[NR_LOCAL_IRQS];
 static DEFINE_SPINLOCK(local_irqs_type_lock);
@@ -423,6 +424,9 @@ int route_irq_to_guest(struct domain *d, unsigned int irq,
 
     gic_route_irq_to_guest(d, desc, cpumask_of(smp_processor_id()),
                            GIC_PRI_IRQ);
+
+    platform_route_irq_to_guest(d, desc);
+
     spin_unlock_irqrestore(&desc->lock, flags);
     return 0;
 
xen/arch/arm/platform.c +6 -0
index 86daf2b..c58e251 100644
@@ -160,6 +160,12 @@ bool_t platform_device_is_blacklisted(const struct dt_device_node *node)
     return (dt_match_node(blacklist, node) != NULL);
 }
 
+void platform_route_irq_to_guest(struct domain *d, struct irq_desc *desc)
+{
+    if ( platform && platform->route_irq_to_guest )
+        platform->route_irq_to_guest(d, desc);
+}
+
 void platform_dom0_gnttab(paddr_t *start, paddr_t *size)
 {
     if ( platform && platform->dom0_gnttab_size )
xen/include/asm-arm/platform.h +5 -0
index 4eba37b..22d1f8b 100644
@@ -26,6 +26,9 @@ struct platform_desc {
     void (*reset)(void);
     /* Platform power-off */
     void (*poweroff)(void);
+
+    void (*route_irq_to_guest)(struct domain *d, struct irq_desc *);
+
     /*
      * Platform quirks
      * Defined has a function because a platform can support multiple
@@ -70,6 +73,8 @@ bool_t platform_device_is_blacklisted(const struct dt_device_node *node);
 unsigned int platform_dom0_evtchn_ppi(void);
 void platform_dom0_gnttab(paddr_t *start, paddr_t *size);
 
+void platform_route_irq_to_guest(struct domain *, struct irq_desc *);
+
 #define PLATFORM_START(_name, _namestr)                         \
 static const struct platform_desc  __plat_desc_##_name __used   \
 __attribute__((__section__(".arch.info"))) = {                  \
Signature · 1 line
2.1.4
#4 lore raw

PATCH 4/10 WIP: xen: ns16550: Add nvidia, tegra20-uart to DT compatible list

In reply to Ian Campbell

DO NOT APPLY. Doesn't work without sync_console *and* the changes from "HACK:
xen: arm: trying to figure out ns16550 vs. Tegra issue".

I suspect and IRQ or FIFO depth issue. Linux has a separate serial-tegra driver so perhaps the device is just not as compatible as I think.

---
 xen/drivers/char/ns16550.c | 1 +
 1 file changed, 1 insertion(+)
xen/drivers/char/ns16550.c +1 -0
index d443880..44045d7 100644
@@ -1189,6 +1189,7 @@ static const struct dt_device_match ns16550_dt_match[] __initconst =
 {
     DT_MATCH_COMPATIBLE("ns16550"),
     DT_MATCH_COMPATIBLE("ns16550a"),
+    DT_MATCH_COMPATIBLE("nvidia,tegra20-uart"),
     DT_MATCH_COMPATIBLE("snps,dw-apb-uart"),
     { /* sentinel */ },
 };
Signature · 1 line
2.1.4
#5 lore raw

PATCH 5/10 WIP: xen: arm: intial platform support for Nvidia TK1

In reply to Ian Campbell

As used on the Jetson board.

This platform has a bunch of specific mappings and, more importantly, an additional interrupt controller (which is used alongside the main GIC and covers the same interrupts etc, so it is not a secondary or chained interrupt controller) which dom0 really wants to poke at, I think for power gating reasons. This is implemented as a whitelist derived from the set of interrupts routed to dom0 (discovered by the new route_irq_to_guest platform hook).

---
 xen/arch/arm/platforms/Makefile |   1 +
 xen/arch/arm/platforms/tegra.c  | 395 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 396 insertions(+)
 create mode 100644 xen/arch/arm/platforms/tegra.c
xen/arch/arm/platforms/Makefile +1 -0
index e173fec..eb512ed 100644
@@ -3,6 +3,7 @@ obj-$(CONFIG_ARM_32) += brcm.o
 obj-$(CONFIG_ARM_32) += exynos5.o
 obj-$(CONFIG_ARM_32) += midway.o
 obj-$(CONFIG_ARM_32) += omap5.o
+obj-$(CONFIG_ARM_32) += tegra.o
 obj-$(CONFIG_ARM_32) += sunxi.o
 obj-$(CONFIG_ARM_32) += rcar2.o
 obj-$(CONFIG_ARM_64) += seattle.o
xen/arch/arm/platforms/tegra.c new file +395 -0

395 lines not on this page · raw message

Signature · 1 line
2.1.4
#6 lore raw

PATCH 6/10 HACK: xen: arm: Map other regions to dom0 after one fails

In reply to Ian Campbell

We can't seem to hanle /pcie-controller@0,01003000/pci@1,0 and /pcie-controller@0,01003000/pci@2,0. Perhaps better solved by DT/PCI series.

---
 xen/arch/arm/domain_build.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)
xen/arch/arm/domain_build.c +3 -2
index 9f1f59f..e754d37 100644
@@ -985,8 +985,9 @@ static int map_device(struct domain *d, struct dt_device_node *dev)
         res = dt_device_get_address(dev, i, &addr, &size);
         if ( res )
         {
-            printk(XENLOG_ERR "Unable to retrieve address %u for %s\n",
-                   i, dt_node_full_name(dev));
+            printk(XENLOG_ERR "Unable to retrieve address %u for %s: %d\n",
+                   i, dt_node_full_name(dev), res);
+            continue;
             return res;
         }
 
Signature · 1 line
2.1.4
#7 lore raw

PATCH 7/10 HACK: xen: arm: trying to figure out ns16550 vs. Tegra issue

In reply to Ian Campbell

Messing with the FIFO depths and trigger levels seems to help, as does messing with the interrupt enable state at various points. The latter might be better handled via the start/stop_tx hooks which were added a while ago.

---
 xen/drivers/char/ns16550.c | 16 +++++++++++++++-
 1 file changed, 15 insertions(+), 1 deletion(-)
xen/drivers/char/ns16550.c +15 -1
index 44045d7..3b32f40 100644
@@ -401,7 +401,14 @@ static void ns16550_interrupt(
     {
         char lsr = ns_read_reg(uart, UART_LSR);
         if ( (lsr & uart->lsr_mask) == uart->lsr_mask )
+        {
             serial_tx_interrupt(port, regs);
+            if ( port->txbufc == port->txbufp ) {
+                u8 reg;
+                reg = ns_read_reg(uart, UART_IER);
+                ns_write_reg(uart, UART_IER, reg & (~UART_IER_ETHREI));
+            }
+        }
         if ( lsr & UART_LSR_DR )
             serial_rx_interrupt(port, regs);
     }
@@ -450,6 +457,13 @@ static int ns16550_tx_ready(struct serial_port *port)
     if ( ns16550_ioport_invalid(uart) )
         return -EIO;
 
+    if ( 1 )
+    {
+        u8 reg;
+        reg = ns_read_reg(uart, UART_IER);
+        ns_write_reg(uart, UART_IER, reg | UART_IER_ETHREI);
+    }
+
     return ( (ns_read_reg(uart, UART_LSR) &
               uart->lsr_mask ) == uart->lsr_mask ) ? uart->fifo_size : 0;
 }
@@ -539,7 +553,7 @@ static void ns16550_setup_preirq(struct ns16550 *uart)
 
     /* Enable and clear the FIFOs. Set a large trigger threshold. */
     ns_write_reg(uart, UART_FCR,
-                 UART_FCR_ENABLE | UART_FCR_CLRX | UART_FCR_CLTX | UART_FCR_TRG14);
+                 UART_FCR_ENABLE | UART_FCR_CLRX | UART_FCR_CLTX | UART_FCR_TRG1/*UART_FCR_TRG14*/);
 }
 
 static void __init ns16550_init_preirq(struct serial_port *port)
Signature · 1 line
2.1.4
#8 lore raw

PATCH 8/10 HACK: xen: arm: Add mask, unmask and eoi platform hooks.

In reply to Ian Campbell

Not to be applied until better understood.

Linux has these hooks and uses them on Tegra.

However I don't think they are strictly needed (only for power gating stuff perhaps?). I implemented them while investigating some other issues, used by later "Tegra hacking" patch which isn't actually needed for a working board, AFAICT.

---
 xen/arch/arm/gic-v2.c          |  3 +++
 xen/arch/arm/platform.c        | 16 ++++++++++++++++
 xen/include/asm-arm/platform.h |  8 ++++++++
 3 files changed, 27 insertions(+)
xen/arch/arm/gic-v2.c +3 -0
index 2f5d33b..033a94a 100644
@@ -537,6 +537,7 @@ static void gicv2_irq_enable(struct irq_desc *desc)
     clear_bit(_IRQ_DISABLED, &desc->status);
     dsb(sy);
     /* Enable routing */
+    platform_irq_unmask(desc);
     writel_gicd((1u << (irq % 32)), GICD_ISENABLER + (irq / 32) * 4);
     spin_unlock_irqrestore(&gicv2.lock, flags);
 }
@@ -552,6 +553,7 @@ static void gicv2_irq_disable(struct irq_desc *desc)
     /* Disable routing */
     writel_gicd(1u << (irq % 32), GICD_ICENABLER + (irq / 32) * 4);
     set_bit(_IRQ_DISABLED, &desc->status);
+    platform_irq_mask(desc);
     spin_unlock_irqrestore(&gicv2.lock, flags);
 }
 
@@ -574,6 +576,7 @@ static void gicv2_irq_ack(struct irq_desc *desc)
 
 static void gicv2_host_irq_end(struct irq_desc *desc)
 {
+    platform_irq_eoi(desc);
     /* Lower the priority */
     gicv2_eoi_irq(desc);
     /* Deactivate */
xen/arch/arm/platform.c +16 -0
index c58e251..3255c6a 100644
@@ -160,6 +160,22 @@ bool_t platform_device_is_blacklisted(const struct dt_device_node *node)
     return (dt_match_node(blacklist, node) != NULL);
 }
 
+void platform_irq_eoi(struct irq_desc *desc)
+{
+    if ( platform && platform->irq_eoi )
+        platform->irq_eoi(desc);
+}
+void platform_irq_mask(struct irq_desc *desc)
+{
+    if ( platform && platform->irq_mask )
+        platform->irq_mask(desc);
+}
+void platform_irq_unmask(struct irq_desc *desc)
+{
+    if ( platform && platform->irq_unmask )
+        platform->irq_unmask(desc);
+}
+
 void platform_route_irq_to_guest(struct domain *d, struct irq_desc *desc)
 {
     if ( platform && platform->route_irq_to_guest )
xen/include/asm-arm/platform.h +8 -0
index 22d1f8b..8b4c807 100644
@@ -27,6 +27,11 @@ struct platform_desc {
     /* Platform power-off */
     void (*poweroff)(void);
 
+    /* GIC hooks */
+    void (*irq_eoi)(struct irq_desc *);
+    void (*irq_mask)(struct irq_desc *);
+    void (*irq_unmask)(struct irq_desc *);
+
     void (*route_irq_to_guest)(struct domain *d, struct irq_desc *);
 
     /*
@@ -72,6 +77,9 @@ bool_t platform_has_quirk(uint32_t quirk);
 bool_t platform_device_is_blacklisted(const struct dt_device_node *node);
 unsigned int platform_dom0_evtchn_ppi(void);
 void platform_dom0_gnttab(paddr_t *start, paddr_t *size);
+void platform_irq_eoi(struct irq_desc *);
+void platform_irq_mask(struct irq_desc *);
+void platform_irq_unmask(struct irq_desc *);
 
 void platform_route_irq_to_guest(struct domain *, struct irq_desc *);
 
Signature · 1 line
2.1.4
#9 lore raw

PATCH 9/10 HACK: xen: arm: stop recursing with dom0 mappings once we've hit a ranges.

In reply to Ian Campbell

Probably better done with improvements to DT/PCI parsing code and doesn't seem to dpo any harm not to have this patch anyway.

---
 xen/arch/arm/domain_build.c | 18 ++++++++++++++----
 1 file changed, 14 insertions(+), 4 deletions(-)
xen/arch/arm/domain_build.c +14 -4
index e754d37..ee27930 100644
@@ -1022,7 +1022,8 @@ static int map_device(struct domain *d, struct dt_device_node *dev)
 }
 
 static int handle_node(struct domain *d, struct kernel_info *kinfo,
-                       struct dt_device_node *node)
+                       struct dt_device_node *node,
+                       bool_t map)
 {
     static const struct dt_device_match skip_matches[] __initconst =
     {
@@ -1051,6 +1052,8 @@ static int handle_node(struct domain *d, struct kernel_info *kinfo,
     int res;
     const char *name;
     const char *path;
+    bool_t map_children = true;
+    u32 ranges_len;
 
     path = dt_node_full_name(node);
 
@@ -1099,7 +1102,8 @@ static int handle_node(struct domain *d, struct kernel_info *kinfo,
      *  property. Therefore these device doesn't need to be mapped. This
      *  solution can be use later for pass through.
      */
-    if ( !dt_device_type_is_equal(node, "memory") &&
+    if ( map &&
+         !dt_device_type_is_equal(node, "memory") &&
          dt_device_is_available(node) )
     {
         res = map_device(d, node);
@@ -1124,9 +1128,15 @@ static int handle_node(struct domain *d, struct kernel_info *kinfo,
     if ( res )
         return res;
 
+    /* Don't need to map anything below a node with a non-empty ranges property
+     * -- it's already covered and we may not know how to translate
+     * anyway. */
+    if ( dt_get_property(node, "ranges", &ranges_len) != NULL && ranges_len )
+        map_children = false;
+
     for ( child = node->child; child != NULL; child = child->sibling )
     {
-        res = handle_node(d, kinfo, child);
+        res = handle_node(d, kinfo, child, map_children);
         if ( res )
             return res;
     }
@@ -1177,7 +1187,7 @@ static int prepare_dtb(struct domain *d, struct kernel_info *kinfo)
 
     fdt_finish_reservemap(kinfo->fdt);
 
-    ret = handle_node(d, kinfo, dt_host);
+    ret = handle_node(d, kinfo, dt_host, true);
     if ( ret )
         goto err;
 
Signature · 1 line
2.1.4
#10 lore raw

PATCH 10/10 Tegra hacking.

In reply to Ian Campbell

Works without all this stuff.

---
 xen/arch/arm/platforms/tegra.c | 68 +++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 67 insertions(+), 1 deletion(-)
xen/arch/arm/platforms/tegra.c +67 -1
index 189ef44..5ec9dda 100644
@@ -191,6 +191,45 @@ static struct mmio_handler_ops tegra_mmio_ictlr = {
     .write_handler = ictlr_write,
 };
 
+static inline void tegra_irq_write_mask(unsigned int irq, unsigned long reg)
+{
+    void __iomem *base;
+    u32 mask;
+
+    BUG_ON(irq < NR_LOCAL_IRQS ||
+           irq >= NR_LOCAL_IRQS + ARRAY_SIZE(ictlr_info) * 32);
+
+    irq -= NR_LOCAL_IRQS;
+    base = ictlr + 0x100 * (irq / 32);
+    mask = BIT(irq % 32);
+
+    writel(mask, base + reg);
+}
+
+static void tegra_irq_eoi(struct irq_desc *desc)
+{
+    int irq = desc->irq;
+    if ( irq < NR_LOCAL_IRQS )
+        return;
+    //tegra_irq_write_mask(irq, ICTLR_CPU_IEP_FIR_CLR);
+}
+
+static void tegra_irq_mask(struct irq_desc *desc)
+{
+    int irq = desc->irq;
+    if ( irq < NR_LOCAL_IRQS )
+        return;
+    tegra_irq_write_mask(irq, ICTLR_CPU_IER_CLR);
+}
+
+static void tegra_irq_unmask(struct irq_desc *desc)
+{
+    int irq = desc->irq;
+    if ( irq < NR_LOCAL_IRQS )
+        return;
+    tegra_irq_write_mask(irq, ICTLR_CPU_IER_SET);
+}
+
 static void tegra_route_irq_to_guest(struct domain *d, struct irq_desc *desc)
 {
     int irq = desc->irq;
@@ -256,7 +295,7 @@ static int map_one_spi(struct domain *d, const char *what,
  */
 static int tegra_specific_mapping(struct domain *d)
 {
-    int ret;
+    int ret/*, i*/;
 
     ret = map_one_mmio(d, "IRAM", paddr_to_pfn(0x40000000),
                                   paddr_to_pfn(0x40040000));
@@ -312,6 +351,29 @@ static int tegra_specific_mapping(struct domain *d)
     if ( ret )
         goto err;
 
+#if 0
+    ret = map_one_spi(d, "PCI INTx", 98, DT_IRQ_TYPE_LEVEL_HIGH);
+    if ( ret )
+        goto err;
+
+    ret = map_one_spi(d, "PCI MSI", 99, DT_IRQ_TYPE_LEVEL_HIGH);
+    if ( ret )
+        goto err;
+
+    for ( i = 104 ; i < 119 ; i++ )
+    {
+        ret = map_one_spi(d, "AHB DMA", i, DT_IRQ_TYPE_LEVEL_HIGH);
+        if ( ret )
+            goto err;
+    }
+    for ( i = 128 ; i < 143 ; i++ )
+    {
+        ret = map_one_spi(d, "AHB DMA", i, DT_IRQ_TYPE_LEVEL_HIGH);
+        if ( ret )
+            goto err;
+    }
+#endif
+
     register_mmio_handler(d, &tegra_mmio_ictlr, ICTLR_BASE, ICTLR_SIZE);
 
     ret = 0;
@@ -379,6 +441,10 @@ PLATFORM_START(tegra, "TEGRA124")
     .reset = tegra_reset,
     .specific_mapping = tegra_specific_mapping,
 
+    .irq_eoi = tegra_irq_eoi,
+    .irq_mask = tegra_irq_mask,
+    .irq_unmask = tegra_irq_unmask,
+
     .route_irq_to_guest = tegra_route_irq_to_guest,
 
     .dom0_gnttab_start = 0x68000000,
Signature · 1 line
2.1.4