From nobody Sat Sep 28 22:39:58 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=linaro.org Return-Path: Received: from lists.gnu.org (209.51.188.17 [209.51.188.17]) by mx.zohomail.com with SMTPS id 1548701651766498.9249580778012; Mon, 28 Jan 2019 10:54:11 -0800 (PST) Received: from localhost ([127.0.0.1]:37007 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1goC2n-0003K3-O4 for importer@patchew.org; Mon, 28 Jan 2019 13:54:05 -0500 Received: from eggs.gnu.org ([209.51.188.92]:41237) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1goBNe-0003AV-O7 for qemu-devel@nongnu.org; Mon, 28 Jan 2019 13:11:36 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1goBNc-0000Yd-Mo for qemu-devel@nongnu.org; Mon, 28 Jan 2019 13:11:34 -0500 Received: from mail-wm1-x333.google.com ([2a00:1450:4864:20::333]:52375) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1goBNc-0000NX-De for qemu-devel@nongnu.org; Mon, 28 Jan 2019 13:11:32 -0500 Received: by mail-wm1-x333.google.com with SMTP id m1so15043046wml.2 for ; Mon, 28 Jan 2019 10:11:17 -0800 (PST) Received: from orth.archaic.org.uk (orth.archaic.org.uk. [81.2.115.148]) by smtp.gmail.com with ESMTPSA id b18sm97910681wrw.83.2019.01.28.10.11.14 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 28 Jan 2019 10:11:15 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:subject:date:message-id:in-reply-to:references:mime-version :content-transfer-encoding; bh=P5GV8ZOhOv+ITXhiylNYBsFbrkOPLRqvGIgOhWeqpxs=; b=J6xd7OcHtP3f+/t/0kpNVbhTrWHn/hwe5+y1TSe7eohVM3K0SpowHOafauG/Hg7RnO Qi+uEMluHvey0r4ilkQsjzANzYtHw770eylZkNwCSCKczMEdtvJhNvodC2R2D7lQn35i tnr41qlZl0BPme1LHZFrCSz62lT0Dz9WWBmJ0= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=P5GV8ZOhOv+ITXhiylNYBsFbrkOPLRqvGIgOhWeqpxs=; b=KWhuasdtgbuUaOZL5UFwWCXSBgUlhZzaFt2Dl0/cg4tm86Lnx0H21peyBfmXuk26b8 bsd1v1Fqf4Simm/sb/jEShurI8i4nNRdqmEKkjzjohjNaDSY9jjmarapnINqzVrjL7u1 Wj4O9Uu6NvaL/Hg90KfnYIND4i2M4xShSYdlu/25N14YFK29bm4yUNBv1bzcO6yKM3Pb qrKPCLQuwAirkTjGRrlOtPYWpRhiwh4sqlSxOzgV6xpBX+6eeB9yPSoRJWwxxxQeWJEX a2K1tRWUr11IWpgZyDQDKn8jILrhy03byk4ZnK4fsl87woKar0SZAxk15VPF4BP+Vy57 UYrg== X-Gm-Message-State: AJcUukcjJXZSlvGjkU1f2ZSI3kOCgzvOWq5G3zCIfghFNEYJMrfhGs+Z mYoo3Tz2Oe7IeKyfA+1Wa3MKd6fqPooj+w== X-Google-Smtp-Source: ALg8bN7UAcA1Ls/ZJDUqC+Xytz6x6QA0TXtrVGjeEFk7t+KfSGNaqeEdAC2IMpQLBdPZL54NIoLkRA== X-Received: by 2002:a1c:7306:: with SMTP id d6mr17474454wmb.98.1548699075994; Mon, 28 Jan 2019 10:11:15 -0800 (PST) From: Peter Maydell To: qemu-devel@nongnu.org Date: Mon, 28 Jan 2019 18:10:42 +0000 Message-Id: <20190128181047.20781-22-peter.maydell@linaro.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190128181047.20781-1-peter.maydell@linaro.org> References: <20190128181047.20781-1-peter.maydell@linaro.org> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2a00:1450:4864:20::333 Subject: [Qemu-devel] [PULL 21/26] aspeed/smc: snoop SPI transfers to fake dummy cycles 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: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) From: C=C3=A9dric Le Goater The m25p80 models dummy cycles using byte transfers. This works well when the transfers are initiated by the QEMU model of a SPI controller but when these are initiated by the OS, it breaks emulation. Snoop the SPI transfer to catch commands requiring dummy cycles and replace them with byte transfers compatible with the m25p80 model. Signed-off-by: C=C3=A9dric Le Goater Reviewed-by: Alistair Francis Reviewed-by: Francisco Iglesias Message-id: 20190124140519.13838-5-clg@kaod.org Signed-off-by: Peter Maydell --- include/hw/ssi/aspeed_smc.h | 3 + hw/ssi/aspeed_smc.c | 115 +++++++++++++++++++++++++++++++++++- 2 files changed, 115 insertions(+), 3 deletions(-) diff --git a/include/hw/ssi/aspeed_smc.h b/include/hw/ssi/aspeed_smc.h index 1f557313fa9..3b1e7fce6c8 100644 --- a/include/hw/ssi/aspeed_smc.h +++ b/include/hw/ssi/aspeed_smc.h @@ -98,6 +98,9 @@ typedef struct AspeedSMCState { uint8_t conf_enable_w0; =20 AspeedSMCFlash *flashes; + + uint8_t snoop_index; + uint8_t snoop_dummies; } AspeedSMCState; =20 #endif /* ASPEED_SMC_H */ diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c index 9f3b6f4b450..f1e66870d71 100644 --- a/hw/ssi/aspeed_smc.c +++ b/hw/ssi/aspeed_smc.c @@ -145,6 +145,9 @@ /* Flash opcodes. */ #define SPI_OP_READ 0x03 /* Read data bytes (low frequency) */ =20 +#define SNOOP_OFF 0xFF +#define SNOOP_START 0x0 + /* * Default segments mapping addresses and size for each slave per * controller. These can be changed when board is initialized with the @@ -566,6 +569,101 @@ static uint64_t aspeed_smc_flash_read(void *opaque, h= waddr addr, unsigned size) return ret; } =20 +/* + * TODO (clg@kaod.org): stolen from xilinx_spips.c. Should move to a + * common include header. + */ +typedef enum { + READ =3D 0x3, READ_4 =3D 0x13, + FAST_READ =3D 0xb, FAST_READ_4 =3D 0x0c, + DOR =3D 0x3b, DOR_4 =3D 0x3c, + QOR =3D 0x6b, QOR_4 =3D 0x6c, + DIOR =3D 0xbb, DIOR_4 =3D 0xbc, + QIOR =3D 0xeb, QIOR_4 =3D 0xec, + + PP =3D 0x2, PP_4 =3D 0x12, + DPP =3D 0xa2, + QPP =3D 0x32, QPP_4 =3D 0x34, +} FlashCMD; + +static int aspeed_smc_num_dummies(uint8_t command) +{ + switch (command) { /* check for dummies */ + case READ: /* no dummy bytes/cycles */ + case PP: + case DPP: + case QPP: + case READ_4: + case PP_4: + case QPP_4: + return 0; + case FAST_READ: + case DOR: + case QOR: + case DOR_4: + case QOR_4: + return 1; + case DIOR: + case FAST_READ_4: + case DIOR_4: + return 2; + case QIOR: + case QIOR_4: + return 4; + default: + return -1; + } +} + +static bool aspeed_smc_do_snoop(AspeedSMCFlash *fl, uint64_t data, + unsigned size) +{ + AspeedSMCState *s =3D fl->controller; + uint8_t addr_width =3D aspeed_smc_flash_is_4byte(fl) ? 4 : 3; + + if (s->snoop_index =3D=3D SNOOP_OFF) { + return false; /* Do nothing */ + + } else if (s->snoop_index =3D=3D SNOOP_START) { + uint8_t cmd =3D data & 0xff; + int ndummies =3D aspeed_smc_num_dummies(cmd); + + /* + * No dummy cycles are expected with the current command. Turn + * off snooping and let the transfer proceed normally. + */ + if (ndummies <=3D 0) { + s->snoop_index =3D SNOOP_OFF; + return false; + } + + s->snoop_dummies =3D ndummies * 8; + + } else if (s->snoop_index >=3D addr_width + 1) { + + /* The SPI transfer has reached the dummy cycles sequence */ + for (; s->snoop_dummies; s->snoop_dummies--) { + ssi_transfer(s->spi, s->regs[R_DUMMY_DATA] & 0xff); + } + + /* If no more dummy cycles are expected, turn off snooping */ + if (!s->snoop_dummies) { + s->snoop_index =3D SNOOP_OFF; + } else { + s->snoop_index +=3D size; + } + + /* + * Dummy cycles have been faked already. Ignore the current + * SPI transfer + */ + return true; + } + + s->snoop_index +=3D size; + return false; +} + static void aspeed_smc_flash_write(void *opaque, hwaddr addr, uint64_t dat= a, unsigned size) { @@ -581,6 +679,10 @@ static void aspeed_smc_flash_write(void *opaque, hwadd= r addr, uint64_t data, =20 switch (aspeed_smc_flash_mode(fl)) { case CTRL_USERMODE: + if (aspeed_smc_do_snoop(fl, data, size)) { + break; + } + for (i =3D 0; i < size; i++) { ssi_transfer(s->spi, (data >> (8 * i)) & 0xff); } @@ -613,7 +715,9 @@ static const MemoryRegionOps aspeed_smc_flash_ops =3D { =20 static void aspeed_smc_flash_update_cs(AspeedSMCFlash *fl) { - const AspeedSMCState *s =3D fl->controller; + AspeedSMCState *s =3D fl->controller; + + s->snoop_index =3D aspeed_smc_is_ce_stop_active(fl) ? SNOOP_OFF : SNOO= P_START; =20 qemu_set_irq(s->cs_lines[fl->id], aspeed_smc_is_ce_stop_active(fl)); } @@ -652,6 +756,9 @@ static void aspeed_smc_reset(DeviceState *d) if (s->ctrl->segments =3D=3D aspeed_segments_fmc) { s->regs[s->r_conf] |=3D (CONF_FLASH_TYPE_SPI << CONF_FLASH_TYPE0); } + + s->snoop_index =3D SNOOP_OFF; + s->snoop_dummies =3D 0; } =20 static uint64_t aspeed_smc_read(void *opaque, hwaddr addr, unsigned int si= ze) @@ -793,10 +900,12 @@ static void aspeed_smc_realize(DeviceState *dev, Erro= r **errp) =20 static const VMStateDescription vmstate_aspeed_smc =3D { .name =3D "aspeed.smc", - .version_id =3D 1, - .minimum_version_id =3D 1, + .version_id =3D 2, + .minimum_version_id =3D 2, .fields =3D (VMStateField[]) { VMSTATE_UINT32_ARRAY(regs, AspeedSMCState, ASPEED_SMC_R_MAX), + VMSTATE_UINT8(snoop_index, AspeedSMCState), + VMSTATE_UINT8(snoop_dummies, AspeedSMCState), VMSTATE_END_OF_LIST() } }; --=20 2.20.1