Patchwork Stellaris RCC2 Support

login
register
mail settings
Submitter Engin AYDOGAN
Date Aug. 3, 2011, 12:31 p.m.
Message ID <CAD+O8Us4nLP=1dQ5JWK-ZCQiTFN_-XyXy9HgGhQSK_3UD0xjSQ@mail.gmail.com>
Download mbox | patch
Permalink /patch/108146/
State New
Headers show

Comments

Engin AYDOGAN - Aug. 3, 2011, 12:31 p.m.
Based on the work http://patchwork.ozlabs.org/patch/31469/ , here's the
patch for HEAD.

From f91c8fb57b599b59f603b2fd9c81c6f9d7e3aad6 Mon Sep 17 00:00:00 2001
From: Engin AYDOGAN <engin@bzzzt.biz>
Date: Wed, 3 Aug 2011 00:36:47 -0700
Subject: [PATCH] Stellaris RCC2 support


Signed-off-by: Engin AYDOGAN <engin@bzzzt.biz>
---
 hw/stellaris.c |   70
+++++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 67 insertions(+), 3 deletions(-)

     case 0x104: /* RCGC1 */
@@ -467,9 +500,21 @@ static uint32_t ssys_read(void *opaque,
target_phys_addr_t offset)
     }
 }

+static bool ssys_use_rcc2(ssys_state *s)
+{
+    return (s->rcc2 >> 31) & 0x1;
+}
+
+/*
+ * Caculate the sys. clock period in ms.
+ */
 static void ssys_calculate_system_clock(ssys_state *s)
 {
-    system_clock_scale = 5 * (((s->rcc >> 23) & 0xf) + 1);
+    if (ssys_use_rcc2(s)) {
+        system_clock_scale = 5 * (((s->rcc2 >> 23) & 0x3f) + 1);
+    } else {
+        system_clock_scale = 5 * (((s->rcc >> 23) & 0xf) + 1);
+    }
 }

 static void ssys_write(void *opaque, target_phys_addr_t offset, uint32_t
value)
@@ -505,6 +550,18 @@ static void ssys_write(void *opaque, target_phys_addr_t
offset, uint32_t value)
         s->rcc = value;
         ssys_calculate_system_clock(s);
         break;
+    case 0x070: /* RCC2 */
+        if (ssys_is_sandstorm(s)) {
+            break;
+        }
+
+        if ((s->rcc2 & (1 << 13)) != 0 && (value & (1 << 13)) == 0) {
+            /* PLL enable.  */
+            s->int_status |= (1 << 6);
+        }
+        s->rcc2 = value;
+        ssys_calculate_system_clock(s);
+        break;
     case 0x100: /* RCGC0 */
         s->rcgc[0] = value;
         break;
@@ -562,6 +619,12 @@ static void ssys_reset(void *opaque)

     s->pborctl = 0x7ffd;
     s->rcc = 0x078e3ac0;
+
+    if (ssys_is_sandstorm(s)) {
+        s->rcc2 = 0;
+    } else {
+        s->rcc2 = 0x07802810;
+    }
     s->rcgc[0] = 1;
     s->scgc[0] = 1;
     s->dcgc[0] = 1;
