Commit df933007 authored by Anthony Liguori's avatar Anthony Liguori
Browse files

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



* pmaydell/arm-devs.next:
  hw/ds1338.c: Fix handling of DAY (wday) register.
  hw/ds1338.c: Implement support for the control register.
  hw/ds1338.c: Ensure state is properly initialized.
  hw/ds1338.c: Fix handling of HOURS register.
  hw/ds1338.c: Add definitions for various flags in the RTC registers.
  hw/ds1338.c: Correct bug in conversion to BCD.
  exynos4210/mct: Avoid infinite loop on non incremental timers
  hw/arm_gic: fix target CPUs affected by set enable/pending ops
  xilinx_zynq: Add one variable to avoid overwriting QSPI bus
  hw/arm_gic_common: Correct GICC_PMR reset value for newer GICs
  hw/arm_gic: Fix comparison with priority mask register
  hw/arm_boot, exynos4210, highbank: Fix secondary boot GIC init

Signed-off-by: default avatarAnthony Liguori <aliguori@us.ibm.com>
parents aa1246ae 871edc5f
Loading
Loading
Loading
Loading
+14 −3
Original line number Diff line number Diff line
@@ -44,11 +44,17 @@ static uint32_t bootloader[] = {
 * for an interprocessor interrupt and polling a configurable
 * location for the kernel secondary CPU entry point.
 */
#define DSB_INSN 0xf57ff04f
#define CP15_DSB_INSN 0xee070f9a /* mcr cp15, 0, r0, c7, c10, 4 */

static uint32_t smpboot[] = {
  0xe59f201c, /* ldr r2, gic_cpu_if */
  0xe59f001c, /* ldr r0, startaddr */
  0xe59f2028, /* ldr r2, gic_cpu_if */
  0xe59f0028, /* ldr r0, startaddr */
  0xe3a01001, /* mov r1, #1 */
  0xe5821000, /* str r1, [r2] */
  0xe5821000, /* str r1, [r2] - set GICC_CTLR.Enable */
  0xe3a010ff, /* mov r1, #0xff */
  0xe5821004, /* str r1, [r2, 4] - set GIC_PMR.Priority to 0xff */
  DSB_INSN,   /* dsb */
  0xe320f003, /* wfi */
  0xe5901000, /* ldr     r1, [r0] */
  0xe1110001, /* tst     r1, r1 */
@@ -65,6 +71,11 @@ static void default_write_secondary(ARMCPU *cpu,
    smpboot[ARRAY_SIZE(smpboot) - 1] = info->smp_bootreg_addr;
    smpboot[ARRAY_SIZE(smpboot) - 2] = info->gic_cpu_if_addr;
    for (n = 0; n < ARRAY_SIZE(smpboot); n++) {
        /* Replace DSB with the pre-v7 DSB if necessary. */
        if (!arm_feature(&cpu->env, ARM_FEATURE_V7) &&
            smpboot[n] == DSB_INSN) {
            smpboot[n] = CP15_DSB_INSN;
        }
        smpboot[n] = tswap32(smpboot[n]);
    }
    rom_add_blob_fixed("smpboot", smpboot, sizeof(smpboot),
+4 −3
Original line number Diff line number Diff line
@@ -73,7 +73,7 @@ void gic_update(GICState *s)
            }
        }
        level = 0;
        if (best_prio <= s->priority_mask[cpu]) {
        if (best_prio < s->priority_mask[cpu]) {
            s->current_pending[cpu] = best_irq;
            if (best_prio < s->running_priority[cpu]) {
                DPRINTF("Raised pending IRQ %d\n", best_irq);
@@ -374,7 +374,8 @@ static void gic_dist_writeb(void *opaque, hwaddr offset,
          value = 0xff;
        for (i = 0; i < 8; i++) {
            if (value & (1 << i)) {
                int mask = (irq < GIC_INTERNAL) ? (1 << cpu) : GIC_TARGET(irq);
                int mask =
                    (irq < GIC_INTERNAL) ? (1 << cpu) : GIC_TARGET(irq + i);
                int cm = (irq < GIC_INTERNAL) ? (1 << cpu) : ALL_CPU_MASK;

                if (!GIC_TEST_ENABLED(irq + i, cm)) {
@@ -417,7 +418,7 @@ static void gic_dist_writeb(void *opaque, hwaddr offset,

        for (i = 0; i < 8; i++) {
            if (value & (1 << i)) {
                GIC_SET_PENDING(irq + i, GIC_TARGET(irq));
                GIC_SET_PENDING(irq + i, GIC_TARGET(irq + i));
            }
        }
    } else if (offset < 0x300) {
+5 −1
Original line number Diff line number Diff line
@@ -127,7 +127,11 @@ static void arm_gic_common_reset(DeviceState *dev)
    int i;
    memset(s->irq_state, 0, GIC_MAXIRQ * sizeof(gic_irq_state));
    for (i = 0 ; i < s->num_cpu; i++) {
        if (s->revision == REV_11MPCORE) {
            s->priority_mask[i] = 0xf0;
        } else {
            s->priority_mask[i] = 0;
        }
        s->current_pending[i] = 1023;
        s->running_irq[i] = 1023;
        s->running_priority[i] = 0x100;
+3 −1
Original line number Diff line number Diff line
@@ -455,9 +455,11 @@ static void armv7m_nvic_reset(DeviceState *dev)
    nc->parent_reset(dev);
    /* Common GIC reset resets to disabled; the NVIC doesn't have
     * per-CPU interfaces so mark our non-existent CPU interface
     * as enabled by default.
     * as enabled by default, and with a priority mask which allows
     * all interrupts through.
     */
    s->gic.cpu_enabled[0] = 1;
    s->gic.priority_mask[0] = 0x100;
    /* The NVIC as a whole is always enabled. */
    s->gic.enabled = 1;
    systick_reset(s);
+62 −19
Original line number Diff line number Diff line
@@ -17,9 +17,16 @@
 */
#define NVRAM_SIZE 64

/* Flags definitions */
#define SECONDS_CH 0x80
#define HOURS_12   0x40
#define HOURS_PM   0x20
#define CTRL_OSF   0x20

typedef struct {
    I2CSlave i2c;
    int64_t offset;
    uint8_t wday_offset;
    uint8_t nvram[NVRAM_SIZE];
    int32_t ptr;
    bool addr_byte;
@@ -27,12 +34,13 @@ typedef struct {

static const VMStateDescription vmstate_ds1338 = {
    .name = "ds1338",
    .version_id = 1,
    .version_id = 2,
    .minimum_version_id = 1,
    .minimum_version_id_old = 1,
    .fields = (VMStateField[]) {
        VMSTATE_I2C_SLAVE(i2c, DS1338State),
        VMSTATE_INT64(offset, DS1338State),
        VMSTATE_UINT8_V(wday_offset, DS1338State, 2),
        VMSTATE_UINT8_ARRAY(nvram, DS1338State, NVRAM_SIZE),
        VMSTATE_INT32(ptr, DS1338State),
        VMSTATE_BOOL(addr_byte, DS1338State),
@@ -49,17 +57,22 @@ static void capture_current_time(DS1338State *s)
    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;
    if (s->nvram[2] & HOURS_12) {
        int tmp = now.tm_hour;
        if (tmp == 0) {
            tmp = 24;
        }
        if (tmp <= 12) {
            s->nvram[2] = HOURS_12 | to_bcd(tmp);
        } else {
            s->nvram[2] = HOURS_12 | HOURS_PM | to_bcd(tmp - 12);
        }
    } else {
        s->nvram[2] = to_bcd(now.tm_hour);
    }
    s->nvram[3] = to_bcd(now.tm_wday) + 1;
    s->nvram[3] = (now.tm_wday + s->wday_offset) % 7 + 1;
    s->nvram[4] = to_bcd(now.tm_mday);
    s->nvram[5] = to_bcd(now.tm_mon) + 1;
    s->nvram[5] = to_bcd(now.tm_mon + 1);
    s->nvram[6] = to_bcd(now.tm_year - 100);
}

@@ -114,7 +127,8 @@ static int ds1338_send(I2CSlave *i2c, uint8_t data)
        s->addr_byte = false;
        return 0;
    }
    if (s->ptr < 8) {
    if (s->ptr < 7) {
        /* Time register. */
        struct tm now;
        qemu_get_timedate(&now, s->offset);
        switch(s->ptr) {
@@ -126,19 +140,27 @@ static int ds1338_send(I2CSlave *i2c, uint8_t data)
            now.tm_min = from_bcd(data & 0x7f);
            break;
        case 2:
            if (data & 0x40) {
                if (data & 0x20) {
                    data = from_bcd(data & 0x4f) + 11;
                } else {
                    data = from_bcd(data & 0x1f) - 1;
            if (data & HOURS_12) {
                int tmp = from_bcd(data & (HOURS_PM - 1));
                if (data & HOURS_PM) {
                    tmp += 12;
                }
                if (tmp == 24) {
                    tmp = 0;
                }
                now.tm_hour = tmp;
            } else {
                data = from_bcd(data);
                now.tm_hour = from_bcd(data & (HOURS_12 - 1));
            }
            now.tm_hour = data;
            break;
        case 3:
            now.tm_wday = from_bcd(data & 7) - 1;
            {
                /* The day field is supposed to contain a value in
                   the range 1-7. Otherwise behavior is undefined.
                 */
                int user_wday = (data & 7) - 1;
                s->wday_offset = (user_wday - now.tm_wday + 7) % 7;
            }
            break;
        case 4:
            now.tm_mday = from_bcd(data & 0x3f);
@@ -149,11 +171,19 @@ static int ds1338_send(I2CSlave *i2c, uint8_t data)
        case 6:
            now.tm_year = from_bcd(data) + 100;
            break;
        case 7:
            /* Control register. Currently ignored.  */
            break;
        }
        s->offset = qemu_timedate_diff(&now);
    } else if (s->ptr == 7) {
        /* Control register. */

        /* Ensure bits 2, 3 and 6 will read back as zero. */
        data &= 0xB3;

        /* Attempting to write the OSF flag to logic 1 leaves the
           value unchanged. */
        data = (data & ~CTRL_OSF) | (data & s->nvram[s->ptr] & CTRL_OSF);

        s->nvram[s->ptr] = data;
    } else {
        s->nvram[s->ptr] = data;
    }
@@ -166,6 +196,18 @@ static int ds1338_init(I2CSlave *i2c)
    return 0;
}

static void ds1338_reset(DeviceState *dev)
{
    DS1338State *s = FROM_I2C_SLAVE(DS1338State, I2C_SLAVE_FROM_QDEV(dev));

    /* The clock is running and synchronized with the host */
    s->offset = 0;
    s->wday_offset = 0;
    memset(s->nvram, 0, NVRAM_SIZE);
    s->ptr = 0;
    s->addr_byte = false;
}

static void ds1338_class_init(ObjectClass *klass, void *data)
{
    DeviceClass *dc = DEVICE_CLASS(klass);
@@ -175,6 +217,7 @@ static void ds1338_class_init(ObjectClass *klass, void *data)
    k->event = ds1338_event;
    k->recv = ds1338_recv;
    k->send = ds1338_send;
    dc->reset = ds1338_reset;
    dc->vmsd = &vmstate_ds1338;
}

Loading