提交 0d2fa03d 编写于 作者: P Peter Maydell

Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20180608' into staging

target-arm queue:
 * arm_gicv3_kvm: fix migration of registers corresponding to
   IRQs 992 to 1020 in the KVM GIC
 * aspeed: remove ignore_memory_transaction_failures on all boards
 * aspeed: add support for the witherspoon-bmc board
 * aspeed: add an I2C RTC device and EEPROM I2C devices
 * aspeed: add the pc9552 chips to the witherspoon machine
 * ftgmac100: fix various bugs
 * hw/arm: Remove the deprecated xlnx-ep108 machine
 * hw/i2c: Add trace events
 * add missing '\n' on various qemu_log() logging strings
 * sdcard: clean up spec version support so we report the
   right spec version to the guest and only implement the
   commands that are supposed to be present in that version

# gpg: Signature made Fri 08 Jun 2018 13:36:37 BST
# gpg:                using RSA key 3C2525ED14360CDE
# gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>"
# gpg:                 aka "Peter Maydell <pmaydell@gmail.com>"
# gpg:                 aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>"
# Primary key fingerprint: E1A5 C593 CD41 9DE2 8E83  15CF 3C25 25ED 1436 0CDE

* remotes/pmaydell/tags/pull-target-arm-20180608: (31 commits)
  sdcard: Disable CMD19/CMD23 for Spec v2
  sdcard: Reflect when the Spec v3 is supported in the Config Register (SCR)
  sdcard: Disable SEND_IF_COND (CMD8) for Spec v1
  sdcard: Add a 'spec_version' property, default to Spec v2.00
  sdcard: Allow commands valid in SPI mode
  sdcard: Update the Configuration Register (SCR) to Spec Version 1.10
  target/xtensa: Add trailing '\n' to qemu_log() calls
  RISC-V: Add trailing '\n' to qemu_log() calls
  target/m68k: Add trailing '\n' to qemu_log() call
  target/arm: Add trailing '\n' to qemu_log() calls
  stellaris: Add trailing '\n' to qemu_log() calls
  hw/mips/boston: Add trailing '\n' to qemu_log() calls
  hw/core/register: Add trailing '\n' to qemu_log() call
  ppc/pnv: Add trailing '\n' to qemu_log() calls
  xilinx-dp: Add trailing '\n' to qemu_log() call
  hw/digic: Add trailing '\n' to qemu_log() calls
  hw/sd/milkymist-memcard: Add trailing '\n' to qemu_log() call
  hw/i2c: Add trace events
  hw/arm: Remove the deprecated xlnx-ep108 machine
  ftgmac100: remove check on runt messages
  ...