@@ -578,7 +641,7 @@ static int stellaris_sys_post_load(void *opaque, int
version_id)

 static const VMStateDescription vmstate_stellaris_sys = {
     .name = "stellaris_sys",
-    .version_id = 1,
+    .version_id = 2,
     .minimum_version_id = 1,
     .minimum_version_id_old = 1,
     .post_load = stellaris_sys_post_load,
@@ -589,6 +652,7 @@ static const VMStateDescription vmstate_stellaris_sys =
{
         VMSTATE_UINT32(int_status, ssys_state),
         VMSTATE_UINT32(resc, ssys_state),
         VMSTATE_UINT32(rcc, ssys_state),
+        VMSTATE_UINT32_V(rcc2, ssys_state, 2),
         VMSTATE_UINT32_ARRAY(rcgc, ssys_state, 3),
         VMSTATE_UINT32_ARRAY(scgc, ssys_state, 3),
         VMSTATE_UINT32_ARRAY(dcgc, ssys_state, 3),
Peter Maydell - Aug. 3, 2011, 2:05 p.m.
On 3 August 2011 13:31, Engin AYDOGAN <engin@bzzzt.biz> wrote:
> Based on the work http://patchwork.ozlabs.org/patch/31469/ , here's the
> patch for HEAD.

Thanks very much for updating this patch. I only have a couple of
review comments.

Patch formatting issues first:
It's better to submit patches with git-send-email, because this
will get the format right (for instance your email wrapped a number
of long lines which meant the patch didn't apply cleanly).
Also it's nice to have a slightly longer commit message
in addition to the initial summary line. In particular in
this case since the patch is based on somebody else's work it's
polite to say something like "Based on an earlier patch by
Vijay Kumar B" (and cc him when mailing qemu-devel). So you
might have something like:

hw/stellaris: Add support for RCC2 register

Add support for the RCC2 register on Fury class devices.
Based on a patch...

Signed-off-by: ...

> +static bool ssys_is_sandstorm(ssys_state *s)
> +{
> +    uint32_t did0 = s->board->did0;
> +
> +    switch (did0 & DID0_VER_MASK) {
> +    case DID0_VER_0:
> +        return 1;
> +    case DID0_VER_1:
> +        return ((did0 & DID0_CLASS_MASK) == DID0_CLASS_SANDSTORM);
> +    default:
> +        return 0;
> +    }
> +}
> +
> +static bool ssys_is_fury(ssys_state *s)
> +{
> +    uint32_t did0 = s->board->did0;
> +
> +    return (((did0 & DID0_VER_MASK) == DID0_VER_1)
> +           && ((did0 & DID0_CLASS_MASK) == DID0_CLASS_FURY));
> +}

These functions kind of inversely duplicate each other.
I think it would be nicer to have:

static int ssys_board_class(ssys_state *s)
{
    uint32_t did0 = s->board->did0;
    if ((did0 & DID0_VER_MASK) == DID0_VER_0) {
        return DID0_CLASS_SANDSTORM;
    }
    return did0 & DID0_CLASS_MASK;
}

and then do
  if (ssys_board_class(s) == DID0_CLASS_SANDSTORM) ...

(or ... == DID0_CLASS_FURY). This will continue to be
useful if we ever add another board class later.

-- PMM

Patch

diff --git a/hw/stellaris.c b/hw/stellaris.c
index a280930..d886a03 100644
--- a/hw/stellaris.c
+++ b/hw/stellaris.c
@@ -332,6 +332,7 @@  typedef struct {
     uint32_t int_mask;
     uint32_t resc;
     uint32_t rcc;
+    uint32_t rcc2;
     uint32_t rcgc[3];
     uint32_t scgc[3];
     uint32_t dcgc[3];
@@ -386,6 +387,36 @@  static uint32_t pllcfg_fury[16] = {
     0xb11c /* 8.192 Mhz */
 };

+#define DID0_VER_MASK        0x70000000
+#define DID0_VER_0           0x00000000
+#define DID0_VER_1           0x10000000
+
+#define DID0_CLASS_MASK      0x00FF0000
+#define DID0_CLASS_SANDSTORM 0x00000000
+#define DID0_CLASS_FURY      0x00010000
+
+static bool ssys_is_sandstorm(ssys_state *s)
+{
+    uint32_t did0 = s->board->did0;
+
+    switch (did0 & DID0_VER_MASK) {
+    case DID0_VER_0:
+        return 1;
+    case DID0_VER_1:
+        return ((did0 & DID0_CLASS_MASK) == DID0_CLASS_SANDSTORM);
+    default:
+        return 0;
+    }
+}
+
+static bool ssys_is_fury(ssys_state *s)
+{
+    uint32_t did0 = s->board->did0;
+
+    return (((did0 & DID0_VER_MASK) == DID0_VER_1)
+           && ((did0 & DID0_CLASS_MASK) == DID0_CLASS_FURY));
+}
+
 static uint32_t ssys_read(void *opaque, target_phys_addr_t offset)
 {
     ssys_state *s = (ssys_state *)opaque;
@@ -429,12 +460,14 @@  static uint32_t ssys_read(void *opaque,
target_phys_addr_t offset)
         {
             int xtal;
             xtal = (s->rcc >> 6) & 0xf;
-            if (s->board->did0 & (1 << 16)) {
+            if (ssys_is_fury(s)) {
                 return pllcfg_fury[xtal];
             } else {
                 return pllcfg_sandstorm[xtal];
             }
         }
+    case 0x070: /* RCC2 */
+        return s->rcc2;
     case 0x100: /* RCGC0 */
         return s->rcgc[0];