qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v3 0/9] various arm fixes
@ 2011-12-27 20:13 Mark Langsdorf
  2011-12-27 20:13 ` [Qemu-devel] [PATCH v3 1/9] arm: add missing scu registers Mark Langsdorf
                   ` (8 more replies)
  0 siblings, 9 replies; 20+ messages in thread
From: Mark Langsdorf @ 2011-12-27 20:13 UTC (permalink / raw)
  To: qemu-devel; +Cc: kwolf, peter.maydell, paul, rob.herring

This is a collection of fixes and additions to the models for various ARM
devices. These changes are needed to support the forthcoming Calxeda
Highbank SoC model.

 Makefile.target     |    2 +
 hw/a9mpcore.c       |   45 +++++-
 hw/arm11mpcore.c    |    2 +-
 hw/arm_gic.c        |   46 ++++---
 hw/arm_l2x0.c       |  180 ++++++++++++++++++++++
 hw/arm_timer.c      |   24 +++-
 hw/armv7m_nvic.c    |    2 +-
 hw/ide/ahci.c       |   45 +++++-
 hw/ide/ich.c        |    4 +-
 hw/realview_gic.c   |    2 +-
 hw/xgmac.c          |  418 +++++++++++++++++++++++++++++++++++++++++++++++++++
 target-arm/cpu.h    |    1 +
 target-arm/helper.c |   14 ++
 13 files changed, 744 insertions(+), 41 deletions(-)

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

* [Qemu-devel] [PATCH v3 1/9] arm: add missing scu registers
  2011-12-27 20:13 [Qemu-devel] [PATCH v3 0/9] various arm fixes Mark Langsdorf
@ 2011-12-27 20:13 ` Mark Langsdorf
  2011-12-27 22:00   ` Peter Maydell
  2011-12-27 20:13 ` [Qemu-devel] [PATCH v3 2/9] arm: Set frequencies for arm_timer Mark Langsdorf
                   ` (7 subsequent siblings)
  8 siblings, 1 reply; 20+ messages in thread
From: Mark Langsdorf @ 2011-12-27 20:13 UTC (permalink / raw)
  To: qemu-devel; +Cc: kwolf, peter.maydell, Mark Langsdorf, paul, rob.herring

From: Rob Herring <rob.herring@calxeda.com>

Add power control register to a9mpcore

Signed-off-by: Rob Herring <rob.herring@calxeda.com>
Signed-off-by: Mark Langsdorf <mark.langsdorf@calxeda.com>
---
Changes from v2:
        Better handling of byte and halfword writes to the power register
        Correct handling of VMState versions
	Improved commit message
Changes from v1:
	Added VMState support
	Checked alignment of writes to the power control register

 hw/a9mpcore.c |   36 +++++++++++++++++++++++++++++++++---
 1 files changed, 33 insertions(+), 3 deletions(-)

