Commit e890966d authored by Peter Maydell's avatar Peter Maydell
Browse files

Merge remote-tracking branch 'remotes/dgibson/tags/ppc-for-2.12-20180111' into staging



ppc patch queue 2018-01-11

This pull request supersedes ppc-for-2.12-20180108 and several before
it.  The earlier pull request included a patch which exposed a bug in
the ARM TCG backend.  I've pulled that out and will repost once the
ARM bug is fixed (a patch has been posted by Richard Henderson).

Higlights from this series:
  * SLOF update
  * Several new devices for embedded platforms
  * Fix to correctly set compatiblity mode for hotplugged CPUs
  * dtc compile fix for older MacOS versions

# gpg: Signature made Thu 11 Jan 2018 04:58:11 GMT
# gpg:                using RSA key 0x6C38CACA20D9B392
# gpg: Good signature from "David Gibson <david@gibson.dropbear.id.au>"
# gpg:                 aka "David Gibson (Red Hat) <dgibson@redhat.com>"
# gpg:                 aka "David Gibson (ozlabs.org) <dgibson@ozlabs.org>"
# gpg:                 aka "David Gibson (kernel.org) <dwg@kernel.org>"
# Primary key fingerprint: 75F4 6586 AE61 A66C C44E  87DC 6C38 CACA 20D9 B392

* remotes/dgibson/tags/ppc-for-2.12-20180111:
  spapr: Correct compatibility mode setting for hotplugged CPUs
  hw/ppc: Remove the deprecated spapr-pci-vfio-host-bridge device
  Update dtc to fix compilation problem on Mac OS 10.6
  target/ppc: more use of the PPC_*() macros
  ppc/pnv: change powernv_ prefix to pnv_ for overall naming consistency
  hw/ide: Emulate SiI3112 SATA controller
  spapr_pci: use warn_report()
  ppc4xx_i2c: Implement basic I2C functions
  sm501: Add some more unimplemented registers
  sm501: Add panel hardware cursor registers also to read function
  pseries: Update SLOF firmware image to qemu-slof-20171214

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents 612061b2 51f84465
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -766,6 +766,12 @@ L: qemu-ppc@nongnu.org
S: Odd Fixes
F: hw/ppc/virtex_ml507.c

sam460ex
M: BALATON Zoltan <balaton@eik.bme.hu>
L: qemu-ppc@nongnu.org
S: Maintained
F: hw/ide/sii3112.c

SH4 Machines
------------
R2D
+1 −0
Original line number Diff line number Diff line
@@ -16,3 +16,4 @@ CONFIG_I8259=y
CONFIG_XILINX=y
CONFIG_XILINX_ETHLITE=y
CONFIG_SM501=y
CONFIG_IDE_SII3112=y

dtc @ e5438801

