From patchwork Thu Jun 14 00:17:00 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: BALATON Zoltan X-Patchwork-Id: 10463021 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 010A7603EE for ; Thu, 14 Jun 2018 00:37:25 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E4A4F28AF3 for ; Thu, 14 Jun 2018 00:37:24 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id D98AE28CF3; Thu, 14 Jun 2018 00:37:24 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00, MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 3132428AF3 for ; Thu, 14 Jun 2018 00:37:24 +0000 (UTC) Received: from localhost ([::1]:37464 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fTGGR-0001no-8E for patchwork-qemu-devel@patchwork.kernel.org; Wed, 13 Jun 2018 20:37:23 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:40215) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fTGBF-0006O6-JO for qemu-devel@nongnu.org; Wed, 13 Jun 2018 20:32:03 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fTGBD-00038Z-R7 for qemu-devel@nongnu.org; Wed, 13 Jun 2018 20:32:01 -0400 Received: from zero.eik.bme.hu ([2001:738:2001:2001::2001]:32758) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fTGBD-00037v-Cv; Wed, 13 Jun 2018 20:31:59 -0400 Received: from zero.eik.bme.hu (blah.eik.bme.hu [152.66.115.182]) by localhost (Postfix) with SMTP id 826A17456BA; Thu, 14 Jun 2018 02:31:56 +0200 (CEST) Received: by zero.eik.bme.hu (Postfix, from userid 432) id A9EB27456BB; Thu, 14 Jun 2018 02:31:55 +0200 (CEST) Message-Id: In-Reply-To: References: From: BALATON Zoltan Date: Thu, 14 Jun 2018 02:17:00 +0200 To: qemu-devel@nongnu.org, qemu-ppc@nongnu.org X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2001:738:2001:2001::2001 Subject: [Qemu-devel] [PATCH v3 7/9] sm501: Implement i2c part for reading monitor EDID X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Peter Maydell , Alexander Graf , David Gibson Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP Signed-off-by: BALATON Zoltan --- default-configs/ppc-softmmu.mak | 1 + default-configs/ppcemb-softmmu.mak | 1 + default-configs/sh4-softmmu.mak | 1 + default-configs/sh4eb-softmmu.mak | 1 + hw/display/sm501.c | 136 +++++++++++++++++++++++++++++++++++-- 5 files changed, 136 insertions(+), 4 deletions(-) diff --git a/default-configs/ppc-softmmu.mak b/default-configs/ppc-softmmu.mak index 9fbaadc..860de80 100644 --- a/default-configs/ppc-softmmu.mak +++ b/default-configs/ppc-softmmu.mak @@ -24,6 +24,7 @@ CONFIG_ETSEC=y # For Sam460ex CONFIG_USB_EHCI_SYSBUS=y CONFIG_SM501=y +CONFIG_DDC=y CONFIG_IDE_SII3112=y CONFIG_I2C=y CONFIG_BITBANG_I2C=y diff --git a/default-configs/ppcemb-softmmu.mak b/default-configs/ppcemb-softmmu.mak index 37af193..ac44f15 100644 --- a/default-configs/ppcemb-softmmu.mak +++ b/default-configs/ppcemb-softmmu.mak @@ -17,6 +17,7 @@ CONFIG_XILINX=y CONFIG_XILINX_ETHLITE=y CONFIG_USB_EHCI_SYSBUS=y CONFIG_SM501=y +CONFIG_DDC=y CONFIG_IDE_SII3112=y CONFIG_I2C=y CONFIG_BITBANG_I2C=y diff --git a/default-configs/sh4-softmmu.mak b/default-configs/sh4-softmmu.mak index 546d855..72d8fca 100644 --- a/default-configs/sh4-softmmu.mak +++ b/default-configs/sh4-softmmu.mak @@ -9,6 +9,7 @@ CONFIG_PFLASH_CFI02=y CONFIG_SH4=y CONFIG_IDE_MMIO=y CONFIG_SM501=y +CONFIG_DDC=y CONFIG_ISA_TESTDEV=y CONFIG_I82378=y CONFIG_I8259=y diff --git a/default-configs/sh4eb-softmmu.mak b/default-configs/sh4eb-softmmu.mak index 2d3fd49..c686637 100644 --- a/default-configs/sh4eb-softmmu.mak +++ b/default-configs/sh4eb-softmmu.mak @@ -9,6 +9,7 @@ CONFIG_PFLASH_CFI02=y CONFIG_SH4=y CONFIG_IDE_MMIO=y CONFIG_SM501=y +CONFIG_DDC=y CONFIG_ISA_TESTDEV=y CONFIG_I82378=y CONFIG_I8259=y diff --git a/hw/display/sm501.c b/hw/display/sm501.c index ca0840f..0625cf5 100644 --- a/hw/display/sm501.c +++ b/hw/display/sm501.c @@ -26,6 +26,7 @@ #include "qemu/osdep.h" #include "qemu/cutils.h" #include "qapi/error.h" +#include "qemu/log.h" #include "qemu-common.h" #include "cpu.h" #include "hw/hw.h" @@ -34,6 +35,8 @@ #include "hw/devices.h" #include "hw/sysbus.h" #include "hw/pci/pci.h" +#include "hw/i2c/i2c.h" +#include "hw/i2c/i2c-ddc.h" #include "qemu/range.h" #include "ui/pixel_ops.h" @@ -471,10 +474,12 @@ typedef struct SM501State { MemoryRegion local_mem_region; MemoryRegion mmio_region; MemoryRegion system_config_region; + MemoryRegion i2c_region; MemoryRegion disp_ctrl_region; MemoryRegion twoD_engine_region; uint32_t last_width; uint32_t last_height; + I2CBus *i2c_bus; /* mmio registers */ uint32_t system_control; @@ -487,6 +492,11 @@ typedef struct SM501State { uint32_t misc_timing; uint32_t power_mode_control; + uint8_t i2c_byte_count; + uint8_t i2c_status; + uint8_t i2c_addr; + uint8_t i2c_data[16]; + uint32_t uart0_ier; uint32_t uart0_lcr; uint32_t uart0_mcr; @@ -897,6 +907,107 @@ static const MemoryRegionOps sm501_system_config_ops = { .endianness = DEVICE_LITTLE_ENDIAN, }; +static uint64_t sm501_i2c_read(void *opaque, hwaddr addr, unsigned size) +{ + SM501State *s = (SM501State *)opaque; + uint8_t ret = 0; + + switch (addr) { + case SM501_I2C_BYTE_COUNT: + ret = s->i2c_byte_count; + break; + case SM501_I2C_STATUS: + ret = s->i2c_status; + break; + case SM501_I2C_SLAVE_ADDRESS: + ret = s->i2c_addr; + break; + case SM501_I2C_DATA ... SM501_I2C_DATA + 15: + ret = s->i2c_data[addr - SM501_I2C_DATA]; + break; + default: + qemu_log_mask(LOG_UNIMP, "sm501 i2c : not implemented register read." + " addr=0x%" HWADDR_PRIx "\n", addr); + } + + SM501_DPRINTF("sm501 i2c regs : read addr=%" HWADDR_PRIx " val=%x\n", + addr, ret); + return ret; +} + +static void sm501_i2c_write(void *opaque, hwaddr addr, uint64_t value, + unsigned size) +{ + SM501State *s = (SM501State *)opaque; + SM501_DPRINTF("sm501 i2c regs : write addr=%" HWADDR_PRIx + " val=%" PRIx64 "\n", addr, value); + + switch (addr) { + case SM501_I2C_BYTE_COUNT: + s->i2c_byte_count = value & 0xf; + break; + case SM501_I2C_CONTROL: + if (value & 1) { + if (value & 4) { + int res = i2c_start_transfer(s->i2c_bus, + s->i2c_addr >> 1, + s->i2c_addr & 1); + s->i2c_status |= (res ? 1 << 2 : 0); + if (!res) { + int i; + SM501_DPRINTF("sm501 i2c : transferring %d bytes to 0x%x\n", + s->i2c_byte_count + 1, s->i2c_addr >> 1); + for (i = 0; i <= s->i2c_byte_count; i++) { + res = i2c_send_recv(s->i2c_bus, &s->i2c_data[i], + !(s->i2c_addr & 1)); + if (res) { + SM501_DPRINTF("sm501 i2c : transfer failed" + " i=%d, res=%d\n", i, res); + s->i2c_status |= (res ? 1 << 2 : 0); + return; + } + } + if (i) { + SM501_DPRINTF("sm501 i2c : transferred %d bytes\n", i); + s->i2c_status = 8; + } + } + } else { + SM501_DPRINTF("sm501 i2c : end transfer\n"); + i2c_end_transfer(s->i2c_bus); + s->i2c_status &= ~4; + } + } + break; + case SM501_I2C_RESET: + s->i2c_status &= ~4; + break; + case SM501_I2C_SLAVE_ADDRESS: + s->i2c_addr = value & 0xff; + break; + case SM501_I2C_DATA ... SM501_I2C_DATA + 15: + s->i2c_data[addr - SM501_I2C_DATA] = value & 0xff; + break; + default: + qemu_log_mask(LOG_UNIMP, "sm501 i2c : not implemented register write. " + "addr=0x%" HWADDR_PRIx " val=%" PRIx64 "\n", addr, value); + } +} + +static const MemoryRegionOps sm501_i2c_ops = { + .read = sm501_i2c_read, + .write = sm501_i2c_write, + .valid = { + .min_access_size = 1, + .max_access_size = 4, + }, + .impl = { + .min_access_size = 1, + .max_access_size = 1, + }, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + static uint32_t sm501_palette_read(void *opaque, hwaddr addr) { SM501State *s = (SM501State *)opaque; @@ -1577,6 +1688,10 @@ static void sm501_reset(SM501State *s) s->irq_mask = 0; s->misc_timing = 0; s->power_mode_control = 0; + s->i2c_byte_count = 0; + s->i2c_status = 0; + s->i2c_addr = 0; + memset(s->i2c_data, 0, 16); s->dc_panel_control = 0x00010000; /* FIFO level 3 */ s->dc_video_control = 0; s->dc_crt_control = 0x00010000; @@ -1615,6 +1730,11 @@ static void sm501_init(SM501State *s, DeviceState *dev, memory_region_set_log(&s->local_mem_region, true, DIRTY_MEMORY_VGA); s->local_mem = memory_region_get_ram_ptr(&s->local_mem_region); + /* i2c */ + s->i2c_bus = i2c_init_bus(dev, "sm501.i2c"); + I2CDDCState *ddc = I2CDDC(qdev_create(BUS(s->i2c_bus), TYPE_I2CDDC)); + i2c_set_slave_address(I2C_SLAVE(ddc), 0x50); + /* mmio */ memory_region_init(&s->mmio_region, OBJECT(dev), "sm501.mmio", MMIO_SIZE); memory_region_init_io(&s->system_config_region, OBJECT(dev), @@ -1622,6 +1742,9 @@ static void sm501_init(SM501State *s, DeviceState *dev, "sm501-system-config", 0x6c); memory_region_add_subregion(&s->mmio_region, SM501_SYS_CONFIG, &s->system_config_region); + memory_region_init_io(&s->i2c_region, OBJECT(dev), &sm501_i2c_ops, s, + "sm501-i2c", 0x14); + memory_region_add_subregion(&s->mmio_region, SM501_I2C, &s->i2c_region); memory_region_init_io(&s->disp_ctrl_region, OBJECT(dev), &sm501_disp_ctrl_ops, s, "sm501-disp-ctrl", 0x1000); @@ -1705,6 +1828,11 @@ static const VMStateDescription vmstate_sm501_state = { VMSTATE_UINT32(twoD_destination_base, SM501State), VMSTATE_UINT32(twoD_alpha, SM501State), VMSTATE_UINT32(twoD_wrap, SM501State), + /* Added in version 2 */ + VMSTATE_UINT8(i2c_byte_count, SM501State), + VMSTATE_UINT8(i2c_status, SM501State), + VMSTATE_UINT8(i2c_addr, SM501State), + VMSTATE_UINT8_ARRAY(i2c_data, SM501State, 16), VMSTATE_END_OF_LIST() } }; @@ -1770,8 +1898,8 @@ static void sm501_reset_sysbus(DeviceState *dev) static const VMStateDescription vmstate_sm501_sysbus = { .name = TYPE_SYSBUS_SM501, - .version_id = 1, - .minimum_version_id = 1, + .version_id = 2, + .minimum_version_id = 2, .fields = (VMStateField[]) { VMSTATE_STRUCT(state, SM501SysBusState, 1, vmstate_sm501_state, SM501State), @@ -1843,8 +1971,8 @@ static void sm501_reset_pci(DeviceState *dev) static const VMStateDescription vmstate_sm501_pci = { .name = TYPE_PCI_SM501, - .version_id = 1, - .minimum_version_id = 1, + .version_id = 2, + .minimum_version_id = 2, .fields = (VMStateField[]) { VMSTATE_PCI_DEVICE(parent_obj, SM501PCIState), VMSTATE_STRUCT(state, SM501PCIState, 1,