Patchwork [RFC,v1,7/7] zynq_slcr: Implement CPU reset and halting

login
register
mail settings
Submitter Peter Crosthwaite
Date March 4, 2013, 9:01 a.m.
Message ID <0cd7b312706e95d9619b2d3de4f4fa062bef6b9d.1362387546.git.peter.crosthwaite@xilinx.com>
Download mbox | patch
Permalink /patch/224645/
State New
Headers show

Comments

Peter Crosthwaite - March 4, 2013, 9:01 a.m.
From: Peter A. G. Crosthwaite <peter.crosthwaite@petalogix.com>

Implement the CPU reset and halt functions of the A9_CPU_RST_CTRL register
(offset 0x244).

Signed-off-by: Peter A. G. Crosthwaite <peter.crosthwaite@petalogix.com>
---
changed from v2:
used device halting API instead of talking to the cpu.

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

Patch

diff --git a/hw/zynq_slcr.c b/hw/zynq_slcr.c
index 4925358..945355e 100644
--- a/hw/zynq_slcr.c
+++ b/hw/zynq_slcr.c
@@ -116,6 +116,9 @@  typedef enum {
   RESET_MAX
 } ResetValues;
 
+#define A9_CPU_RST_CTRL_RST_SHIFT 0
+#define A9_CPU_RST_CTRL_CLKSTOP_SHIFT 4
+
 typedef struct {
     SysBusDevice busdev;
     MemoryRegion iomem;
@@ -346,6 +349,7 @@  static void zynq_slcr_write(void *opaque, hwaddr offset,
                           uint64_t val, unsigned size)
 {
     ZynqSLCRState *s = (ZynqSLCRState *)opaque;
+    int i;
 
     DB_PRINT("offset: %08x data: %08x\n", (unsigned)offset, (unsigned)val);
 
@@ -400,6 +404,21 @@  static void zynq_slcr_write(void *opaque, hwaddr offset,
                 goto bad_reg;
             }
             s->reset[(offset - 0x200) / 4] = val;
+            if (offset - 0x200 == A9_CPU * 4) { /* CPU Reset */
+                for (i = 0; i < NUM_CPUS && s->cpus[i]; ++i) {
+                    bool is_rst = val & (1 << (A9_CPU_RST_CTRL_RST_SHIFT + i));
+                    bool is_clkstop = val &
+                                    (1 << (A9_CPU_RST_CTRL_CLKSTOP_SHIFT + i));
+                    if (is_rst) {
+                        DB_PRINT("resetting cpu %d\n", i);
+                        device_reset(s->cpus[i]);
+                    }
+                    DB_PRINT("%shalting cpu %d\n", is_rst || is_clkstop ?
+                             "" : "un", i);
+                    (is_rst || is_clkstop ?
+                                device_halt : device_unhalt)(s->cpus[i]);
+                }
+            }
             break;
         case 0x300:
             s->apu_ctrl = val;