[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
RE: [Qemu-devel] [PATCH] Implement RCC2 in Stellaris
From: |
Krumme, Chris |
Subject: |
RE: [Qemu-devel] [PATCH] Implement RCC2 in Stellaris |
Date: |
Thu, 13 Aug 2009 20:34:00 -0700 |
> -----Original Message-----
> From:
> address@hidden
> [mailto:address@hidden
> rg] On Behalf Of Vijay Kumar
> Sent: Thursday, August 13, 2009 7:10 AM
> To: address@hidden
> Cc: address@hidden
> Subject: [Qemu-devel] [PATCH] Implement RCC2 in Stellaris
>
> Code from Stellarisware fails to execute in qemu, since it tries to
> read/write to RCC2, that is not available in the Sandstorm register
> interface. But the Stellarisware code assumes that the processor
> ignores writes to RCC2 and reads return 0. This patch implements the
> RCC2 register, which provides the required behaviour in the Fury and
> Sandstorm interface.
>
> * Added RCC2 register in the SYSCTL block.
> * Moved Sandstorm and Fury identification helper functions.
> * Save and restore RCC2.
>
> Signed-off-by: Vijay Kumar B. <address@hidden>
>
> diff --git a/hw/stellaris.c b/hw/stellaris.c
> index d9434ca..1de53ee 100644
> --- a/hw/stellaris.c
> +++ b/hw/stellaris.c
> @@ -7,6 +7,8 @@
> * This code is licenced under the GPL.
> */
>
> +#include <stdbool.h>
> +
> #include "sysbus.h"
> #include "ssi.h"
> #include "arm-misc.h"
> @@ -367,6 +369,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];
> @@ -421,6 +424,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;
> @@ -464,12 +497,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];
> case 0x104: /* RCGC1 */
> @@ -502,9 +537,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)
> @@ -540,6 +587,17 @@ 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;
> @@ -597,6 +655,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;
> @@ -612,6 +676,7 @@ static void ssys_save(QEMUFile *f, void *opaque)
> qemu_put_be32(f, s->int_status);
> qemu_put_be32(f, s->resc);
> qemu_put_be32(f, s->rcc);
> + qemu_put_be32(f, s->rcc2);
> qemu_put_be32(f, s->rcgc[0]);
> qemu_put_be32(f, s->rcgc[1]);
> qemu_put_be32(f, s->rcgc[2]);
> @@ -629,7 +694,7 @@ static int ssys_load(QEMUFile *f, void
> *opaque, int version_id)
> {
> ssys_state *s = (ssys_state *)opaque;
>
> - if (version_id != 1)
> + if (version_id != 2)
> return -EINVAL;
>
> s->pborctl = qemu_get_be32(f);
> @@ -638,6 +703,7 @@ static int ssys_load(QEMUFile *f, void
> *opaque, int version_id)
> s->int_status = qemu_get_be32(f);
> s->resc = qemu_get_be32(f);
> s->rcc = qemu_get_be32(f);
> + s->rcc2 = qemu_get_be32(f);
If I understand correctly this should be protected by an if (version ==
2), and the if above should support both 1 and 2.
This does not seem like a change that should break old --> new
migration.
There are examples in other modules.
Hope this helps.
Chris
> s->rcgc[0] = qemu_get_be32(f);
> s->rcgc[1] = qemu_get_be32(f);
> s->rcgc[2] = qemu_get_be32(f);
> @@ -672,7 +738,7 @@ static void stellaris_sys_init(uint32_t
> base, qemu_irq irq,
> ssys_writefn, s);
> cpu_register_physical_memory(base, 0x00001000, iomemtype);
> ssys_reset(s);
> - register_savevm("stellaris_sys", -1, 1, ssys_save, ssys_load, s);
> + register_savevm("stellaris_sys", -1, 2, ssys_save, ssys_load, s);
> }
>
>
>
>
>