aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2018-03-01 15:37:31 +0000
committerPeter Maydell <peter.maydell@linaro.org>2018-03-01 15:37:31 +0000
commit9db0855e8501365334e859370800c240d25322a2 (patch)
treebd4a8f0576258a43bf446035c26f9e5c1b1d2c40 /hw
parent8cb340c613ee3e626b070e0429c589f8a60ac657 (diff)
parentc22e580c2ad1cccef582e1490e732f254d4ac064 (diff)
Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20180301' into staging
target-arm queue: * update MAINTAINERS for Alistair's new email address * add Arm v8.2 FP16 arithmetic extension for linux-user * implement display connector emulation for vexpress board * xilinx_spips: Enable only two slaves when reading/writing with stripe * xilinx_spips: Use 8 dummy cycles with the QIOR/QIOR4 commands * hw: register: Run post_write hook on reset # gpg: Signature made Thu 01 Mar 2018 11:22:46 GMT # 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-20180301: (42 commits) MAINTAINERS: Update my email address linux-user: Report AArch64 FP16 support via hwcap bits target/arm: Enable ARM_V8_FP16 feature bit for the AArch64 "any" CPU arm/translate-a64: add all single op FP16 to handle_fp_1src_half arm/translate-a64: implement simd_scalar_three_reg_same_fp16 arm/translate-a64: add all FP16 ops in simd_scalar_pairwise arm/translate-a64: add FP16 FMOV to simd_mod_imm arm/translate-a64: add FP16 FRSQRTE to simd_two_reg_misc_fp16 arm/helper.c: re-factor rsqrte and add rsqrte_f16 arm/translate-a64: add FP16 FSQRT to simd_two_reg_misc_fp16 arm/translate-a64: add FP16 FRCPX to simd_two_reg_misc_fp16 arm/translate-a64: add FP16 FRECPE arm/helper.c: re-factor recpe and add recepe_f16 arm/translate-a64: add FP16 FNEG/FABS to simd_two_reg_misc_fp16 arm/translate-a64: add FP16 SCVTF/UCVFT to simd_two_reg_misc_fp16 arm/translate-a64: add FP16 FCMxx (zero) to simd_two_reg_misc_fp16 arm/translate-a64: add FCVTxx to simd_two_reg_misc_fp16 arm/translate-a64: add FP16 FPRINTx to simd_two_reg_misc_fp16 arm/translate-a64: initial decode for simd_two_reg_misc_fp16 arm/translate-a64: add FP16 x2 ops for simd_indexed ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw')
-rw-r--r--hw/arm/vexpress.c6
-rw-r--r--hw/core/register.c8
-rw-r--r--hw/display/Makefile.objs1
-rw-r--r--hw/display/sii9022.c191
-rw-r--r--hw/display/trace-events5
-rw-r--r--hw/i2c/core.c18
-rw-r--r--hw/i2c/i2c-ddc.c4
-rw-r--r--hw/ssi/xilinx_spips.c43
8 files changed, 250 insertions, 26 deletions
diff --git a/hw/arm/vexpress.c b/hw/arm/vexpress.c
index dc5928ae1a..9fad79177a 100644
--- a/hw/arm/vexpress.c
+++ b/hw/arm/vexpress.c
@@ -29,6 +29,7 @@
#include "hw/arm/arm.h"
#include "hw/arm/primecell.h"
#include "hw/devices.h"
+#include "hw/i2c/i2c.h"
#include "net/net.h"
#include "sysemu/sysemu.h"
#include "hw/boards.h"
@@ -537,6 +538,7 @@ static void vexpress_common_init(MachineState *machine)
uint32_t sys_id;
DriveInfo *dinfo;
pflash_t *pflash0;
+ I2CBus *i2c;
ram_addr_t vram_size, sram_size;
MemoryRegion *sysmem = get_system_memory();
MemoryRegion *vram = g_new(MemoryRegion, 1);
@@ -628,7 +630,9 @@ static void vexpress_common_init(MachineState *machine)
sysbus_create_simple("sp804", map[VE_TIMER01], pic[2]);
sysbus_create_simple("sp804", map[VE_TIMER23], pic[3]);
- /* VE_SERIALDVI: not modelled */
+ dev = sysbus_create_simple("versatile_i2c", map[VE_SERIALDVI], NULL);
+ i2c = (I2CBus *)qdev_get_child_bus(dev, "i2c");
+ i2c_create_slave(i2c, "sii9022", 0x39);
sysbus_create_simple("pl031", map[VE_RTC], pic[4]); /* RTC */
diff --git a/hw/core/register.c b/hw/core/register.c
index 900294b9c4..0741a1af32 100644
--- a/hw/core/register.c
+++ b/hw/core/register.c
@@ -159,13 +159,21 @@ uint64_t register_read(RegisterInfo *reg, uint64_t re, const char* prefix,
void register_reset(RegisterInfo *reg)
{
+ const RegisterAccessInfo *ac;
+
g_assert(reg);
if (!reg->data || !reg->access) {
return;
}
+ ac = reg->access;
+
register_write_val(reg, reg->access->reset);
+
+ if (ac->post_write) {
+ ac->post_write(reg, reg->access->reset);
+ }
}
void register_init(RegisterInfo *reg)
diff --git a/hw/display/Makefile.objs b/hw/display/Makefile.objs
index d3a4cb396e..3c7c75b94d 100644
--- a/hw/display/Makefile.objs
+++ b/hw/display/Makefile.objs
@@ -3,6 +3,7 @@ common-obj-$(CONFIG_VGA_CIRRUS) += cirrus_vga.o
common-obj-$(CONFIG_G364FB) += g364fb.o
common-obj-$(CONFIG_JAZZ_LED) += jazz_led.o
common-obj-$(CONFIG_PL110) += pl110.o
+common-obj-$(CONFIG_SII9022) += sii9022.o
common-obj-$(CONFIG_SSD0303) += ssd0303.o
common-obj-$(CONFIG_SSD0323) += ssd0323.o
common-obj-$(CONFIG_XEN) += xenfb.o
diff --git a/hw/display/sii9022.c b/hw/display/sii9022.c
new file mode 100644
index 0000000000..eaf11a6e7b
--- /dev/null
+++ b/hw/display/sii9022.c
@@ -0,0 +1,191 @@
+/*
+ * Silicon Image SiI9022
+ *
+ * This is a pretty hollow emulation: all we do is acknowledge that we
+ * exist (chip ID) and confirm that we get switched over into DDC mode
+ * so the emulated host can proceed to read out EDID data. All subsequent
+ * set-up of connectors etc will be acknowledged and ignored.
+ *
+ * Copyright (C) 2018 Linus Walleij
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "qemu-common.h"
+#include "hw/i2c/i2c.h"
+#include "hw/i2c/i2c-ddc.h"
+#include "trace.h"
+
+#define SII9022_SYS_CTRL_DATA 0x1a
+#define SII9022_SYS_CTRL_PWR_DWN 0x10
+#define SII9022_SYS_CTRL_AV_MUTE 0x08
+#define SII9022_SYS_CTRL_DDC_BUS_REQ 0x04
+#define SII9022_SYS_CTRL_DDC_BUS_GRTD 0x02
+#define SII9022_SYS_CTRL_OUTPUT_MODE 0x01
+#define SII9022_SYS_CTRL_OUTPUT_HDMI 1
+#define SII9022_SYS_CTRL_OUTPUT_DVI 0
+#define SII9022_REG_CHIPID 0x1b
+#define SII9022_INT_ENABLE 0x3c
+#define SII9022_INT_STATUS 0x3d
+#define SII9022_INT_STATUS_HOTPLUG 0x01;
+#define SII9022_INT_STATUS_PLUGGED 0x04;
+
+#define TYPE_SII9022 "sii9022"
+#define SII9022(obj) OBJECT_CHECK(sii9022_state, (obj), TYPE_SII9022)
+
+typedef struct sii9022_state {
+ I2CSlave parent_obj;
+ uint8_t ptr;
+ bool addr_byte;
+ bool ddc_req;
+ bool ddc_skip_finish;
+ bool ddc;
+} sii9022_state;
+
+static const VMStateDescription vmstate_sii9022 = {
+ .name = "sii9022",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_I2C_SLAVE(parent_obj, sii9022_state),
+ VMSTATE_UINT8(ptr, sii9022_state),
+ VMSTATE_BOOL(addr_byte, sii9022_state),
+ VMSTATE_BOOL(ddc_req, sii9022_state),
+ VMSTATE_BOOL(ddc_skip_finish, sii9022_state),
+ VMSTATE_BOOL(ddc, sii9022_state),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static int sii9022_event(I2CSlave *i2c, enum i2c_event event)
+{
+ sii9022_state *s = SII9022(i2c);
+
+ switch (event) {
+ case I2C_START_SEND:
+ s->addr_byte = true;
+ break;
+ case I2C_START_RECV:
+ break;
+ case I2C_FINISH:
+ break;
+ case I2C_NACK:
+ break;
+ }
+
+ return 0;
+}
+
+static int sii9022_rx(I2CSlave *i2c)
+{
+ sii9022_state *s = SII9022(i2c);
+ uint8_t res = 0x00;
+
+ switch (s->ptr) {
+ case SII9022_SYS_CTRL_DATA:
+ if (s->ddc_req) {
+ /* Acknowledge DDC bus request */
+ res = SII9022_SYS_CTRL_DDC_BUS_GRTD | SII9022_SYS_CTRL_DDC_BUS_REQ;
+ }
+ break;
+ case SII9022_REG_CHIPID:
+ res = 0xb0;
+ break;
+ case SII9022_INT_STATUS:
+ /* Something is cold-plugged in, no interrupts */
+ res = SII9022_INT_STATUS_PLUGGED;
+ break;
+ default:
+ break;
+ }
+
+ trace_sii9022_read_reg(s->ptr, res);
+ s->ptr++;
+
+ return res;
+}
+
+static int sii9022_tx(I2CSlave *i2c, uint8_t data)
+{
+ sii9022_state *s = SII9022(i2c);
+
+ if (s->addr_byte) {
+ s->ptr = data;
+ s->addr_byte = false;
+ return 0;
+ }
+
+ switch (s->ptr) {
+ case SII9022_SYS_CTRL_DATA:
+ if (data & SII9022_SYS_CTRL_DDC_BUS_REQ) {
+ s->ddc_req = true;
+ if (data & SII9022_SYS_CTRL_DDC_BUS_GRTD) {
+ s->ddc = true;
+ /* Skip this finish since we just switched to DDC */
+ s->ddc_skip_finish = true;
+ trace_sii9022_switch_mode("DDC");
+ }
+ } else {
+ s->ddc_req = false;
+ s->ddc = false;
+ trace_sii9022_switch_mode("normal");
+ }
+ break;
+ default:
+ break;
+ }
+
+ trace_sii9022_write_reg(s->ptr, data);
+ s->ptr++;
+
+ return 0;
+}
+
+static void sii9022_reset(DeviceState *dev)
+{
+ sii9022_state *s = SII9022(dev);
+
+ s->ptr = 0;
+ s->addr_byte = false;
+ s->ddc_req = false;
+ s->ddc_skip_finish = false;
+ s->ddc = false;
+}
+
+static void sii9022_realize(DeviceState *dev, Error **errp)
+{
+ I2CBus *bus;
+
+ bus = I2C_BUS(qdev_get_parent_bus(dev));
+ i2c_create_slave(bus, TYPE_I2CDDC, 0x50);
+}
+
+static void sii9022_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ I2CSlaveClass *k = I2C_SLAVE_CLASS(klass);
+
+ k->event = sii9022_event;
+ k->recv = sii9022_rx;
+ k->send = sii9022_tx;
+ dc->reset = sii9022_reset;
+ dc->realize = sii9022_realize;
+ dc->vmsd = &vmstate_sii9022;
+}
+
+static const TypeInfo sii9022_info = {
+ .name = TYPE_SII9022,
+ .parent = TYPE_I2C_SLAVE,
+ .instance_size = sizeof(sii9022_state),
+ .class_init = sii9022_class_init,
+};
+
+static void sii9022_register_types(void)
+{
+ type_register_static(&sii9022_info);
+}
+
+type_init(sii9022_register_types)
diff --git a/hw/display/trace-events b/hw/display/trace-events
index da498c1def..5a48c6cb6a 100644
--- a/hw/display/trace-events
+++ b/hw/display/trace-events
@@ -132,3 +132,8 @@ vga_cirrus_read_io(uint32_t addr, uint32_t val) "addr 0x%x, val 0x%x"
vga_cirrus_write_io(uint32_t addr, uint32_t val) "addr 0x%x, val 0x%x"
vga_cirrus_read_blt(uint32_t offset, uint32_t val) "offset 0x%x, val 0x%x"
vga_cirrus_write_blt(uint32_t offset, uint32_t val) "offset 0x%x, val 0x%x"
+
+# hw/display/sii9022.c
+sii9022_read_reg(uint8_t addr, uint8_t val) "addr 0x%02x, val 0x%02x"
+sii9022_write_reg(uint8_t addr, uint8_t val) "addr 0x%02x, val 0x%02x"
+sii9022_switch_mode(const char *mode) "mode: %s"
diff --git a/hw/i2c/core.c b/hw/i2c/core.c
index 59068f157e..cfccefca3d 100644
--- a/hw/i2c/core.c
+++ b/hw/i2c/core.c
@@ -10,31 +10,13 @@
#include "qemu/osdep.h"
#include "hw/i2c/i2c.h"
-typedef struct I2CNode I2CNode;
-
-struct I2CNode {
- I2CSlave *elt;
- QLIST_ENTRY(I2CNode) next;
-};
-
#define I2C_BROADCAST 0x00
-struct I2CBus
-{
- BusState qbus;
- QLIST_HEAD(, I2CNode) current_devs;
- uint8_t saved_address;
- bool broadcast;
-};
-
static Property i2c_props[] = {
DEFINE_PROP_UINT8("address", struct I2CSlave, address, 0),
DEFINE_PROP_END_OF_LIST(),
};
-#define TYPE_I2C_BUS "i2c-bus"
-#define I2C_BUS(obj) OBJECT_CHECK(I2CBus, (obj), TYPE_I2C_BUS)
-
static const TypeInfo i2c_bus_info = {
.name = TYPE_I2C_BUS,
.parent = TYPE_BUS,
diff --git a/hw/i2c/i2c-ddc.c b/hw/i2c/i2c-ddc.c
index 199dac9e41..bec0c91e2d 100644
--- a/hw/i2c/i2c-ddc.c
+++ b/hw/i2c/i2c-ddc.c
@@ -259,12 +259,12 @@ static int i2c_ddc_tx(I2CSlave *i2c, uint8_t data)
s->reg = data;
s->firstbyte = false;
DPRINTF("[EDID] Written new pointer: %u\n", data);
- return 1;
+ return 0;
}
/* Ignore all writes */
s->reg++;
- return 1;
+ return 0;
}
static void i2c_ddc_init(Object *obj)
diff --git a/hw/ssi/xilinx_spips.c b/hw/ssi/xilinx_spips.c
index 8af36ca3d4..426f971311 100644
--- a/hw/ssi/xilinx_spips.c
+++ b/hw/ssi/xilinx_spips.c
@@ -223,7 +223,7 @@ static void xilinx_spips_update_cs(XilinxSPIPS *s, int field)
{
int i;
- for (i = 0; i < s->num_cs; i++) {
+ for (i = 0; i < s->num_cs * s->num_busses; i++) {
bool old_state = s->cs_lines_state[i];
bool new_state = field & (1 << i);
@@ -234,7 +234,7 @@ static void xilinx_spips_update_cs(XilinxSPIPS *s, int field)
}
qemu_set_irq(s->cs_lines[i], !new_state);
}
- if (!(field & ((1 << s->num_cs) - 1))) {
+ if (!(field & ((1 << (s->num_cs * s->num_busses)) - 1))) {
s->snoop_state = SNOOP_CHECKING;
s->cmd_dummies = 0;
s->link_state = 1;
@@ -248,7 +248,40 @@ static void xlnx_zynqmp_qspips_update_cs_lines(XlnxZynqMPQSPIPS *s)
{
if (s->regs[R_GQSPI_GF_SNAPSHOT]) {
int field = ARRAY_FIELD_EX32(s->regs, GQSPI_GF_SNAPSHOT, CHIP_SELECT);
- xilinx_spips_update_cs(XILINX_SPIPS(s), field);
+ bool upper_cs_sel = field & (1 << 1);
+ bool lower_cs_sel = field & 1;
+ bool bus0_enabled;
+ bool bus1_enabled;
+ uint8_t buses;
+ int cs = 0;
+
+ buses = ARRAY_FIELD_EX32(s->regs, GQSPI_GF_SNAPSHOT, DATA_BUS_SELECT);
+ bus0_enabled = buses & 1;
+ bus1_enabled = buses & (1 << 1);
+
+ if (bus0_enabled && bus1_enabled) {
+ if (lower_cs_sel) {
+ cs |= 1;
+ }
+ if (upper_cs_sel) {
+ cs |= 1 << 3;
+ }
+ } else if (bus0_enabled) {
+ if (lower_cs_sel) {
+ cs |= 1;
+ }
+ if (upper_cs_sel) {
+ cs |= 1 << 1;
+ }
+ } else if (bus1_enabled) {
+ if (lower_cs_sel) {
+ cs |= 1 << 2;
+ }
+ if (upper_cs_sel) {
+ cs |= 1 << 3;
+ }
+ }
+ xilinx_spips_update_cs(XILINX_SPIPS(s), cs);
}
}
@@ -260,7 +293,7 @@ static void xilinx_spips_update_cs_lines(XilinxSPIPS *s)
if (num_effective_busses(s) == 2) {
/* Single bit chip-select for qspi */
field &= 0x1;
- field |= field << 1;
+ field |= field << 3;
/* Dual stack U-Page */
} else if (s->regs[R_LQSPI_CFG] & LQSPI_CFG_TWO_MEM &&
s->regs[R_LQSPI_STS] & LQSPI_CFG_U_PAGE) {
@@ -544,7 +577,7 @@ static int xilinx_spips_num_dummies(XilinxQSPIPS *qs, uint8_t command)
return 2;
case QIOR:
case QIOR_4:
- return 5;
+ return 4;
default:
return -1;
}