Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/1197469/?format=api
{ "id": 1197469, "url": "http://patchwork.ozlabs.org/api/patches/1197469/?format=api", "web_url": "http://patchwork.ozlabs.org/project/qemu-devel/patch/20191119141211.25716-5-clg@kaod.org/", "project": { "id": 14, "url": "http://patchwork.ozlabs.org/api/projects/14/?format=api", "name": "QEMU Development", "link_name": "qemu-devel", "list_id": "qemu-devel.nongnu.org", "list_email": "qemu-devel@nongnu.org", "web_url": "", "scm_url": "", "webscm_url": "", "list_archive_url": "", "list_archive_url_format": "", "commit_url_format": "" }, "msgid": "<20191119141211.25716-5-clg@kaod.org>", "list_archive_url": null, "date": "2019-11-19T14:11:58", "name": "[04/17] aspeed/i2c: Add support for DMA transfers", "commit_ref": null, "pull_url": null, "state": "new", "archived": false, "hash": "3b719dea769da55ee7bf3d8002227f452a6be014", "submitter": { "id": 68548, "url": "http://patchwork.ozlabs.org/api/people/68548/?format=api", "name": "Cédric Le Goater", "email": "clg@kaod.org" }, "delegate": null, "mbox": "http://patchwork.ozlabs.org/project/qemu-devel/patch/20191119141211.25716-5-clg@kaod.org/mbox/", "series": [ { "id": 143789, "url": "http://patchwork.ozlabs.org/api/series/143789/?format=api", "web_url": "http://patchwork.ozlabs.org/project/qemu-devel/list/?series=143789", "date": "2019-11-19T14:11:54", "name": "aspeed: extensions and fixes", "version": 1, "mbox": "http://patchwork.ozlabs.org/series/143789/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/1197469/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/1197469/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "<qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org>", "X-Original-To": "incoming@patchwork.ozlabs.org", "Delivered-To": "patchwork-incoming@bilbo.ozlabs.org", "Authentication-Results": [ "ozlabs.org; spf=pass (sender SPF authorized)\n\tsmtp.mailfrom=nongnu.org (client-ip=209.51.188.17;\n\thelo=lists.gnu.org;\n\tenvelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org;\n\treceiver=<UNKNOWN>)", "ozlabs.org;\n\tdmarc=none (p=none dis=none) header.from=kaod.org" ], "Received": [ "from lists.gnu.org (lists.gnu.org [209.51.188.17])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256\n\tbits)) (No client certificate requested)\n\tby ozlabs.org (Postfix) with ESMTPS id 47HSYT5R0dz9sPf\n\tfor <incoming@patchwork.ozlabs.org>;\n\tWed, 20 Nov 2019 01:16:29 +1100 (AEDT)", "from localhost ([::1]:45966 helo=lists1p.gnu.org)\n\tby lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from\n\t<qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org>)\n\tid 1iX4It-0000fC-0W\n\tfor incoming@patchwork.ozlabs.org; Tue, 19 Nov 2019 09:16:27 -0500", "from eggs.gnu.org ([2001:470:142:3::10]:41867)\n\tby lists.gnu.org with esmtp (Exim 4.90_1)\n\t(envelope-from <clg@kaod.org>) id 1iX4FW-0005mq-E3\n\tfor qemu-devel@nongnu.org; Tue, 19 Nov 2019 09:13:00 -0500", "from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71)\n\t(envelope-from <clg@kaod.org>) id 1iX4FU-0005EI-IK\n\tfor qemu-devel@nongnu.org; Tue, 19 Nov 2019 09:12:58 -0500", "from 1.mo7.mail-out.ovh.net ([178.33.45.51]:57623)\n\tby eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32)\n\t(Exim 4.71) (envelope-from <clg@kaod.org>) id 1iX4FU-0005Da-BP\n\tfor qemu-devel@nongnu.org; Tue, 19 Nov 2019 09:12:56 -0500", "from player795.ha.ovh.net (unknown [10.108.42.174])\n\tby mo7.mail-out.ovh.net (Postfix) with ESMTP id 9378713E349\n\tfor <qemu-devel@nongnu.org>; Tue, 19 Nov 2019 15:12:54 +0100 (CET)", "from kaod.org (deibp9eh1--blueice1n4.emea.ibm.com [195.212.29.166])\n\t(Authenticated sender: clg@kaod.org)\n\tby player795.ha.ovh.net (Postfix) with ESMTPSA id BF1F2C18A8E3;\n\tTue, 19 Nov 2019 14:12:46 +0000 (UTC)" ], "From": "=?utf-8?q?C=C3=A9dric_Le_Goater?= <clg@kaod.org>", "To": "Peter Maydell <peter.maydell@linaro.org>", "Subject": "[PATCH 04/17] aspeed/i2c: Add support for DMA transfers", "Date": "Tue, 19 Nov 2019 15:11:58 +0100", "Message-Id": "<20191119141211.25716-5-clg@kaod.org>", "X-Mailer": "git-send-email 2.21.0", "In-Reply-To": "<20191119141211.25716-1-clg@kaod.org>", "References": "<20191119141211.25716-1-clg@kaod.org>", "MIME-Version": "1.0", "Content-Type": "text/plain; charset=UTF-8", "X-Ovh-Tracer-Id": "17898993770433973009", "X-VR-SPAMSTATE": "OK", "X-VR-SPAMSCORE": "-100", "X-VR-SPAMCAUSE": "gggruggvucftvghtrhhoucdtuddrgedufedrudegkedgiedvucetufdoteggodetrfdotffvucfrrhhofhhilhgvmecuqfggjfdqfffguegfifdpvefjgfevmfevgfenuceurghilhhouhhtmecuhedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmnecujfgurhephffvufffkffojghfgggtgfesthekredtredtjeenucfhrhhomhepveorughrihgtucfnvgcuifhorghtvghruceotghlgheskhgrohgurdhorhhgqeenucfkpheptddrtddrtddrtddpudelhedrvdduvddrvdelrdduieeinecurfgrrhgrmhepmhhouggvpehsmhhtphdqohhuthdphhgvlhhopehplhgrhigvrhejleehrdhhrgdrohhvhhdrnhgvthdpihhnvghtpedtrddtrddtrddtpdhmrghilhhfrhhomheptghlgheskhgrohgurdhorhhgpdhrtghpthhtohepqhgvmhhuqdguvghvvghlsehnohhnghhnuhdrohhrghenucevlhhushhtvghrufhiiigvpedu", "Content-Transfer-Encoding": "quoted-printable", "X-detected-operating-system": "by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic]\n\t[fuzzy]", "X-Received-From": "178.33.45.51", "X-BeenThere": "qemu-devel@nongnu.org", "X-Mailman-Version": "2.1.23", "Precedence": "list", "List-Id": "<qemu-devel.nongnu.org>", "List-Unsubscribe": "<https://lists.nongnu.org/mailman/options/qemu-devel>,\n\t<mailto:qemu-devel-request@nongnu.org?subject=unsubscribe>", "List-Archive": "<https://lists.nongnu.org/archive/html/qemu-devel>", "List-Post": "<mailto:qemu-devel@nongnu.org>", "List-Help": "<mailto:qemu-devel-request@nongnu.org?subject=help>", "List-Subscribe": "<https://lists.nongnu.org/mailman/listinfo/qemu-devel>,\n\t<mailto:qemu-devel-request@nongnu.org?subject=subscribe>", "Cc": "Jae Hyun Yoo <jae.hyun.yoo@linux.intel.com>, Andrew Jeffery\n\t<andrew@aj.id.au>, qemu-devel@nongnu.org, qemu-arm@nongnu.org,\n\t=?utf-8?q?C=C3=A9dric_Le_Goater?= <clg@kaod.org>,\n\tJoel Stanley <joel@jms.id.au>", "Errors-To": "qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org", "Sender": "\"Qemu-devel\"\n\t<qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org>" }, "content": "The I2C controller of the Aspeed AST2500 and AST2600 SoCs supports DMA\ntransfers to and from DRAM.\n\nA pair of registers defines the buffer address and the length of the\nDMA transfer. The address should be aligned on 4 bytes and the maximum\nlength should not exceed 4K. The receive or transmit DMA transfer can\nthen be initiated with specific bits in the Command/Status register of\nthe controller.\n\nSigned-off-by: Cédric Le Goater <clg@kaod.org>\nReviewed-by: Joel Stanley <joel@jms.id.au>\nTested-by: Jae Hyun Yoo <jae.hyun.yoo@linux.intel.com>\nSigned-off-by: Cédric Le Goater <clg@kaod.org>\n---\n include/hw/i2c/aspeed_i2c.h | 5 ++\n hw/arm/aspeed_ast2600.c | 5 ++\n hw/arm/aspeed_soc.c | 5 ++\n hw/i2c/aspeed_i2c.c | 126 +++++++++++++++++++++++++++++++++++-\n 4 files changed, 138 insertions(+), 3 deletions(-)", "diff": "diff --git a/include/hw/i2c/aspeed_i2c.h b/include/hw/i2c/aspeed_i2c.h\nindex 7a555072dfbf..f1b9e5bf91e2 100644\n--- a/include/hw/i2c/aspeed_i2c.h\n+++ b/include/hw/i2c/aspeed_i2c.h\n@@ -52,6 +52,8 @@ typedef struct AspeedI2CBus {\n uint32_t cmd;\n uint32_t buf;\n uint32_t pool_ctrl;\n+ uint32_t dma_addr;\n+ uint32_t dma_len;\n } AspeedI2CBus;\n \n typedef struct AspeedI2CState {\n@@ -66,6 +68,8 @@ typedef struct AspeedI2CState {\n uint8_t pool[ASPEED_I2C_MAX_POOL_SIZE];\n \n AspeedI2CBus busses[ASPEED_I2C_NR_BUSSES];\n+ MemoryRegion *dram_mr;\n+ AddressSpace dram_as;\n } AspeedI2CState;\n \n #define ASPEED_I2C_CLASS(klass) \\\n@@ -85,6 +89,7 @@ typedef struct AspeedI2CClass {\n hwaddr pool_base;\n uint8_t *(*bus_pool_base)(AspeedI2CBus *);\n bool check_sram;\n+ bool has_dma;\n \n } AspeedI2CClass;\n \ndiff --git a/hw/arm/aspeed_ast2600.c b/hw/arm/aspeed_ast2600.c\nindex a403c2aae067..0881eb25983e 100644\n--- a/hw/arm/aspeed_ast2600.c\n+++ b/hw/arm/aspeed_ast2600.c\n@@ -343,6 +343,11 @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, Error **errp)\n }\n \n /* I2C */\n+ object_property_set_link(OBJECT(&s->i2c), OBJECT(s->dram_mr), \"dram\", &err);\n+ if (err) {\n+ error_propagate(errp, err);\n+ return;\n+ }\n object_property_set_bool(OBJECT(&s->i2c), true, \"realized\", &err);\n if (err) {\n error_propagate(errp, err);\ndiff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c\nindex dd1ee0e3336d..b01c97744196 100644\n--- a/hw/arm/aspeed_soc.c\n+++ b/hw/arm/aspeed_soc.c\n@@ -311,6 +311,11 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp)\n }\n \n /* I2C */\n+ object_property_set_link(OBJECT(&s->i2c), OBJECT(s->dram_mr), \"dram\", &err);\n+ if (err) {\n+ error_propagate(errp, err);\n+ return;\n+ }\n object_property_set_bool(OBJECT(&s->i2c), true, \"realized\", &err);\n if (err) {\n error_propagate(errp, err);\ndiff --git a/hw/i2c/aspeed_i2c.c b/hw/i2c/aspeed_i2c.c\nindex c7929aa2850f..030d9c56be65 100644\n--- a/hw/i2c/aspeed_i2c.c\n+++ b/hw/i2c/aspeed_i2c.c\n@@ -23,8 +23,11 @@\n #include \"migration/vmstate.h\"\n #include \"qemu/log.h\"\n #include \"qemu/module.h\"\n+#include \"qemu/error-report.h\"\n+#include \"qapi/error.h\"\n #include \"hw/i2c/aspeed_i2c.h\"\n #include \"hw/irq.h\"\n+#include \"hw/qdev-properties.h\"\n \n /* I2C Global Register */\n \n@@ -138,7 +141,8 @@\n #define I2CD_BYTE_BUF_TX_MASK 0xff\n #define I2CD_BYTE_BUF_RX_SHIFT 8\n #define I2CD_BYTE_BUF_RX_MASK 0xff\n-\n+#define I2CD_DMA_ADDR 0x24 /* DMA Buffer Address */\n+#define I2CD_DMA_LEN 0x28 /* DMA Transfer Length < 4KB */\n \n static inline bool aspeed_i2c_bus_is_master(AspeedI2CBus *bus)\n {\n@@ -165,6 +169,7 @@ static uint64_t aspeed_i2c_bus_read(void *opaque, hwaddr offset,\n unsigned size)\n {\n AspeedI2CBus *bus = opaque;\n+ AspeedI2CClass *aic = ASPEED_I2C_GET_CLASS(bus->controller);\n \n switch (offset) {\n case I2CD_FUN_CTRL_REG:\n@@ -183,6 +188,18 @@ static uint64_t aspeed_i2c_bus_read(void *opaque, hwaddr offset,\n return bus->buf;\n case I2CD_CMD_REG:\n return bus->cmd | (i2c_bus_busy(bus->bus) << 16);\n+ case I2CD_DMA_ADDR:\n+ if (!aic->has_dma) {\n+ qemu_log_mask(LOG_GUEST_ERROR, \"%s: No DMA support\\n\", __func__);\n+ return -1;\n+ }\n+ return bus->dma_addr;\n+ case I2CD_DMA_LEN:\n+ if (!aic->has_dma) {\n+ qemu_log_mask(LOG_GUEST_ERROR, \"%s: No DMA support\\n\", __func__);\n+ return -1;\n+ }\n+ return bus->dma_len;\n default:\n qemu_log_mask(LOG_GUEST_ERROR,\n \"%s: Bad offset 0x%\" HWADDR_PRIx \"\\n\", __func__, offset);\n@@ -201,6 +218,24 @@ static uint8_t aspeed_i2c_get_state(AspeedI2CBus *bus)\n return (bus->cmd >> I2CD_TX_STATE_SHIFT) & I2CD_TX_STATE_MASK;\n }\n \n+static int aspeed_i2c_dma_read(AspeedI2CBus *bus, uint8_t *data)\n+{\n+ MemTxResult result;\n+ AspeedI2CState *s = bus->controller;\n+\n+ result = address_space_read(&s->dram_as, bus->dma_addr,\n+ MEMTXATTRS_UNSPECIFIED, data, 1);\n+ if (result != MEMTX_OK) {\n+ qemu_log_mask(LOG_GUEST_ERROR, \"%s: DRAM read failed @%08x\\n\",\n+ __func__, bus->dma_addr);\n+ return -1;\n+ }\n+\n+ bus->dma_addr++;\n+ bus->dma_len--;\n+ return 0;\n+}\n+\n static int aspeed_i2c_bus_send(AspeedI2CBus *bus, uint8_t pool_start)\n {\n AspeedI2CClass *aic = ASPEED_I2C_GET_CLASS(bus->controller);\n@@ -217,6 +252,16 @@ static int aspeed_i2c_bus_send(AspeedI2CBus *bus, uint8_t pool_start)\n }\n }\n bus->cmd &= ~I2CD_TX_BUFF_ENABLE;\n+ } else if (bus->cmd & I2CD_TX_DMA_ENABLE) {\n+ while (bus->dma_len) {\n+ uint8_t data;\n+ aspeed_i2c_dma_read(bus, &data);\n+ ret = i2c_send(bus->bus, data);\n+ if (ret) {\n+ break;\n+ }\n+ }\n+ bus->cmd &= ~I2CD_TX_DMA_ENABLE;\n } else {\n ret = i2c_send(bus->bus, bus->buf);\n }\n@@ -242,6 +287,24 @@ static void aspeed_i2c_bus_recv(AspeedI2CBus *bus)\n bus->pool_ctrl &= ~(0xff << 24);\n bus->pool_ctrl |= (i & 0xff) << 24;\n bus->cmd &= ~I2CD_RX_BUFF_ENABLE;\n+ } else if (bus->cmd & I2CD_RX_DMA_ENABLE) {\n+ uint8_t data;\n+\n+ while (bus->dma_len) {\n+ MemTxResult result;\n+\n+ data = i2c_recv(bus->bus);\n+ result = address_space_write(&s->dram_as, bus->dma_addr,\n+ MEMTXATTRS_UNSPECIFIED, &data, 1);\n+ if (result != MEMTX_OK) {\n+ qemu_log_mask(LOG_GUEST_ERROR, \"%s: DRAM write failed @%08x\\n\",\n+ __func__, bus->dma_addr);\n+ return;\n+ }\n+ bus->dma_addr++;\n+ bus->dma_len--;\n+ }\n+ bus->cmd &= ~I2CD_RX_DMA_ENABLE;\n } else {\n data = i2c_recv(bus->bus);\n bus->buf = (data & I2CD_BYTE_BUF_RX_MASK) << I2CD_BYTE_BUF_RX_SHIFT;\n@@ -268,6 +331,11 @@ static uint8_t aspeed_i2c_get_addr(AspeedI2CBus *bus)\n uint8_t *pool_base = aic->bus_pool_base(bus);\n \n return pool_base[0];\n+ } else if (bus->cmd & I2CD_TX_DMA_ENABLE) {\n+ uint8_t data;\n+\n+ aspeed_i2c_dma_read(bus, &data);\n+ return data;\n } else {\n return bus->buf;\n }\n@@ -344,6 +412,10 @@ static void aspeed_i2c_bus_handle_cmd(AspeedI2CBus *bus, uint64_t value)\n */\n pool_start++;\n }\n+ } else if (bus->cmd & I2CD_TX_DMA_ENABLE) {\n+ if (bus->dma_len == 0) {\n+ bus->cmd &= ~I2CD_M_TX_CMD;\n+ }\n } else {\n bus->cmd &= ~I2CD_M_TX_CMD;\n }\n@@ -447,9 +519,35 @@ static void aspeed_i2c_bus_write(void *opaque, hwaddr offset,\n break;\n }\n \n+ if (!aic->has_dma &&\n+ value & (I2CD_RX_DMA_ENABLE | I2CD_TX_DMA_ENABLE)) {\n+ qemu_log_mask(LOG_GUEST_ERROR, \"%s: No DMA support\\n\", __func__);\n+ break;\n+ }\n+\n aspeed_i2c_bus_handle_cmd(bus, value);\n aspeed_i2c_bus_raise_interrupt(bus);\n break;\n+ case I2CD_DMA_ADDR:\n+ if (!aic->has_dma) {\n+ qemu_log_mask(LOG_GUEST_ERROR, \"%s: No DMA support\\n\", __func__);\n+ break;\n+ }\n+\n+ bus->dma_addr = value & 0xfffffffc;\n+ break;\n+\n+ case I2CD_DMA_LEN:\n+ if (!aic->has_dma) {\n+ qemu_log_mask(LOG_GUEST_ERROR, \"%s: No DMA support\\n\", __func__);\n+ break;\n+ }\n+\n+ bus->dma_len = value & 0xfff;\n+ if (!bus->dma_len) {\n+ qemu_log_mask(LOG_UNIMP, \"%s: invalid DMA length\\n\", __func__);\n+ }\n+ break;\n \n default:\n qemu_log_mask(LOG_GUEST_ERROR, \"%s: Bad offset 0x%\" HWADDR_PRIx \"\\n\",\n@@ -542,8 +640,8 @@ static const MemoryRegionOps aspeed_i2c_pool_ops = {\n \n static const VMStateDescription aspeed_i2c_bus_vmstate = {\n .name = TYPE_ASPEED_I2C,\n- .version_id = 2,\n- .minimum_version_id = 2,\n+ .version_id = 3,\n+ .minimum_version_id = 3,\n .fields = (VMStateField[]) {\n VMSTATE_UINT8(id, AspeedI2CBus),\n VMSTATE_UINT32(ctrl, AspeedI2CBus),\n@@ -553,6 +651,8 @@ static const VMStateDescription aspeed_i2c_bus_vmstate = {\n VMSTATE_UINT32(cmd, AspeedI2CBus),\n VMSTATE_UINT32(buf, AspeedI2CBus),\n VMSTATE_UINT32(pool_ctrl, AspeedI2CBus),\n+ VMSTATE_UINT32(dma_addr, AspeedI2CBus),\n+ VMSTATE_UINT32(dma_len, AspeedI2CBus),\n VMSTATE_END_OF_LIST()\n }\n };\n@@ -584,6 +684,8 @@ static void aspeed_i2c_reset(DeviceState *dev)\n s->busses[i].intr_status = 0;\n s->busses[i].cmd = 0;\n s->busses[i].buf = 0;\n+ s->busses[i].dma_addr = 0;\n+ s->busses[i].dma_len = 0;\n i2c_end_transfer(s->busses[i].bus);\n }\n }\n@@ -640,14 +742,30 @@ static void aspeed_i2c_realize(DeviceState *dev, Error **errp)\n memory_region_init_io(&s->pool_iomem, OBJECT(s), &aspeed_i2c_pool_ops, s,\n \"aspeed.i2c-pool\", aic->pool_size);\n memory_region_add_subregion(&s->iomem, aic->pool_base, &s->pool_iomem);\n+\n+ if (aic->has_dma) {\n+ if (!s->dram_mr) {\n+ error_setg(errp, TYPE_ASPEED_I2C \": 'dram' link not set\");\n+ return;\n+ }\n+\n+ address_space_init(&s->dram_as, s->dram_mr, \"dma-dram\");\n+ }\n }\n \n+static Property aspeed_i2c_properties[] = {\n+ DEFINE_PROP_LINK(\"dram\", AspeedI2CState, dram_mr,\n+ TYPE_MEMORY_REGION, MemoryRegion *),\n+ DEFINE_PROP_END_OF_LIST(),\n+};\n+\n static void aspeed_i2c_class_init(ObjectClass *klass, void *data)\n {\n DeviceClass *dc = DEVICE_CLASS(klass);\n \n dc->vmsd = &aspeed_i2c_vmstate;\n dc->reset = aspeed_i2c_reset;\n+ dc->props = aspeed_i2c_properties;\n dc->realize = aspeed_i2c_realize;\n dc->desc = \"Aspeed I2C Controller\";\n }\n@@ -721,6 +839,7 @@ static void aspeed_2500_i2c_class_init(ObjectClass *klass, void *data)\n aic->pool_base = 0x200;\n aic->bus_pool_base = aspeed_2500_i2c_bus_pool_base;\n aic->check_sram = true;\n+ aic->has_dma = true;\n }\n \n static const TypeInfo aspeed_2500_i2c_info = {\n@@ -753,6 +872,7 @@ static void aspeed_2600_i2c_class_init(ObjectClass *klass, void *data)\n aic->pool_size = 0x200;\n aic->pool_base = 0xC00;\n aic->bus_pool_base = aspeed_2600_i2c_bus_pool_base;\n+ aic->has_dma = true;\n }\n \n static const TypeInfo aspeed_2600_i2c_info = {\n", "prefixes": [ "04/17" ] }