From nobody Tue Nov 4 05:28:36 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 152984079359665.8106791621185; Sun, 24 Jun 2018 04:46:33 -0700 (PDT) Received: from localhost ([::1]:41435 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fX3TU-0003t4-Qu for importer@patchew.org; Sun, 24 Jun 2018 07:46:32 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:55975) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fX3Pd-0001EA-U3 for qemu-devel@nongnu.org; Sun, 24 Jun 2018 07:42:35 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fX3PZ-0007nT-9Q for qemu-devel@nongnu.org; Sun, 24 Jun 2018 07:42:33 -0400 Received: from zero.eik.bme.hu ([152.66.115.2]:18836) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fX3PY-0007lg-Qa; Sun, 24 Jun 2018 07:42:29 -0400 Received: from zero.eik.bme.hu (blah.eik.bme.hu [152.66.115.182]) by localhost (Postfix) with SMTP id 8AD607456C6; Sun, 24 Jun 2018 13:42:20 +0200 (CEST) Received: by zero.eik.bme.hu (Postfix, from userid 432) id F291A7456C9; Sun, 24 Jun 2018 13:42:19 +0200 (CEST) Message-Id: <61b9cf7d09f0f12a86f036b828665c3fc91c3ce9.1529839203.git.balaton@eik.bme.hu> In-Reply-To: References: From: BALATON Zoltan Date: Sun, 24 Jun 2018 13:20:03 +0200 To: qemu-devel@nongnu.org, qemu-ppc@nongnu.org X-detected-operating-system: by eggs.gnu.org: FreeBSD 9.x [fuzzy] X-Received-From: 152.66.115.2 Subject: [Qemu-devel] [PATCH v5 1/4] ppc4xx_i2c: Rewrite to model hardware more closely 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: Alexander Graf , David Gibson Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Rewrite to make it closer to how real device works so that guest OS drivers can access I2C devices. Previously this was only a hack to allow U-Boot to get past accessing SPD EEPROMs but to support other I2C devices and allow guests to access them we need to model real device more properly. Signed-off-by: BALATON Zoltan Reviewed-by: C=C3=A9dric Le Goater --- hw/i2c/ppc4xx_i2c.c | 222 +++++++++++++++++++++-------------------= ---- include/hw/i2c/ppc4xx_i2c.h | 3 +- 2 files changed, 110 insertions(+), 115 deletions(-) diff --git a/hw/i2c/ppc4xx_i2c.c b/hw/i2c/ppc4xx_i2c.c index fca80d6..3ebce17 100644 --- a/hw/i2c/ppc4xx_i2c.c +++ b/hw/i2c/ppc4xx_i2c.c @@ -38,13 +38,26 @@ #define IIC_CNTL_READ (1 << 1) #define IIC_CNTL_CHT (1 << 2) #define IIC_CNTL_RPST (1 << 3) +#define IIC_CNTL_AMD (1 << 6) +#define IIC_CNTL_HMT (1 << 7) + +#define IIC_MDCNTL_EINT (1 << 2) +#define IIC_MDCNTL_ESM (1 << 3) +#define IIC_MDCNTL_FMDB (1 << 6) =20 #define IIC_STS_PT (1 << 0) +#define IIC_STS_IRQA (1 << 1) #define IIC_STS_ERR (1 << 2) +#define IIC_STS_MDBF (1 << 4) #define IIC_STS_MDBS (1 << 5) =20 #define IIC_EXTSTS_XFRA (1 << 0) =20 +#define IIC_INTRMSK_EIMTC (1 << 0) +#define IIC_INTRMSK_EITA (1 << 1) +#define IIC_INTRMSK_EIIC (1 << 2) +#define IIC_INTRMSK_EIHE (1 << 3) + #define IIC_XTCNTLSS_SRST (1 << 0) =20 #define IIC_DIRECTCNTL_SDAC (1 << 3) @@ -56,21 +69,13 @@ static void ppc4xx_i2c_reset(DeviceState *s) { PPC4xxI2CState *i2c =3D PPC4xx_I2C(s); =20 - /* FIXME: Should also reset bus? - *if (s->address !=3D ADDR_RESET) { - * i2c_end_transfer(s->bus); - *} - */ - - i2c->mdata =3D 0; - i2c->lmadr =3D 0; - i2c->hmadr =3D 0; + i2c->mdidx =3D -1; + memset(i2c->mdata, 0, ARRAY_SIZE(i2c->mdata)); + /* [hl][ms]addr are not affected by reset */ i2c->cntl =3D 0; i2c->mdcntl =3D 0; i2c->sts =3D 0; - i2c->extsts =3D 0x8f; - i2c->lsadr =3D 0; - i2c->hsadr =3D 0; + i2c->extsts =3D (1 << 6); i2c->clkdiv =3D 0; i2c->intrmsk =3D 0; i2c->xfrcnt =3D 0; @@ -78,69 +83,29 @@ static void ppc4xx_i2c_reset(DeviceState *s) i2c->directcntl =3D 0xf; } =20 -static inline bool ppc4xx_i2c_is_master(PPC4xxI2CState *i2c) -{ - return true; -} - static uint64_t ppc4xx_i2c_readb(void *opaque, hwaddr addr, unsigned int s= ize) { PPC4xxI2CState *i2c =3D PPC4xx_I2C(opaque); uint64_t ret; + int i; =20 switch (addr) { case 0: - ret =3D i2c->mdata; - if (ppc4xx_i2c_is_master(i2c)) { + if (i2c->mdidx < 0) { ret =3D 0xff; - - if (!(i2c->sts & IIC_STS_MDBS)) { - qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Trying to read " - "without starting transfer\n", - TYPE_PPC4xx_I2C, __func__); - } else { - int pending =3D (i2c->cntl >> 4) & 3; - - /* get the next byte */ - int byte =3D i2c_recv(i2c->bus); - - if (byte < 0) { - qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: read failed " - "for device 0x%02x\n", TYPE_PPC4xx_I2C, - __func__, i2c->lmadr); - ret =3D 0xff; - } else { - ret =3D byte; - /* Raise interrupt if enabled */ - /*ppc4xx_i2c_raise_interrupt(i2c)*/; - } - - if (!pending) { - i2c->sts &=3D ~IIC_STS_MDBS; - /*i2c_end_transfer(i2c->bus);*/ - /*} else if (i2c->cntl & (IIC_CNTL_RPST | IIC_CNTL_CHT)) {= */ - } else if (pending) { - /* current smbus implementation doesn't like - multibyte xfer repeated start */ - i2c_end_transfer(i2c->bus); - if (i2c_start_transfer(i2c->bus, i2c->lmadr >> 1, 1)) { - /* if non zero is returned, the adress is not vali= d */ - i2c->sts &=3D ~IIC_STS_PT; - i2c->sts |=3D IIC_STS_ERR; - i2c->extsts |=3D IIC_EXTSTS_XFRA; - } else { - /*i2c->sts |=3D IIC_STS_PT;*/ - i2c->sts |=3D IIC_STS_MDBS; - i2c->sts &=3D ~IIC_STS_ERR; - i2c->extsts =3D 0; - } - } - pending--; - i2c->cntl =3D (i2c->cntl & 0xcf) | (pending << 4); - } - } else { - qemu_log_mask(LOG_UNIMP, "[%s]%s: slave mode not implemented\n= ", - TYPE_PPC4xx_I2C, __func__); + break; + } + ret =3D i2c->mdata[0]; + if (i2c->mdidx =3D=3D 3) { + i2c->sts &=3D ~IIC_STS_MDBF; + } else if (i2c->mdidx =3D=3D 0) { + i2c->sts &=3D ~IIC_STS_MDBS; + } + for (i =3D 0; i < i2c->mdidx; i++) { + i2c->mdata[i] =3D i2c->mdata[i + 1]; + } + if (i2c->mdidx >=3D 0) { + i2c->mdidx--; } break; case 4: @@ -160,6 +125,7 @@ static uint64_t ppc4xx_i2c_readb(void *opaque, hwaddr a= ddr, unsigned int size) break; case 9: ret =3D i2c->extsts; + ret |=3D !!i2c_bus_busy(i2c->bus) << 4; break; case 10: ret =3D i2c->lsadr; @@ -203,70 +169,98 @@ static void ppc4xx_i2c_writeb(void *opaque, hwaddr ad= dr, uint64_t value, =20 switch (addr) { case 0: - i2c->mdata =3D value; - if (!i2c_bus_busy(i2c->bus)) { - /* assume we start a write transfer */ - if (i2c_start_transfer(i2c->bus, i2c->lmadr >> 1, 0)) { - /* if non zero is returned, the adress is not valid */ - i2c->sts &=3D ~IIC_STS_PT; - i2c->sts |=3D IIC_STS_ERR; - i2c->extsts |=3D IIC_EXTSTS_XFRA; - } else { - i2c->sts |=3D IIC_STS_PT; - i2c->sts &=3D ~IIC_STS_ERR; - i2c->extsts =3D 0; - } + if (i2c->mdidx >=3D 3) { + break; } - if (i2c_bus_busy(i2c->bus)) { - if (i2c_send(i2c->bus, i2c->mdata)) { - /* if the target return non zero then end the transfer */ - i2c->sts &=3D ~IIC_STS_PT; - i2c->sts |=3D IIC_STS_ERR; - i2c->extsts |=3D IIC_EXTSTS_XFRA; - i2c_end_transfer(i2c->bus); - } + i2c->mdata[++i2c->mdidx] =3D value; + if (i2c->mdidx =3D=3D 3) { + i2c->sts |=3D IIC_STS_MDBF; + } else if (i2c->mdidx =3D=3D 0) { + i2c->sts |=3D IIC_STS_MDBS; } break; case 4: i2c->lmadr =3D value; - if (i2c_bus_busy(i2c->bus)) { - i2c_end_transfer(i2c->bus); - } break; case 5: i2c->hmadr =3D value; break; case 6: - i2c->cntl =3D value; - if (i2c->cntl & IIC_CNTL_PT) { - if (i2c->cntl & IIC_CNTL_READ) { - if (i2c_bus_busy(i2c->bus)) { - /* end previous transfer */ - i2c->sts &=3D ~IIC_STS_PT; - i2c_end_transfer(i2c->bus); + i2c->cntl =3D value & 0xfe; + if (value & IIC_CNTL_AMD) { + qemu_log_mask(LOG_UNIMP, "%s: only 7 bit addresses supported\n= ", + __func__); + } + if (value & IIC_CNTL_HMT && i2c_bus_busy(i2c->bus)) { + i2c_end_transfer(i2c->bus); + if (i2c->mdcntl & IIC_MDCNTL_EINT && + i2c->intrmsk & IIC_INTRMSK_EIHE) { + i2c->sts |=3D IIC_STS_IRQA; + qemu_irq_raise(i2c->irq); + } + } else if (value & IIC_CNTL_PT) { + int recv =3D (value & IIC_CNTL_READ) >> 1; + int tct =3D value >> 4 & 3; + int i; + + if (recv && (i2c->lmadr >> 1) >=3D 0x50 && (i2c->lmadr >> 1) <= 0x58) { + /* smbus emulation does not like multi byte reads w/o rest= art */ + value |=3D IIC_CNTL_RPST; + } + + for (i =3D 0; i <=3D tct; i++) { + if (!i2c_bus_busy(i2c->bus)) { + i2c->extsts =3D (1 << 6); + if (i2c_start_transfer(i2c->bus, i2c->lmadr >> 1, recv= )) { + i2c->sts |=3D IIC_STS_ERR; + i2c->extsts |=3D IIC_EXTSTS_XFRA; + break; + } else { + i2c->sts &=3D ~IIC_STS_ERR; + } + } + if (!(i2c->sts & IIC_STS_ERR) && + i2c_send_recv(i2c->bus, &i2c->mdata[i], !recv)) { + i2c->sts |=3D IIC_STS_ERR; + i2c->extsts |=3D IIC_EXTSTS_XFRA; + break; } - if (i2c_start_transfer(i2c->bus, i2c->lmadr >> 1, 1)) { - /* if non zero is returned, the adress is not valid */ - i2c->sts &=3D ~IIC_STS_PT; - i2c->sts |=3D IIC_STS_ERR; - i2c->extsts |=3D IIC_EXTSTS_XFRA; - } else { - /*i2c->sts |=3D IIC_STS_PT;*/ - i2c->sts |=3D IIC_STS_MDBS; - i2c->sts &=3D ~IIC_STS_ERR; - i2c->extsts =3D 0; + if (value & IIC_CNTL_RPST || !(value & IIC_CNTL_CHT)) { + i2c_end_transfer(i2c->bus); } - } else { - /* we actually already did the write transfer... */ - i2c->sts &=3D ~IIC_STS_PT; + } + i2c->xfrcnt =3D i; + i2c->mdidx =3D i - 1; + if (recv && i2c->mdidx >=3D 0) { + i2c->sts |=3D IIC_STS_MDBS; + } + if (recv && i2c->mdidx =3D=3D 3) { + i2c->sts |=3D IIC_STS_MDBF; + } + if (i && i2c->mdcntl & IIC_MDCNTL_EINT && + i2c->intrmsk & IIC_INTRMSK_EIMTC) { + i2c->sts |=3D IIC_STS_IRQA; + qemu_irq_raise(i2c->irq); } } break; case 7: - i2c->mdcntl =3D value & 0xdf; + i2c->mdcntl =3D value & 0x3d; + if (value & IIC_MDCNTL_ESM) { + qemu_log_mask(LOG_UNIMP, "%s: slave mode not implemented\n", + __func__); + } + if (value & IIC_MDCNTL_FMDB) { + i2c->mdidx =3D -1; + memset(i2c->mdata, 0, ARRAY_SIZE(i2c->mdata)); + i2c->sts &=3D ~(IIC_STS_MDBF | IIC_STS_MDBS); + } break; case 8: - i2c->sts &=3D ~(value & 0xa); + i2c->sts &=3D ~(value & 0x0a); + if (value & IIC_STS_IRQA && i2c->mdcntl & IIC_MDCNTL_EINT) { + qemu_irq_lower(i2c->irq); + } break; case 9: i2c->extsts &=3D ~(value & 0x8f); @@ -287,12 +281,12 @@ static void ppc4xx_i2c_writeb(void *opaque, hwaddr ad= dr, uint64_t value, i2c->xfrcnt =3D value & 0x77; break; case 15: + i2c->xtcntlss &=3D ~(value & 0xf0); if (value & IIC_XTCNTLSS_SRST) { /* Is it actually a full reset? U-Boot sets some regs before */ ppc4xx_i2c_reset(DEVICE(i2c)); break; } - i2c->xtcntlss =3D value; break; case 16: i2c->directcntl =3D value & (IIC_DIRECTCNTL_SDAC & IIC_DIRECTCNTL_= SCLC); diff --git a/include/hw/i2c/ppc4xx_i2c.h b/include/hw/i2c/ppc4xx_i2c.h index ea6c8e1..0891a9c 100644 --- a/include/hw/i2c/ppc4xx_i2c.h +++ b/include/hw/i2c/ppc4xx_i2c.h @@ -46,7 +46,8 @@ typedef struct PPC4xxI2CState { qemu_irq irq; MemoryRegion iomem; bitbang_i2c_interface *bitbang; - uint8_t mdata; + int mdidx; + uint8_t mdata[4]; uint8_t lmadr; uint8_t hmadr; uint8_t cntl; --=20 2.7.6 From nobody Tue Nov 4 05:28:36 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1529840665824434.348213134205; Sun, 24 Jun 2018 04:44:25 -0700 (PDT) Received: from localhost ([::1]:41419 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fX3RP-0002DL-0U for importer@patchew.org; Sun, 24 Jun 2018 07:44:23 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:55968) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fX3Pd-0001E6-SL for qemu-devel@nongnu.org; Sun, 24 Jun 2018 07:42:35 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fX3PZ-0007nE-5y for qemu-devel@nongnu.org; Sun, 24 Jun 2018 07:42:33 -0400 Received: from zero.eik.bme.hu ([2001:738:2001:2001::2001]:18835) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fX3PY-0007lf-Q1; Sun, 24 Jun 2018 07:42:29 -0400 Received: from zero.eik.bme.hu (blah.eik.bme.hu [152.66.115.182]) by localhost (Postfix) with SMTP id 7E46D7456CB; Sun, 24 Jun 2018 13:42:20 +0200 (CEST) Received: by zero.eik.bme.hu (Postfix, from userid 432) id 01C2C74569D; Sun, 24 Jun 2018 13:42:20 +0200 (CEST) Message-Id: <8ea68a0d623241bfa190e295debe66765c9a3cfb.1529839203.git.balaton@eik.bme.hu> In-Reply-To: References: From: BALATON Zoltan Date: Sun, 24 Jun 2018 13:20:03 +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 v5 2/4] hw/timer: Add basic M41T80 emulation 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: Alexander Graf , David Gibson Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Basic emulation of the M41T80 serial (I2C) RTC chip. Only getting time of day is implemented. Setting time and RTC alarm are not supported. Signed-off-by: BALATON Zoltan Reviewed-by: C=C3=A9dric Le Goater --- MAINTAINERS | 1 + default-configs/ppc-softmmu.mak | 1 + hw/timer/Makefile.objs | 1 + hw/timer/m41t80.c | 117 ++++++++++++++++++++++++++++++++++++= ++++ 4 files changed, 120 insertions(+) create mode 100644 hw/timer/m41t80.c diff --git a/MAINTAINERS b/MAINTAINERS index 2874ddc..3bfc4a8 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -839,6 +839,7 @@ M: BALATON Zoltan L: qemu-ppc@nongnu.org S: Maintained F: hw/ide/sii3112.c +F: hw/timer/m41t80.c =20 SH4 Machines ------------ diff --git a/default-configs/ppc-softmmu.mak b/default-configs/ppc-softmmu.= mak index 851b4af..b8b0526 100644 --- a/default-configs/ppc-softmmu.mak +++ b/default-configs/ppc-softmmu.mak @@ -27,6 +27,7 @@ CONFIG_SM501=3Dy CONFIG_IDE_SII3112=3Dy CONFIG_I2C=3Dy CONFIG_BITBANG_I2C=3Dy +CONFIG_M41T80=3Dy =20 # For Macs CONFIG_MAC=3Dy diff --git a/hw/timer/Makefile.objs b/hw/timer/Makefile.objs index 8b27a4b..e16b2b9 100644 --- a/hw/timer/Makefile.objs +++ b/hw/timer/Makefile.objs @@ -6,6 +6,7 @@ common-obj-$(CONFIG_CADENCE) +=3D cadence_ttc.o common-obj-$(CONFIG_DS1338) +=3D ds1338.o common-obj-$(CONFIG_HPET) +=3D hpet.o common-obj-$(CONFIG_I8254) +=3D i8254_common.o i8254.o +common-obj-$(CONFIG_M41T80) +=3D m41t80.o common-obj-$(CONFIG_M48T59) +=3D m48t59.o ifeq ($(CONFIG_ISA_BUS),y) common-obj-$(CONFIG_M48T59) +=3D m48t59-isa.o diff --git a/hw/timer/m41t80.c b/hw/timer/m41t80.c new file mode 100644 index 0000000..734d7d9 --- /dev/null +++ b/hw/timer/m41t80.c @@ -0,0 +1,117 @@ +/* + * M41T80 serial rtc emulation + * + * Copyright (c) 2018 BALATON Zoltan + * + * This work is licensed under the GNU GPL license version 2 or later. + * + */ + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "qemu/timer.h" +#include "qemu/bcd.h" +#include "hw/i2c/i2c.h" + +#define TYPE_M41T80 "m41t80" +#define M41T80(obj) OBJECT_CHECK(M41t80State, (obj), TYPE_M41T80) + +typedef struct M41t80State { + I2CSlave parent_obj; + int8_t addr; +} M41t80State; + +static void m41t80_realize(DeviceState *dev, Error **errp) +{ + M41t80State *s =3D M41T80(dev); + + s->addr =3D -1; +} + +static int m41t80_send(I2CSlave *i2c, uint8_t data) +{ + M41t80State *s =3D M41T80(i2c); + + if (s->addr < 0) { + s->addr =3D data; + } else { + s->addr++; + } + return 0; +} + +static int m41t80_recv(I2CSlave *i2c) +{ + M41t80State *s =3D M41T80(i2c); + struct tm now; + qemu_timeval tv; + + if (s->addr < 0) { + s->addr =3D 0; + } + if (s->addr >=3D 1 && s->addr <=3D 7) { + qemu_get_timedate(&now, -1); + } + switch (s->addr++) { + case 0: + qemu_gettimeofday(&tv); + return to_bcd(tv.tv_usec / 10000); + case 1: + return to_bcd(now.tm_sec); + case 2: + return to_bcd(now.tm_min); + case 3: + return to_bcd(now.tm_hour); + case 4: + return to_bcd(now.tm_wday); + case 5: + return to_bcd(now.tm_mday); + case 6: + return to_bcd(now.tm_mon + 1); + case 7: + return to_bcd(now.tm_year % 100); + case 8 ... 19: + qemu_log_mask(LOG_UNIMP, "%s: unimplemented register: %d\n", + __func__, s->addr - 1); + return 0; + default: + qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid register: %d\n", + __func__, s->addr - 1); + return 0; + } +} + +static int m41t80_event(I2CSlave *i2c, enum i2c_event event) +{ + M41t80State *s =3D M41T80(i2c); + + if (event =3D=3D I2C_START_SEND) { + s->addr =3D -1; + } + return 0; +} + +static void m41t80_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc =3D DEVICE_CLASS(klass); + I2CSlaveClass *sc =3D I2C_SLAVE_CLASS(klass); + + dc->realize =3D m41t80_realize; + sc->send =3D m41t80_send; + sc->recv =3D m41t80_recv; + sc->event =3D m41t80_event; +} + +static const TypeInfo m41t80_info =3D { + .name =3D TYPE_M41T80, + .parent =3D TYPE_I2C_SLAVE, + .instance_size =3D sizeof(M41t80State), + .class_init =3D m41t80_class_init, +}; + +static void m41t80_register_types(void) +{ + type_register_static(&m41t80_info); +} + +type_init(m41t80_register_types) --=20 2.7.6 From nobody Tue Nov 4 05:28:36 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (208.118.235.17 [208.118.235.17]) by mx.zohomail.com with SMTPS id 1529840673068585.8894163509805; Sun, 24 Jun 2018 04:44:33 -0700 (PDT) Received: from localhost ([::1]:41418 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fX3RN-0002C5-KN for importer@patchew.org; Sun, 24 Jun 2018 07:44:21 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:55969) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fX3Pd-0001E7-Sc for qemu-devel@nongnu.org; Sun, 24 Jun 2018 07:42:34 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fX3PZ-0007n3-1a for qemu-devel@nongnu.org; Sun, 24 Jun 2018 07:42:33 -0400 Received: from zero.eik.bme.hu ([152.66.115.2]:18834) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fX3PY-0007le-Qj; Sun, 24 Jun 2018 07:42:28 -0400 Received: from zero.eik.bme.hu (blah.eik.bme.hu [152.66.115.182]) by localhost (Postfix) with SMTP id 768187456B3; Sun, 24 Jun 2018 13:42:20 +0200 (CEST) Received: by zero.eik.bme.hu (Postfix, from userid 432) id 0518D7456C6; Sun, 24 Jun 2018 13:42:20 +0200 (CEST) Message-Id: <35f80e9e4960ce04b8918c5208914daad4073c89.1529839203.git.balaton@eik.bme.hu> In-Reply-To: References: From: BALATON Zoltan Date: Sun, 24 Jun 2018 13:20:03 +0200 To: qemu-devel@nongnu.org, qemu-ppc@nongnu.org X-detected-operating-system: by eggs.gnu.org: FreeBSD 9.x [fuzzy] X-Received-From: 152.66.115.2 Subject: [Qemu-devel] [PATCH v5 3/4] sam460ex: Add RTC device 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: Alexander Graf , David Gibson Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" The Sam460ex has an M41T80 serial RTC chip on I2C bus 0 at address 0x68. Signed-off-by: BALATON Zoltan Reviewed-by: C=C3=A9dric Le Goater --- hw/ppc/sam460ex.c | 1 + 1 file changed, 1 insertion(+) diff --git a/hw/ppc/sam460ex.c b/hw/ppc/sam460ex.c index bdc53d2..dc730cc 100644 --- a/hw/ppc/sam460ex.c +++ b/hw/ppc/sam460ex.c @@ -457,6 +457,7 @@ static void sam460ex_init(MachineState *machine) object_property_set_bool(OBJECT(dev), true, "realized", NULL); smbus_eeprom_init(i2c[0]->bus, 8, smbus_eeprom_buf, smbus_eeprom_size); g_free(smbus_eeprom_buf); + i2c_create_slave(i2c[0]->bus, "m41t80", 0x68); =20 dev =3D sysbus_create_simple(TYPE_PPC4xx_I2C, 0x4ef600800, uic[0][3]); i2c[1] =3D PPC4xx_I2C(dev); --=20 2.7.6 From nobody Tue Nov 4 05:28:36 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1529840794546357.9149235336138; Sun, 24 Jun 2018 04:46:34 -0700 (PDT) Received: from localhost ([::1]:41436 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fX3TV-0003tb-Ro for importer@patchew.org; Sun, 24 Jun 2018 07:46:33 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:55973) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fX3Pd-0001E9-TN for qemu-devel@nongnu.org; Sun, 24 Jun 2018 07:42:35 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fX3PZ-0007nN-9A for qemu-devel@nongnu.org; Sun, 24 Jun 2018 07:42:33 -0400 Received: from zero.eik.bme.hu ([2001:738:2001:2001::2001]:18832) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fX3PY-0007ld-Qo; Sun, 24 Jun 2018 07:42:29 -0400 Received: from zero.eik.bme.hu (blah.eik.bme.hu [152.66.115.182]) by localhost (Postfix) with SMTP id 50AE37456AF; Sun, 24 Jun 2018 13:42:20 +0200 (CEST) Received: by zero.eik.bme.hu (Postfix, from userid 432) id 08F197456CB; Sun, 24 Jun 2018 13:42:20 +0200 (CEST) Message-Id: In-Reply-To: References: From: BALATON Zoltan Date: Sun, 24 Jun 2018 13:20:03 +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 v5 4/4] ppc440_uc: Basic emulation of PPC440 DMA controller 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: Alexander Graf , David Gibson Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" PPC440 SoCs such as the AMCC 460EX have a DMA controller which is used by AmigaOS on the sam460ex. Implement the parts used by AmigaOS so it can get further booting on the sam460ex machine. Signed-off-by: BALATON Zoltan --- hw/ppc/ppc440.h | 1 + hw/ppc/ppc440_uc.c | 215 +++++++++++++++++++++++++++++++++++++++++++++++++= ++++ hw/ppc/sam460ex.c | 3 + 3 files changed, 219 insertions(+) diff --git a/hw/ppc/ppc440.h b/hw/ppc/ppc440.h index ad27db1..7cef936 100644 --- a/hw/ppc/ppc440.h +++ b/hw/ppc/ppc440.h @@ -21,6 +21,7 @@ void ppc440_sdram_init(CPUPPCState *env, int nbanks, hwaddr *ram_bases, hwaddr *ram_sizes, int do_init); void ppc4xx_ahb_init(CPUPPCState *env); +void ppc4xx_dma_init(CPUPPCState *env, int dcr_base); void ppc460ex_pcie_init(CPUPPCState *env); =20 #endif /* PPC440_H */ diff --git a/hw/ppc/ppc440_uc.c b/hw/ppc/ppc440_uc.c index 123f4ac..38aadd9 100644 --- a/hw/ppc/ppc440_uc.c +++ b/hw/ppc/ppc440_uc.c @@ -13,6 +13,7 @@ #include "qemu/cutils.h" #include "qemu/error-report.h" #include "qapi/error.h" +#include "qemu/log.h" #include "cpu.h" #include "hw/hw.h" #include "exec/address-spaces.h" @@ -803,6 +804,220 @@ void ppc4xx_ahb_init(CPUPPCState *env) } =20 /*************************************************************************= ****/ +/* DMA controller */ + +#define DMA0_CR_CE (1 << 31) +#define DMA0_CR_PW (1 << 26 | 1 << 25) +#define DMA0_CR_DAI (1 << 24) +#define DMA0_CR_SAI (1 << 23) +#define DMA0_CR_DEC (1 << 2) + +enum { + DMA0_CR =3D 0x00, + DMA0_CT, + DMA0_SAH, + DMA0_SAL, + DMA0_DAH, + DMA0_DAL, + DMA0_SGH, + DMA0_SGL, + + DMA0_SR =3D 0x20, + DMA0_SGC =3D 0x23, + DMA0_SLP =3D 0x25, + DMA0_POL =3D 0x26, +}; + +typedef struct { + uint32_t cr; + uint32_t ct; + uint64_t sa; + uint64_t da; + uint64_t sg; +} ppc4xx_dma_ch_t; + +typedef struct { + int base; + ppc4xx_dma_ch_t ch[4]; + uint32_t sr; +} ppc4xx_dma_t; + +static uint32_t dcr_read_dma(void *opaque, int dcrn) +{ + ppc4xx_dma_t *dma =3D opaque; + uint32_t val =3D 0; + int addr =3D dcrn - dma->base; + int chnl =3D addr / 8; + + switch (addr) { + case 0x00 ... 0x1f: + switch (addr % 8) { + case DMA0_CR: + val =3D dma->ch[chnl].cr; + break; + case DMA0_CT: + val =3D dma->ch[chnl].ct; + break; + case DMA0_SAH: + val =3D dma->ch[chnl].sa >> 32; + break; + case DMA0_SAL: + val =3D dma->ch[chnl].sa; + break; + case DMA0_DAH: + val =3D dma->ch[chnl].da >> 32; + break; + case DMA0_DAL: + val =3D dma->ch[chnl].da; + break; + case DMA0_SGH: + val =3D dma->ch[chnl].sg >> 32; + break; + case DMA0_SGL: + val =3D dma->ch[chnl].sg; + break; + } + break; + case DMA0_SR: + val =3D dma->sr; + break; + default: + qemu_log_mask(LOG_UNIMP, "%s: unimplemented register %x (%d, %x)\n= ", + __func__, dcrn, chnl, addr); + } + + return val; +} + +static void dcr_write_dma(void *opaque, int dcrn, uint32_t val) +{ + ppc4xx_dma_t *dma =3D opaque; + int addr =3D dcrn - dma->base; + int chnl =3D addr / 8; + + switch (addr) { + case 0x00 ... 0x1f: + switch (addr % 8) { + case DMA0_CR: + dma->ch[chnl].cr =3D val; + if (val & DMA0_CR_CE) { + int count =3D dma->ch[chnl].ct & 0xffff; + + if (count) { + int width, i, sidx, didx; + uint8_t *rptr, *wptr; + hwaddr rlen, wlen; + + width =3D 1 << ((val & DMA0_CR_PW) >> 25); + rptr =3D cpu_physical_memory_map(dma->ch[chnl].sa, &rl= en, 0); + wptr =3D cpu_physical_memory_map(dma->ch[chnl].da, &wl= en, 1); + if (!(val & DMA0_CR_DEC) && + val & DMA0_CR_SAI && val & DMA0_CR_DAI) { + /* optimise common case */ + memmove(wptr, rptr, count * width); + sidx =3D didx =3D count * width; + } else { + /* do it the slow way */ + for (sidx =3D didx =3D i =3D 0; i < count; i++) { + uint64_t v =3D ldn_le_p(rptr + sidx, width); + stn_le_p(wptr + didx, width, v); + if (val & DMA0_CR_SAI) { + sidx +=3D width; + } + if (val & DMA0_CR_DAI) { + didx +=3D width; + } + } + } + cpu_physical_memory_unmap(wptr, wlen, 1, didx); + cpu_physical_memory_unmap(rptr, rlen, 0, sidx); + } + } + break; + case DMA0_CT: + dma->ch[chnl].ct =3D val; + break; + case DMA0_SAH: + dma->ch[chnl].sa &=3D 0xffffffffULL; + dma->ch[chnl].sa |=3D (uint64_t)val << 32; + break; + case DMA0_SAL: + dma->ch[chnl].sa &=3D 0xffffffff00000000ULL; + dma->ch[chnl].sa |=3D val; + break; + case DMA0_DAH: + dma->ch[chnl].da &=3D 0xffffffffULL; + dma->ch[chnl].da |=3D (uint64_t)val << 32; + break; + case DMA0_DAL: + dma->ch[chnl].da &=3D 0xffffffff00000000ULL; + dma->ch[chnl].da |=3D val; + break; + case DMA0_SGH: + dma->ch[chnl].sg &=3D 0xffffffffULL; + dma->ch[chnl].sg |=3D (uint64_t)val << 32; + break; + case DMA0_SGL: + dma->ch[chnl].sg &=3D 0xffffffff00000000ULL; + dma->ch[chnl].sg |=3D val; + break; + } + break; + case DMA0_SR: + dma->sr &=3D ~val; + break; + default: + qemu_log_mask(LOG_UNIMP, "%s: unimplemented register %x (%d, %x)\n= ", + __func__, dcrn, chnl, addr); + } +} + +static void ppc4xx_dma_reset(void *opaque) +{ + ppc4xx_dma_t *dma =3D opaque; + int dma_base =3D dma->base; + + memset(dma, 0, sizeof(*dma)); + dma->base =3D dma_base; +} + +void ppc4xx_dma_init(CPUPPCState *env, int dcr_base) +{ + ppc4xx_dma_t *dma; + int i; + + dma =3D g_malloc0(sizeof(*dma)); + dma->base =3D dcr_base; + qemu_register_reset(&ppc4xx_dma_reset, dma); + for (i =3D 0; i < 4; i++) { + ppc_dcr_register(env, dcr_base + i * 8 + DMA0_CR, + dma, &dcr_read_dma, &dcr_write_dma); + ppc_dcr_register(env, dcr_base + i * 8 + DMA0_CT, + dma, &dcr_read_dma, &dcr_write_dma); + ppc_dcr_register(env, dcr_base + i * 8 + DMA0_SAH, + dma, &dcr_read_dma, &dcr_write_dma); + ppc_dcr_register(env, dcr_base + i * 8 + DMA0_SAL, + dma, &dcr_read_dma, &dcr_write_dma); + ppc_dcr_register(env, dcr_base + i * 8 + DMA0_DAH, + dma, &dcr_read_dma, &dcr_write_dma); + ppc_dcr_register(env, dcr_base + i * 8 + DMA0_DAL, + dma, &dcr_read_dma, &dcr_write_dma); + ppc_dcr_register(env, dcr_base + i * 8 + DMA0_SGH, + dma, &dcr_read_dma, &dcr_write_dma); + ppc_dcr_register(env, dcr_base + i * 8 + DMA0_SGL, + dma, &dcr_read_dma, &dcr_write_dma); + } + ppc_dcr_register(env, dcr_base + DMA0_SR, + dma, &dcr_read_dma, &dcr_write_dma); + ppc_dcr_register(env, dcr_base + DMA0_SGC, + dma, &dcr_read_dma, &dcr_write_dma); + ppc_dcr_register(env, dcr_base + DMA0_SLP, + dma, &dcr_read_dma, &dcr_write_dma); + ppc_dcr_register(env, dcr_base + DMA0_POL, + dma, &dcr_read_dma, &dcr_write_dma); +} + +/*************************************************************************= ****/ /* PCI Express controller */ /* FIXME: This is not complete and does not work, only implemented partial= ly * to allow firmware and guests to find an empty bus. Cards should use PCI. diff --git a/hw/ppc/sam460ex.c b/hw/ppc/sam460ex.c index dc730cc..4f9248e 100644 --- a/hw/ppc/sam460ex.c +++ b/hw/ppc/sam460ex.c @@ -477,6 +477,9 @@ static void sam460ex_init(MachineState *machine) /* MAL */ ppc4xx_mal_init(env, 4, 16, &uic[2][3]); =20 + /* DMA */ + ppc4xx_dma_init(env, 0x200); + /* 256K of L2 cache as memory */ ppc4xx_l2sram_init(env); /* FIXME: remove this after fixing l2sram mapping in ppc440_uc.c? */ --=20 2.7.6