From 4e5f0fb72ee2a8872cec469fd9fe414711de3908 Mon Sep 17 00:00:00 2001 From: Alistair Francis Date: Thu, 1 Mar 2018 11:05:43 +0000 Subject: hw: register: Run post_write hook on reset MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ensure that the post write hook is called during reset. This allows us to rely on the post write functions instead of having to call them from the reset() function. Signed-off-by: Alistair Francis Reviewed-by: Philippe Mathieu-Daudé Message-id: d131e24b911653a945e46ca2d8f90f572469e1dd.1517856214.git.alistair.francis@xilinx.com Signed-off-by: Peter Maydell --- hw/core/register.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'hw') 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) -- cgit v1.2.3 From 0c4a94b8e3904cffedfbb959587ddce8643e45fd Mon Sep 17 00:00:00 2001 From: Francisco Iglesias Date: Thu, 1 Mar 2018 11:05:44 +0000 Subject: xilinx_spips: Enable only two slaves when reading/writing with stripe Assert only the lower cs on bus 0 and upper cs on bus 1 when both buses and chip selects are enabled (e.g reading/writing with stripe). Signed-off-by: Francisco Iglesias Reviewed-by: Alistair Francis Tested-by: Alistair Francis Message-id: 20180223232233.31482-2-frasse.iglesias@gmail.com Signed-off-by: Peter Maydell --- hw/ssi/xilinx_spips.c | 41 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 37 insertions(+), 4 deletions(-) (limited to 'hw') diff --git a/hw/ssi/xilinx_spips.c b/hw/ssi/xilinx_spips.c index 8af36ca3d4..0cb484ecf4 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) { -- cgit v1.2.3 From b8cc8503521282fe741e4d24ade9157210fdf3ba Mon Sep 17 00:00:00 2001 From: Francisco Iglesias Date: Thu, 1 Mar 2018 11:05:44 +0000 Subject: xilinx_spips: Use 8 dummy cycles with the QIOR/QIOR4 commands Use 8 dummy cycles (4 dummy bytes) with the QIOR/QIOR4 commands in legacy mode for matching what is expected by Micron (Numonyx) flashes (the default target flash type of the QSPI). Signed-off-by: Francisco Iglesias Tested-by: Alistair Francis Reviewed-by: Alistair Francis Message-id: 20180223232233.31482-3-frasse.iglesias@gmail.com Signed-off-by: Peter Maydell --- hw/ssi/xilinx_spips.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'hw') diff --git a/hw/ssi/xilinx_spips.c b/hw/ssi/xilinx_spips.c index 0cb484ecf4..426f971311 100644 --- a/hw/ssi/xilinx_spips.c +++ b/hw/ssi/xilinx_spips.c @@ -577,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; } -- cgit v1.2.3 From 373b8ac794291c9a20198ac671728dbd74ac3771 Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Thu, 1 Mar 2018 11:05:44 +0000 Subject: i2c: Fix some brace style issues Signed-off-by: Corey Minyard Reviewed-by: Peter Maydell Signed-off-by: Linus Walleij Message-id: 20180227104903.21353-2-linus.walleij@linaro.org Signed-off-by: Peter Maydell --- hw/i2c/core.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'hw') diff --git a/hw/i2c/core.c b/hw/i2c/core.c index 59068f157e..9a54b61c1d 100644 --- a/hw/i2c/core.c +++ b/hw/i2c/core.c @@ -19,8 +19,7 @@ struct I2CNode { #define I2C_BROADCAST 0x00 -struct I2CBus -{ +struct I2CBus { BusState qbus; QLIST_HEAD(, I2CNode) current_devs; uint8_t saved_address; -- cgit v1.2.3 From aa88d7ad28eafaa7ac187d5bbb0c46f987fac3a4 Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Thu, 1 Mar 2018 11:05:45 +0000 Subject: i2c: Move the bus class to i2c.h Some devices need access to it. Signed-off-by: Corey Minyard Reviewed-by: Peter Maydell Signed-off-by: Linus Walleij Message-id: 20180227104903.21353-3-linus.walleij@linaro.org Signed-off-by: Peter Maydell --- hw/i2c/core.c | 17 ----------------- 1 file changed, 17 deletions(-) (limited to 'hw') diff --git a/hw/i2c/core.c b/hw/i2c/core.c index 9a54b61c1d..cfccefca3d 100644 --- a/hw/i2c/core.c +++ b/hw/i2c/core.c @@ -10,30 +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, -- cgit v1.2.3 From 839a2b28d01290c96554be42c3faaa05c847c2e3 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 1 Mar 2018 11:05:45 +0000 Subject: hw/i2c-ddc: Do not fail writes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The tx function of the DDC I2C slave emulation was returning 1 on all writes resulting in NACK in the I2C bus. Changing it to 0 makes the DDC I2C work fine with bit-banged I2C such as the versatile I2C. I guess it was not affecting whatever I2C controller this was used with until now, but with the Versatile I2C it surely does not work. Reviewed-by: Peter Maydell Signed-off-by: Linus Walleij Message-id: 20180227104903.21353-4-linus.walleij@linaro.org Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Peter Maydell --- hw/i2c/i2c-ddc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'hw') 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) -- cgit v1.2.3 From a643bd7749d41de2cfc54940636442ebc4f9e531 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 1 Mar 2018 11:05:45 +0000 Subject: hw/sii9022: Add support for Silicon Image SII9022 This adds support for emulating the Silicon Image SII9022 DVI/HDMI bridge. It's not very clever right now, it just acknowledges the switch into DDC I2C mode and back. Combining this with the existing DDC I2C emulation gives the right behavior on the Versatile Express emulation passing through the QEMU EDID to the emulated platform. Cc: Peter Maydell Signed-off-by: Linus Walleij Message-id: 20180227104903.21353-5-linus.walleij@linaro.org Reviewed-by: Peter Maydell [PMM: explictly reset ddc_req/ddc_skip_finish/ddc] Signed-off-by: Peter Maydell --- hw/display/Makefile.objs | 1 + hw/display/sii9022.c | 191 +++++++++++++++++++++++++++++++++++++++++++++++ hw/display/trace-events | 5 ++ 3 files changed, 197 insertions(+) create mode 100644 hw/display/sii9022.c (limited to 'hw') 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" -- cgit v1.2.3 From 0b72476810a83de270194b1de65027e4be204779 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 1 Mar 2018 11:05:46 +0000 Subject: arm/vexpress: Add proper display connector emulation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adds the SiI9022 (and implicitly EDID I2C) device to the ARM Versatile Express machine, and selects the two I2C devices necessary in the arm-softmmu.mak configuration so everything will build smoothly. I am implementing proper handling of the graphics in the Linux kernel and adding proper emulation of SiI9022 and EDID makes the driver probe as nicely as before, retrieving the resolutions supported by the "QEMU monitor" and overall just working nice. Cc: Peter Maydell Signed-off-by: Linus Walleij Message-id: 20180227104903.21353-6-linus.walleij@linaro.org Reviewed-by: Peter Maydell Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Peter Maydell --- hw/arm/vexpress.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'hw') 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 */ -- cgit v1.2.3