Original line number Diff line number Diff line
Subproject commit 558cd81bdd432769b59bff01240c44f82cfb1a9d
Subproject commit e54388015af1fb4bf04d0bca99caba1074d9cc42
+30 −0
Original line number Diff line number Diff line
@@ -795,6 +795,8 @@ static uint64_t sm501_system_config_read(void *opaque, hwaddr addr,
    case SM501_ARBTRTN_CONTROL:
        ret = s->arbitration_control;
        break;
    case SM501_COMMAND_LIST_STATUS:
        ret = 0x00180002; /* FIFOs are empty, everything idle */
    case SM501_IRQ_MASK:
        ret = s->irq_mask;
        break;
@@ -812,6 +814,9 @@ static uint64_t sm501_system_config_read(void *opaque, hwaddr addr,
    case SM501_POWER_MODE_CONTROL:
        ret = s->power_mode_control;
        break;
    case SM501_ENDIAN_CONTROL:
        ret = 0; /* Only default little endian mode is supported */
        break;

    default:
        printf("sm501 system config : not implemented register read."
@@ -865,6 +870,12 @@ static void sm501_system_config_write(void *opaque, hwaddr addr,
    case SM501_POWER_MODE_CONTROL:
        s->power_mode_control = value & 0x00000003;
        break;
    case SM501_ENDIAN_CONTROL:
        if (value & 0x00000001) {
            printf("sm501 system config : big endian mode not implemented.\n");
            abort();
        }
        break;

    default:
        printf("sm501 system config : not implemented register write."
@@ -924,6 +935,9 @@ static uint64_t sm501_disp_ctrl_read(void *opaque, hwaddr addr,
    case SM501_DC_PANEL_PANNING_CONTROL:
        ret = s->dc_panel_panning_control;
        break;
    case SM501_DC_PANEL_COLOR_KEY:
        /* Not implemented yet */
        break;
    case SM501_DC_PANEL_FB_ADDR:
        ret = s->dc_panel_fb_addr;
        break;
@@ -956,6 +970,19 @@ static uint64_t sm501_disp_ctrl_read(void *opaque, hwaddr addr,
        ret = s->dc_panel_v_sync;
        break;

    case SM501_DC_PANEL_HWC_ADDR:
        ret = s->dc_panel_hwc_addr;
        break;
    case SM501_DC_PANEL_HWC_LOC:
        ret = s->dc_panel_hwc_location;
        break;
    case SM501_DC_PANEL_HWC_COLOR_1_2:
        ret = s->dc_panel_hwc_color_1_2;
        break;
    case SM501_DC_PANEL_HWC_COLOR_3:
        ret = s->dc_panel_hwc_color_3;
        break;

    case SM501_DC_VIDEO_CONTROL:
        ret = s->dc_video_control;
        break;
@@ -1022,6 +1049,9 @@ static void sm501_disp_ctrl_write(void *opaque, hwaddr addr,
    case SM501_DC_PANEL_PANNING_CONTROL:
        s->dc_panel_panning_control = value & 0xFF3FFF3F;
        break;
    case SM501_DC_PANEL_COLOR_KEY:
        /* Not implemented yet */
        break;
    case SM501_DC_PANEL_FB_ADDR:
        s->dc_panel_fb_addr = value & 0x8FFFFFF0;
        break;
+168 −30
Original line number Diff line number Diff line
@@ -2,6 +2,8 @@
 * PPC4xx I2C controller emulation
 *
 * Copyright (c) 2007 Jocelyn Mayer
 * Copyright (c) 2012 François Revol
 * Copyright (c) 2016 BALATON Zoltan
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
@@ -25,26 +27,118 @@
#include "qemu/osdep.h"
#include "qapi/error.h"
#include "qemu-common.h"
#include "qemu/log.h"
#include "cpu.h"
#include "hw/hw.h"
#include "hw/i2c/ppc4xx_i2c.h"

/*#define DEBUG_I2C*/
#define PPC4xx_I2C_MEM_SIZE 0x12

#define PPC4xx_I2C_MEM_SIZE 0x11
#define IIC_CNTL_PT         (1 << 0)
#define IIC_CNTL_READ       (1 << 1)
#define IIC_CNTL_CHT        (1 << 2)
#define IIC_CNTL_RPST       (1 << 3)

#define IIC_STS_PT          (1 << 0)
#define IIC_STS_ERR         (1 << 2)
#define IIC_STS_MDBS        (1 << 5)

#define IIC_EXTSTS_XFRA     (1 << 0)

#define IIC_XTCNTLSS_SRST   (1 << 0)

static void ppc4xx_i2c_reset(DeviceState *s)
{
    PPC4xxI2CState *i2c = PPC4xx_I2C(s);

    /* FIXME: Should also reset bus?
     *if (s->address != ADDR_RESET) {
     *    i2c_end_transfer(s->bus);
     *}
     */

    i2c->mdata = 0;
    i2c->lmadr = 0;
    i2c->hmadr = 0;
    i2c->cntl = 0;
    i2c->mdcntl = 0;
    i2c->sts = 0;
    i2c->extsts = 0x8f;
    i2c->sdata = 0;
    i2c->lsadr = 0;
    i2c->hsadr = 0;
    i2c->clkdiv = 0;
    i2c->intrmsk = 0;
    i2c->xfrcnt = 0;
    i2c->xtcntlss = 0;
    i2c->directcntl = 0x0f;
    i2c->intr = 0;
}

static inline bool ppc4xx_i2c_is_master(PPC4xxI2CState *i2c)
{
    return true;
}

static uint64_t ppc4xx_i2c_readb(void *opaque, hwaddr addr, unsigned int size)
{
    PPC4xxI2CState *i2c = PPC4xx_I2C(opaque);
    uint64_t ret;

#ifdef DEBUG_I2C
    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
#endif
    switch (addr) {
    case 0x00:
        /*i2c_readbyte(&i2c->mdata);*/
        ret = i2c->mdata;
        if (ppc4xx_i2c_is_master(i2c)) {
            ret = 0xff;

            if (!(i2c->sts & IIC_STS_MDBS)) {
                qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Trying to read "
                              "without starting transfer\n",
                              TYPE_PPC4xx_I2C, __func__);
            } else {
                int pending = (i2c->cntl >> 4) & 3;

                /* get the next byte */
                int byte = i2c_recv(i2c->bus);

                if (byte < 0) {
                    qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: read failed "
                                  "for device 0x%02x\n", TYPE_PPC4xx_I2C,
                                  __func__, i2c->lmadr);
                    ret = 0xff;
                } else {
                    ret = byte;
                    /* Raise interrupt if enabled */
                    /*ppc4xx_i2c_raise_interrupt(i2c)*/;
                }

                if (!pending) {
                    i2c->sts &= ~IIC_STS_MDBS;
                    /*i2c_end_transfer(i2c->bus);*/
                /*} else if (i2c->cntl & (IIC_CNTL_RPST | IIC_CNTL_CHT)) {*/
                } else if (pending) {
                    /* current smbus implementation doesn't like
                       multibyte xfer repeated start */
                    i2c_end_transfer(i2c->bus);
                    if (i2c_start_transfer(i2c->bus, i2c->lmadr >> 1, 1)) {
                        /* if non zero is returned, the adress is not valid */
                        i2c->sts &= ~IIC_STS_PT;
                        i2c->sts |= IIC_STS_ERR;
                        i2c->extsts |= IIC_EXTSTS_XFRA;
                    } else {
                        /*i2c->sts |= IIC_STS_PT;*/
                        i2c->sts |= IIC_STS_MDBS;
                        i2c->sts &= ~IIC_STS_ERR;
                        i2c->extsts = 0;
                    }
                }
                pending--;
                i2c->cntl = (i2c->cntl & 0xcf) | (pending << 4);
            }
        } else {
            qemu_log_mask(LOG_UNIMP, "[%s]%s: slave mode not implemented\n",
                          TYPE_PPC4xx_I2C, __func__);
        }
        break;
    case 0x02:
        ret = i2c->sdata;
@@ -88,13 +182,15 @@ static uint64_t ppc4xx_i2c_readb(void *opaque, hwaddr addr, unsigned int size)
    case 0x10:
        ret = i2c->directcntl;
        break;
    case 0x11:
        ret = i2c->intr;
        break;
    default:
        ret = 0x00;
        qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad address at offset 0x%"
                      HWADDR_PRIx "\n", TYPE_PPC4xx_I2C, __func__, addr);
        ret = 0;
        break;
    }
#ifdef DEBUG_I2C
    printf("%s: addr " TARGET_FMT_plx " %02" PRIx64 "\n", __func__, addr, ret);
#endif

    return ret;
}
@@ -103,26 +199,70 @@ static void ppc4xx_i2c_writeb(void *opaque, hwaddr addr, uint64_t value,
                              unsigned int size)
{
    PPC4xxI2CState *i2c = opaque;
#ifdef DEBUG_I2C
    printf("%s: addr " TARGET_FMT_plx " val %08" PRIx64 "\n",
           __func__, addr, value);
#endif

    switch (addr) {
    case 0x00:
        i2c->mdata = value;
        /*i2c_sendbyte(&i2c->mdata);*/
        if (!i2c_bus_busy(i2c->bus)) {
            /* assume we start a write transfer */
            if (i2c_start_transfer(i2c->bus, i2c->lmadr >> 1, 0)) {
                /* if non zero is returned, the adress is not valid */
                i2c->sts &= ~IIC_STS_PT;
                i2c->sts |= IIC_STS_ERR;
                i2c->extsts |= IIC_EXTSTS_XFRA;
            } else {
                i2c->sts |= IIC_STS_PT;
                i2c->sts &= ~IIC_STS_ERR;
                i2c->extsts = 0;
            }
        }
        if (i2c_bus_busy(i2c->bus)) {
            if (i2c_send(i2c->bus, i2c->mdata)) {
                /* if the target return non zero then end the transfer */
                i2c->sts &= ~IIC_STS_PT;
                i2c->sts |= IIC_STS_ERR;
                i2c->extsts |= IIC_EXTSTS_XFRA;
                i2c_end_transfer(i2c->bus);
            }
        }
        break;
    case 0x02:
        i2c->sdata = value;
        break;
    case 0x04:
        i2c->lmadr = value;
        if (i2c_bus_busy(i2c->bus)) {
            i2c_end_transfer(i2c->bus);
        }
        break;
    case 0x05:
        i2c->hmadr = value;
        break;
    case 0x06:
        i2c->cntl = value;
        if (i2c->cntl & IIC_CNTL_PT) {
            if (i2c->cntl & IIC_CNTL_READ) {
                if (i2c_bus_busy(i2c->bus)) {
                    /* end previous transfer */
                    i2c->sts &= ~IIC_STS_PT;
                    i2c_end_transfer(i2c->bus);
                }
                if (i2c_start_transfer(i2c->bus, i2c->lmadr >> 1, 1)) {
                    /* if non zero is returned, the adress is not valid */
                    i2c->sts &= ~IIC_STS_PT;
                    i2c->sts |= IIC_STS_ERR;
                    i2c->extsts |= IIC_EXTSTS_XFRA;
                } else {
                    /*i2c->sts |= IIC_STS_PT;*/
                    i2c->sts |= IIC_STS_MDBS;
                    i2c->sts &= ~IIC_STS_ERR;
                    i2c->extsts = 0;
                }
            } else {
                /* we actually already did the write transfer... */
                i2c->sts &= ~IIC_STS_PT;
            }
        }
        break;
    case 0x07:
        i2c->mdcntl = value & 0xDF;
@@ -135,6 +275,7 @@ static void ppc4xx_i2c_writeb(void *opaque, hwaddr addr, uint64_t value,
        break;
    case 0x0A:
        i2c->lsadr = value;
        /*i2c_set_slave_address(i2c->bus, i2c->lsadr);*/
        break;
    case 0x0B:
        i2c->hsadr = value;
@@ -149,11 +290,23 @@ static void ppc4xx_i2c_writeb(void *opaque, hwaddr addr, uint64_t value,
        i2c->xfrcnt = value & 0x77;
        break;
    case 0x0F:
        if (value & IIC_XTCNTLSS_SRST) {
            /* Is it actually a full reset? U-Boot sets some regs before */
            ppc4xx_i2c_reset(DEVICE(i2c));
            break;
        }
        i2c->xtcntlss = value;
        break;
    case 0x10:
        i2c->directcntl = value & 0x7;
        break;
    case 0x11:
        i2c->intr = value;
        break;
    default:
        qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad address at offset 0x%"
                      HWADDR_PRIx "\n", TYPE_PPC4xx_I2C, __func__, addr);
        break;
    }
}

@@ -167,21 +320,6 @@ static const MemoryRegionOps ppc4xx_i2c_ops = {
    .endianness = DEVICE_NATIVE_ENDIAN,
};

static void ppc4xx_i2c_reset(DeviceState *s)
{
    PPC4xxI2CState *i2c = PPC4xx_I2C(s);

    i2c->mdata = 0x00;
    i2c->sdata = 0x00;
    i2c->cntl = 0x00;
    i2c->mdcntl = 0x00;
    i2c->sts = 0x00;
    i2c->extsts = 0x00;
    i2c->clkdiv = 0x00;
    i2c->xfrcnt = 0x00;
    i2c->directcntl = 0x0F;
}

static void ppc4xx_i2c_init(Object *o)
{
    PPC4xxI2CState *s = PPC4xx_I2C(o);
Loading