Merge remote-tracking branch 'pmaydell/arm-devs.for-upstream' into staging

* pmaydell/arm-devs.for-upstream:
  arm_gic: Rename gic_state to GICState
  zynq_slcr: Fixed ResetValues enum
  versatilepb: add gpio pl061 support
  hw/ds1338: Implement state save/restore
  hw/ds1338: Remove 'now' field from state struct
  hw/ds1338: Recapture current time when register pointer wraps around
  hw/ds1338: Fix mishandling of register pointer
  hw/arm_gic.c: Fix improper DPRINTF output.
  cadence_ttc: Fix 'clear on read' behavior
This commit is contained in:
Anthony Liguori 2012-10-12 11:20:14 -05:00
commit ae72f3f539
8 changed files with 137 additions and 83 deletions

View file

@ -36,7 +36,7 @@ static const uint8_t gic_id[] = {
#define NUM_CPU(s) ((s)->num_cpu)
static inline int gic_get_current_cpu(gic_state *s)
static inline int gic_get_current_cpu(GICState *s)
{
if (s->num_cpu > 1) {
return cpu_single_env->cpu_index;
@ -46,7 +46,7 @@ static inline int gic_get_current_cpu(gic_state *s)
/* TODO: Many places that call this routine could be optimized. */
/* Update interrupt status after enabled or pending bits have been changed. */
void gic_update(gic_state *s)
void gic_update(GICState *s)
{
int best_irq;
int best_prio;
@ -84,7 +84,7 @@ void gic_update(gic_state *s)
}
}
void gic_set_pending_private(gic_state *s, int cpu, int irq)
void gic_set_pending_private(GICState *s, int cpu, int irq)
{
int cm = 1 << cpu;
@ -105,7 +105,7 @@ static void gic_set_irq(void *opaque, int irq, int level)
* [N+32..N+63] : PPI (internal interrupts for CPU 1
* ...
*/
gic_state *s = (gic_state *)opaque;
GICState *s = (GICState *)opaque;
int cm, target;
if (irq < (s->num_irq - GIC_INTERNAL)) {
/* The first external input line is internal interrupt 32. */
@ -137,7 +137,7 @@ static void gic_set_irq(void *opaque, int irq, int level)
gic_update(s);
}
static void gic_set_running_irq(gic_state *s, int cpu, int irq)
static void gic_set_running_irq(GICState *s, int cpu, int irq)
{
s->running_irq[cpu] = irq;
if (irq == 1023) {
@ -148,7 +148,7 @@ static void gic_set_running_irq(gic_state *s, int cpu, int irq)
gic_update(s);
}
uint32_t gic_acknowledge_irq(gic_state *s, int cpu)
uint32_t gic_acknowledge_irq(GICState *s, int cpu)
{
int new_irq;
int cm = 1 << cpu;
@ -167,7 +167,7 @@ uint32_t gic_acknowledge_irq(gic_state *s, int cpu)
return new_irq;
}
void gic_complete_irq(gic_state *s, int cpu, int irq)
void gic_complete_irq(GICState *s, int cpu, int irq)
{
int update = 0;
int cm = 1 << cpu;
@ -214,7 +214,7 @@ void gic_complete_irq(gic_state *s, int cpu, int irq)
static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
{
gic_state *s = (gic_state *)opaque;
GICState *s = (GICState *)opaque;
uint32_t res;
int irq;
int i;
@ -347,7 +347,7 @@ static uint32_t gic_dist_readl(void *opaque, target_phys_addr_t offset)
static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
uint32_t value)
{
gic_state *s = (gic_state *)opaque;
GICState *s = (GICState *)opaque;
int irq;
int i;
int cpu;
@ -500,7 +500,7 @@ static void gic_dist_writew(void *opaque, target_phys_addr_t offset,
static void gic_dist_writel(void *opaque, target_phys_addr_t offset,
uint32_t value)
{
gic_state *s = (gic_state *)opaque;
GICState *s = (GICState *)opaque;
if (offset == 0xf00) {
int cpu;
int irq;
@ -539,7 +539,7 @@ static const MemoryRegionOps gic_dist_ops = {
.endianness = DEVICE_NATIVE_ENDIAN,
};
static uint32_t gic_cpu_read(gic_state *s, int cpu, int offset)
static uint32_t gic_cpu_read(GICState *s, int cpu, int offset)
{
switch (offset) {
case 0x00: /* Control */
@ -561,12 +561,12 @@ static uint32_t gic_cpu_read(gic_state *s, int cpu, int offset)
}
}
static void gic_cpu_write(gic_state *s, int cpu, int offset, uint32_t value)
static void gic_cpu_write(GICState *s, int cpu, int offset, uint32_t value)
{
switch (offset) {
case 0x00: /* Control */
s->cpu_enabled[cpu] = (value & 1);
DPRINTF("CPU %d %sabled\n", cpu, s->cpu_enabled ? "En" : "Dis");
DPRINTF("CPU %d %sabled\n", cpu, s->cpu_enabled[cpu] ? "En" : "Dis");
break;
case 0x04: /* Priority mask */
s->priority_mask[cpu] = (value & 0xff);
@ -587,25 +587,25 @@ static void gic_cpu_write(gic_state *s, int cpu, int offset, uint32_t value)
static uint64_t gic_thiscpu_read(void *opaque, target_phys_addr_t addr,
unsigned size)
{
gic_state *s = (gic_state *)opaque;
GICState *s = (GICState *)opaque;
return gic_cpu_read(s, gic_get_current_cpu(s), addr);
}
static void gic_thiscpu_write(void *opaque, target_phys_addr_t addr,
uint64_t value, unsigned size)
{
gic_state *s = (gic_state *)opaque;
GICState *s = (GICState *)opaque;
gic_cpu_write(s, gic_get_current_cpu(s), addr, value);
}
/* Wrappers to read/write the GIC CPU interface for a specific CPU.
* These just decode the opaque pointer into gic_state* + cpu id.
* These just decode the opaque pointer into GICState* + cpu id.
*/
static uint64_t gic_do_cpu_read(void *opaque, target_phys_addr_t addr,
unsigned size)
{
gic_state **backref = (gic_state **)opaque;
gic_state *s = *backref;
GICState **backref = (GICState **)opaque;
GICState *s = *backref;
int id = (backref - s->backref);
return gic_cpu_read(s, id, addr);
}
@ -613,8 +613,8 @@ static uint64_t gic_do_cpu_read(void *opaque, target_phys_addr_t addr,
static void gic_do_cpu_write(void *opaque, target_phys_addr_t addr,
uint64_t value, unsigned size)
{
gic_state **backref = (gic_state **)opaque;
gic_state *s = *backref;
GICState **backref = (GICState **)opaque;
GICState *s = *backref;
int id = (backref - s->backref);
gic_cpu_write(s, id, addr, value);
}
@ -631,7 +631,7 @@ static const MemoryRegionOps gic_cpu_ops = {
.endianness = DEVICE_NATIVE_ENDIAN,
};
void gic_init_irqs_and_distributor(gic_state *s, int num_irq)
void gic_init_irqs_and_distributor(GICState *s, int num_irq)
{
int i;
@ -657,7 +657,7 @@ static int arm_gic_init(SysBusDevice *dev)
{
/* Device instance init function for the GIC sysbus device */
int i;
gic_state *s = FROM_SYSBUS(gic_state, dev);
GICState *s = FROM_SYSBUS(GICState, dev);
ARMGICClass *agc = ARM_GIC_GET_CLASS(s);
agc->parent_init(dev);
@ -701,7 +701,7 @@ static void arm_gic_class_init(ObjectClass *klass, void *data)
static TypeInfo arm_gic_info = {
.name = TYPE_ARM_GIC,
.parent = TYPE_ARM_GIC_COMMON,
.instance_size = sizeof(gic_state),
.instance_size = sizeof(GICState),
.class_init = arm_gic_class_init,
.class_size = sizeof(ARMGICClass),
};

View file

@ -22,7 +22,7 @@
static void gic_save(QEMUFile *f, void *opaque)
{
gic_state *s = (gic_state *)opaque;
GICState *s = (GICState *)opaque;
int i;
int j;
@ -56,7 +56,7 @@ static void gic_save(QEMUFile *f, void *opaque)
static int gic_load(QEMUFile *f, void *opaque, int version_id)
{
gic_state *s = (gic_state *)opaque;
GICState *s = (GICState *)opaque;
int i;
int j;
@ -96,7 +96,7 @@ static int gic_load(QEMUFile *f, void *opaque, int version_id)
static int arm_gic_common_init(SysBusDevice *dev)
{
gic_state *s = FROM_SYSBUS(gic_state, dev);
GICState *s = FROM_SYSBUS(GICState, dev);
int num_irq = s->num_irq;
if (s->num_cpu > NCPU) {
@ -123,7 +123,7 @@ static int arm_gic_common_init(SysBusDevice *dev)
static void arm_gic_common_reset(DeviceState *dev)
{
gic_state *s = FROM_SYSBUS(gic_state, sysbus_from_qdev(dev));
GICState *s = FROM_SYSBUS(GICState, sysbus_from_qdev(dev));
int i;
memset(s->irq_state, 0, GIC_MAXIRQ * sizeof(gic_irq_state));
for (i = 0 ; i < s->num_cpu; i++) {
@ -147,13 +147,13 @@ static void arm_gic_common_reset(DeviceState *dev)
}
static Property arm_gic_common_properties[] = {
DEFINE_PROP_UINT32("num-cpu", gic_state, num_cpu, 1),
DEFINE_PROP_UINT32("num-irq", gic_state, num_irq, 32),
DEFINE_PROP_UINT32("num-cpu", GICState, num_cpu, 1),
DEFINE_PROP_UINT32("num-irq", GICState, num_irq, 32),
/* Revision can be 1 or 2 for GIC architecture specification
* versions 1 or 2, or 0 to indicate the legacy 11MPCore GIC.
* (Internally, 0xffffffff also indicates "not a GIC but an NVIC".)
*/
DEFINE_PROP_UINT32("revision", gic_state, revision, 1),
DEFINE_PROP_UINT32("revision", GICState, revision, 1),
DEFINE_PROP_END_OF_LIST(),
};
@ -170,7 +170,7 @@ static void arm_gic_common_class_init(ObjectClass *klass, void *data)
static TypeInfo arm_gic_common_type = {
.name = TYPE_ARM_GIC_COMMON,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(gic_state),
.instance_size = sizeof(GICState),
.class_size = sizeof(ARMGICCommonClass),
.class_init = arm_gic_common_class_init,
.abstract = true,

View file

@ -69,7 +69,7 @@ typedef struct gic_irq_state {
unsigned trigger:1; /* nonzero = edge triggered. */
} gic_irq_state;
typedef struct gic_state {
typedef struct GICState {
SysBusDevice busdev;
qemu_irq parent_irq[NCPU];
int enabled;
@ -92,25 +92,25 @@ typedef struct gic_state {
/* This is just so we can have an opaque pointer which identifies
* both this GIC and which CPU interface we should be accessing.
*/
struct gic_state *backref[NCPU];
struct GICState *backref[NCPU];
MemoryRegion cpuiomem[NCPU+1]; /* CPU interfaces */
uint32_t num_irq;
uint32_t revision;
} gic_state;
} GICState;
/* The special cases for the revision property: */
#define REV_11MPCORE 0
#define REV_NVIC 0xffffffff
void gic_set_pending_private(gic_state *s, int cpu, int irq);
uint32_t gic_acknowledge_irq(gic_state *s, int cpu);
void gic_complete_irq(gic_state *s, int cpu, int irq);
void gic_update(gic_state *s);
void gic_init_irqs_and_distributor(gic_state *s, int num_irq);
void gic_set_pending_private(GICState *s, int cpu, int irq);
uint32_t gic_acknowledge_irq(GICState *s, int cpu);
void gic_complete_irq(GICState *s, int cpu, int irq);
void gic_update(GICState *s);
void gic_init_irqs_and_distributor(GICState *s, int num_irq);
#define TYPE_ARM_GIC_COMMON "arm_gic_common"
#define ARM_GIC_COMMON(obj) \
OBJECT_CHECK(gic_state, (obj), TYPE_ARM_GIC_COMMON)
OBJECT_CHECK(GICState, (obj), TYPE_ARM_GIC_COMMON)
#define ARM_GIC_COMMON_CLASS(klass) \
OBJECT_CLASS_CHECK(ARMGICCommonClass, (klass), TYPE_ARM_GIC_COMMON)
#define ARM_GIC_COMMON_GET_CLASS(obj) \
@ -122,7 +122,7 @@ typedef struct ARMGICCommonClass {
#define TYPE_ARM_GIC "arm_gic"
#define ARM_GIC(obj) \
OBJECT_CHECK(gic_state, (obj), TYPE_ARM_GIC)
OBJECT_CHECK(GICState, (obj), TYPE_ARM_GIC)
#define ARM_GIC_CLASS(klass) \
OBJECT_CLASS_CHECK(ARMGICClass, (klass), TYPE_ARM_GIC)
#define ARM_GIC_GET_CLASS(obj) \

View file

@ -17,7 +17,7 @@
#include "arm_gic_internal.h"
typedef struct {
gic_state gic;
GICState gic;
struct {
uint32_t control;
uint32_t reload;
@ -505,9 +505,9 @@ static void armv7m_nvic_instance_init(Object *obj)
* than our superclass. This function runs after qdev init
* has set the defaults from the Property array and before
* any user-specified property setting, so just modify the
* value in the gic_state struct.
* value in the GICState struct.
*/
gic_state *s = ARM_GIC_COMMON(obj);
GICState *s = ARM_GIC_COMMON(obj);
/* The ARM v7m may have anything from 0 to 496 external interrupt
* IRQ lines. We default to 64. Other boards may differ and should
* set the num-irq property appropriately.

View file

@ -274,6 +274,7 @@ static uint32_t cadence_ttc_read_imp(void *opaque, target_phys_addr_t offset)
/* cleared after read */
value = s->reg_intr;
s->reg_intr = 0;
cadence_timer_update(s);
return value;
case 0x60: /* interrupt enable */
@ -355,7 +356,6 @@ static void cadence_ttc_write(void *opaque, target_phys_addr_t offset,
case 0x54: /* interrupt register */
case 0x58:
case 0x5c:
s->reg_intr &= (~value & 0xfff);
break;
case 0x60: /* interrupt enable */

View file

@ -12,39 +12,84 @@
#include "i2c.h"
/* Size of NVRAM including both the user-accessible area and the
* secondary register area.
*/
#define NVRAM_SIZE 64
typedef struct {
I2CSlave i2c;
time_t offset;
struct tm now;
uint8_t nvram[56];
int ptr;
int addr_byte;
int64_t offset;
uint8_t nvram[NVRAM_SIZE];
int32_t ptr;
bool addr_byte;
} DS1338State;
static const VMStateDescription vmstate_ds1338 = {
.name = "ds1338",
.version_id = 1,
.minimum_version_id = 1,
.minimum_version_id_old = 1,
.fields = (VMStateField[]) {
VMSTATE_I2C_SLAVE(i2c, DS1338State),
VMSTATE_INT64(offset, DS1338State),
VMSTATE_UINT8_ARRAY(nvram, DS1338State, NVRAM_SIZE),
VMSTATE_INT32(ptr, DS1338State),
VMSTATE_BOOL(addr_byte, DS1338State),
VMSTATE_END_OF_LIST()
}
};
static void capture_current_time(DS1338State *s)
{
/* Capture the current time into the secondary registers
* which will be actually read by the data transfer operation.
*/
struct tm now;
qemu_get_timedate(&now, s->offset);
s->nvram[0] = to_bcd(now.tm_sec);
s->nvram[1] = to_bcd(now.tm_min);
if (s->nvram[2] & 0x40) {
s->nvram[2] = (to_bcd((now.tm_hour % 12)) + 1) | 0x40;
if (now.tm_hour >= 12) {
s->nvram[2] |= 0x20;
}
} else {
s->nvram[2] = to_bcd(now.tm_hour);
}
s->nvram[3] = to_bcd(now.tm_wday) + 1;
s->nvram[4] = to_bcd(now.tm_mday);
s->nvram[5] = to_bcd(now.tm_mon) + 1;
s->nvram[6] = to_bcd(now.tm_year - 100);
}
static void inc_regptr(DS1338State *s)
{
/* The register pointer wraps around after 0x3F; wraparound
* causes the current time/date to be retransferred into
* the secondary registers.
*/
s->ptr = (s->ptr + 1) & (NVRAM_SIZE - 1);
if (!s->ptr) {
capture_current_time(s);
}
}
static void ds1338_event(I2CSlave *i2c, enum i2c_event event)
{
DS1338State *s = FROM_I2C_SLAVE(DS1338State, i2c);
switch (event) {
case I2C_START_RECV:
qemu_get_timedate(&s->now, s->offset);
s->nvram[0] = to_bcd(s->now.tm_sec);
s->nvram[1] = to_bcd(s->now.tm_min);
if (s->nvram[2] & 0x40) {
s->nvram[2] = (to_bcd((s->now.tm_hour % 12)) + 1) | 0x40;
if (s->now.tm_hour >= 12) {
s->nvram[2] |= 0x20;
}
} else {
s->nvram[2] = to_bcd(s->now.tm_hour);
}
s->nvram[3] = to_bcd(s->now.tm_wday) + 1;
s->nvram[4] = to_bcd(s->now.tm_mday);
s->nvram[5] = to_bcd(s->now.tm_mon) + 1;
s->nvram[6] = to_bcd(s->now.tm_year - 100);
/* In h/w, capture happens on any START condition, not just a
* START_RECV, but there is no need to actually capture on
* START_SEND, because the guest can't get at that data
* without going through a START_RECV which would overwrite it.
*/
capture_current_time(s);
break;
case I2C_START_SEND:
s->addr_byte = 1;
s->addr_byte = true;
break;
default:
break;
@ -57,7 +102,7 @@ static int ds1338_recv(I2CSlave *i2c)
uint8_t res;
res = s->nvram[s->ptr];
s->ptr = (s->ptr + 1) & 0xff;
inc_regptr(s);
return res;
}
@ -65,20 +110,20 @@ static int ds1338_send(I2CSlave *i2c, uint8_t data)
{
DS1338State *s = FROM_I2C_SLAVE(DS1338State, i2c);
if (s->addr_byte) {
s->ptr = data;
s->addr_byte = 0;
s->ptr = data & (NVRAM_SIZE - 1);
s->addr_byte = false;
return 0;
}
s->nvram[s->ptr - 8] = data;
if (data < 8) {
qemu_get_timedate(&s->now, s->offset);
switch(data) {
if (s->ptr < 8) {
struct tm now;
qemu_get_timedate(&now, s->offset);
switch(s->ptr) {
case 0:
/* TODO: Implement CH (stop) bit. */
s->now.tm_sec = from_bcd(data & 0x7f);
now.tm_sec = from_bcd(data & 0x7f);
break;
case 1:
s->now.tm_min = from_bcd(data & 0x7f);
now.tm_min = from_bcd(data & 0x7f);
break;
case 2:
if (data & 0x40) {
@ -90,27 +135,29 @@ static int ds1338_send(I2CSlave *i2c, uint8_t data)
} else {
data = from_bcd(data);
}
s->now.tm_hour = data;
now.tm_hour = data;
break;
case 3:
s->now.tm_wday = from_bcd(data & 7) - 1;
now.tm_wday = from_bcd(data & 7) - 1;
break;
case 4:
s->now.tm_mday = from_bcd(data & 0x3f);
now.tm_mday = from_bcd(data & 0x3f);
break;
case 5:
s->now.tm_mon = from_bcd(data & 0x1f) - 1;
now.tm_mon = from_bcd(data & 0x1f) - 1;
break;
case 6:
s->now.tm_year = from_bcd(data) + 100;
now.tm_year = from_bcd(data) + 100;
break;
case 7:
/* Control register. Currently ignored. */
break;
}
s->offset = qemu_timedate_diff(&s->now);
s->offset = qemu_timedate_diff(&now);
} else {
s->nvram[s->ptr] = data;
}
s->ptr = (s->ptr + 1) & 0xff;
inc_regptr(s);
return 0;
}
@ -121,12 +168,14 @@ static int ds1338_init(I2CSlave *i2c)
static void ds1338_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
I2CSlaveClass *k = I2C_SLAVE_CLASS(klass);
k->init = ds1338_init;
k->event = ds1338_event;
k->recv = ds1338_recv;
k->send = ds1338_send;
dc->vmsd = &vmstate_ds1338;
}
static TypeInfo ds1338_info = {

View file

@ -266,6 +266,11 @@ static void versatile_init(ram_addr_t ram_size,
sysbus_create_simple("sp804", 0x101e2000, pic[4]);
sysbus_create_simple("sp804", 0x101e3000, pic[5]);
sysbus_create_simple("pl061", 0x101e4000, pic[6]);
sysbus_create_simple("pl061", 0x101e5000, pic[7]);
sysbus_create_simple("pl061", 0x101e6000, pic[8]);
sysbus_create_simple("pl061", 0x101e7000, pic[9]);
/* The versatile/PB actually has a modified Color LCD controller
that includes hardware cursor support from the PL111. */
dev = sysbus_create_simple("pl110_versatile", 0x10120000, pic[16]);

View file

@ -91,7 +91,7 @@ typedef enum {
typedef enum {
PSS,
DDDR,
DMAC,
DMAC = 3,
USB,
GEM,
SDIO,