* [Qemu-devel] [PATCH] Implement RCC2 in Stellaris
@ 2009-08-13 12:09 Vijay Kumar
2009-08-14 3:34 ` Krumme, Chris
0 siblings, 1 reply; 3+ messages in thread
From: Vijay Kumar @ 2009-08-13 12:09 UTC (permalink / raw)
To: qemu-devel; +Cc: paul
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. <vijaykumar@bravegnu.org>
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);
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);
}
^ permalink raw reply related [flat|nested] 3+ messages in thread
* RE: [Qemu-devel] [PATCH] Implement RCC2 in Stellaris
2009-08-13 12:09 [Qemu-devel] [PATCH] Implement RCC2 in Stellaris Vijay Kumar
@ 2009-08-14 3:34 ` Krumme, Chris
2009-08-15 6:24 ` Vijay Kumar
0 siblings, 1 reply; 3+ messages in thread
From: Krumme, Chris @ 2009-08-14 3:34 UTC (permalink / raw)
To: Vijay Kumar, qemu-devel; +Cc: paul
> -----Original Message-----
> From:
> qemu-devel-bounces+chris.krumme=windriver.com@nongnu.org
> [mailto:qemu-devel-bounces+chris.krumme=windriver.com@nongnu.o
> rg] On Behalf Of Vijay Kumar
> Sent: Thursday, August 13, 2009 7:10 AM
> To: qemu-devel@nongnu.org
> Cc: paul@codesourcery.com
> 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. <vijaykumar@bravegnu.org>
>
> 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);
> }
>
>
>
>
>
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [Qemu-devel] [PATCH] Implement RCC2 in Stellaris
2009-08-14 3:34 ` Krumme, Chris
@ 2009-08-15 6:24 ` Vijay Kumar
0 siblings, 0 replies; 3+ messages in thread
From: Vijay Kumar @ 2009-08-15 6:24 UTC (permalink / raw)
To: Krumme, Chris; +Cc: qemu-devel, paul
Krumme, Chris wrote:
>> 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.
Thanks for the suggestion Chris. I will incorporate this and
send the updated patch.
Regards,
Vijay
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2009-08-15 6:26 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-08-13 12:09 [Qemu-devel] [PATCH] Implement RCC2 in Stellaris Vijay Kumar
2009-08-14 3:34 ` Krumme, Chris
2009-08-15 6:24 ` Vijay Kumar
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).