Signed-off-by: NPeter Maydell <peter.maydell@linaro.org>
...@@ -213,6 +213,7 @@ trace-events-subdirs += hw/char ...@@ -213,6 +213,7 @@ trace-events-subdirs += hw/char
trace-events-subdirs += hw/display trace-events-subdirs += hw/display
trace-events-subdirs += hw/dma trace-events-subdirs += hw/dma
trace-events-subdirs += hw/hppa trace-events-subdirs += hw/hppa
trace-events-subdirs += hw/i2c
trace-events-subdirs += hw/i386 trace-events-subdirs += hw/i386
trace-events-subdirs += hw/i386/xen trace-events-subdirs += hw/i386/xen
trace-events-subdirs += hw/ide trace-events-subdirs += hw/ide
......
...@@ -16,6 +16,7 @@ CONFIG_TSC2005=y ...@@ -16,6 +16,7 @@ CONFIG_TSC2005=y
CONFIG_LM832X=y CONFIG_LM832X=y
CONFIG_TMP105=y CONFIG_TMP105=y
CONFIG_TMP421=y CONFIG_TMP421=y
CONFIG_PCA9552=y
CONFIG_STELLARIS=y CONFIG_STELLARIS=y
CONFIG_STELLARIS_INPUT=y CONFIG_STELLARIS_INPUT=y
CONFIG_STELLARIS_ENET=y CONFIG_STELLARIS_ENET=y
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include "hw/arm/arm.h" #include "hw/arm/arm.h"
#include "hw/arm/aspeed_soc.h" #include "hw/arm/aspeed_soc.h"
#include "hw/boards.h" #include "hw/boards.h"
#include "hw/i2c/smbus.h"
#include "qemu/log.h" #include "qemu/log.h"
#include "sysemu/block-backend.h" #include "sysemu/block-backend.h"
#include "hw/loader.h" #include "hw/loader.h"
...@@ -45,6 +46,7 @@ enum { ...@@ -45,6 +46,7 @@ enum {
PALMETTO_BMC, PALMETTO_BMC,
AST2500_EVB, AST2500_EVB,
ROMULUS_BMC, ROMULUS_BMC,
WITHERSPOON_BMC,
}; };
/* Palmetto hardware value: 0x120CE416 */ /* Palmetto hardware value: 0x120CE416 */
...@@ -82,8 +84,13 @@ enum { ...@@ -82,8 +84,13 @@ enum {
SCU_AST2500_HW_STRAP_ACPI_ENABLE | \ SCU_AST2500_HW_STRAP_ACPI_ENABLE | \
SCU_HW_STRAP_SPI_MODE(SCU_HW_STRAP_SPI_MASTER)) SCU_HW_STRAP_SPI_MODE(SCU_HW_STRAP_SPI_MASTER))
/* Witherspoon hardware value: 0xF10AD216 (but use romulus definition) */
#define WITHERSPOON_BMC_HW_STRAP1 ROMULUS_BMC_HW_STRAP1
static void palmetto_bmc_i2c_init(AspeedBoardState *bmc); static void palmetto_bmc_i2c_init(AspeedBoardState *bmc);
static void ast2500_evb_i2c_init(AspeedBoardState *bmc); static void ast2500_evb_i2c_init(AspeedBoardState *bmc);
static void romulus_bmc_i2c_init(AspeedBoardState *bmc);
static void witherspoon_bmc_i2c_init(AspeedBoardState *bmc);
static const AspeedBoardConfig aspeed_boards[] = { static const AspeedBoardConfig aspeed_boards[] = {
[PALMETTO_BMC] = { [PALMETTO_BMC] = {
...@@ -108,6 +115,15 @@ static const AspeedBoardConfig aspeed_boards[] = { ...@@ -108,6 +115,15 @@ static const AspeedBoardConfig aspeed_boards[] = {
.fmc_model = "n25q256a", .fmc_model = "n25q256a",
.spi_model = "mx66l1g45g", .spi_model = "mx66l1g45g",
.num_cs = 2, .num_cs = 2,
.i2c_init = romulus_bmc_i2c_init,
},
[WITHERSPOON_BMC] = {
.soc_name = "ast2500-a1",
.hw_strap1 = WITHERSPOON_BMC_HW_STRAP1,
.fmc_model = "mx25l25635e",
.spi_model = "mx66l1g45g",
.num_cs = 2,
.i2c_init = witherspoon_bmc_i2c_init,
}, },
}; };
...@@ -248,11 +264,15 @@ static void palmetto_bmc_i2c_init(AspeedBoardState *bmc) ...@@ -248,11 +264,15 @@ static void palmetto_bmc_i2c_init(AspeedBoardState *bmc)
{ {
AspeedSoCState *soc = &bmc->soc; AspeedSoCState *soc = &bmc->soc;
DeviceState *dev; DeviceState *dev;
uint8_t *eeprom_buf = g_malloc0(32 * 1024);
/* The palmetto platform expects a ds3231 RTC but a ds1338 is /* The palmetto platform expects a ds3231 RTC but a ds1338 is
* enough to provide basic RTC features. Alarms will be missing */ * enough to provide basic RTC features. Alarms will be missing */
i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 0), "ds1338", 0x68); i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 0), "ds1338", 0x68);
smbus_eeprom_init_one(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 0), 0x50,
eeprom_buf);
/* add a TMP423 temperature sensor */ /* add a TMP423 temperature sensor */
dev = i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 2), dev = i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 2),
"tmp423", 0x4c); "tmp423", 0x4c);
...@@ -278,7 +298,6 @@ static void palmetto_bmc_class_init(ObjectClass *oc, void *data) ...@@ -278,7 +298,6 @@ static void palmetto_bmc_class_init(ObjectClass *oc, void *data)
mc->no_floppy = 1; mc->no_floppy = 1;
mc->no_cdrom = 1; mc->no_cdrom = 1;
mc->no_parallel = 1; mc->no_parallel = 1;
mc->ignore_memory_transaction_failures = true;
} }
static const TypeInfo palmetto_bmc_type = { static const TypeInfo palmetto_bmc_type = {
...@@ -290,9 +309,17 @@ static const TypeInfo palmetto_bmc_type = { ...@@ -290,9 +309,17 @@ static const TypeInfo palmetto_bmc_type = {
static void ast2500_evb_i2c_init(AspeedBoardState *bmc) static void ast2500_evb_i2c_init(AspeedBoardState *bmc)
{ {
AspeedSoCState *soc = &bmc->soc; AspeedSoCState *soc = &bmc->soc;
uint8_t *eeprom_buf = g_malloc0(8 * 1024);
smbus_eeprom_init_one(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 3), 0x50,
eeprom_buf);
/* The AST2500 EVB expects a LM75 but a TMP105 is compatible */ /* The AST2500 EVB expects a LM75 but a TMP105 is compatible */
i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 7), "tmp105", 0x4d); i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 7), "tmp105", 0x4d);
/* The AST2500 EVB does not have an RTC. Let's pretend that one is
* plugged on the I2C bus header */
i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 11), "ds1338", 0x32);
} }
static void ast2500_evb_init(MachineState *machine) static void ast2500_evb_init(MachineState *machine)
...@@ -311,7 +338,6 @@ static void ast2500_evb_class_init(ObjectClass *oc, void *data) ...@@ -311,7 +338,6 @@ static void ast2500_evb_class_init(ObjectClass *oc, void *data)
mc->no_floppy = 1; mc->no_floppy = 1;
mc->no_cdrom = 1; mc->no_cdrom = 1;
mc->no_parallel = 1; mc->no_parallel = 1;
mc->ignore_memory_transaction_failures = true;
} }
static const TypeInfo ast2500_evb_type = { static const TypeInfo ast2500_evb_type = {
...@@ -320,6 +346,15 @@ static const TypeInfo ast2500_evb_type = { ...@@ -320,6 +346,15 @@ static const TypeInfo ast2500_evb_type = {
.class_init = ast2500_evb_class_init, .class_init = ast2500_evb_class_init,
}; };
static void romulus_bmc_i2c_init(AspeedBoardState *bmc)
{
AspeedSoCState *soc = &bmc->soc;
/* The romulus board expects Epson RX8900 I2C RTC but a ds1338 is
* good enough */
i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 11), "ds1338", 0x32);
}
static void romulus_bmc_init(MachineState *machine) static void romulus_bmc_init(MachineState *machine)
{ {
aspeed_board_init(machine, &aspeed_boards[ROMULUS_BMC]); aspeed_board_init(machine, &aspeed_boards[ROMULUS_BMC]);
...@@ -336,7 +371,6 @@ static void romulus_bmc_class_init(ObjectClass *oc, void *data) ...@@ -336,7 +371,6 @@ static void romulus_bmc_class_init(ObjectClass *oc, void *data)
mc->no_floppy = 1; mc->no_floppy = 1;
mc->no_cdrom = 1; mc->no_cdrom = 1;
mc->no_parallel = 1; mc->no_parallel = 1;
mc->ignore_memory_transaction_failures = true;
} }
static const TypeInfo romulus_bmc_type = { static const TypeInfo romulus_bmc_type = {
...@@ -345,11 +379,59 @@ static const TypeInfo romulus_bmc_type = { ...@@ -345,11 +379,59 @@ static const TypeInfo romulus_bmc_type = {
.class_init = romulus_bmc_class_init, .class_init = romulus_bmc_class_init,
}; };
static void witherspoon_bmc_i2c_init(AspeedBoardState *bmc)
{
AspeedSoCState *soc = &bmc->soc;
uint8_t *eeprom_buf = g_malloc0(8 * 1024);
i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 3), "pca9552", 0x60);
i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 4), "tmp423", 0x4c);
i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 5), "tmp423", 0x4c);
/* The Witherspoon expects a TMP275 but a TMP105 is compatible */
i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 9), "tmp105", 0x4a);
/* The witherspoon board expects Epson RX8900 I2C RTC but a ds1338 is
* good enough */
i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 11), "ds1338", 0x32);
smbus_eeprom_init_one(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 11), 0x51,
eeprom_buf);
i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 11), "pca9552",
0x60);
}
static void witherspoon_bmc_init(MachineState *machine)
{
aspeed_board_init(machine, &aspeed_boards[WITHERSPOON_BMC]);
}
static void witherspoon_bmc_class_init(ObjectClass *oc, void *data)
{
MachineClass *mc = MACHINE_CLASS(oc);
mc->desc = "OpenPOWER Witherspoon BMC (ARM1176)";
mc->init = witherspoon_bmc_init;
mc->max_cpus = 1;
mc->no_sdcard = 1;
mc->no_floppy = 1;
mc->no_cdrom = 1;
mc->no_parallel = 1;
}
static const TypeInfo witherspoon_bmc_type = {
.name = MACHINE_TYPE_NAME("witherspoon-bmc"),
.parent = TYPE_MACHINE,
.class_init = witherspoon_bmc_class_init,
};
static void aspeed_machine_init(void) static void aspeed_machine_init(void)
{ {
type_register_static(&palmetto_bmc_type); type_register_static(&palmetto_bmc_type);
type_register_static(&ast2500_evb_type); type_register_static(&ast2500_evb_type);
type_register_static(&romulus_bmc_type); type_register_static(&romulus_bmc_type);
type_register_static(&witherspoon_bmc_type);
} }
type_init(aspeed_machine_init) type_init(aspeed_machine_init)
...@@ -203,11 +203,11 @@ static uint64_t gptm_read(void *opaque, hwaddr offset, ...@@ -203,11 +203,11 @@ static uint64_t gptm_read(void *opaque, hwaddr offset,
return s->rtc; return s->rtc;
} }
qemu_log_mask(LOG_UNIMP, qemu_log_mask(LOG_UNIMP,
"GPTM: read of TAR but timer read not supported"); "GPTM: read of TAR but timer read not supported\n");
return 0; return 0;
case 0x4c: /* TBR */ case 0x4c: /* TBR */
qemu_log_mask(LOG_UNIMP, qemu_log_mask(LOG_UNIMP,
"GPTM: read of TBR but timer read not supported"); "GPTM: read of TBR but timer read not supported\n");
return 0; return 0;
default: default:
qemu_log_mask(LOG_GUEST_ERROR, qemu_log_mask(LOG_GUEST_ERROR,
...@@ -836,11 +836,12 @@ static void stellaris_i2c_write(void *opaque, hwaddr offset, ...@@ -836,11 +836,12 @@ static void stellaris_i2c_write(void *opaque, hwaddr offset,
break; break;
case 0x20: /* MCR */ case 0x20: /* MCR */
if (value & 1) { if (value & 1) {
qemu_log_mask(LOG_UNIMP, "stellaris_i2c: Loopback not implemented"); qemu_log_mask(LOG_UNIMP,
"stellaris_i2c: Loopback not implemented\n");
} }
if (value & 0x20) { if (value & 0x20) {
qemu_log_mask(LOG_UNIMP, qemu_log_mask(LOG_UNIMP,
"stellaris_i2c: Slave mode not implemented"); "stellaris_i2c: Slave mode not implemented\n");
} }
s->mcr = value & 0x31; s->mcr = value & 0x31;
break; break;
...@@ -1124,7 +1125,7 @@ static void stellaris_adc_write(void *opaque, hwaddr offset, ...@@ -1124,7 +1125,7 @@ static void stellaris_adc_write(void *opaque, hwaddr offset,
s->sspri = value; s->sspri = value;
break; break;
case 0x28: /* PSSI */ case 0x28: /* PSSI */
qemu_log_mask(LOG_UNIMP, "ADC: sample initiate unimplemented"); qemu_log_mask(LOG_UNIMP, "ADC: sample initiate unimplemented\n");
break; break;
case 0x30: /* SAC */ case 0x30: /* SAC */
s->sac = value; s->sac = value;
......
...@@ -39,10 +39,6 @@ typedef struct XlnxZCU102 { ...@@ -39,10 +39,6 @@ typedef struct XlnxZCU102 {
#define ZCU102_MACHINE(obj) \ #define ZCU102_MACHINE(obj) \
OBJECT_CHECK(XlnxZCU102, (obj), TYPE_ZCU102_MACHINE) OBJECT_CHECK(XlnxZCU102, (obj), TYPE_ZCU102_MACHINE)
#define TYPE_EP108_MACHINE MACHINE_TYPE_NAME("xlnx-ep108")
#define EP108_MACHINE(obj) \
OBJECT_CHECK(XlnxZCU102, (obj), TYPE_EP108_MACHINE)
static struct arm_boot_info xlnx_zcu102_binfo; static struct arm_boot_info xlnx_zcu102_binfo;
static bool zcu102_get_secure(Object *obj, Error **errp) static bool zcu102_get_secure(Object *obj, Error **errp)
...@@ -73,8 +69,9 @@ static void zcu102_set_virt(Object *obj, bool value, Error **errp) ...@@ -73,8 +69,9 @@ static void zcu102_set_virt(Object *obj, bool value, Error **errp)
s->virt = value; s->virt = value;
} }
static void xlnx_zynqmp_init(XlnxZCU102 *s, MachineState *machine) static void xlnx_zcu102_init(MachineState *machine)
{ {
XlnxZCU102 *s = ZCU102_MACHINE(machine);
int i; int i;
uint64_t ram_size = machine->ram_size; uint64_t ram_size = machine->ram_size;
...@@ -183,60 +180,6 @@ static void xlnx_zynqmp_init(XlnxZCU102 *s, MachineState *machine) ...@@ -183,60 +180,6 @@ static void xlnx_zynqmp_init(XlnxZCU102 *s, MachineState *machine)
arm_load_kernel(s->soc.boot_cpu_ptr, &xlnx_zcu102_binfo); arm_load_kernel(s->soc.boot_cpu_ptr, &xlnx_zcu102_binfo);
} }
static void xlnx_ep108_init(MachineState *machine)
{
XlnxZCU102 *s = EP108_MACHINE(machine);
if (!qtest_enabled()) {
info_report("The Xilinx EP108 machine is deprecated, please use the "
"ZCU102 machine (which has the same features) instead.");
}
xlnx_zynqmp_init(s, machine);
}
static void xlnx_ep108_machine_instance_init(Object *obj)
{
XlnxZCU102 *s = EP108_MACHINE(obj);
/* EP108, we don't support setting secure or virt */
s->secure = false;
s->virt = false;
}
static void xlnx_ep108_machine_class_init(ObjectClass *oc, void *data)
{
MachineClass *mc = MACHINE_CLASS(oc);
mc->desc = "Xilinx ZynqMP EP108 board (Deprecated, please use xlnx-zcu102)";
mc->init = xlnx_ep108_init;
mc->block_default_type = IF_IDE;
mc->units_per_default_bus = 1;
mc->ignore_memory_transaction_failures = true;
mc->max_cpus = XLNX_ZYNQMP_NUM_APU_CPUS + XLNX_ZYNQMP_NUM_RPU_CPUS;
mc->default_cpus = XLNX_ZYNQMP_NUM_APU_CPUS;
}
static const TypeInfo xlnx_ep108_machine_init_typeinfo = {
.name = MACHINE_TYPE_NAME("xlnx-ep108"),
.parent = TYPE_MACHINE,
.class_init = xlnx_ep108_machine_class_init,
.instance_init = xlnx_ep108_machine_instance_init,
.instance_size = sizeof(XlnxZCU102),
};
static void xlnx_ep108_machine_init_register_types(void)
{
type_register_static(&xlnx_ep108_machine_init_typeinfo);
}
static void xlnx_zcu102_init(MachineState *machine)
{
XlnxZCU102 *s = ZCU102_MACHINE(machine);
xlnx_zynqmp_init(s, machine);
}
static void xlnx_zcu102_machine_instance_init(Object *obj) static void xlnx_zcu102_machine_instance_init(Object *obj)
{ {
XlnxZCU102 *s = ZCU102_MACHINE(obj); XlnxZCU102 *s = ZCU102_MACHINE(obj);
...@@ -289,4 +232,3 @@ static void xlnx_zcu102_machine_init_register_types(void) ...@@ -289,4 +232,3 @@ static void xlnx_zcu102_machine_init_register_types(void)
} }
type_init(xlnx_zcu102_machine_init_register_types) type_init(xlnx_zcu102_machine_init_register_types)
type_init(xlnx_ep108_machine_init_register_types)
...@@ -60,7 +60,7 @@ static uint64_t digic_uart_read(void *opaque, hwaddr addr, ...@@ -60,7 +60,7 @@ static uint64_t digic_uart_read(void *opaque, hwaddr addr,
default: default:
qemu_log_mask(LOG_UNIMP, qemu_log_mask(LOG_UNIMP,
"digic-uart: read access to unknown register 0x" "digic-uart: read access to unknown register 0x"
TARGET_FMT_plx, addr << 2); TARGET_FMT_plx "\n", addr << 2);
} }
return ret; return ret;
...@@ -98,7 +98,7 @@ static void digic_uart_write(void *opaque, hwaddr addr, uint64_t value, ...@@ -98,7 +98,7 @@ static void digic_uart_write(void *opaque, hwaddr addr, uint64_t value,
default: default:
qemu_log_mask(LOG_UNIMP, qemu_log_mask(LOG_UNIMP,
"digic-uart: write access to unknown register 0x" "digic-uart: write access to unknown register 0x"
TARGET_FMT_plx, addr << 2); TARGET_FMT_plx "\n", addr << 2);
} }
} }
......
...@@ -96,7 +96,7 @@ void register_write(RegisterInfo *reg, uint64_t val, uint64_t we, ...@@ -96,7 +96,7 @@ void register_write(RegisterInfo *reg, uint64_t val, uint64_t we,
if (test) { if (test) {
qemu_log_mask(LOG_UNIMP, qemu_log_mask(LOG_UNIMP,
"%s:%s writing %#" PRIx64 " to unimplemented bits:" \ "%s:%s writing %#" PRIx64 " to unimplemented bits:" \
" %#" PRIx64 "", " %#" PRIx64 "\n",
prefix, reg->access->name, val, ac->unimp); prefix, reg->access->name, val, ac->unimp);
} }
......
...@@ -1074,7 +1074,9 @@ static void xlnx_dp_avbufm_write(void *opaque, hwaddr offset, uint64_t value, ...@@ -1074,7 +1074,9 @@ static void xlnx_dp_avbufm_write(void *opaque, hwaddr offset, uint64_t value,
case AV_BUF_STC_SNAPSHOT1: case AV_BUF_STC_SNAPSHOT1:
case AV_BUF_HCOUNT_VCOUNT_INT0: case AV_BUF_HCOUNT_VCOUNT_INT0:
case AV_BUF_HCOUNT_VCOUNT_INT1: case AV_BUF_HCOUNT_VCOUNT_INT1:
qemu_log_mask(LOG_UNIMP, "avbufm: unimplmented"); qemu_log_mask(LOG_UNIMP, "avbufm: unimplemented register 0x%04"
PRIx64 "\n",
offset << 2);
break; break;
default: default:
s->avbufm_registers[offset] = value; s->avbufm_registers[offset] = value;
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include "qemu/osdep.h" #include "qemu/osdep.h"
#include "hw/i2c/i2c.h" #include "hw/i2c/i2c.h"
#include "trace.h"
#define I2C_BROADCAST 0x00 #define I2C_BROADCAST 0x00
...@@ -130,14 +131,16 @@ int i2c_start_transfer(I2CBus *bus, uint8_t address, int recv) ...@@ -130,14 +131,16 @@ int i2c_start_transfer(I2CBus *bus, uint8_t address, int recv)
} }
QLIST_FOREACH(node, &bus->current_devs, next) { QLIST_FOREACH(node, &bus->current_devs, next) {
I2CSlave *s = node->elt;
int rv; int rv;
sc = I2C_SLAVE_GET_CLASS(node->elt); sc = I2C_SLAVE_GET_CLASS(s);
/* If the bus is already busy, assume this is a repeated /* If the bus is already busy, assume this is a repeated
start condition. */ start condition. */
if (sc->event) { if (sc->event) {
rv = sc->event(node->elt, recv ? I2C_START_RECV : I2C_START_SEND); trace_i2c_event("start", s->address);
rv = sc->event(s, recv ? I2C_START_RECV : I2C_START_SEND);
if (rv && !bus->broadcast) { if (rv && !bus->broadcast) {
if (bus_scanned) { if (bus_scanned) {
/* First call, terminate the transfer. */ /* First call, terminate the transfer. */
...@@ -156,9 +159,11 @@ void i2c_end_transfer(I2CBus *bus) ...@@ -156,9 +159,11 @@ void i2c_end_transfer(I2CBus *bus)
I2CNode *node, *next; I2CNode *node, *next;
QLIST_FOREACH_SAFE(node, &bus->current_devs, next, next) { QLIST_FOREACH_SAFE(node, &bus->current_devs, next, next) {
sc = I2C_SLAVE_GET_CLASS(node->elt); I2CSlave *s = node->elt;
sc = I2C_SLAVE_GET_CLASS(s);
if (sc->event) { if (sc->event) {
sc->event(node->elt, I2C_FINISH); trace_i2c_event("finish", s->address);
sc->event(s, I2C_FINISH);
} }
QLIST_REMOVE(node, next); QLIST_REMOVE(node, next);
g_free(node); g_free(node);
...@@ -169,14 +174,17 @@ void i2c_end_transfer(I2CBus *bus) ...@@ -169,14 +174,17 @@ void i2c_end_transfer(I2CBus *bus)
int i2c_send_recv(I2CBus *bus, uint8_t *data, bool send) int i2c_send_recv(I2CBus *bus, uint8_t *data, bool send)
{ {
I2CSlaveClass *sc; I2CSlaveClass *sc;
I2CSlave *s;
I2CNode *node; I2CNode *node;
int ret = 0; int ret = 0;
if (send) { if (send) {
QLIST_FOREACH(node, &bus->current_devs, next) { QLIST_FOREACH(node, &bus->current_devs, next) {
sc = I2C_SLAVE_GET_CLASS(node->elt); s = node->elt;
sc = I2C_SLAVE_GET_CLASS(s);
if (sc->send) { if (sc->send) {
ret = ret || sc->send(node->elt, *data); trace_i2c_send(s->address, *data);
ret = ret || sc->send(s, *data);
} else { } else {
ret = -1; ret = -1;
} }
...@@ -189,7 +197,9 @@ int i2c_send_recv(I2CBus *bus, uint8_t *data, bool send) ...@@ -189,7 +197,9 @@ int i2c_send_recv(I2CBus *bus, uint8_t *data, bool send)
sc = I2C_SLAVE_GET_CLASS(QLIST_FIRST(&bus->current_devs)->elt); sc = I2C_SLAVE_GET_CLASS(QLIST_FIRST(&bus->current_devs)->elt);
if (sc->recv) { if (sc->recv) {
ret = sc->recv(QLIST_FIRST(&bus->current_devs)->elt); s = QLIST_FIRST(&bus->current_devs)->elt;
ret = sc->recv(s);
trace_i2c_recv(s->address, ret);
if (ret < 0) { if (ret < 0) {
return ret; return ret;
} else { } else {
...@@ -226,6 +236,7 @@ void i2c_nack(I2CBus *bus) ...@@ -226,6 +236,7 @@ void i2c_nack(I2CBus *bus)
QLIST_FOREACH(node, &bus->current_devs, next) { QLIST_FOREACH(node, &bus->current_devs, next) {
sc = I2C_SLAVE_GET_CLASS(node->elt); sc = I2C_SLAVE_GET_CLASS(node->elt);
if (sc->event) { if (sc->event) {
trace_i2c_event("nack", node->elt->address);
sc->event(node->elt, I2C_NACK); sc->event(node->elt, I2C_NACK);
} }
} }
......
...@@ -139,6 +139,16 @@ static void smbus_eeprom_register_types(void) ...@@ -139,6 +139,16 @@ static void smbus_eeprom_register_types(void)
type_init(smbus_eeprom_register_types) type_init(smbus_eeprom_register_types)
void smbus_eeprom_init_one(I2CBus *smbus, uint8_t address, uint8_t *eeprom_buf)
{
DeviceState *dev;
dev = qdev_create((BusState *) smbus, "smbus-eeprom");
qdev_prop_set_uint8(dev, "address", address);
qdev_prop_set_ptr(dev, "data", eeprom_buf);
qdev_init_nofail(dev);
}
void smbus_eeprom_init(I2CBus *smbus, int nb_eeprom, void smbus_eeprom_init(I2CBus *smbus, int nb_eeprom,
const uint8_t *eeprom_spd, int eeprom_spd_size) const uint8_t *eeprom_spd, int eeprom_spd_size)
{ {
...@@ -149,10 +159,6 @@ void smbus_eeprom_init(I2CBus *smbus, int nb_eeprom, ...@@ -149,10 +159,6 @@ void smbus_eeprom_init(I2CBus *smbus, int nb_eeprom,
} }
for (i = 0; i < nb_eeprom; i++) { for (i = 0; i < nb_eeprom; i++) {
DeviceState *eeprom; smbus_eeprom_init_one(smbus, 0x50 + i, eeprom_buf + (i * 256));
eeprom = qdev_create((BusState *)smbus, "smbus-eeprom");
qdev_prop_set_uint8(eeprom, "address", 0x50 + i);
qdev_prop_set_ptr(eeprom, "data", eeprom_buf + (i * 256));
qdev_init_nofail(eeprom);
} }
} }
# See docs/devel/tracing.txt for syntax documentation.
# hw/i2c/core.c
i2c_event(const char *event, uint8_t address) "%s(addr:0x%02x)"
i2c_send(uint8_t address, uint8_t data) "send(addr:0x%02x) data:0x%02x"
i2c_recv(uint8_t address, uint8_t data) "recv(addr:0x%02x) data:0x%02x"
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include "hw/intc/arm_gicv3_common.h" #include "hw/intc/arm_gicv3_common.h"
#include "gicv3_internal.h" #include "gicv3_internal.h"
#include "hw/arm/linux-boot-if.h" #include "hw/arm/linux-boot-if.h"
#include "sysemu/kvm.h"
static int gicv3_pre_save(void *opaque) static int gicv3_pre_save(void *opaque)
{ {
...@@ -141,6 +142,79 @@ static const VMStateDescription vmstate_gicv3_cpu = { ...@@ -141,6 +142,79 @@ static const VMStateDescription vmstate_gicv3_cpu = {
} }
}; };
static int gicv3_gicd_no_migration_shift_bug_pre_load(void *opaque)
{
GICv3State *cs = opaque;
/*
* The gicd_no_migration_shift_bug flag is used for migration compatibility
* for old version QEMU which may have the GICD bmp shift bug under KVM mode.
* Strictly, what we want to know is whether the migration source is using
* KVM. Since we don't have any way to determine that, we look at whether the
* destination is using KVM; this is close enough because for the older QEMU
* versions with this bug KVM -> TCG migration didn't work anyway. If the
* source is a newer QEMU without this bug it will transmit the migration
* subsection which sets the flag to true; otherwise it will remain set to
* the value we select here.
*/
if (kvm_enabled()) {
cs->gicd_no_migration_shift_bug = false;
}
return 0;
}
static int gicv3_gicd_no_migration_shift_bug_post_load(void *opaque,
int version_id)
{
GICv3State *cs = opaque;
if (cs->gicd_no_migration_shift_bug) {
return 0;
}
/* Older versions of QEMU had a bug in the handling of state save/restore
* to the KVM GICv3: they got the offset in the bitmap arrays wrong,
* so that instead of the data for external interrupts 32 and up
* starting at bit position 32 in the bitmap, it started at bit
* position 64. If we're receiving data from a QEMU with that bug,
* we must move the data down into the right place.
*/
memmove(cs->group, (uint8_t *)cs->group + GIC_INTERNAL / 8,
sizeof(cs->group) - GIC_INTERNAL / 8);
memmove(cs->grpmod, (uint8_t *)cs->grpmod + GIC_INTERNAL / 8,
sizeof(cs->grpmod) - GIC_INTERNAL / 8);
memmove(cs->enabled, (uint8_t *)cs->enabled + GIC_INTERNAL / 8,
sizeof(cs->enabled) - GIC_INTERNAL / 8);
memmove(cs->pending, (uint8_t *)cs->pending + GIC_INTERNAL / 8,
sizeof(cs->pending) - GIC_INTERNAL / 8);
memmove(cs->active, (uint8_t *)cs->active + GIC_INTERNAL / 8,
sizeof(cs->active) - GIC_INTERNAL / 8);
memmove(cs->edge_trigger, (uint8_t *)cs->edge_trigger + GIC_INTERNAL / 8,
sizeof(cs->edge_trigger) - GIC_INTERNAL / 8);
/*
* While this new version QEMU doesn't have this kind of bug as we fix it,
* so it needs to set the flag to true to indicate that and it's necessary
* for next migration to work from this new version QEMU.
*/
cs->gicd_no_migration_shift_bug = true;
return 0;
}
const VMStateDescription vmstate_gicv3_gicd_no_migration_shift_bug = {
.name = "arm_gicv3/gicd_no_migration_shift_bug",
.version_id = 1,
.minimum_version_id = 1,
.pre_load = gicv3_gicd_no_migration_shift_bug_pre_load,
.post_load = gicv3_gicd_no_migration_shift_bug_post_load,
.fields = (VMStateField[]) {
VMSTATE_BOOL(gicd_no_migration_shift_bug, GICv3State),
VMSTATE_END_OF_LIST()
}
};
static const VMStateDescription vmstate_gicv3 = { static const VMStateDescription vmstate_gicv3 = {
.name = "arm_gicv3", .name = "arm_gicv3",
.version_id = 1, .version_id = 1,
...@@ -165,6 +239,10 @@ static const VMStateDescription vmstate_gicv3 = { ...@@ -165,6 +239,10 @@ static const VMStateDescription vmstate_gicv3 = {
VMSTATE_STRUCT_VARRAY_POINTER_UINT32(cpu, GICv3State, num_cpu, VMSTATE_STRUCT_VARRAY_POINTER_UINT32(cpu, GICv3State, num_cpu,
vmstate_gicv3_cpu, GICv3CPUState), vmstate_gicv3_cpu, GICv3CPUState),
VMSTATE_END_OF_LIST() VMSTATE_END_OF_LIST()
},
.subsections = (const VMStateDescription * []) {
&vmstate_gicv3_gicd_no_migration_shift_bug,
NULL
} }
}; };
...@@ -364,6 +442,7 @@ static void arm_gicv3_common_reset(DeviceState *dev) ...@@ -364,6 +442,7 @@ static void arm_gicv3_common_reset(DeviceState *dev)
gicv3_gicd_group_set(s, i); gicv3_gicd_group_set(s, i);
} }
} }
s->gicd_no_migration_shift_bug = true;
} }
static void arm_gic_common_linux_init(ARMLinuxBootIf *obj, static void arm_gic_common_linux_init(ARMLinuxBootIf *obj,
......
...@@ -164,6 +164,14 @@ static void kvm_dist_get_edge_trigger(GICv3State *s, uint32_t offset, ...@@ -164,6 +164,14 @@ static void kvm_dist_get_edge_trigger(GICv3State *s, uint32_t offset,
uint32_t reg; uint32_t reg;
int irq; int irq;
/* For the KVM GICv3, affinity routing is always enabled, and the first 2
* GICD_ICFGR<n> registers are always RAZ/WI. The corresponding
* functionality is replaced by GICR_ICFGR<n>. It doesn't need to sync
* them. So it should increase the offset to skip GIC_INTERNAL irqs.
* This matches the for_each_dist_irq_reg() macro which also skips the
* first GIC_INTERNAL irqs.
*/
offset += (GIC_INTERNAL * 2) / 8;
for_each_dist_irq_reg(irq, s->num_irq, 2) { for_each_dist_irq_reg(irq, s->num_irq, 2) {
kvm_gicd_access(s, offset, &reg, false); kvm_gicd_access(s, offset, &reg, false);
reg = half_unshuffle32(reg >> 1); reg = half_unshuffle32(reg >> 1);
...@@ -181,6 +189,14 @@ static void kvm_dist_put_edge_trigger(GICv3State *s, uint32_t offset, ...@@ -181,6 +189,14 @@ static void kvm_dist_put_edge_trigger(GICv3State *s, uint32_t offset,
uint32_t reg; uint32_t reg;
int irq; int irq;
/* For the KVM GICv3, affinity routing is always enabled, and the first 2
* GICD_ICFGR<n> registers are always RAZ/WI. The corresponding
* functionality is replaced by GICR_ICFGR<n>. It doesn't need to sync
* them. So it should increase the offset to skip GIC_INTERNAL irqs.
* This matches the for_each_dist_irq_reg() macro which also skips the
* first GIC_INTERNAL irqs.
*/
offset += (GIC_INTERNAL * 2) / 8;
for_each_dist_irq_reg(irq, s->num_irq, 2) { for_each_dist_irq_reg(irq, s->num_irq, 2) {
reg = *gic_bmp_ptr32(bmp, irq); reg = *gic_bmp_ptr32(bmp, irq);
if (irq % 32 != 0) { if (irq % 32 != 0) {
...@@ -222,6 +238,15 @@ static void kvm_dist_getbmp(GICv3State *s, uint32_t offset, uint32_t *bmp) ...@@ -222,6 +238,15 @@ static void kvm_dist_getbmp(GICv3State *s, uint32_t offset, uint32_t *bmp)
uint32_t reg; uint32_t reg;
int irq; int irq;
/* For the KVM GICv3, affinity routing is always enabled, and the
* GICD_IGROUPR0/GICD_IGRPMODR0/GICD_ISENABLER0/GICD_ISPENDR0/
* GICD_ISACTIVER0 registers are always RAZ/WI. The corresponding
* functionality is replaced by the GICR registers. It doesn't need to sync
* them. So it should increase the offset to skip GIC_INTERNAL irqs.
* This matches the for_each_dist_irq_reg() macro which also skips the
* first GIC_INTERNAL irqs.
*/
offset += (GIC_INTERNAL * 1) / 8;
for_each_dist_irq_reg(irq, s->num_irq, 1) { for_each_dist_irq_reg(irq, s->num_irq, 1) {
kvm_gicd_access(s, offset, &reg, false); kvm_gicd_access(s, offset, &reg, false);
*gic_bmp_ptr32(bmp, irq) = reg; *gic_bmp_ptr32(bmp, irq) = reg;
...@@ -235,6 +260,19 @@ static void kvm_dist_putbmp(GICv3State *s, uint32_t offset, ...@@ -235,6 +260,19 @@ static void kvm_dist_putbmp(GICv3State *s, uint32_t offset,
uint32_t reg; uint32_t reg;
int irq; int irq;
/* For the KVM GICv3, affinity routing is always enabled, and the
* GICD_IGROUPR0/GICD_IGRPMODR0/GICD_ISENABLER0/GICD_ISPENDR0/
* GICD_ISACTIVER0 registers are always RAZ/WI. The corresponding
* functionality is replaced by the GICR registers. It doesn't need to sync
* them. So it should increase the offset and clroffset to skip GIC_INTERNAL
* irqs. This matches the for_each_dist_irq_reg() macro which also skips the
* first GIC_INTERNAL irqs.
*/
offset += (GIC_INTERNAL * 1) / 8;
if (clroffset != 0) {
clroffset += (GIC_INTERNAL * 1) / 8;
}
for_each_dist_irq_reg(irq, s->num_irq, 1) { for_each_dist_irq_reg(irq, s->num_irq, 1) {
/* If this bitmap is a set/clear register pair, first write to the /* If this bitmap is a set/clear register pair, first write to the
* clear-reg to clear all bits before using the set-reg to write * clear-reg to clear all bits before using the set-reg to write
......
...@@ -176,7 +176,7 @@ static uint64_t boston_platreg_read(void *opaque, hwaddr addr, ...@@ -176,7 +176,7 @@ static uint64_t boston_platreg_read(void *opaque, hwaddr addr,
uint32_t gic_freq, val; uint32_t gic_freq, val;
if (size != 4) { if (size != 4) {
qemu_log_mask(LOG_UNIMP, "%uB platform register read", size); qemu_log_mask(LOG_UNIMP, "%uB platform register read\n", size);
return 0; return 0;
} }
...@@ -205,7 +205,7 @@ static uint64_t boston_platreg_read(void *opaque, hwaddr addr, ...@@ -205,7 +205,7 @@ static uint64_t boston_platreg_read(void *opaque, hwaddr addr,
val |= PLAT_DDR_CFG_MHZ; val |= PLAT_DDR_CFG_MHZ;
return val; return val;
default: default:
qemu_log_mask(LOG_UNIMP, "Read platform register 0x%" HWADDR_PRIx, qemu_log_mask(LOG_UNIMP, "Read platform register 0x%" HWADDR_PRIx "\n",
addr & 0xffff); addr & 0xffff);
return 0; return 0;
} }
...@@ -215,7 +215,7 @@ static void boston_platreg_write(void *opaque, hwaddr addr, ...@@ -215,7 +215,7 @@ static void boston_platreg_write(void *opaque, hwaddr addr,
uint64_t val, unsigned size) uint64_t val, unsigned size)
{ {
if (size != 4) { if (size != 4) {
qemu_log_mask(LOG_UNIMP, "%uB platform register write", size); qemu_log_mask(LOG_UNIMP, "%uB platform register write\n", size);
return; return;
} }
...@@ -237,7 +237,7 @@ static void boston_platreg_write(void *opaque, hwaddr addr, ...@@ -237,7 +237,7 @@ static void boston_platreg_write(void *opaque, hwaddr addr,
break; break;
default: default:
qemu_log_mask(LOG_UNIMP, "Write platform register 0x%" HWADDR_PRIx qemu_log_mask(LOG_UNIMP, "Write platform register 0x%" HWADDR_PRIx
" = 0x%" PRIx64, addr & 0xffff, val); " = 0x%" PRIx64 "\n", addr & 0xffff, val);
break; break;
} }
} }
......
...@@ -7,6 +7,7 @@ common-obj-$(CONFIG_SGA) += sga.o ...@@ -7,6 +7,7 @@ common-obj-$(CONFIG_SGA) += sga.o
common-obj-$(CONFIG_ISA_TESTDEV) += pc-testdev.o common-obj-$(CONFIG_ISA_TESTDEV) += pc-testdev.o
common-obj-$(CONFIG_PCI_TESTDEV) += pci-testdev.o common-obj-$(CONFIG_PCI_TESTDEV) += pci-testdev.o
common-obj-$(CONFIG_EDU) += edu.o common-obj-$(CONFIG_EDU) += edu.o
common-obj-$(CONFIG_PCA9552) += pca9552.o
common-obj-y += unimp.o common-obj-y += unimp.o
common-obj-$(CONFIG_FW_CFG_DMA) += vmcoreinfo.o common-obj-$(CONFIG_FW_CFG_DMA) += vmcoreinfo.o
......
/*
* PCA9552 I2C LED blinker
*
* https://www.nxp.com/docs/en/application-note/AN264.pdf
*
* Copyright (c) 2017-2018, IBM Corporation.
*
* This work is licensed under the terms of the GNU GPL, version 2 or
* later. See the COPYING file in the top-level directory.
*/
#include "qemu/osdep.h"
#include "qemu/log.h"
#include "hw/hw.h"
#include "hw/misc/pca9552.h"
#include "hw/misc/pca9552_regs.h"
#define PCA9552_LED_ON 0x0
#define PCA9552_LED_OFF 0x1
#define PCA9552_LED_PWM0 0x2
#define PCA9552_LED_PWM1 0x3
static uint8_t pca9552_pin_get_config(PCA9552State *s, int pin)
{
uint8_t reg = PCA9552_LS0 + (pin / 4);
uint8_t shift = (pin % 4) << 1;
return extract32(s->regs[reg], shift, 2);
}
static void pca9552_update_pin_input(PCA9552State *s)
{
int i;
for (i = 0; i < s->nr_leds; i++) {
uint8_t input_reg = PCA9552_INPUT0 + (i / 8);
uint8_t input_shift = (i % 8);
uint8_t config = pca9552_pin_get_config(s, i);
switch (config) {
case PCA9552_LED_ON:
s->regs[input_reg] |= 1 << input_shift;
break;
case PCA9552_LED_OFF:
s->regs[input_reg] &= ~(1 << input_shift);
break;
case PCA9552_LED_PWM0:
case PCA9552_LED_PWM1:
/* TODO */
default:
break;
}
}
}
static uint8_t pca9552_read(PCA9552State *s, uint8_t reg)
{
switch (reg) {
case PCA9552_INPUT0:
case PCA9552_INPUT1:
case PCA9552_PSC0:
case PCA9552_PWM0:
case PCA9552_PSC1:
case PCA9552_PWM1:
case PCA9552_LS0:
case PCA9552_LS1:
case PCA9552_LS2:
case PCA9552_LS3:
return s->regs[reg];
default:
qemu_log_mask(LOG_GUEST_ERROR, "%s: unexpected read to register %d\n",
__func__, reg);
return 0xFF;
}
}
static void pca9552_write(PCA9552State *s, uint8_t reg, uint8_t data)
{
switch (reg) {
case PCA9552_PSC0:
case PCA9552_PWM0:
case PCA9552_PSC1:
case PCA9552_PWM1:
s->regs[reg] = data;
break;
case PCA9552_LS0:
case PCA9552_LS1:
case PCA9552_LS2:
case PCA9552_LS3:
s->regs[reg] = data;
pca9552_update_pin_input(s);
break;
case PCA9552_INPUT0:
case PCA9552_INPUT1:
default:
qemu_log_mask(LOG_GUEST_ERROR, "%s: unexpected write to register %d\n",
__func__, reg);
}
}
/*
* When Auto-Increment is on, the register address is incremented
* after each byte is sent to or received by the device. The index
* rollovers to 0 when the maximum register address is reached.
*/
static void pca9552_autoinc(PCA9552State *s)
{
if (s->pointer != 0xFF && s->pointer & PCA9552_AUTOINC) {
uint8_t reg = s->pointer & 0xf;
reg = (reg + 1) % (s->max_reg + 1);
s->pointer = reg | PCA9552_AUTOINC;
}
}
static int pca9552_recv(I2CSlave *i2c)
{
PCA9552State *s = PCA9552(i2c);
uint8_t ret;
ret = pca9552_read(s, s->pointer & 0xf);
/*
* From the Specs:
*
* Important Note: When a Read sequence is initiated and the
* AI bit is set to Logic Level 1, the Read Sequence MUST
* start by a register different from 0.
*
* I don't know what should be done in this case, so throw an
* error.
*/
if (s->pointer == PCA9552_AUTOINC) {
qemu_log_mask(LOG_GUEST_ERROR,
"%s: Autoincrement read starting with register 0\n",
__func__);
}
pca9552_autoinc(s);
return ret;
}
static int pca9552_send(I2CSlave *i2c, uint8_t data)
{
PCA9552State *s = PCA9552(i2c);
/* First byte sent by is the register address */
if (s->len == 0) {
s->pointer = data;
s->len++;
} else {
pca9552_write(s, s->pointer & 0xf, data);
pca9552_autoinc(s);
}
return 0;
}
static int pca9552_event(I2CSlave *i2c, enum i2c_event event)
{
PCA9552State *s = PCA9552(i2c);
s->len = 0;
return 0;
}
static const VMStateDescription pca9552_vmstate = {
.name = "PCA9552",
.version_id = 0,
.minimum_version_id = 0,
.fields = (VMStateField[]) {
VMSTATE_UINT8(len, PCA9552State),
VMSTATE_UINT8(pointer, PCA9552State),
VMSTATE_UINT8_ARRAY(regs, PCA9552State, PCA9552_NR_REGS),
VMSTATE_I2C_SLAVE(i2c, PCA9552State),
VMSTATE_END_OF_LIST()
}
};
static void pca9552_reset(DeviceState *dev)
{
PCA9552State *s = PCA9552(dev);
s->regs[PCA9552_PSC0] = 0xFF;
s->regs[PCA9552_PWM0] = 0x80;
s->regs[PCA9552_PSC1] = 0xFF;
s->regs[PCA9552_PWM1] = 0x80;
s->regs[PCA9552_LS0] = 0x55; /* all OFF */
s->regs[PCA9552_LS1] = 0x55;
s->regs[PCA9552_LS2] = 0x55;
s->regs[PCA9552_LS3] = 0x55;
pca9552_update_pin_input(s);
s->pointer = 0xFF;
s->len = 0;
}
static void pca9552_initfn(Object *obj)
{
PCA9552State *s = PCA9552(obj);
/* If support for the other PCA955X devices are implemented, these
* constant values might be part of class structure describing the
* PCA955X device
*/
s->max_reg = PCA9552_LS3;
s->nr_leds = 16;
}
static void pca9552_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
I2CSlaveClass *k = I2C_SLAVE_CLASS(klass);
k->event = pca9552_event;
k->recv = pca9552_recv;
k->send = pca9552_send;
dc->reset = pca9552_reset;
dc->vmsd = &pca9552_vmstate;
}
static const TypeInfo pca9552_info = {
.name = TYPE_PCA9552,
.parent = TYPE_I2C_SLAVE,
.instance_init = pca9552_initfn,
.instance_size = sizeof(PCA9552State),
.class_init = pca9552_class_init,
};
static void pca9552_register_types(void)
{
type_register_static(&pca9552_info);
}
type_init(pca9552_register_types)
...@@ -207,16 +207,18 @@ typedef struct { ...@@ -207,16 +207,18 @@ typedef struct {
/* /*
* Max frame size for the receiving buffer * Max frame size for the receiving buffer
*/ */
#define FTGMAC100_MAX_FRAME_SIZE 10240 #define FTGMAC100_MAX_FRAME_SIZE 9220
/* Limits depending on the type of the frame /* Limits depending on the type of the frame
* *
* 9216 for Jumbo frames (+ 4 for VLAN) * 9216 for Jumbo frames (+ 4 for VLAN)
* 1518 for other frames (+ 4 for VLAN) * 1518 for other frames (+ 4 for VLAN)
*/ */
static int ftgmac100_max_frame_size(FTGMAC100State *s) static int ftgmac100_max_frame_size(FTGMAC100State *s, uint16_t proto)
{ {
return (s->maccr & FTGMAC100_MACCR_JUMBO_LF ? 9216 : 1518) + 4; int max = (s->maccr & FTGMAC100_MACCR_JUMBO_LF ? 9216 : 1518);
return max + (proto == ETH_P_VLAN ? 4 : 0);
} }
static void ftgmac100_update_irq(FTGMAC100State *s) static void ftgmac100_update_irq(FTGMAC100State *s)
...@@ -408,7 +410,6 @@ static void ftgmac100_do_tx(FTGMAC100State *s, uint32_t tx_ring, ...@@ -408,7 +410,6 @@ static void ftgmac100_do_tx(FTGMAC100State *s, uint32_t tx_ring,
uint8_t *ptr = s->frame; uint8_t *ptr = s->frame;
uint32_t addr = tx_descriptor; uint32_t addr = tx_descriptor;
uint32_t flags = 0; uint32_t flags = 0;
int max_frame_size = ftgmac100_max_frame_size(s);
while (1) { while (1) {
FTGMAC100Desc bd; FTGMAC100Desc bd;
...@@ -427,11 +428,12 @@ static void ftgmac100_do_tx(FTGMAC100State *s, uint32_t tx_ring, ...@@ -427,11 +428,12 @@ static void ftgmac100_do_tx(FTGMAC100State *s, uint32_t tx_ring,
flags = bd.des1; flags = bd.des1;
} }
len = bd.des0 & 0x3FFF; len = FTGMAC100_TXDES0_TXBUF_SIZE(bd.des0);
if (frame_size + len > max_frame_size) { if (frame_size + len > sizeof(s->frame)) {
qemu_log_mask(LOG_GUEST_ERROR, "%s: frame too big : %d bytes\n", qemu_log_mask(LOG_GUEST_ERROR, "%s: frame too big : %d bytes\n",
__func__, len); __func__, len);
len = max_frame_size - frame_size; s->isr |= FTGMAC100_INT_XPKT_LOST;
len = sizeof(s->frame) - frame_size;
} }
if (dma_memory_read(&address_space_memory, bd.des3, ptr, len)) { if (dma_memory_read(&address_space_memory, bd.des3, ptr, len)) {
...@@ -441,6 +443,22 @@ static void ftgmac100_do_tx(FTGMAC100State *s, uint32_t tx_ring, ...@@ -441,6 +443,22 @@ static void ftgmac100_do_tx(FTGMAC100State *s, uint32_t tx_ring,
break; break;
} }
/* Check for VLAN */
if (bd.des0 & FTGMAC100_TXDES0_FTS &&
bd.des1 & FTGMAC100_TXDES1_INS_VLANTAG &&
be16_to_cpu(PKT_GET_ETH_HDR(ptr)->h_proto) != ETH_P_VLAN) {
if (frame_size + len + 4 > sizeof(s->frame)) {
qemu_log_mask(LOG_GUEST_ERROR, "%s: frame too big : %d bytes\n",
__func__, len);
s->isr |= FTGMAC100_INT_XPKT_LOST;
len = sizeof(s->frame) - frame_size - 4;
}
memmove(ptr + 16, ptr + 12, len - 12);
stw_be_p(ptr + 12, ETH_P_VLAN);
stw_be_p(ptr + 14, bd.des1);
len += 4;
}
ptr += len; ptr += len;
frame_size += len; frame_size += len;
if (bd.des0 & FTGMAC100_TXDES0_LTS) { if (bd.des0 & FTGMAC100_TXDES0_LTS) {
...@@ -758,8 +776,8 @@ static int ftgmac100_filter(FTGMAC100State *s, const uint8_t *buf, size_t len) ...@@ -758,8 +776,8 @@ static int ftgmac100_filter(FTGMAC100State *s, const uint8_t *buf, size_t len)
return 0; return 0;
} }
/* TODO: this does not seem to work for ftgmac100 */ mcast_idx = net_crc32_le(buf, ETH_ALEN);
mcast_idx = net_crc32(buf, ETH_ALEN) >> 26; mcast_idx = (~(mcast_idx >> 2)) & 0x3f;
if (!(s->math[mcast_idx / 32] & (1 << (mcast_idx % 32)))) { if (!(s->math[mcast_idx / 32] & (1 << (mcast_idx % 32)))) {
return 0; return 0;
} }
...@@ -788,7 +806,8 @@ static ssize_t ftgmac100_receive(NetClientState *nc, const uint8_t *buf, ...@@ -788,7 +806,8 @@ static ssize_t ftgmac100_receive(NetClientState *nc, const uint8_t *buf,
uint32_t buf_len; uint32_t buf_len;
size_t size = len; size_t size = len;
uint32_t first = FTGMAC100_RXDES0_FRS; uint32_t first = FTGMAC100_RXDES0_FRS;
int max_frame_size = ftgmac100_max_frame_size(s); uint16_t proto = be16_to_cpu(PKT_GET_ETH_HDR(buf)->h_proto);
int max_frame_size = ftgmac100_max_frame_size(s, proto);
if ((s->maccr & (FTGMAC100_MACCR_RXDMA_EN | FTGMAC100_MACCR_RXMAC_EN)) if ((s->maccr & (FTGMAC100_MACCR_RXDMA_EN | FTGMAC100_MACCR_RXMAC_EN))
!= (FTGMAC100_MACCR_RXDMA_EN | FTGMAC100_MACCR_RXMAC_EN)) { != (FTGMAC100_MACCR_RXDMA_EN | FTGMAC100_MACCR_RXMAC_EN)) {
...@@ -803,12 +822,6 @@ static ssize_t ftgmac100_receive(NetClientState *nc, const uint8_t *buf, ...@@ -803,12 +822,6 @@ static ssize_t ftgmac100_receive(NetClientState *nc, const uint8_t *buf,
return size; return size;
} }
if (size < 64 && !(s->maccr & FTGMAC100_MACCR_RX_RUNT)) {
qemu_log_mask(LOG_GUEST_ERROR, "%s: dropped runt frame of %zd bytes\n",
__func__, size);
return size;
}
if (!ftgmac100_filter(s, buf, size)) { if (!ftgmac100_filter(s, buf, size)) {
return size; return size;
} }
...@@ -820,9 +833,9 @@ static ssize_t ftgmac100_receive(NetClientState *nc, const uint8_t *buf, ...@@ -820,9 +833,9 @@ static ssize_t ftgmac100_receive(NetClientState *nc, const uint8_t *buf,
/* Huge frames are truncated. */ /* Huge frames are truncated. */
if (size > max_frame_size) { if (size > max_frame_size) {
size = max_frame_size;
qemu_log_mask(LOG_GUEST_ERROR, "%s: frame too big : %zd bytes\n", qemu_log_mask(LOG_GUEST_ERROR, "%s: frame too big : %zd bytes\n",
__func__, size); __func__, size);
size = max_frame_size;
flags |= FTGMAC100_RXDES0_FTL; flags |= FTGMAC100_RXDES0_FTL;
} }
...@@ -861,7 +874,20 @@ static ssize_t ftgmac100_receive(NetClientState *nc, const uint8_t *buf, ...@@ -861,7 +874,20 @@ static ssize_t ftgmac100_receive(NetClientState *nc, const uint8_t *buf,
buf_len += size - 4; buf_len += size - 4;
} }
buf_addr = bd.des3; buf_addr = bd.des3;
dma_memory_write(&address_space_memory, buf_addr, buf, buf_len); if (first && proto == ETH_P_VLAN && buf_len >= 18) {
bd.des1 = lduw_be_p(buf + 14) | FTGMAC100_RXDES1_VLANTAG_AVAIL;
if (s->maccr & FTGMAC100_MACCR_RM_VLAN) {
dma_memory_write(&address_space_memory, buf_addr, buf, 12);
dma_memory_write(&address_space_memory, buf_addr + 12, buf + 16,
buf_len - 16);
} else {
dma_memory_write(&address_space_memory, buf_addr, buf, buf_len);
}
} else {
bd.des1 = 0;
dma_memory_write(&address_space_memory, buf_addr, buf, buf_len);
}
buf += buf_len; buf += buf_len;
if (size < 4) { if (size < 4) {
dma_memory_write(&address_space_memory, buf_addr + buf_len, dma_memory_write(&address_space_memory, buf_addr + buf_len,
...@@ -940,8 +966,6 @@ static void ftgmac100_realize(DeviceState *dev, Error **errp) ...@@ -940,8 +966,6 @@ static void ftgmac100_realize(DeviceState *dev, Error **errp)
object_get_typename(OBJECT(dev)), DEVICE(dev)->id, object_get_typename(OBJECT(dev)), DEVICE(dev)->id,
s); s);
qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
s->frame = g_malloc(FTGMAC100_MAX_FRAME_SIZE);
} }
static const VMStateDescription vmstate_ftgmac100 = { static const VMStateDescription vmstate_ftgmac100 = {
......
...@@ -97,7 +97,7 @@ static uint64_t pnv_core_xscom_read(void *opaque, hwaddr addr, ...@@ -97,7 +97,7 @@ static uint64_t pnv_core_xscom_read(void *opaque, hwaddr addr,
val = 0x24f000000000000ull; val = 0x24f000000000000ull;
break; break;
default: default:
qemu_log_mask(LOG_UNIMP, "Warning: reading reg=0x%" HWADDR_PRIx, qemu_log_mask(LOG_UNIMP, "Warning: reading reg=0x%" HWADDR_PRIx "\n",
addr); addr);
} }
...@@ -107,7 +107,7 @@ static uint64_t pnv_core_xscom_read(void *opaque, hwaddr addr, ...@@ -107,7 +107,7 @@ static uint64_t pnv_core_xscom_read(void *opaque, hwaddr addr,
static void pnv_core_xscom_write(void *opaque, hwaddr addr, uint64_t val, static void pnv_core_xscom_write(void *opaque, hwaddr addr, uint64_t val,
unsigned int width) unsigned int width)
{ {
qemu_log_mask(LOG_UNIMP, "Warning: writing to reg=0x%" HWADDR_PRIx, qemu_log_mask(LOG_UNIMP, "Warning: writing to reg=0x%" HWADDR_PRIx "\n",
addr); addr);
} }
......
...@@ -140,7 +140,7 @@ static uint64_t memcard_read(void *opaque, hwaddr addr, ...@@ -140,7 +140,7 @@ static uint64_t memcard_read(void *opaque, hwaddr addr,
r = s->response[s->response_read_ptr++]; r = s->response[s->response_read_ptr++];
if (s->response_read_ptr > s->response_len) { if (s->response_read_ptr > s->response_len) {
qemu_log_mask(LOG_GUEST_ERROR, "milkymist_memcard: " qemu_log_mask(LOG_GUEST_ERROR, "milkymist_memcard: "
"read more cmd bytes than available. Clipping."); "read more cmd bytes than available: clipping\n");
s->response_read_ptr = 0; s->response_read_ptr = 0;
} }
} }
......
/* /*
* SD Memory Card emulation as defined in the "SD Memory Card Physical * SD Memory Card emulation as defined in the "SD Memory Card Physical
* layer specification, Version 1.10." * layer specification, Version 2.00."
* *
* Copyright (c) 2006 Andrzej Zaborowski <balrog@zabor.org> * Copyright (c) 2006 Andrzej Zaborowski <balrog@zabor.org>
* Copyright (c) 2007 CodeSourcery * Copyright (c) 2007 CodeSourcery
* Copyright (c) 2018 Philippe Mathieu-Daudé <f4bug@amsat.org>
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
...@@ -91,6 +92,7 @@ struct SDState { ...@@ -91,6 +92,7 @@ struct SDState {
uint8_t sd_status[64]; uint8_t sd_status[64];
/* Configurable properties */ /* Configurable properties */
uint8_t spec_version;
BlockBackend *blk; BlockBackend *blk;
bool spi; bool spi;
...@@ -310,11 +312,18 @@ static void sd_ocr_powerup(void *opaque) ...@@ -310,11 +312,18 @@ static void sd_ocr_powerup(void *opaque)
static void sd_set_scr(SDState *sd) static void sd_set_scr(SDState *sd)
{ {
sd->scr[0] = (0 << 4) /* SCR version 1.0 */ sd->scr[0] = 0 << 4; /* SCR structure version 1.0 */
| 0; /* Spec Versions 1.0 and 1.01 */ if (sd->spec_version == SD_PHY_SPECv1_10_VERS) {
sd->scr[0] |= 1; /* Spec Version 1.10 */
} else {
sd->scr[0] |= 2; /* Spec Version 2.00 or Version 3.0X */
}
sd->scr[1] = (2 << 4) /* SDSC Card (Security Version 1.01) */ sd->scr[1] = (2 << 4) /* SDSC Card (Security Version 1.01) */
| 0b0101; /* 1-bit or 4-bit width bus modes */ | 0b0101; /* 1-bit or 4-bit width bus modes */
sd->scr[2] = 0x00; /* Extended Security is not supported. */ sd->scr[2] = 0x00; /* Extended Security is not supported. */
if (sd->spec_version >= SD_PHY_SPECv3_01_VERS) {
sd->scr[2] |= 1 << 7; /* Spec Version 3.0X */
}
sd->scr[3] = 0x00; sd->scr[3] = 0x00;
/* reserved for manufacturer usage */ /* reserved for manufacturer usage */
sd->scr[4] = 0x00; sd->scr[4] = 0x00;
...@@ -960,8 +969,6 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req) ...@@ -960,8 +969,6 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req)
return sd_illegal; return sd_illegal;
case 6: /* CMD6: SWITCH_FUNCTION */ case 6: /* CMD6: SWITCH_FUNCTION */
if (sd->spi)
goto bad_cmd;
switch (sd->mode) { switch (sd->mode) {
case sd_data_transfer_mode: case sd_data_transfer_mode:
sd_function_switch(sd, req.arg); sd_function_switch(sd, req.arg);
...@@ -1014,7 +1021,9 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req) ...@@ -1014,7 +1021,9 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req)
break; break;
case 8: /* CMD8: SEND_IF_COND */ case 8: /* CMD8: SEND_IF_COND */
/* Physical Layer Specification Version 2.00 command */ if (sd->spec_version < SD_PHY_SPECv2_00_VERS) {
break;
}
if (sd->state != sd_idle_state) { if (sd->state != sd_idle_state) {
break; break;
} }
...@@ -1170,6 +1179,9 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req) ...@@ -1170,6 +1179,9 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req)
break; break;
case 19: /* CMD19: SEND_TUNING_BLOCK (SD) */ case 19: /* CMD19: SEND_TUNING_BLOCK (SD) */
if (sd->spec_version < SD_PHY_SPECv3_01_VERS) {
break;
}
if (sd->state == sd_transfer_state) { if (sd->state == sd_transfer_state) {
sd->state = sd_sendingdata_state; sd->state = sd_sendingdata_state;
sd->data_offset = 0; sd->data_offset = 0;
...@@ -1178,6 +1190,9 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req) ...@@ -1178,6 +1190,9 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req)
break; break;
case 23: /* CMD23: SET_BLOCK_COUNT */ case 23: /* CMD23: SET_BLOCK_COUNT */
if (sd->spec_version < SD_PHY_SPECv3_01_VERS) {
break;
}
switch (sd->state) { switch (sd->state) {
case sd_transfer_state: case sd_transfer_state:
sd->multi_blk_cnt = req.arg; sd->multi_blk_cnt = req.arg;
...@@ -1190,9 +1205,6 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req) ...@@ -1190,9 +1205,6 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req)
/* Block write commands (Class 4) */ /* Block write commands (Class 4) */
case 24: /* CMD24: WRITE_SINGLE_BLOCK */ case 24: /* CMD24: WRITE_SINGLE_BLOCK */
if (sd->spi) {
goto unimplemented_spi_cmd;
}
switch (sd->state) { switch (sd->state) {
case sd_transfer_state: case sd_transfer_state:
/* Writing in SPI mode not implemented. */ /* Writing in SPI mode not implemented. */
...@@ -1217,9 +1229,6 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req) ...@@ -1217,9 +1229,6 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req)
break; break;
case 25: /* CMD25: WRITE_MULTIPLE_BLOCK */ case 25: /* CMD25: WRITE_MULTIPLE_BLOCK */
if (sd->spi) {
goto unimplemented_spi_cmd;
}
switch (sd->state) { switch (sd->state) {
case sd_transfer_state: case sd_transfer_state:
/* Writing in SPI mode not implemented. */ /* Writing in SPI mode not implemented. */
...@@ -1259,9 +1268,6 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req) ...@@ -1259,9 +1268,6 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req)
break; break;
case 27: /* CMD27: PROGRAM_CSD */ case 27: /* CMD27: PROGRAM_CSD */
if (sd->spi) {
goto unimplemented_spi_cmd;
}
switch (sd->state) { switch (sd->state) {
case sd_transfer_state: case sd_transfer_state:
sd->state = sd_receivingdata_state; sd->state = sd_receivingdata_state;
...@@ -1371,9 +1377,6 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req) ...@@ -1371,9 +1377,6 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req)
/* Lock card commands (Class 7) */ /* Lock card commands (Class 7) */
case 42: /* CMD42: LOCK_UNLOCK */ case 42: /* CMD42: LOCK_UNLOCK */
if (sd->spi) {
goto unimplemented_spi_cmd;
}
switch (sd->state) { switch (sd->state) {
case sd_transfer_state: case sd_transfer_state:
sd->state = sd_receivingdata_state; sd->state = sd_receivingdata_state;
...@@ -2072,6 +2075,15 @@ static void sd_realize(DeviceState *dev, Error **errp) ...@@ -2072,6 +2075,15 @@ static void sd_realize(DeviceState *dev, Error **errp)
sd->proto_name = sd->spi ? "SPI" : "SD"; sd->proto_name = sd->spi ? "SPI" : "SD";
switch (sd->spec_version) {
case SD_PHY_SPECv1_10_VERS
... SD_PHY_SPECv3_01_VERS:
break;
default:
error_setg(errp, "Invalid SD card Spec version: %u", sd->spec_version);
return;
}
if (sd->blk && blk_is_read_only(sd->blk)) { if (sd->blk && blk_is_read_only(sd->blk)) {
error_setg(errp, "Cannot use read-only drive as SD card"); error_setg(errp, "Cannot use read-only drive as SD card");
return; return;
...@@ -2088,6 +2100,8 @@ static void sd_realize(DeviceState *dev, Error **errp) ...@@ -2088,6 +2100,8 @@ static void sd_realize(DeviceState *dev, Error **errp)
} }
static Property sd_properties[] = { static Property sd_properties[] = {
DEFINE_PROP_UINT8("spec_version", SDState,
spec_version, SD_PHY_SPECv2_00_VERS),
DEFINE_PROP_DRIVE("drive", SDState, blk), DEFINE_PROP_DRIVE("drive", SDState, blk),
/* We do not model the chip select pin, so allow the board to select /* We do not model the chip select pin, so allow the board to select
* whether card should be in SSI or MMC/SD mode. It is also up to the * whether card should be in SSI or MMC/SD mode. It is also up to the
......
...@@ -73,7 +73,7 @@ static uint64_t digic_timer_read(void *opaque, hwaddr offset, unsigned size) ...@@ -73,7 +73,7 @@ static uint64_t digic_timer_read(void *opaque, hwaddr offset, unsigned size)
default: default:
qemu_log_mask(LOG_UNIMP, qemu_log_mask(LOG_UNIMP,
"digic-timer: read access to unknown register 0x" "digic-timer: read access to unknown register 0x"
TARGET_FMT_plx, offset); TARGET_FMT_plx "\n", offset);
} }
return ret; return ret;
...@@ -109,7 +109,7 @@ static void digic_timer_write(void *opaque, hwaddr offset, ...@@ -109,7 +109,7 @@ static void digic_timer_write(void *opaque, hwaddr offset,
default: default:
qemu_log_mask(LOG_UNIMP, qemu_log_mask(LOG_UNIMP,
"digic-timer: read access to unknown register 0x" "digic-timer: read access to unknown register 0x"
TARGET_FMT_plx, offset); TARGET_FMT_plx "\n", offset);
} }
} }
......
...@@ -76,6 +76,7 @@ int smbus_read_block(I2CBus *bus, uint8_t addr, uint8_t command, uint8_t *data); ...@@ -76,6 +76,7 @@ int smbus_read_block(I2CBus *bus, uint8_t addr, uint8_t command, uint8_t *data);
int smbus_write_block(I2CBus *bus, uint8_t addr, uint8_t command, uint8_t *data, int smbus_write_block(I2CBus *bus, uint8_t addr, uint8_t command, uint8_t *data,
int len); int len);
void smbus_eeprom_init_one(I2CBus *smbus, uint8_t address, uint8_t *eeprom_buf);
void smbus_eeprom_init(I2CBus *smbus, int nb_eeprom, void smbus_eeprom_init(I2CBus *smbus, int nb_eeprom,
const uint8_t *eeprom_spd, int size); const uint8_t *eeprom_spd, int size);
......
...@@ -217,6 +217,7 @@ struct GICv3State { ...@@ -217,6 +217,7 @@ struct GICv3State {
uint32_t revision; uint32_t revision;
bool security_extn; bool security_extn;
bool irq_reset_nonsecure; bool irq_reset_nonsecure;
bool gicd_no_migration_shift_bug;
int dev_fd; /* kvm device fd if backed by kvm vgic support */ int dev_fd; /* kvm device fd if backed by kvm vgic support */
Error *migration_blocker; Error *migration_blocker;
......
/*
* PCA9552 I2C LED blinker
*
* Copyright (c) 2017-2018, IBM Corporation.
*
* This work is licensed under the terms of the GNU GPL, version 2 or
* later. See the COPYING file in the top-level directory.
*/
#ifndef PCA9552_H
#define PCA9552_H
#include "hw/i2c/i2c.h"
#define TYPE_PCA9552 "pca9552"
#define PCA9552(obj) OBJECT_CHECK(PCA9552State, (obj), TYPE_PCA9552)
#define PCA9552_NR_REGS 10
typedef struct PCA9552State {
/*< private >*/
I2CSlave i2c;
/*< public >*/
uint8_t len;
uint8_t pointer;
uint8_t regs[PCA9552_NR_REGS];
uint8_t max_reg;
uint8_t nr_leds;
} PCA9552State;
#endif
/*
* PCA9552 I2C LED blinker registers
*
* Copyright (c) 2017-2018, IBM Corporation.
*
* This work is licensed under the terms of the GNU GPL, version 2 or
* later. See the COPYING file in the top-level directory.
*/
#ifndef PCA9552_REGS_H
#define PCA9552_REGS_H
/*
* Bits [0:3] are used to address a specific register.
*/
#define PCA9552_INPUT0 0 /* read only input register 0 */
#define PCA9552_INPUT1 1 /* read only input register 1 */
#define PCA9552_PSC0 2 /* read/write frequency prescaler 0 */
#define PCA9552_PWM0 3 /* read/write PWM register 0 */
#define PCA9552_PSC1 4 /* read/write frequency prescaler 1 */
#define PCA9552_PWM1 5 /* read/write PWM register 1 */
#define PCA9552_LS0 6 /* read/write LED0 to LED3 selector */
#define PCA9552_LS1 7 /* read/write LED4 to LED7 selector */
#define PCA9552_LS2 8 /* read/write LED8 to LED11 selector */
#define PCA9552_LS3 9 /* read/write LED12 to LED15 selector */
/*
* Bit [4] is used to activate the Auto-Increment option of the
* register address
*/
#define PCA9552_AUTOINC (1 << 4)
#endif
...@@ -16,6 +16,11 @@ ...@@ -16,6 +16,11 @@
#include "hw/sysbus.h" #include "hw/sysbus.h"
#include "net/net.h" #include "net/net.h"
/*
* Max frame size for the receiving buffer
*/
#define FTGMAC100_MAX_FRAME_SIZE 9220
typedef struct FTGMAC100State { typedef struct FTGMAC100State {
/*< private >*/ /*< private >*/
SysBusDevice parent_obj; SysBusDevice parent_obj;
...@@ -26,7 +31,7 @@ typedef struct FTGMAC100State { ...@@ -26,7 +31,7 @@ typedef struct FTGMAC100State {
qemu_irq irq; qemu_irq irq;
MemoryRegion iomem; MemoryRegion iomem;
uint8_t *frame; uint8_t frame[FTGMAC100_MAX_FRAME_SIZE];
uint32_t irq_state; uint32_t irq_state;
uint32_t isr; uint32_t isr;
......
...@@ -54,6 +54,12 @@ ...@@ -54,6 +54,12 @@
#define APP_CMD (1 << 5) #define APP_CMD (1 << 5)
#define AKE_SEQ_ERROR (1 << 3) #define AKE_SEQ_ERROR (1 << 3)
enum SDPhySpecificationVersion {
SD_PHY_SPECv1_10_VERS = 1,
SD_PHY_SPECv2_00_VERS = 2,
SD_PHY_SPECv3_01_VERS = 3,
};
typedef enum { typedef enum {
SD_VOLTAGE_0_4V = 400, /* currently not supported */ SD_VOLTAGE_0_4V = 400, /* currently not supported */
SD_VOLTAGE_1_8V = 1800, SD_VOLTAGE_1_8V = 1800,
......
...@@ -2965,11 +2965,6 @@ support page sizes < 4096 any longer. ...@@ -2965,11 +2965,6 @@ support page sizes < 4096 any longer.
@section System emulator machines @section System emulator machines
@subsection Xilinx EP108 (since 2.11.0)
The ``xlnx-ep108'' machine has been replaced by the ``xlnx-zcu102'' machine.
The ``xlnx-zcu102'' machine has the same features and capabilites in QEMU.
@section Block device options @section Block device options
@subsection "backing": "" (since 2.12.0) @subsection "backing": "" (since 2.12.0)
......
...@@ -4570,7 +4570,7 @@ void hw_breakpoint_update(ARMCPU *cpu, int n) ...@@ -4570,7 +4570,7 @@ void hw_breakpoint_update(ARMCPU *cpu, int n)
case 4: /* unlinked address mismatch (reserved if AArch64) */ case 4: /* unlinked address mismatch (reserved if AArch64) */
case 5: /* linked address mismatch (reserved if AArch64) */ case 5: /* linked address mismatch (reserved if AArch64) */
qemu_log_mask(LOG_UNIMP, qemu_log_mask(LOG_UNIMP,
"arm: address mismatch breakpoint types not implemented"); "arm: address mismatch breakpoint types not implemented\n");
return; return;
case 0: /* unlinked address match */ case 0: /* unlinked address match */
case 1: /* linked address match */ case 1: /* linked address match */
...@@ -4604,7 +4604,7 @@ void hw_breakpoint_update(ARMCPU *cpu, int n) ...@@ -4604,7 +4604,7 @@ void hw_breakpoint_update(ARMCPU *cpu, int n)
case 8: /* unlinked VMID match (reserved if no EL2) */ case 8: /* unlinked VMID match (reserved if no EL2) */
case 10: /* unlinked context ID and VMID match (reserved if no EL2) */ case 10: /* unlinked context ID and VMID match (reserved if no EL2) */
qemu_log_mask(LOG_UNIMP, qemu_log_mask(LOG_UNIMP,
"arm: unlinked context breakpoint types not implemented"); "arm: unlinked context breakpoint types not implemented\n");
return; return;
case 9: /* linked VMID match (reserved if no EL2) */ case 9: /* linked VMID match (reserved if no EL2) */
case 11: /* linked context ID and VMID match (reserved if no EL2) */ case 11: /* linked context ID and VMID match (reserved if no EL2) */
......
...@@ -1556,7 +1556,7 @@ DISAS_INSN(undef) ...@@ -1556,7 +1556,7 @@ DISAS_INSN(undef)
/* ??? This is both instructions that are as yet unimplemented /* ??? This is both instructions that are as yet unimplemented
for the 680x0 series, as well as those that are implemented for the 680x0 series, as well as those that are implemented
but actually illegal for CPU32 or pre-68020. */ but actually illegal for CPU32 or pre-68020. */
qemu_log_mask(LOG_UNIMP, "Illegal instruction: %04x @ %08x", qemu_log_mask(LOG_UNIMP, "Illegal instruction: %04x @ %08x\n",
insn, s->insn_pc); insn, s->insn_pc);
gen_exception(s, s->insn_pc, EXCP_UNSUPPORTED); gen_exception(s, s->insn_pc, EXCP_UNSUPPORTED);
} }
......
...@@ -293,7 +293,8 @@ void csr_write_helper(CPURISCVState *env, target_ulong val_to_write, ...@@ -293,7 +293,8 @@ void csr_write_helper(CPURISCVState *env, target_ulong val_to_write,
if ((val_to_write & 3) == 0) { if ((val_to_write & 3) == 0) {
env->stvec = val_to_write >> 2 << 2; env->stvec = val_to_write >> 2 << 2;
} else { } else {
qemu_log_mask(LOG_UNIMP, "CSR_STVEC: vectored traps not supported"); qemu_log_mask(LOG_UNIMP,
"CSR_STVEC: vectored traps not supported\n");
} }
break; break;
case CSR_SCOUNTEREN: case CSR_SCOUNTEREN:
...@@ -320,7 +321,8 @@ void csr_write_helper(CPURISCVState *env, target_ulong val_to_write, ...@@ -320,7 +321,8 @@ void csr_write_helper(CPURISCVState *env, target_ulong val_to_write,
if ((val_to_write & 3) == 0) { if ((val_to_write & 3) == 0) {
env->mtvec = val_to_write >> 2 << 2; env->mtvec = val_to_write >> 2 << 2;
} else { } else {
qemu_log_mask(LOG_UNIMP, "CSR_MTVEC: vectored traps not supported"); qemu_log_mask(LOG_UNIMP,
"CSR_MTVEC: vectored traps not supported\n");
} }
break; break;
case CSR_MCOUNTEREN: case CSR_MCOUNTEREN:
......
...@@ -2234,7 +2234,7 @@ static void translate_rur(DisasContext *dc, const uint32_t arg[], ...@@ -2234,7 +2234,7 @@ static void translate_rur(DisasContext *dc, const uint32_t arg[],
if (uregnames[par[0]].name) { if (uregnames[par[0]].name) {
tcg_gen_mov_i32(cpu_R[arg[0]], cpu_UR[par[0]]); tcg_gen_mov_i32(cpu_R[arg[0]], cpu_UR[par[0]]);
} else { } else {
qemu_log_mask(LOG_UNIMP, "RUR %d not implemented, ", par[0]); qemu_log_mask(LOG_UNIMP, "RUR %d not implemented\n", par[0]);
} }
} }
} }
...@@ -2375,7 +2375,7 @@ static void translate_slli(DisasContext *dc, const uint32_t arg[], ...@@ -2375,7 +2375,7 @@ static void translate_slli(DisasContext *dc, const uint32_t arg[],
{ {
if (gen_window_check2(dc, arg[0], arg[1])) { if (gen_window_check2(dc, arg[0], arg[1])) {
if (arg[2] == 32) { if (arg[2] == 32) {
qemu_log_mask(LOG_GUEST_ERROR, "slli a%d, a%d, 32 is undefined", qemu_log_mask(LOG_GUEST_ERROR, "slli a%d, a%d, 32 is undefined\n",
arg[0], arg[1]); arg[0], arg[1]);
} }
tcg_gen_shli_i32(cpu_R[arg[0]], cpu_R[arg[1]], arg[2] & 0x1f); tcg_gen_shli_i32(cpu_R[arg[0]], cpu_R[arg[1]], arg[2] & 0x1f);
...@@ -2571,7 +2571,7 @@ static void translate_wur(DisasContext *dc, const uint32_t arg[], ...@@ -2571,7 +2571,7 @@ static void translate_wur(DisasContext *dc, const uint32_t arg[],
if (uregnames[par[0]].name) { if (uregnames[par[0]].name) {
gen_wur(par[0], cpu_R[arg[0]]); gen_wur(par[0], cpu_R[arg[0]]);
} else { } else {
qemu_log_mask(LOG_UNIMP, "WUR %d not implemented, ", par[0]); qemu_log_mask(LOG_UNIMP, "WUR %d not implemented\n", par[0]);
} }
} }
} }
......
...@@ -373,6 +373,7 @@ check-qtest-sparc64-y += tests/prom-env-test$(EXESUF) ...@@ -373,6 +373,7 @@ check-qtest-sparc64-y += tests/prom-env-test$(EXESUF)
check-qtest-sparc64-y += tests/boot-serial-test$(EXESUF) check-qtest-sparc64-y += tests/boot-serial-test$(EXESUF)
check-qtest-arm-y = tests/tmp105-test$(EXESUF) check-qtest-arm-y = tests/tmp105-test$(EXESUF)
check-qtest-arm-y += tests/pca9552-test$(EXESUF)
check-qtest-arm-y += tests/ds1338-test$(EXESUF) check-qtest-arm-y += tests/ds1338-test$(EXESUF)
check-qtest-arm-y += tests/m25p80-test$(EXESUF) check-qtest-arm-y += tests/m25p80-test$(EXESUF)
gcov-files-arm-y += hw/misc/tmp105.c gcov-files-arm-y += hw/misc/tmp105.c
...@@ -778,6 +779,7 @@ tests/bios-tables-test$(EXESUF): tests/bios-tables-test.o \ ...@@ -778,6 +779,7 @@ tests/bios-tables-test$(EXESUF): tests/bios-tables-test.o \
tests/boot-sector.o tests/acpi-utils.o $(libqos-obj-y) tests/boot-sector.o tests/acpi-utils.o $(libqos-obj-y)
tests/pxe-test$(EXESUF): tests/pxe-test.o tests/boot-sector.o $(libqos-obj-y) tests/pxe-test$(EXESUF): tests/pxe-test.o tests/boot-sector.o $(libqos-obj-y)
tests/tmp105-test$(EXESUF): tests/tmp105-test.o $(libqos-omap-obj-y) tests/tmp105-test$(EXESUF): tests/tmp105-test.o $(libqos-omap-obj-y)
tests/pca9552-test$(EXESUF): tests/pca9552-test.o $(libqos-omap-obj-y)
tests/ds1338-test$(EXESUF): tests/ds1338-test.o $(libqos-imx-obj-y) tests/ds1338-test$(EXESUF): tests/ds1338-test.o $(libqos-imx-obj-y)
tests/m25p80-test$(EXESUF): tests/m25p80-test.o tests/m25p80-test$(EXESUF): tests/m25p80-test.o
tests/i440fx-test$(EXESUF): tests/i440fx-test.o $(libqos-pc-obj-y) tests/i440fx-test$(EXESUF): tests/i440fx-test.o $(libqos-pc-obj-y)
......
...@@ -21,6 +21,8 @@ struct I2CAdapter { ...@@ -21,6 +21,8 @@ struct I2CAdapter {
QTestState *qts; QTestState *qts;
}; };
#define OMAP2_I2C_1_BASE 0x48070000
void i2c_send(I2CAdapter *i2c, uint8_t addr, void i2c_send(I2CAdapter *i2c, uint8_t addr,
const uint8_t *buf, uint16_t len); const uint8_t *buf, uint16_t len);
void i2c_recv(I2CAdapter *i2c, uint8_t addr, void i2c_recv(I2CAdapter *i2c, uint8_t addr,
......
/*
* QTest testcase for the PCA9552 LED blinker
*
* Copyright (c) 2017-2018, IBM Corporation.
*
* This work is licensed under the terms of the GNU GPL, version 2 or later.
* See the COPYING file in the top-level directory.
*/
#include "qemu/osdep.h"
#include "libqtest.h"
#include "libqos/i2c.h"
#include "hw/misc/pca9552_regs.h"
#define PCA9552_TEST_ID "pca9552-test"
#define PCA9552_TEST_ADDR 0x60
static I2CAdapter *i2c;
static uint8_t pca9552_get8(I2CAdapter *i2c, uint8_t addr, uint8_t reg)
{
uint8_t resp[1];
i2c_send(i2c, addr, &reg, 1);
i2c_recv(i2c, addr, resp, 1);
return resp[0];
}
static void pca9552_set8(I2CAdapter *i2c, uint8_t addr, uint8_t reg,
uint8_t value)
{
uint8_t cmd[2];
uint8_t resp[1];
cmd[0] = reg;
cmd[1] = value;
i2c_send(i2c, addr, cmd, 2);
i2c_recv(i2c, addr, resp, 1);
g_assert_cmphex(resp[0], ==, cmd[1]);
}
static void receive_autoinc(void)
{
uint8_t resp;
uint8_t reg = PCA9552_LS0 | PCA9552_AUTOINC;
i2c_send(i2c, PCA9552_TEST_ADDR, &reg, 1);
/* PCA9552_LS0 */
i2c_recv(i2c, PCA9552_TEST_ADDR, &resp, 1);
g_assert_cmphex(resp, ==, 0x54);
/* PCA9552_LS1 */
i2c_recv(i2c, PCA9552_TEST_ADDR, &resp, 1);
g_assert_cmphex(resp, ==, 0x55);
/* PCA9552_LS2 */
i2c_recv(i2c, PCA9552_TEST_ADDR, &resp, 1);
g_assert_cmphex(resp, ==, 0x55);
/* PCA9552_LS3 */
i2c_recv(i2c, PCA9552_TEST_ADDR, &resp, 1);
g_assert_cmphex(resp, ==, 0x54);
}
static void send_and_receive(void)
{
uint8_t value;
value = pca9552_get8(i2c, PCA9552_TEST_ADDR, PCA9552_LS0);
g_assert_cmphex(value, ==, 0x55);
value = pca9552_get8(i2c, PCA9552_TEST_ADDR, PCA9552_INPUT0);
g_assert_cmphex(value, ==, 0x0);
/* Switch on LED 0 */
pca9552_set8(i2c, PCA9552_TEST_ADDR, PCA9552_LS0, 0x54);
value = pca9552_get8(i2c, PCA9552_TEST_ADDR, PCA9552_LS0);
g_assert_cmphex(value, ==, 0x54);
value = pca9552_get8(i2c, PCA9552_TEST_ADDR, PCA9552_INPUT0);
g_assert_cmphex(value, ==, 0x01);
/* Switch on LED 12 */
pca9552_set8(i2c, PCA9552_TEST_ADDR, PCA9552_LS3, 0x54);
value = pca9552_get8(i2c, PCA9552_TEST_ADDR, PCA9552_LS3);
g_assert_cmphex(value, ==, 0x54);
value = pca9552_get8(i2c, PCA9552_TEST_ADDR, PCA9552_INPUT1);
g_assert_cmphex(value, ==, 0x10);
}
int main(int argc, char **argv)
{
QTestState *s = NULL;
int ret;
g_test_init(&argc, &argv, NULL);
s = qtest_start("-machine n800 "
"-device pca9552,bus=i2c-bus.0,id=" PCA9552_TEST_ID
",address=0x60");
i2c = omap_i2c_create(s, OMAP2_I2C_1_BASE);
qtest_add_func("/pca9552/tx-rx", send_and_receive);
qtest_add_func("/pca9552/rx-autoinc", receive_autoinc);
ret = g_test_run();
if (s) {
qtest_quit(s);
}
g_free(i2c);
return ret;
}
...@@ -14,8 +14,6 @@ ...@@ -14,8 +14,6 @@
#include "qapi/qmp/qdict.h" #include "qapi/qmp/qdict.h"
#include "hw/misc/tmp105_regs.h" #include "hw/misc/tmp105_regs.h"
#define OMAP2_I2C_1_BASE 0x48070000
#define TMP105_TEST_ID "tmp105-test" #define TMP105_TEST_ID "tmp105-test"
#define TMP105_TEST_ADDR 0x49 #define TMP105_TEST_ADDR 0x49
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册