mirror of https://github.com/xemu-project/xemu.git
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:
commit
ae72f3f539
46
hw/arm_gic.c
46
hw/arm_gic.c
|
@ -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),
|
||||
};
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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) \
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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 */
|
||||
|
|
123
hw/ds1338.c
123
hw/ds1338.c
|
@ -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 = {
|
||||
|
|
|
@ -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]);
|
||||
|
|
|
@ -91,7 +91,7 @@ typedef enum {
|
|||
typedef enum {
|
||||
PSS,
|
||||
DDDR,
|
||||
DMAC,
|
||||
DMAC = 3,
|
||||
USB,
|
||||
GEM,
|
||||
SDIO,
|
||||
|
|
Loading…
Reference in New Issue