diff --git a/hw/a9mpcore.c b/hw/a9mpcore.c
index cd2985f..3ef0e13 100644
--- a/hw/a9mpcore.c
+++ b/hw/a9mpcore.c
@@ -29,6 +29,7 @@ gic_get_current_cpu(void)
 typedef struct a9mp_priv_state {
     gic_state gic;
     uint32_t scu_control;
+    uint32_t scu_status;
     uint32_t old_timer_status[8];
     uint32_t num_cpu;
     qemu_irq *timer_irq;
@@ -48,7 +49,13 @@ static uint64_t a9_scu_read(void *opaque, target_phys_addr_t offset,
     case 0x04: /* Configuration */
         return (((1 << s->num_cpu) - 1) << 4) | (s->num_cpu - 1);
     case 0x08: /* CPU Power Status */
-        return 0;
+        return s->scu_status;
+    case 0x09: /* CPU status.  */
+        return s->scu_status >> 8;
+    case 0x0a: /* CPU status.  */
+        return s->scu_status >> 16;
+    case 0x0b: /* CPU status.  */
+        return s->scu_status >> 24;
     case 0x0c: /* Invalidate All Registers In Secure State */
         return 0;
     case 0x40: /* Filtering Start Address Register */
@@ -67,12 +74,35 @@ static void a9_scu_write(void *opaque, target_phys_addr_t offset,
                          uint64_t value, unsigned size)
 {
     a9mp_priv_state *s = (a9mp_priv_state *)opaque;
+    uint32_t mask;
+    uint32_t shift;
+    switch (size) {
+    case 1:
+        mask = 0xff;
+        break;
+    case 2:
+        mask = 0xffff;
+        break;
+    case 4:
+        mask = 0xffffffff;
+        break;
+    default:
+        fprintf(stderr, "Invalid size %u in write to a9 scu register %x\n",
+                size, offset);
+        return;
+    }
+
     switch (offset) {
     case 0x00: /* Control */
         s->scu_control = value & 1;
         break;
     case 0x4: /* Configuration: RO */
         break;
+    case 0x08: case 0x09: case 0x0A: case 0x0B: /* Power Control */
+        shift = (offset - 0x8) * 8;
+        s->scu_status &= ~(mask << shift);
+        s->scu_status |= ((value & mask) << shift);
+        break;
     case 0x0c: /* Invalidate All Registers In Secure State */
         /* no-op as we do not implement caches */
         break;
@@ -80,7 +110,6 @@ static void a9_scu_write(void *opaque, target_phys_addr_t offset,
     case 0x44: /* Filtering End Address Register */
         /* RAZ/WI, like an implementation with only one AXI master */
         break;
-    case 0x8: /* CPU Power Status */
     case 0x50: /* SCU Access Control Register */
     case 0x54: /* SCU Non-secure Access Control Register */
         /* unimplemented, fall through */
@@ -169,11 +198,12 @@ static int a9mp_priv_init(SysBusDevice *dev)
 
 static const VMStateDescription vmstate_a9mp_priv = {
     .name = "a9mpcore_priv",
-    .version_id = 1,
+    .version_id = 2,
     .minimum_version_id = 1,
     .fields = (VMStateField[]) {
         VMSTATE_UINT32(scu_control, a9mp_priv_state),
         VMSTATE_UINT32_ARRAY(old_timer_status, a9mp_priv_state, 8),
+        VMSTATE_UINT32_V(scu_status, a9mp_priv_state, 2),
         VMSTATE_END_OF_LIST()
     }
 };
-- 
1.7.5.4

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

* [Qemu-devel] [PATCH v3 2/9] arm: Set frequencies for arm_timer
  2011-12-27 20:13 [Qemu-devel] [PATCH v3 0/9] various arm fixes Mark Langsdorf
  2011-12-27 20:13 ` [Qemu-devel] [PATCH v3 1/9] arm: add missing scu registers Mark Langsdorf
@ 2011-12-27 20:13 ` Mark Langsdorf
  2011-12-27 22:02   ` Peter Maydell
  2011-12-27 20:13 ` [Qemu-devel] [PATCH v3 3/9] arm: add dummy v7 cp15 config_base_register Mark Langsdorf
                   ` (6 subsequent siblings)
  8 siblings, 1 reply; 20+ messages in thread
From: Mark Langsdorf @ 2011-12-27 20:13 UTC (permalink / raw)
  To: qemu-devel; +Cc: kwolf, peter.maydell, Mark Langsdorf, paul, rob.herring

Use qdev properties to allow board modelers to set the frequencies
for the sp804 timer. Each of the sp804's timers can have an
individual frequency. The timers default to 1MHz.

Signed-off-by: Mark Langsdorf <mark.langsdorf@calxeda.com>
---
Changes from v2
	Comment correctly describes behavior of properties
	freqX variables are defined as uint32_t, not int
Changes from v1
        Simplified multiple timer frequency handling
        Removed the shared default

 hw/arm_timer.c |   24 +++++++++++++++++++-----
 1 files changed, 19 insertions(+), 5 deletions(-)

diff --git a/hw/arm_timer.c b/hw/arm_timer.c
index 0a5b9d2..60e1c63 100644
--- a/hw/arm_timer.c
+++ b/hw/arm_timer.c
@@ -9,6 +9,8 @@
 
 #include "sysbus.h"
 #include "qemu-timer.h"
+#include "qemu-common.h"
+#include "qdev.h"
 
 /* Common timer implementation.  */
 
@@ -178,6 +180,7 @@ typedef struct {
     SysBusDevice busdev;
     MemoryRegion iomem;
     arm_timer_state *timer[2];
+    uint32_t freq0, freq1;
     int level[2];
     qemu_irq irq;
 } sp804_state;
@@ -269,10 +272,11 @@ static int sp804_init(SysBusDevice *dev)
 
     qi = qemu_allocate_irqs(sp804_set_irq, s, 2);
     sysbus_init_irq(dev, &s->irq);
-    /* ??? The timers are actually configurable between 32kHz and 1MHz, but
-       we don't implement that.  */
-    s->timer[0] = arm_timer_init(1000000);
-    s->timer[1] = arm_timer_init(1000000);
+    /* The timers are configurable between 32kHz and 1MHz
+     * defaulting to 1MHz but overrideable as individual properties */
+    s->timer[0] = arm_timer_init(s->freq0);
+    s->timer[1] = arm_timer_init(s->freq1);
+
     s->timer[0]->irq = qi[0];
     s->timer[1]->irq = qi[1];
     memory_region_init_io(&s->iomem, &sp804_ops, s, "sp804", 0x1000);
@@ -281,6 +285,16 @@ static int sp804_init(SysBusDevice *dev)
     return 0;
 }
 
+static SysBusDeviceInfo sp804_info = {
+    .init = sp804_init,
+    .qdev.name = "sp804",
+    .qdev.size = sizeof(sp804_state),
+    .qdev.props = (Property[]) {
+        DEFINE_PROP_UINT32("freq0", sp804_state, freq0, 1000000),
+        DEFINE_PROP_UINT32("freq1", sp804_state, freq1, 1000000),
+        DEFINE_PROP_END_OF_LIST(),
+    }
+};
 
 /* Integrator/CP timer module.  */
 
@@ -349,7 +363,7 @@ static int icp_pit_init(SysBusDevice *dev)
 static void arm_timer_register_devices(void)
 {
     sysbus_register_dev("integrator_pit", sizeof(icp_pit_state), icp_pit_init);
-    sysbus_register_dev("sp804", sizeof(sp804_state), sp804_init);
+    sysbus_register_withprop(&sp804_info);
 }
 
 device_init(arm_timer_register_devices)
-- 
1.7.5.4

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

* [Qemu-devel] [PATCH v3 3/9] arm: add dummy v7 cp15 config_base_register
  2011-12-27 20:13 [Qemu-devel] [PATCH v3 0/9] various arm fixes Mark Langsdorf
  2011-12-27 20:13 ` [Qemu-devel] [PATCH v3 1/9] arm: add missing scu registers Mark Langsdorf
  2011-12-27 20:13 ` [Qemu-devel] [PATCH v3 2/9] arm: Set frequencies for arm_timer Mark Langsdorf
@ 2011-12-27 20:13 ` Mark Langsdorf
  2011-12-27 22:05   ` Peter Maydell
  2011-12-27 20:13 ` [Qemu-devel] [PATCH v3 4/9] arm: add dummy gic security registers Mark Langsdorf
                   ` (5 subsequent siblings)
  8 siblings, 1 reply; 20+ messages in thread
From: Mark Langsdorf @ 2011-12-27 20:13 UTC (permalink / raw)
  To: qemu-devel; +Cc: kwolf, peter.maydell, Mark Langsdorf, paul, rob.herring

Add a cp15 config_base_register that currently defaults to 0.
After the QOM CPU support is added, the value will be properly
set to the periphal base value.

Signed-off-by: Mark Langsdorf <mark.langsdorf@calxeda.com>
---
Changes from v2
	Added test against op2 
hanges from v1
        renamed the register
        added comments about how it will change when QOM CPUs are added

 target-arm/cpu.h    |    1 +
 target-arm/helper.c |   14 ++++++++++++++
 2 files changed, 15 insertions(+), 0 deletions(-)

diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index c4d742f..449e620 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -149,6 +149,7 @@ typedef struct CPUARMState {
         uint32_t c15_i_max; /* Maximum D-cache dirty line index.  */
         uint32_t c15_i_min; /* Minimum D-cache dirty line index.  */
         uint32_t c15_threadid; /* TI debugger thread-ID.  */
+        uint32_t c15_config_base_address; /* SCU base address.  */
     } cp15;
 
     struct {
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 65f4fbf..b235fed 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -2111,6 +2111,20 @@ uint32_t HELPER(get_cp15)(CPUState *env, uint32_t insn)
              * 0x200 << ($rn & 0xfff), when MMU is off.  */
             goto bad_reg;
         }
+        if (ARM_CPUID(env) == ARM_CPUID_CORTEXA9) {
+            switch (crm) {
+            case 0:
+                /* The config_base_address should hold the value of
+                 * the peripheral base. ARM should get this from a CPU
+                 * object property, but that support isn't available in
+                 * December 2011. Default to 0 for now and board models
+                 * that care can set it by a private hook */
+                if ((op1 == 4) && (op2 == 0)) {
+                    return env->cp15.c15_config_base_address;
+                }
+            }
+            goto bad_reg;
+        }
         return 0;
     }
 bad_reg:
-- 
1.7.5.4

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

* [Qemu-devel] [PATCH v3 4/9] arm: add dummy gic security registers
  2011-12-27 20:13 [Qemu-devel] [PATCH v3 0/9] various arm fixes Mark Langsdorf
                   ` (2 preceding siblings ...)
  2011-12-27 20:13 ` [Qemu-devel] [PATCH v3 3/9] arm: add dummy v7 cp15 config_base_register Mark Langsdorf
@ 2011-12-27 20:13 ` Mark Langsdorf
  2011-12-27 20:13 ` [Qemu-devel] [PATCH v3 5/9] ahci: convert ahci_reset to use AHCIState Mark Langsdorf
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 20+ messages in thread
From: Mark Langsdorf @ 2011-12-27 20:13 UTC (permalink / raw)
  To: qemu-devel; +Cc: kwolf, peter.maydell, Mark Langsdorf, paul, rob.herring

From: Rob Herring <rob.herring@calxeda.com>

Implement handling for the RAZ/WI gic security registers.

Signed-off-by: Rob Herring <rob.herring@calxeda.com>
Signed-off-by: Mark Langsdorf <mark.langsdorf@calxeda.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
---
Changes from v2
	None
Changes from v1
        Moved handling back inside the 0-0x100 block
        Added more clarifying comments

 hw/arm_gic.c |    6 ++++++
 1 files changed, 6 insertions(+), 0 deletions(-)

diff --git a/hw/arm_gic.c b/hw/arm_gic.c
index 9b52119..0339cf5 100644
--- a/hw/arm_gic.c
+++ b/hw/arm_gic.c
@@ -282,6 +282,10 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
             return ((GIC_NIRQ / 32) - 1) | ((NUM_CPU(s) - 1) << 5);
         if (offset < 0x08)
             return 0;
+        if (offset >= 0x80) {
+            /* Interrupt Security , RAZ/WI */
+            return 0;
+        }
 #endif
         goto bad_reg;
     } else if (offset < 0x200) {
@@ -413,6 +417,8 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
             DPRINTF("Distribution %sabled\n", s->enabled ? "En" : "Dis");
         } else if (offset < 4) {
             /* ignored.  */
+        } else if (offset >= 0x80) {
+            /* Interrupt Security Registers, RAZ/WI */
         } else {
             goto bad_reg;
         }
-- 
1.7.5.4

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

* [Qemu-devel] [PATCH v3 5/9] ahci: convert ahci_reset to use AHCIState
  2011-12-27 20:13 [Qemu-devel] [PATCH v3 0/9] various arm fixes Mark Langsdorf
                   ` (3 preceding siblings ...)
  2011-12-27 20:13 ` [Qemu-devel] [PATCH v3 4/9] arm: add dummy gic security registers Mark Langsdorf
@ 2011-12-27 20:13 ` Mark Langsdorf
  2011-12-27 22:54   ` Peter Maydell
  2011-12-27 20:13 ` [Qemu-devel] [PATCH v3 6/9] ahci: add support for non-PCI based controllers Mark Langsdorf
                   ` (3 subsequent siblings)
  8 siblings, 1 reply; 20+ messages in thread
From: Mark Langsdorf @ 2011-12-27 20:13 UTC (permalink / raw)
  To: qemu-devel; +Cc: kwolf, peter.maydell, Mark Langsdorf, paul, rob.herring

From: Rob Herring <rob.herring@calxeda.com>

Use AHCIState instead of AHCIPCIState so the function can be used for
non-PCI based AHCI controllers.

Signed-off-by: Rob Herring <rob.herring@calxeda.com>
Signed-off-by: Mark Langsdorf <mark.langsdorf@calxeda.com>
---
Changes from v1, v2
	None

 hw/ide/ahci.c |   14 +++++++-------
 hw/ide/ich.c  |    4 ++--
 2 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c
index 0af201d..135d0ee 100644
--- a/hw/ide/ahci.c
+++ b/hw/ide/ahci.c
@@ -336,7 +336,7 @@ static void ahci_mem_write(void *opaque, target_phys_addr_t addr,
             case HOST_CTL: /* R/W */
                 if (val & HOST_CTL_RESET) {
                     DPRINTF(-1, "HBA Reset\n");
-                    ahci_reset(container_of(s, AHCIPCIState, ahci));
+                    ahci_reset(s);
                 } else {
                     s->control_regs.ghc = (val & 0x3) | HOST_CTL_AHCI_EN;
                     ahci_check_irq(s);
@@ -1199,18 +1199,18 @@ void ahci_uninit(AHCIState *s)
 
 void ahci_reset(void *opaque)
 {
-    struct AHCIPCIState *d = opaque;
+    struct AHCIState *s = opaque;
     AHCIPortRegs *pr;
     int i;
 
-    d->ahci.control_regs.irqstatus = 0;
-    d->ahci.control_regs.ghc = 0;
+    s->control_regs.irqstatus = 0;
+    s->control_regs.ghc = 0;
 
-    for (i = 0; i < d->ahci.ports; i++) {
-        pr = &d->ahci.dev[i].port_regs;
+    for (i = 0; i < s->ports; i++) {
+        pr = &s->dev[i].port_regs;
         pr->irq_stat = 0;
         pr->irq_mask = 0;
         pr->scr_ctl = 0;
-        ahci_reset_port(&d->ahci, i);
+        ahci_reset_port(s, i);
     }
 }
diff --git a/hw/ide/ich.c b/hw/ide/ich.c
index 3f7510f..44363ec 100644
--- a/hw/ide/ich.c
+++ b/hw/ide/ich.c
@@ -102,7 +102,7 @@ static int pci_ich9_ahci_init(PCIDevice *dev)
     /* XXX Software should program this register */
     d->card.config[0x90]   = 1 << 6; /* Address Map Register - AHCI mode */
 
-    qemu_register_reset(ahci_reset, d);
+    qemu_register_reset(ahci_reset, &d->ahci);
 
     msi_init(dev, 0x50, 1, true, false);
     d->ahci.irq = d->card.irq[0];
@@ -133,7 +133,7 @@ static int pci_ich9_uninit(PCIDevice *dev)
     d = DO_UPCAST(struct AHCIPCIState, card, dev);
 
     msi_uninit(dev);
-    qemu_unregister_reset(ahci_reset, d);
+    qemu_unregister_reset(ahci_reset, &d->ahci);
     ahci_uninit(&d->ahci);
 
     return 0;
-- 
1.7.5.4

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

* [Qemu-devel] [PATCH v3 6/9] ahci: add support for non-PCI based controllers
  2011-12-27 20:13 [Qemu-devel] [PATCH v3 0/9] various arm fixes Mark Langsdorf
                   ` (4 preceding siblings ...)
  2011-12-27 20:13 ` [Qemu-devel] [PATCH v3 5/9] ahci: convert ahci_reset to use AHCIState Mark Langsdorf
@ 2011-12-27 20:13 ` Mark Langsdorf
  2011-12-27 20:13 ` [Qemu-devel] [PATCH v3 7/9] add L2x0/PL310 cache controller device Mark Langsdorf
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 20+ messages in thread
From: Mark Langsdorf @ 2011-12-27 20:13 UTC (permalink / raw)
  To: qemu-devel; +Cc: kwolf, peter.maydell, Mark Langsdorf, paul, rob.herring

From: Rob Herring <rob.herring@calxeda.com>

Add support for ahci on sysbus.

Signed-off-by: Rob Herring <rob.herring@calxeda.com>
Signed-off-by: Mark Langsdorf <mark.langsdorf@calxeda.com>
---
Changes from v1, v2
	Corrected indentation of PlatAHCIState members
	Made plat_ahci_info into a single structure, not a list

 hw/ide/ahci.c |   31 +++++++++++++++++++++++++++++++
 1 files changed, 31 insertions(+), 0 deletions(-)

diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c
index 135d0ee..f052e55 100644
--- a/hw/ide/ahci.c
+++ b/hw/ide/ahci.c
@@ -25,6 +25,7 @@
 #include <hw/msi.h>
 #include <hw/pc.h>
 #include <hw/pci.h>
+#include <hw/sysbus.h>
 
 #include "monitor.h"
 #include "dma.h"
@@ -1214,3 +1215,33 @@ void ahci_reset(void *opaque)
         ahci_reset_port(s, i);
     }
 }
+
+typedef struct PlatAHCIState {
+    SysBusDevice busdev;
+    AHCIState ahci;
+} PlatAHCIState;
+
+static int plat_ahci_init(SysBusDevice *dev)
+{
+    PlatAHCIState *s = FROM_SYSBUS(PlatAHCIState, dev);
+    ahci_init(&s->ahci, &dev->qdev, 1);
+
+    sysbus_init_mmio(dev, &s->ahci.mem);
+    sysbus_init_irq(dev, &s->ahci.irq);
+
+    qemu_register_reset(ahci_reset, &s->ahci);
+    return 0;
+}
+
+static SysBusDeviceInfo plat_ahci_info = {
+    .qdev.name    = "plat-ahci",
+    .qdev.size    = sizeof(PlatAHCIState),
+    .init         = plat_ahci_init,
+};
+
+static void plat_ahci_register(void)
+{
+    sysbus_register_withprop(&plat_ahci_info);
+}
+device_init(plat_ahci_register);
+
-- 
1.7.5.4

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

* [Qemu-devel] [PATCH v3 7/9] add L2x0/PL310 cache controller device
  2011-12-27 20:13 [Qemu-devel] [PATCH v3 0/9] various arm fixes Mark Langsdorf
                   ` (5 preceding siblings ...)
  2011-12-27 20:13 ` [Qemu-devel] [PATCH v3 6/9] ahci: add support for non-PCI based controllers Mark Langsdorf
@ 2011-12-27 20:13 ` Mark Langsdorf
  2011-12-28  0:23   ` Peter Maydell
  2011-12-27 20:13 ` [Qemu-devel] [PATCH v3 8/9] Add xgmac ethernet model Mark Langsdorf
  2011-12-27 20:13 ` [Qemu-devel] [PATCH v3 9/9] arm: make number of a9mpcore GIC interrupts configurable Mark Langsdorf
  8 siblings, 1 reply; 20+ messages in thread
From: Mark Langsdorf @ 2011-12-27 20:13 UTC (permalink / raw)
  To: qemu-devel; +Cc: kwolf, peter.maydell, Mark Langsdorf, paul, rob.herring

From: Rob Herring <rob.herring@calxeda.com>

This is just a dummy device for ARM L2 cache controllers, based on the
pl310. The cache type parameter can be defined by a property value
and has a meaningful default.

Signed-off-by: Rob Herring <rob.herring@calxeda.com>
Signed-off-by: Mark Langsdorf <mark.langsdorf@calxeda.com>
---
Changes from v2
	Reformatted a couple of function definitions to be 80 lines long
Changes from v1
        Corrected formatting
        Clarified the copyrights
        Clarified GPL revision
        Clarified model version
        Removed hw_error() calls
        Added a reset function
        Restructed everything as switch/case statements
        Added a type cache property

 Makefile.target |    1 +
 hw/arm_l2x0.c   |  180 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 181 insertions(+), 0 deletions(-)
 create mode 100644 hw/arm_l2x0.c

diff --git a/Makefile.target b/Makefile.target
index 3261383..db5e44c 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -336,6 +336,7 @@ obj-arm-y = integratorcp.o versatilepb.o arm_pic.o arm_timer.o
 obj-arm-y += arm_boot.o pl011.o pl031.o pl050.o pl080.o pl110.o pl181.o pl190.o
 obj-arm-y += versatile_pci.o
 obj-arm-y += realview_gic.o realview.o arm_sysctl.o arm11mpcore.o a9mpcore.o
+obj-arm-y += arm_l2x0.o
 obj-arm-y += arm_mptimer.o
 obj-arm-y += armv7m.o armv7m_nvic.o stellaris.o pl022.o stellaris_enet.o
 obj-arm-y += pl061.o
diff --git a/hw/arm_l2x0.c b/hw/arm_l2x0.c
new file mode 100644
index 0000000..07092e3
--- /dev/null
+++ b/hw/arm_l2x0.c
@@ -0,0 +1,180 @@
+/*
+ * ARM dummy L210, L220, PL310 cache controller.
+ *
+ * Copyright (c) 2010-2012 Calxeda
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or any later version, as published by the Free Software
+ * Foundation.
+ *
+ * This program is distributed in the hope 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/>.
+ *
+ */
+
+#include "sysbus.h"
+
+/* L2C-310 r3p2 */
+#define CACHE_ID 0x410000c8
+#define DEFAULT_CACHE_TYPE 0x19080800
+
+typedef struct l2x0_state {
+    SysBusDevice busdev;
+    MemoryRegion iomem;
+    uint32_t cache_type;
+    uint32_t ctrl;
+    uint32_t aux_ctrl;
+    uint32_t data_ctrl;
+    uint32_t tag_ctrl;
+    uint32_t filter_start;
+    uint32_t filter_end;
+} l2x0_state;
+
+static const VMStateDescription vmstate_l2x0 = {
+    .name = "l2x0",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32(ctrl, l2x0_state),
+        VMSTATE_UINT32(aux_ctrl, l2x0_state),
+        VMSTATE_UINT32(data_ctrl, l2x0_state),
+        VMSTATE_UINT32(tag_ctrl, l2x0_state),
+        VMSTATE_UINT32(filter_start, l2x0_state),
+        VMSTATE_UINT32(filter_end, l2x0_state),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+
+static uint64_t l2x0_priv_read(void *opaque, target_phys_addr_t offset,
+                               unsigned size)
+{
+    l2x0_state *s = (l2x0_state *)opaque;
+    offset &= 0xfff;
+    if (offset >= 0x730 && offset < 0x800) {
+        return 0; /* cache ops complete */
+    }
+    switch (offset) {
+    case 0:
+        return CACHE_ID;
+    case 0x4:
+        return s->cache_type;
+    case 0x100:
+        return s->ctrl;
+    case 0x104:
+        return s->aux_ctrl;
+    case 0x108:
+        return s->tag_ctrl;
+    case 0x10C:
+        return s->data_ctrl;
+    case 0xC00:
+        return s->filter_start;
+    case 0xC04:
+        return s->filter_end;
+    case 0xF40:
+        return 0;
+    case 0xF60:
+        return 0;
+    case 0xF80:
+        return 0;
+    default:
+        fprintf(stderr, "l2x0_priv_read: Bad offset %x\n", (int)offset);
+        break;
+    }
+    return 0;
+}
+
+static void l2x0_priv_write(void *opaque, target_phys_addr_t offset,
+                            uint64_t value, unsigned size)
+{
+    l2x0_state *s = (l2x0_state *)opaque;
+    offset &= 0xfff;
+    if (offset >= 0x730 && offset < 0x800) {
+        /* ignore */
+        return;
+    }
+    switch (offset) {
+    case 0x100:
+        s->ctrl = value & 1;
+        break;
+    case 0x104:
+        s->aux_ctrl = value;
+        break;
+    case 0x108:
+        s->tag_ctrl = value;
+        break;
+    case 0x10C:
+        s->data_ctrl = value;
+        break;
+    case 0xC00:
+        s->filter_start = value;
+        break;
+    case 0xC04:
+        s->filter_end = value;
+        break;
+    case 0xF40:
+        return;
+    case 0xF60:
+        return;
+    case 0xF80:
+        return;
+    default:
+        fprintf(stderr, "l2x0_priv_write: Bad offset %x\n", (int)offset);
+        break;
+    }
+}
+
+static void l2x0_priv_reset(DeviceState *dev)
+{
+    l2x0_state *s = DO_UPCAST(l2x0_state, busdev.qdev, dev);
+
+    s->cache_type = 0x1c100100;
+    s->ctrl = 0;
+    s->aux_ctrl = 0x02020000;
+    s->tag_ctrl = 0;
+    s->data_ctrl = 0;
+    s->filter_start = 0;
+    s->filter_end = 0;
+}
+
+static const MemoryRegionOps l2x0_mem_ops = {
+    .read = l2x0_priv_read,
+    .write = l2x0_priv_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+ };
+
+static int l2x0_priv_init(SysBusDevice *dev)
+{
+    l2x0_state *s = FROM_SYSBUS(l2x0_state, dev);
+
+    memory_region_init_io(&s->iomem, &l2x0_mem_ops, s, "l2x0_cc", 0x1000);
+    sysbus_init_mmio(dev, &s->iomem);
+    return 0;
+}
+
+static SysBusDeviceInfo l2x0_info = {
+    .init = l2x0_priv_init,
+    .qdev.name = "l2x0",
+    .qdev.size = sizeof(l2x0_state),
+    .qdev.vmsd = &vmstate_l2x0,
+    .qdev.no_user = 1,
+    .qdev.props = (Property[]) {
+        DEFINE_PROP_UINT32("type", l2x0_state, cache_type, DEFAULT_CACHE_TYPE),
+        DEFINE_PROP_END_OF_LIST(),
+    },
+    .qdev.reset = l2x0_priv_reset,
+};
+
+static void l2x0_register_device(void)
+{
+    sysbus_register_withprop(&l2x0_info);
+}
+
+device_init(l2x0_register_device)
+
-- 
1.7.5.4

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

* [Qemu-devel] [PATCH v3 8/9] Add xgmac ethernet model
  2011-12-27 20:13 [Qemu-devel] [PATCH v3 0/9] various arm fixes Mark Langsdorf
                   ` (6 preceding siblings ...)
  2011-12-27 20:13 ` [Qemu-devel] [PATCH v3 7/9] add L2x0/PL310 cache controller device Mark Langsdorf
@ 2011-12-27 20:13 ` Mark Langsdorf
  2011-12-28  0:39   ` Peter Maydell
  2011-12-27 20:13 ` [Qemu-devel] [PATCH v3 9/9] arm: make number of a9mpcore GIC interrupts configurable Mark Langsdorf
  8 siblings, 1 reply; 20+ messages in thread
From: Mark Langsdorf @ 2011-12-27 20:13 UTC (permalink / raw)
  To: qemu-devel; +Cc: kwolf, peter.maydell, Mark Langsdorf, paul, rob.herring

This adds very basic support for XG-mac ethernet core from Synopsis and
others. Missing things include:

- statistics counters
- WoL support
- rx checksum offload
- chained descriptors (only linear descriptor ring)
- broadcast and multicast handling

Signed-off-by: Rob Herring <rob.herring@calxeda.com>
Signed-off-by: Mark Langsdorf <mark.langsdorf@calxeda.com>
---
Changes from v2
	None
Changes from v1
        Reformated most lines to fit within 80 columns
        Removed a bunch of unused variables in the state structures
        Got rid of some camelcase structure names
        Added vmstate support

 Makefile.target |    1 +
 hw/xgmac.c      |  418 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 419 insertions(+), 0 deletions(-)
 create mode 100644 hw/xgmac.c

diff --git a/Makefile.target b/Makefile.target
index db5e44c..94cb9ff 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -340,6 +340,7 @@ obj-arm-y += arm_l2x0.o
 obj-arm-y += arm_mptimer.o
 obj-arm-y += armv7m.o armv7m_nvic.o stellaris.o pl022.o stellaris_enet.o
 obj-arm-y += pl061.o
+obj-arm-y += xgmac.o
 obj-arm-y += arm-semi.o
 obj-arm-y += pxa2xx.o pxa2xx_pic.o pxa2xx_gpio.o pxa2xx_timer.o pxa2xx_dma.o
 obj-arm-y += pxa2xx_lcd.o pxa2xx_mmci.o pxa2xx_pcmcia.o pxa2xx_keypad.o
diff --git a/hw/xgmac.c b/hw/xgmac.c
new file mode 100644
index 0000000..a496b31
--- /dev/null
+++ b/hw/xgmac.c
@@ -0,0 +1,418 @@
+/*
+ * QEMU model of XGMAC Ethernet.
+ *
+ * derived from the Xilinx AXI-Ethernet by Edgar E. Iglesias.
+ *
+ * Copyright (c) 2011 Calxeda, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "sysbus.h"
+#include "qemu-char.h"
+#include "qemu-log.h"
+#include "net.h"
+#include "net/checksum.h"
+
+#define XGMAC_CONTROL           0x00000000   /* MAC Configuration */
+#define XGMAC_FRAME_FILTER      0x00000001   /* MAC Frame Filter */
+#define XGMAC_FLOW_CTRL         0x00000006   /* MAC Flow Control */
+#define XGMAC_VLAN_TAG          0x00000007   /* VLAN Tags */
+#define XGMAC_VERSION           0x00000008   /* Version */
+/* VLAN tag for insertion or replacement into tx frames */
+#define XGMAC_VLAN_INCL         0x00000009
+#define XGMAC_LPI_CTRL          0x0000000a   /* LPI Control and Status */
+#define XGMAC_LPI_TIMER         0x0000000b   /* LPI Timers Control */
+#define XGMAC_TX_PACE           0x0000000c   /* Transmit Pace and Stretch */
+#define XGMAC_VLAN_HASH         0x0000000d   /* VLAN Hash Table */
+#define XGMAC_DEBUG             0x0000000e   /* Debug */
+#define XGMAC_INT_STATUS        0x0000000f   /* Interrupt and Control */
+/* HASH table registers */
+#define XGMAC_HASH(n)           ((0x00000300/4) + (n))
+#define XGMAC_NUM_HASH          16
+/* Operation Mode */
+#define XGMAC_OPMODE            (0x00000400/4)
+/* Remote Wake-Up Frame Filter */
+#define XGMAC_REMOTE_WAKE       (0x00000700/4)
+/* PMT Control and Status */
+#define XGMAC_PMT               (0x00000704/4)
+
+#define XGMAC_ADDR_HIGH(reg)    (0x00000010+((reg) * 2))
+#define XGMAC_ADDR_LOW(reg)     (0x00000011+((reg) * 2))
+
+#define DMA_BUS_MODE            0x000003c0   /* Bus Mode */
+#define DMA_XMT_POLL_DEMAND     0x000003c1   /* Transmit Poll Demand */
+#define DMA_RCV_POLL_DEMAND     0x000003c2   /* Received Poll Demand */
+#define DMA_RCV_BASE_ADDR       0x000003c3   /* Receive List Base */
+#define DMA_TX_BASE_ADDR        0x000003c4   /* Transmit List Base */
+#define DMA_STATUS              0x000003c5   /* Status Register */
+#define DMA_CONTROL             0x000003c6   /* Ctrl (Operational Mode) */
+#define DMA_INTR_ENA            0x000003c7   /* Interrupt Enable */
+#define DMA_MISSED_FRAME_CTR    0x000003c8   /* Missed Frame Counter */
+/* Receive Interrupt Watchdog Timer */
+#define DMA_RI_WATCHDOG_TIMER   0x000003c9
+#define DMA_AXI_BUS             0x000003ca   /* AXI Bus Mode */
+#define DMA_AXI_STATUS          0x000003cb   /* AXI Status */
+#define DMA_CUR_TX_DESC_ADDR    0x000003d2   /* Current Host Tx Descriptor */
+#define DMA_CUR_RX_DESC_ADDR    0x000003d3   /* Current Host Rx Descriptor */
+#define DMA_CUR_TX_BUF_ADDR     0x000003d4   /* Current Host Tx Buffer */
+#define DMA_CUR_RX_BUF_ADDR     0x000003d5   /* Current Host Rx Buffer */
+#define DMA_HW_FEATURE          0x000003d6   /* Enabled Hardware Features */
+
+/* DMA Status register defines */
+#define DMA_STATUS_GMI          0x08000000   /* MMC interrupt */
+#define DMA_STATUS_GLI          0x04000000   /* GMAC Line interface int */
+#define DMA_STATUS_EB_MASK      0x00380000   /* Error Bits Mask */
+#define DMA_STATUS_EB_TX_ABORT  0x00080000   /* Error Bits - TX Abort */
+#define DMA_STATUS_EB_RX_ABORT  0x00100000   /* Error Bits - RX Abort */
+#define DMA_STATUS_TS_MASK      0x00700000   /* Transmit Process State */
+#define DMA_STATUS_TS_SHIFT     20
+#define DMA_STATUS_RS_MASK      0x000e0000   /* Receive Process State */
+#define DMA_STATUS_RS_SHIFT     17
+#define DMA_STATUS_NIS          0x00010000   /* Normal Interrupt Summary */
+#define DMA_STATUS_AIS          0x00008000   /* Abnormal Interrupt Summary */
+#define DMA_STATUS_ERI          0x00004000   /* Early Receive Interrupt */
+#define DMA_STATUS_FBI          0x00002000   /* Fatal Bus Error Interrupt */
+#define DMA_STATUS_ETI          0x00000400   /* Early Transmit Interrupt */
+#define DMA_STATUS_RWT          0x00000200   /* Receive Watchdog Timeout */
+#define DMA_STATUS_RPS          0x00000100   /* Receive Process Stopped */
+#define DMA_STATUS_RU           0x00000080   /* Receive Buffer Unavailable */
+#define DMA_STATUS_RI           0x00000040   /* Receive Interrupt */
+#define DMA_STATUS_UNF          0x00000020   /* Transmit Underflow */
+#define DMA_STATUS_OVF          0x00000010   /* Receive Overflow */
+#define DMA_STATUS_TJT          0x00000008   /* Transmit Jabber Timeout */
+#define DMA_STATUS_TU           0x00000004   /* Transmit Buffer Unavailable */
+#define DMA_STATUS_TPS          0x00000002   /* Transmit Process Stopped */
+#define DMA_STATUS_TI           0x00000001   /* Transmit Interrupt */
+
+/* DMA Control register defines */
+#define DMA_CONTROL_ST          0x00002000   /* Start/Stop Transmission */
+#define DMA_CONTROL_SR          0x00000002   /* Start/Stop Receive */
+#define DMA_CONTROL_DFF         0x01000000   /* Disable flush of rx frames */
+
+struct desc {
+    uint32_t ctl_stat;
+    uint16_t buffer1_size;
+    uint16_t buffer2_size;
+    uint32_t buffer1_addr;
+    uint32_t buffer2_addr;
+    uint32_t ext_stat;
+    uint32_t res[3];
+};
+
+#define R_MAX 0x400
+
+typedef struct rxtx_stats {
+    uint64_t rx_bytes;
+    uint64_t tx_bytes;
+
+    uint64_t rx;
+    uint64_t rx_bcast;
+    uint64_t rx_mcast;
+} rxtx_stats;
+
+typedef struct xgmac_state {
+    SysBusDevice busdev;
+    MemoryRegion iomem;
+    qemu_irq sbd_irq;
+    qemu_irq pmt_irq;
+    qemu_irq mci_irq;
+    NICState *nic;
+    NICConf conf;
+
+    uint32_t c_phyaddr;
+    struct rxtx_stats stats;
+    uint32_t regs[R_MAX];
+} xgmac_state;
+
+const VMStateDescription vmstate_rxtx_stats = {
+    .name = "xgmac_stats",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields      = (VMStateField[]) {
+        VMSTATE_UINT64(rx_bytes, rxtx_stats),
+        VMSTATE_UINT64(tx_bytes, rxtx_stats),
+        VMSTATE_UINT64(rx, rxtx_stats),
+        VMSTATE_UINT64(rx_bcast, rxtx_stats),
+        VMSTATE_UINT64(rx_mcast, rxtx_stats),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static const VMStateDescription vmstate_xgmac = {
+    .name = "xgmac",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32(c_phyaddr, xgmac_state),
+        VMSTATE_STRUCT(stats, xgmac_state, 0, vmstate_rxtx_stats, rxtx_stats),
+        VMSTATE_UINT32_ARRAY(regs, xgmac_state, R_MAX),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void xgmac_read_desc(struct xgmac_state *s, struct desc *d, int rx)
+{
+    uint32_t addr = rx ? s->regs[DMA_CUR_RX_DESC_ADDR] :
+        s->regs[DMA_CUR_TX_DESC_ADDR];
+    cpu_physical_memory_read(addr, d, sizeof(*d));
+}
+
+static void xgmac_write_desc(struct xgmac_state *s, struct desc *d, int rx)
+{
+    int reg = rx ? DMA_CUR_RX_DESC_ADDR : DMA_CUR_TX_DESC_ADDR;
+    uint32_t addr = s->regs[reg];
+
+    if (!rx && (d->ctl_stat & 0x00200000)) {
+        s->regs[reg] = s->regs[DMA_TX_BASE_ADDR];
+    } else if (rx && (d->buffer1_size & 0x8000)) {
+        s->regs[reg] = s->regs[DMA_RCV_BASE_ADDR];
+    } else {
+        s->regs[reg] += sizeof(*d);
+    }
+    cpu_physical_memory_write(addr, d, sizeof(*d));
+}
+
+static void xgmac_enet_send(struct xgmac_state *s)
+{
+    struct desc bd;
+    int frame_size;
+    int len;
+    uint8_t frame[8192];
+    uint8_t *ptr;
+
+    ptr = frame;
+    frame_size = 0;
+    while (1) {
+        xgmac_read_desc(s, &bd, 0);
+        if ((bd.ctl_stat & 0x80000000) == 0) {
+            /* Run out of descriptors to transmit.  */
+            break;
+        }
+        len = (bd.buffer1_size & 0xfff) + (bd.buffer2_size & 0xfff);
+
+        if ((bd.buffer1_size & 0xfff) > 2048) {
+            fprintf(stdout, "qemu:%s:ERROR...ERROR...ERROR... -- "
+                        "xgmac buffer 1 len on send > 2048 (0x%x)\n",
+                         __func__, bd.buffer1_size & 0xfff);
+            fflush(stdout);
+        }
+        if ((bd.buffer2_size & 0xfff) != 0) {
+            fprintf(stdout, "qemu:%s:ERROR...ERROR...ERROR... -- "
+                        "xgmac buffer 2 len on send != 0 (0x%x)\n",
+                        __func__, bd.buffer2_size & 0xfff);
+            fflush(stdout);
+        }
+        if (len >= sizeof(frame)) {
+            fprintf(stdout, "qemu:%s: buffer overflow %d read into %zu "
+                        "buffer\n" , __func__, len, sizeof(frame));
+            fprintf(stdout, "qemu:%s: buffer1.size=%d; buffer2.size=%d\n",
+                        __func__, bd.buffer1_size, bd.buffer2_size);
+            fflush(stdout);
+        }
+
+        cpu_physical_memory_read(bd.buffer1_addr, ptr, len);
+        ptr += len;
+        frame_size += len;
+        if (bd.ctl_stat & 0x20000000) {
+            /* Last buffer in frame.  */
+            qemu_send_packet(&s->nic->nc, frame, len);
+            ptr = frame;
+            frame_size = 0;
+            s->regs[DMA_STATUS] |= DMA_STATUS_TI | DMA_STATUS_NIS;
+        }
+        bd.ctl_stat &= ~0x80000000;
+        /* Write back the modified descriptor.  */
+        xgmac_write_desc(s, &bd, 0);
+    }
+}
+
+static void enet_update_irq(struct xgmac_state *s)
+{
+    int stat = s->regs[DMA_STATUS] & s->regs[DMA_INTR_ENA];
+    qemu_set_irq(s->sbd_irq, !!stat);
+}
+
+static uint64_t enet_read(void *opaque, target_phys_addr_t addr, unsigned size)
+{
+    struct xgmac_state *s = opaque;
+    uint64_t r = 0;
+    addr >>= 2;
+
+    switch (addr) {
+    case XGMAC_VERSION:
+        r = 0x1012;
+        break;
+    default:
+        if (addr < ARRAY_SIZE(s->regs)) {
+            r = s->regs[addr];
+        }
+        break;
+    }
+    return r;
+}
+
+static void enet_write(void *opaque, target_phys_addr_t addr, uint64_t value, unsigned size)
+{
+    struct xgmac_state *s = opaque;
+
+    addr >>= 2;
+    switch (addr) {
+    case DMA_BUS_MODE:
+        s->regs[DMA_BUS_MODE] = value & ~0x1;
+        break;
+    case DMA_XMT_POLL_DEMAND:
+        xgmac_enet_send(s);
+        break;
+    case DMA_STATUS:
+        s->regs[DMA_STATUS] = s->regs[DMA_STATUS] & ~value;
+        break;
+    case DMA_RCV_BASE_ADDR:
+        s->regs[DMA_RCV_BASE_ADDR] = s->regs[DMA_CUR_RX_DESC_ADDR] = value;
+        break;
+    case DMA_TX_BASE_ADDR:
+        s->regs[DMA_TX_BASE_ADDR] = s->regs[DMA_CUR_TX_DESC_ADDR] = value;
+        break;
+    default:
+        if (addr < ARRAY_SIZE(s->regs)) {
+            s->regs[addr] = value;
+        }
+        break;
+    }
+    enet_update_irq(s);
+}
+
+static const MemoryRegionOps enet_mem_ops = {
+    .read = enet_read,
+    .write = enet_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+static int eth_can_rx(VLANClientState *nc)
+{
+    struct xgmac_state *s = DO_UPCAST(NICState, nc, nc)->opaque;
+
+    /* RX enabled?  */
+    return s->regs[DMA_CONTROL] & DMA_CONTROL_SR;
+}
+
+static ssize_t eth_rx(VLANClientState *nc, const uint8_t *buf, size_t size)
+{
+    struct xgmac_state *s = DO_UPCAST(NICState, nc, nc)->opaque;
+    static const unsigned char sa_bcast[6] = {0xff, 0xff, 0xff,
+                                              0xff, 0xff, 0xff};
+    int unicast, broadcast, multicast;
+    struct desc bd;
+    ssize_t ret;
+
+    unicast = ~buf[0] & 0x1;
+    broadcast = memcmp(buf, sa_bcast, 6) == 0;
+    multicast = !unicast && !broadcast;
+    if (size < 12) {
+        s->regs[DMA_STATUS] |= DMA_STATUS_RI | DMA_STATUS_NIS;
+        ret = -1;
+        goto out;
+    }
+
+    xgmac_read_desc(s, &bd, 1);
+    if ((bd.ctl_stat & 0x80000000) == 0) {
+        s->regs[DMA_STATUS] |= DMA_STATUS_RU | DMA_STATUS_AIS;
+        ret = size;
+        goto out;
+    }
+
+    cpu_physical_memory_write(bd.buffer1_addr, buf, size);
+
+    /* Add in the 4 bytes for crc (the real hw returns length incl crc) */
+    size += 4;
+    bd.ctl_stat = (size << 16) | 0x300;
+    xgmac_write_desc(s, &bd, 1);
+
+    s->stats.rx_bytes += size;
+    s->stats.rx++;
+    if (multicast) {
+        s->stats.rx_mcast++;
+    } else if (broadcast) {
+        s->stats.rx_bcast++;
+    }
+
+    s->regs[DMA_STATUS] |= DMA_STATUS_RI | DMA_STATUS_NIS;
+    ret = size;
+
+out:
+    enet_update_irq(s);
+    return ret;
+}
+
+static void eth_cleanup(VLANClientState *nc)
+{
+    struct xgmac_state *s = DO_UPCAST(NICState, nc, nc)->opaque;
+    s->nic = NULL;
+}
+
+static NetClientInfo net_xgmac_enet_info = {
+    .type = NET_CLIENT_TYPE_NIC,
+    .size = sizeof(NICState),
+    .can_receive = eth_can_rx,
+    .receive = eth_rx,
+    .cleanup = eth_cleanup,
+};
+
+static int xgmac_enet_init(SysBusDevice *dev)
+{
+    struct xgmac_state *s = FROM_SYSBUS(typeof(*s), dev);
+
+    memory_region_init_io(&s->iomem, &enet_mem_ops, s, "xgmac", 0x1000);
+    sysbus_init_mmio(dev, &s->iomem);
+    sysbus_init_irq(dev, &s->sbd_irq);
+    sysbus_init_irq(dev, &s->pmt_irq);
+    sysbus_init_irq(dev, &s->mci_irq);
+
+    qemu_macaddr_default_if_unset(&s->conf.macaddr);
+    s->nic = qemu_new_nic(&net_xgmac_enet_info, &s->conf,
+                          dev->qdev.info->name, dev->qdev.id, s);
+    qemu_format_nic_info_str(&s->nic->nc, s->conf.macaddr.a);
+
+    s->regs[XGMAC_ADDR_HIGH(0)] = (s->conf.macaddr.a[5] << 8) |
+                                   s->conf.macaddr.a[4];
+    s->regs[XGMAC_ADDR_LOW(0)] = (s->conf.macaddr.a[3] << 24) |
+                                 (s->conf.macaddr.a[2] << 16) |
+                                 (s->conf.macaddr.a[1] << 8) |
+                                  s->conf.macaddr.a[0];
+
+    return 0;
+}
+
+static SysBusDeviceInfo xgmac_enet_info = {
+    .init = xgmac_enet_init,
+    .qdev.name  = "xgmac",
+    .qdev.size  = sizeof(struct xgmac_state),
+    .qdev.vmsd = &vmstate_xgmac,
+    .qdev.props = (Property[]) {
+        DEFINE_PROP_UINT32("phyaddr", struct xgmac_state, c_phyaddr, 7),
+        DEFINE_NIC_PROPERTIES(struct xgmac_state, conf),
+        DEFINE_PROP_END_OF_LIST(),
+    }
+};
+static void xgmac_enet_register(void)
+{
+    sysbus_register_withprop(&xgmac_enet_info);
+}
+
+device_init(xgmac_enet_register)
-- 
1.7.5.4

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

* [Qemu-devel] [PATCH v3 9/9] arm: make number of a9mpcore GIC interrupts configurable
  2011-12-27 20:13 [Qemu-devel] [PATCH v3 0/9] various arm fixes Mark Langsdorf
                   ` (7 preceding siblings ...)
  2011-12-27 20:13 ` [Qemu-devel] [PATCH v3 8/9] Add xgmac ethernet model Mark Langsdorf
@ 2011-12-27 20:13 ` Mark Langsdorf
  2011-12-27 21:59   ` Peter Maydell
  8 siblings, 1 reply; 20+ messages in thread
From: Mark Langsdorf @ 2011-12-27 20:13 UTC (permalink / raw)
  To: qemu-devel; +Cc: kwolf, peter.maydell, Mark Langsdorf, paul, rob.herring

Increase the maximum number of GIC interrupts for a9mp to 192, and
create a configurable property defaulting to 96 so that device
modelers can set the value appropriately for their SoC.

Signed-off-by: Mark Langsdorf <mark.langsdorf@calxeda.com>
---
Changes from v2
	Skipped
Changes from v1
	Increase the number of a9mp interrupts to 192
	Add a property defaulting to 96
	Add a num_irq member in the gic state structure
	Use the num_irq value as appropriate
	Add num_irq argument to gic_init()
	Add num_irq to various CPU calls to gic_init

 hw/a9mpcore.c     |    9 +++++++--
 hw/arm11mpcore.c  |    2 +-
 hw/arm_gic.c      |   40 +++++++++++++++++++++-------------------
 hw/armv7m_nvic.c  |    2 +-
 hw/realview_gic.c |    2 +-
 5 files changed, 31 insertions(+), 24 deletions(-)

diff --git a/hw/a9mpcore.c b/hw/a9mpcore.c
index 3ef0e13..89504c4 100644
--- a/hw/a9mpcore.c
+++ b/hw/a9mpcore.c
@@ -13,7 +13,7 @@
 /* Configuration for arm_gic.c:
  * number of external IRQ lines, max number of CPUs, how to ID current CPU
  */
-#define GIC_NIRQ 96
+#define GIC_NIRQ 192
 #define NCPU 4
 
 static inline int
@@ -37,6 +37,7 @@ typedef struct a9mp_priv_state {
     MemoryRegion ptimer_iomem;
     MemoryRegion container;
     DeviceState *mptimer;
+    uint32_t num_irq;
 } a9mp_priv_state;
 
 static uint64_t a9_scu_read(void *opaque, target_phys_addr_t offset,
@@ -152,8 +153,11 @@ static int a9mp_priv_init(SysBusDevice *dev)
     if (s->num_cpu > NCPU) {
         hw_error("a9mp_priv_init: num-cpu may not be more than %d\n", NCPU);
     }
+    if (s->num_irq > GIC_NIRQ) {
+        hw_error("a9mp_priv_init: num-irq may not be more than %d\n", GIC_NIRQ);
+    }
 
-    gic_init(&s->gic, s->num_cpu);
+    gic_init(&s->gic, s->num_cpu, s->num_irq);
 
     s->mptimer = qdev_create(NULL, "arm_mptimer");
     qdev_prop_set_uint32(s->mptimer, "num-cpu", s->num_cpu);
@@ -216,6 +220,7 @@ static SysBusDeviceInfo a9mp_priv_info = {
     .qdev.reset = a9mp_priv_reset,
     .qdev.props = (Property[]) {
         DEFINE_PROP_UINT32("num-cpu", a9mp_priv_state, num_cpu, 1),
+        DEFINE_PROP_UINT32("num-irq", a9mp_priv_state, num_irq, 96),
         DEFINE_PROP_END_OF_LIST(),
     }
 };
diff --git a/hw/arm11mpcore.c b/hw/arm11mpcore.c
index bc0457e..039b401 100644
--- a/hw/arm11mpcore.c
+++ b/hw/arm11mpcore.c
@@ -132,7 +132,7 @@ static int mpcore_priv_init(SysBusDevice *dev)
 {
     mpcore_priv_state *s = FROM_SYSBUSGIC(mpcore_priv_state, dev);
 
-    gic_init(&s->gic, s->num_cpu);
+    gic_init(&s->gic, s->num_cpu, GIC_NIRQ);
     s->mptimer = qdev_create(NULL, "arm_mptimer");
     qdev_prop_set_uint32(s->mptimer, "num-cpu", s->num_cpu);
     qdev_init_nofail(s->mptimer);
diff --git a/hw/arm_gic.c b/hw/arm_gic.c
index 0339cf5..cc21262 100644
--- a/hw/arm_gic.c
+++ b/hw/arm_gic.c
@@ -111,6 +111,7 @@ typedef struct gic_state
     struct gic_state *backref[NCPU];
     MemoryRegion cpuiomem[NCPU+1]; /* CPU interfaces */
 #endif
+    int num_irq;
 } gic_state;
 
 /* TODO: Many places that call this routine could be optimized.  */
@@ -133,7 +134,7 @@ static void gic_update(gic_state *s)
         }
         best_prio = 0x100;
         best_irq = 1023;
-        for (irq = 0; irq < GIC_NIRQ; irq++) {
+        for (irq = 0; irq < s->num_irq; irq++) {
             if (GIC_TEST_ENABLED(irq, cm) && GIC_TEST_PENDING(irq, cm)) {
                 if (GIC_GET_PRIORITY(irq, cpu) < best_prio) {
                     best_prio = GIC_GET_PRIORITY(irq, cpu);
@@ -222,7 +223,7 @@ static void gic_complete_irq(gic_state * s, int cpu, int irq)
     int update = 0;
     int cm = 1 << cpu;
     DPRINTF("EOI %d\n", irq);
-    if (irq >= GIC_NIRQ) {
+    if (irq >= s->num_irq) {
         /* This handles two cases:
          * 1. If software writes the ID of a spurious interrupt [ie 1023]
          * to the GICC_EOIR, the GIC ignores that write.
@@ -279,7 +280,7 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
         if (offset == 0)
             return s->enabled;
         if (offset == 4)
-            return ((GIC_NIRQ / 32) - 1) | ((NUM_CPU(s) - 1) << 5);
+            return ((s->num_irq / 32) - 1) | ((NUM_CPU(s) - 1) << 5);
         if (offset < 0x08)
             return 0;
         if (offset >= 0x80) {
@@ -295,7 +296,7 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
         else
             irq = (offset - 0x180) * 8;
         irq += GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         res = 0;
         for (i = 0; i < 8; i++) {
@@ -310,7 +311,7 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
         else
             irq = (offset - 0x280) * 8;
         irq += GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         res = 0;
         mask = (irq < 32) ?  cm : ALL_CPU_MASK;
@@ -322,7 +323,7 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
     } else if (offset < 0x400) {
         /* Interrupt Active.  */
         irq = (offset - 0x300) * 8 + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         res = 0;
         mask = (irq < 32) ?  cm : ALL_CPU_MASK;
@@ -334,14 +335,14 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
     } else if (offset < 0x800) {
         /* Interrupt Priority.  */
         irq = (offset - 0x400) + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         res = GIC_GET_PRIORITY(irq, cpu);
 #ifndef NVIC
     } else if (offset < 0xc00) {
         /* Interrupt CPU Target.  */
         irq = (offset - 0x800) + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         if (irq >= 29 && irq <= 31) {
             res = cm;
@@ -351,7 +352,7 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
     } else if (offset < 0xf00) {
         /* Interrupt Configuration.  */
         irq = (offset - 0xc00) * 2 + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         res = 0;
         for (i = 0; i < 4; i++) {
@@ -426,7 +427,7 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
     } else if (offset < 0x180) {
         /* Interrupt Set Enable.  */
         irq = (offset - 0x100) * 8 + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         if (irq < 16)
           value = 0xff;
@@ -451,7 +452,7 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
     } else if (offset < 0x200) {
         /* Interrupt Clear Enable.  */
         irq = (offset - 0x180) * 8 + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         if (irq < 16)
           value = 0;
@@ -468,7 +469,7 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
     } else if (offset < 0x280) {
         /* Interrupt Set Pending.  */
         irq = (offset - 0x200) * 8 + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         if (irq < 16)
           irq = 0;
@@ -481,7 +482,7 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
     } else if (offset < 0x300) {
         /* Interrupt Clear Pending.  */
         irq = (offset - 0x280) * 8 + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         for (i = 0; i < 8; i++) {
             /* ??? This currently clears the pending bit for all CPUs, even
@@ -497,7 +498,7 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
     } else if (offset < 0x800) {
         /* Interrupt Priority.  */
         irq = (offset - 0x400) + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         if (irq < 32) {
             s->priority1[irq][cpu] = value;
@@ -508,7 +509,7 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
     } else if (offset < 0xc00) {
         /* Interrupt CPU Target.  */
         irq = (offset - 0x800) + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         if (irq < 29)
             value = 0;
@@ -518,7 +519,7 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
     } else if (offset < 0xf00) {
         /* Interrupt Configuration.  */
         irq = (offset - 0xc00) * 4 + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         if (irq < 32)
             value |= 0xaa;
@@ -798,9 +799,9 @@ static int gic_load(QEMUFile *f, void *opaque, int version_id)
 }
 
 #if NCPU > 1
-static void gic_init(gic_state *s, int num_cpu)
+static void gic_init(gic_state *s, int num_cpu, int num_irq)
 #else
-static void gic_init(gic_state *s)
+static void gic_init(gic_state *s, int num_irq)
 #endif
 {
     int i;
@@ -808,7 +809,8 @@ static void gic_init(gic_state *s)
 #if NCPU > 1
     s->num_cpu = num_cpu;
 #endif
-    qdev_init_gpio_in(&s->busdev.qdev, gic_set_irq, GIC_NIRQ - 32);
+    s->num_irq = num_irq;
+    qdev_init_gpio_in(&s->busdev.qdev, gic_set_irq, s->num_irq - 32);
     for (i = 0; i < NUM_CPU(s); i++) {
         sysbus_init_irq(&s->busdev, &s->parent_irq[i]);
     }
diff --git a/hw/armv7m_nvic.c b/hw/armv7m_nvic.c
index bf8c3c5..b97c904 100644
--- a/hw/armv7m_nvic.c
+++ b/hw/armv7m_nvic.c
@@ -384,7 +384,7 @@ static int armv7m_nvic_init(SysBusDevice *dev)
 {
     nvic_state *s= FROM_SYSBUSGIC(nvic_state, dev);
 
-    gic_init(&s->gic);
+    gic_init(&s->gic, GIC_NIRQ);
     memory_region_add_subregion(get_system_memory(), 0xe000e000, &s->gic.iomem);
     s->systick.timer = qemu_new_timer_ns(vm_clock, systick_timer_tick, s);
     vmstate_register(&dev->qdev, -1, &vmstate_nvic, s);
diff --git a/hw/realview_gic.c b/hw/realview_gic.c
index 8c4d509..a967f36 100644
--- a/hw/realview_gic.c
+++ b/hw/realview_gic.c
@@ -37,7 +37,7 @@ static int realview_gic_init(SysBusDevice *dev)
 {
     RealViewGICState *s = FROM_SYSBUSGIC(RealViewGICState, dev);
 
-    gic_init(&s->gic);
+    gic_init(&s->gic, GIC_NIRQ);
     realview_gic_map_setup(s);
     sysbus_init_mmio(dev, &s->container);
     return 0;
-- 
1.7.5.4

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

* Re: [Qemu-devel] [PATCH v3 9/9] arm: make number of a9mpcore GIC interrupts configurable
  2011-12-27 20:13 ` [Qemu-devel] [PATCH v3 9/9] arm: make number of a9mpcore GIC interrupts configurable Mark Langsdorf
@ 2011-12-27 21:59   ` Peter Maydell
  2011-12-27 22:04     ` Mark Langsdorf
  0 siblings, 1 reply; 20+ messages in thread
From: Peter Maydell @ 2011-12-27 21:59 UTC (permalink / raw)
  To: Mark Langsdorf; +Cc: kwolf, qemu-devel, rob.herring, paul

On 27 December 2011 20:13, Mark Langsdorf <mark.langsdorf@calxeda.com> wrote:
> Increase the maximum number of GIC interrupts for a9mp to 192, and
> create a configurable property defaulting to 96 so that device
> modelers can set the value appropriately for their SoC.

>  /* Configuration for arm_gic.c:
>  * number of external IRQ lines, max number of CPUs, how to ID current CPU
>  */
> -#define GIC_NIRQ 96
> +#define GIC_NIRQ 192

This (still) isn't the maximum number of GIC interrupts for
an A9MP. You want 256.

Moreover:
now we have a per-cpu #define which is setting the compile-time
maximum on a run-time parameter. That's pretty pointless --
we should just have arm_gic.c have its own (purely internal)
#define of the maximum number of interrupts it can permit,
and the cpu-specific private peripheral code should only be
setting the run-time parameter. You can drop the #define completely
from a9mpcore.c &co. (don't forget to update the comment)

The GIC architectural limit on number of interrupts is 1020;
that would (I think) imply a ~64K memory usage by the GIC,
which we can live with I think.

>  #define NCPU 4
>
>  static inline int
> @@ -37,6 +37,7 @@ typedef struct a9mp_priv_state {
>     MemoryRegion ptimer_iomem;
>     MemoryRegion container;
>     DeviceState *mptimer;
> +    uint32_t num_irq;
>  } a9mp_priv_state;
>
>  static uint64_t a9_scu_read(void *opaque, target_phys_addr_t offset,
> @@ -152,8 +153,11 @@ static int a9mp_priv_init(SysBusDevice *dev)
>     if (s->num_cpu > NCPU) {
>         hw_error("a9mp_priv_init: num-cpu may not be more than %d\n", NCPU);
>     }
> +    if (s->num_irq > GIC_NIRQ) {
> +        hw_error("a9mp_priv_init: num-irq may not be more than %d\n", GIC_NIRQ);
> +    }

No need to check this here -- just pass it through
to gic_init() and let gic_init() hw_error if needed.

> --- a/hw/arm11mpcore.c
> +++ b/hw/arm11mpcore.c
> @@ -132,7 +132,7 @@ static int mpcore_priv_init(SysBusDevice *dev)
>  {
>     mpcore_priv_state *s = FROM_SYSBUSGIC(mpcore_priv_state, dev);
>
> -    gic_init(&s->gic, s->num_cpu);
> +    gic_init(&s->gic, s->num_cpu, GIC_NIRQ);

11MPCore, like A9MP, has a configurable number of interrupt lines
(up to 256 including the 32 internal ones, also like A9MP).

> -static void gic_init(gic_state *s)
> +static void gic_init(gic_state *s, int num_irq)
>  #endif
>  {
>     int i;
> @@ -808,7 +809,8 @@ static void gic_init(gic_state *s)
>  #if NCPU > 1
>     s->num_cpu = num_cpu;
>  #endif
> -    qdev_init_gpio_in(&s->busdev.qdev, gic_set_irq, GIC_NIRQ - 32);
> +    s->num_irq = num_irq;

This is where you should be hw_error()ing if num_irq is
too big.

I didn't see any changes to gic_load/gic_save, which means they
will still be saving all GIC_NIRQ entries in each of the per-irq
state arrays; this means that you've broken save/load compatibility.
I think this can be fixed by having save/load only save/load the
entries which are actually used (ie loop up to s->num_irq rather
than GIC_NIRQ).

-- PMM

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

* Re: [Qemu-devel] [PATCH v3 1/9] arm: add missing scu registers
  2011-12-27 20:13 ` [Qemu-devel] [PATCH v3 1/9] arm: add missing scu registers Mark Langsdorf
@ 2011-12-27 22:00   ` Peter Maydell
  0 siblings, 0 replies; 20+ messages in thread
From: Peter Maydell @ 2011-12-27 22:00 UTC (permalink / raw)
  To: Mark Langsdorf; +Cc: kwolf, qemu-devel, rob.herring, paul

On 27 December 2011 20:13, Mark Langsdorf <mark.langsdorf@calxeda.com> wrote:
> From: Rob Herring <rob.herring@calxeda.com>
>
> Add power control register to a9mpcore
>
> Signed-off-by: Rob Herring <rob.herring@calxeda.com>
> Signed-off-by: Mark Langsdorf <mark.langsdorf@calxeda.com>

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

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

* Re: [Qemu-devel] [PATCH v3 2/9] arm: Set frequencies for arm_timer
  2011-12-27 20:13 ` [Qemu-devel] [PATCH v3 2/9] arm: Set frequencies for arm_timer Mark Langsdorf
@ 2011-12-27 22:02   ` Peter Maydell
  0 siblings, 0 replies; 20+ messages in thread
From: Peter Maydell @ 2011-12-27 22:02 UTC (permalink / raw)
  To: Mark Langsdorf; +Cc: kwolf, qemu-devel, rob.herring, paul

On 27 December 2011 20:13, Mark Langsdorf <mark.langsdorf@calxeda.com> wrote:
> Use qdev properties to allow board modelers to set the frequencies
> for the sp804 timer. Each of the sp804's timers can have an
> individual frequency. The timers default to 1MHz.
>
> Signed-off-by: Mark Langsdorf <mark.langsdorf@calxeda.com>

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

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

* Re: [Qemu-devel] [PATCH v3 9/9] arm: make number of a9mpcore GIC interrupts configurable
  2011-12-27 21:59   ` Peter Maydell
@ 2011-12-27 22:04     ` Mark Langsdorf
  2011-12-27 22:09       ` Peter Maydell
  0 siblings, 1 reply; 20+ messages in thread
From: Mark Langsdorf @ 2011-12-27 22:04 UTC (permalink / raw)
  To: Peter Maydell
  Cc: kwolf@redhat.com, qemu-devel@nongnu.org, Rob Herring,
	paul@codesourcery.com

On 12/27/2011 03:59 PM, Peter Maydell wrote:
> On 27 December 2011 20:13, Mark Langsdorf <mark.langsdorf@calxeda.com> wrote:
>> Increase the maximum number of GIC interrupts for a9mp to 192, and
>> create a configurable property defaulting to 96 so that device
>> modelers can set the value appropriately for their SoC.
> 
>>  /* Configuration for arm_gic.c:
>>  * number of external IRQ lines, max number of CPUs, how to ID current CPU
>>  */
>> -#define GIC_NIRQ 96
>> +#define GIC_NIRQ 192
> 
> This (still) isn't the maximum number of GIC interrupts for
> an A9MP. You want 256.

I know, but I figured "more than anyone would be using" would
be sufficient.

> Moreover:
> now we have a per-cpu #define which is setting the compile-time
> maximum on a run-time parameter. That's pretty pointless --
> we should just have arm_gic.c have its own (purely internal)
> #define of the maximum number of interrupts it can permit,
> and the cpu-specific private peripheral code should only be
> setting the run-time parameter. You can drop the #define completely
> from a9mpcore.c &co. (don't forget to update the comment)

Okay.

> The GIC architectural limit on number of interrupts is 1020;
> that would (I think) imply a ~64K memory usage by the GIC,
> which we can live with I think.

I think you just said you wanted me to define the gic internal
maximum as 1020. I just want to be sure I understood you there.

>> --- a/hw/arm11mpcore.c
>> +++ b/hw/arm11mpcore.c
>> @@ -132,7 +132,7 @@ static int mpcore_priv_init(SysBusDevice *dev)
>>  {
>>     mpcore_priv_state *s = FROM_SYSBUSGIC(mpcore_priv_state, dev);
>>
>> -    gic_init(&s->gic, s->num_cpu);
>> +    gic_init(&s->gic, s->num_cpu, GIC_NIRQ);
> 
> 11MPCore, like A9MP, has a configurable number of interrupt lines
> (up to 256 including the 32 internal ones, also like A9MP).

I don't have 11mpcore to test with, but I'll make the change.

>> -static void gic_init(gic_state *s)
>> +static void gic_init(gic_state *s, int num_irq)
>>  #endif
>>  {
>>     int i;
>> @@ -808,7 +809,8 @@ static void gic_init(gic_state *s)
>>  #if NCPU > 1
>>     s->num_cpu = num_cpu;
>>  #endif
>> -    qdev_init_gpio_in(&s->busdev.qdev, gic_set_irq, GIC_NIRQ - 32);
>> +    s->num_irq = num_irq;
> 
> This is where you should be hw_error()ing if num_irq is
> too big.
> 
> I didn't see any changes to gic_load/gic_save, which means they
> will still be saving all GIC_NIRQ entries in each of the per-irq
> state arrays; this means that you've broken save/load compatibility.
> I think this can be fixed by having save/load only save/load the
> entries which are actually used (ie loop up to s->num_irq rather
> than GIC_NIRQ).

I had considered that, but wasn't sure enough about the pros and
cons. I'll make the changes and thanks for the feedback.

--Mark Langsdorf
Calxeda, Inc.

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

* Re: [Qemu-devel] [PATCH v3 3/9] arm: add dummy v7 cp15 config_base_register
  2011-12-27 20:13 ` [Qemu-devel] [PATCH v3 3/9] arm: add dummy v7 cp15 config_base_register Mark Langsdorf
@ 2011-12-27 22:05   ` Peter Maydell
  0 siblings, 0 replies; 20+ messages in thread
From: Peter Maydell @ 2011-12-27 22:05 UTC (permalink / raw)
  To: Mark Langsdorf; +Cc: kwolf, qemu-devel, rob.herring, paul

On 27 December 2011 20:13, Mark Langsdorf <mark.langsdorf@calxeda.com> wrote:
> Add a cp15 config_base_register that currently defaults to 0.
> After the QOM CPU support is added, the value will be properly
> set to the periphal base value.
>
> Signed-off-by: Mark Langsdorf <mark.langsdorf@calxeda.com>

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

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

* Re: [Qemu-devel] [PATCH v3 9/9] arm: make number of a9mpcore GIC interrupts configurable
  2011-12-27 22:04     ` Mark Langsdorf
@ 2011-12-27 22:09       ` Peter Maydell
  0 siblings, 0 replies; 20+ messages in thread
From: Peter Maydell @ 2011-12-27 22:09 UTC (permalink / raw)
  To: Mark Langsdorf
  Cc: kwolf@redhat.com, qemu-devel@nongnu.org, Rob Herring,
	paul@codesourcery.com

On 27 December 2011 22:04, Mark Langsdorf <mark.langsdorf@calxeda.com> wrote:
> On 12/27/2011 03:59 PM, Peter Maydell wrote:
>> The GIC architectural limit on number of interrupts is 1020;
>> that would (I think) imply a ~64K memory usage by the GIC,
>> which we can live with I think.
>
> I think you just said you wanted me to define the gic internal
> maximum as 1020. I just want to be sure I understood you there.

That's "we should define it as 1020 unless you or somebody else
thinks that's a terrible idea for some reason". Sorry, that was
a bit cryptic.

-- PMM

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

* Re: [Qemu-devel] [PATCH v3 5/9] ahci: convert ahci_reset to use AHCIState
  2011-12-27 20:13 ` [Qemu-devel] [PATCH v3 5/9] ahci: convert ahci_reset to use AHCIState Mark Langsdorf
@ 2011-12-27 22:54   ` Peter Maydell
  2011-12-27 23:20     ` Mark Langsdorf
  0 siblings, 1 reply; 20+ messages in thread
From: Peter Maydell @ 2011-12-27 22:54 UTC (permalink / raw)
  To: Mark Langsdorf; +Cc: kwolf, qemu-devel, rob.herring, paul

On 27 December 2011 20:13, Mark Langsdorf <mark.langsdorf@calxeda.com> wrote:
> From: Rob Herring <rob.herring@calxeda.com>
>
> Use AHCIState instead of AHCIPCIState so the function can be used for
> non-PCI based AHCI controllers.
>
> Signed-off-by: Rob Herring <rob.herring@calxeda.com>
> Signed-off-by: Mark Langsdorf <mark.langsdorf@calxeda.com>

Since there aren't any later patches in this set which depend
on these IDE fixes, I'm going to suggest that you split them
out into their own patchset. I can take the others into
arm-devs.next and target-arm.next, but not these.

-- PMM

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

* Re: [Qemu-devel] [PATCH v3 5/9] ahci: convert ahci_reset to use AHCIState
  2011-12-27 22:54   ` Peter Maydell
@ 2011-12-27 23:20     ` Mark Langsdorf
  0 siblings, 0 replies; 20+ messages in thread
From: Mark Langsdorf @ 2011-12-27 23:20 UTC (permalink / raw)
  To: Peter Maydell
  Cc: kwolf@redhat.com, qemu-devel@nongnu.org, Rob Herring,
	paul@codesourcery.com

On 12/27/2011 04:54 PM, Peter Maydell wrote:
> On 27 December 2011 20:13, Mark Langsdorf <mark.langsdorf@calxeda.com> wrote:
>> From: Rob Herring <rob.herring@calxeda.com>
>>
>> Use AHCIState instead of AHCIPCIState so the function can be used for
>> non-PCI based AHCI controllers.
>>
>> Signed-off-by: Rob Herring <rob.herring@calxeda.com>
>> Signed-off-by: Mark Langsdorf <mark.langsdorf@calxeda.com>
> 
> Since there aren't any later patches in this set which depend
> on these IDE fixes, I'm going to suggest that you split them
> out into their own patchset. I can take the others into
> arm-devs.next and target-arm.next, but not these.

I'll do that.

Does that mean you're satisfied with patches 7 and 8? If so,
I can resubmit the 7 patches since I've made the requested
changes from patch 9.

--Mark Langsdorf
Calxeda, Inc.

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

* Re: [Qemu-devel] [PATCH v3 7/9] add L2x0/PL310 cache controller device
  2011-12-27 20:13 ` [Qemu-devel] [PATCH v3 7/9] add L2x0/PL310 cache controller device Mark Langsdorf
@ 2011-12-28  0:23   ` Peter Maydell
  0 siblings, 0 replies; 20+ messages in thread
From: Peter Maydell @ 2011-12-28  0:23 UTC (permalink / raw)
  To: Mark Langsdorf; +Cc: kwolf, qemu-devel, rob.herring, paul

On 27 December 2011 20:13, Mark Langsdorf <mark.langsdorf@calxeda.com> wrote:
> +#define DEFAULT_CACHE_TYPE 0x19080800

Could use a comment saying what this actually is.
As far as I can tell it's actually specifying an invalid
I/D size for a PL310, which makes me suspicious of it.
(I might have misdecoded the bit fields, do check; also see below)

> +static void l2x0_priv_reset(DeviceState *dev)
> +{
> +    l2x0_state *s = DO_UPCAST(l2x0_state, busdev.qdev, dev);
> +
> +    s->cache_type = 0x1c100100;

cache_type is a constant (qdev property), right? You shouldn't
need to touch it in the reset function...

Also this number (which matches the PL310 TRM reset value)
doesn't match your DEFAULT_CACHE_TYPE constant. I know which
I'd rather make the default :-)

I've just looked a bit more closely at the TRM, and many
of the bits in the cache_type actually track bits from
the auxcr. Specifically:
bits [22:20], [10:8] track auxcr [19:17]
bits [18], [6] track auxcr [16]
(on PL220 [18:15], [6:3] track auxcr [16:13], which is an
awkward distinction between the two although I don't suppose
it's one anybody's taking advantage of.)

(the remaining bits in cache_type are for banking, lockdown
and harvard-vs-unified cache.)

-- PMM

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

* Re: [Qemu-devel] [PATCH v3 8/9] Add xgmac ethernet model
  2011-12-27 20:13 ` [Qemu-devel] [PATCH v3 8/9] Add xgmac ethernet model Mark Langsdorf
@ 2011-12-28  0:39   ` Peter Maydell
  0 siblings, 0 replies; 20+ messages in thread
From: Peter Maydell @ 2011-12-28  0:39 UTC (permalink / raw)
  To: Mark Langsdorf; +Cc: kwolf, qemu-devel, rob.herring, paul

On 27 December 2011 20:13, Mark Langsdorf <mark.langsdorf@calxeda.com> wrote:
> This adds very basic support for XG-mac ethernet core from Synopsis and
> others. Missing things include:
> +        if ((bd.buffer1_size & 0xfff) > 2048) {
> +            fprintf(stdout, "qemu:%s:ERROR...ERROR...ERROR... -- "
> +                        "xgmac buffer 1 len on send > 2048 (0x%x)\n",
> +                         __func__, bd.buffer1_size & 0xfff);
> +            fflush(stdout);
> +        }

This kind of chattiness (a) usually goes on stderr
(which would let you drop that fflush) (b)
is usually a macro so you can enable/disable it.

Otherwise looks OK I think (that's more of a "will-let-pass"
than a confident "reviewed" :-)).

-- PMM

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

end of thread, other threads:[~2011-12-28  0:39 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-12-27 20:13 [Qemu-devel] [PATCH v3 0/9] various arm fixes Mark Langsdorf
2011-12-27 20:13 ` [Qemu-devel] [PATCH v3 1/9] arm: add missing scu registers Mark Langsdorf
2011-12-27 22:00   ` Peter Maydell
2011-12-27 20:13 ` [Qemu-devel] [PATCH v3 2/9] arm: Set frequencies for arm_timer Mark Langsdorf
2011-12-27 22:02   ` Peter Maydell
2011-12-27 20:13 ` [Qemu-devel] [PATCH v3 3/9] arm: add dummy v7 cp15 config_base_register Mark Langsdorf
2011-12-27 22:05   ` Peter Maydell
2011-12-27 20:13 ` [Qemu-devel] [PATCH v3 4/9] arm: add dummy gic security registers Mark Langsdorf
2011-12-27 20:13 ` [Qemu-devel] [PATCH v3 5/9] ahci: convert ahci_reset to use AHCIState Mark Langsdorf
2011-12-27 22:54   ` Peter Maydell
2011-12-27 23:20     ` Mark Langsdorf
2011-12-27 20:13 ` [Qemu-devel] [PATCH v3 6/9] ahci: add support for non-PCI based controllers Mark Langsdorf
2011-12-27 20:13 ` [Qemu-devel] [PATCH v3 7/9] add L2x0/PL310 cache controller device Mark Langsdorf
2011-12-28  0:23   ` Peter Maydell
2011-12-27 20:13 ` [Qemu-devel] [PATCH v3 8/9] Add xgmac ethernet model Mark Langsdorf
2011-12-28  0:39   ` Peter Maydell
2011-12-27 20:13 ` [Qemu-devel] [PATCH v3 9/9] arm: make number of a9mpcore GIC interrupts configurable Mark Langsdorf
2011-12-27 21:59   ` Peter Maydell
2011-12-27 22:04     ` Mark Langsdorf
2011-12-27 22:09       ` Peter Maydell

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).