From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id BA8A9C433EF for ; Tue, 24 May 2022 06:00:23 +0000 (UTC) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 15874842BE; Tue, 24 May 2022 07:58:52 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=none (p=none dis=none) header.from=aspeedtech.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Received: by phobos.denx.de (Postfix, from userid 109) id 3AAAC8429E; Tue, 24 May 2022 07:58:31 +0200 (CEST) Received: from twspam01.aspeedtech.com (twspam01.aspeedtech.com [211.20.114.71]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id A418B84285 for ; Tue, 24 May 2022 07:58:23 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=none (p=none dis=none) header.from=aspeedtech.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=chin-ting_kuo@aspeedtech.com Received: from mail.aspeedtech.com ([192.168.0.24]) by twspam01.aspeedtech.com with ESMTP id 24O5h54B062557; Tue, 24 May 2022 13:43:06 +0800 (GMT-8) (envelope-from chin-ting_kuo@aspeedtech.com) Received: from localhost.localdomain (192.168.10.10) by TWMBX02.aspeed.com (192.168.0.24) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Tue, 24 May 2022 13:57:06 +0800 From: Chin-Ting Kuo To: , , , , , , , , , Subject: [v4 09/12] spi: aspeed: SPI dirmap read support Date: Tue, 24 May 2022 13:56:47 +0800 Message-ID: <20220524055650.1115899-10-chin-ting_kuo@aspeedtech.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220524055650.1115899-1-chin-ting_kuo@aspeedtech.com> References: <20220524055650.1115899-1-chin-ting_kuo@aspeedtech.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Content-Type: text/plain X-Originating-IP: [192.168.10.10] X-ClientProxiedBy: TWMBX02.aspeed.com (192.168.0.24) To TWMBX02.aspeed.com (192.168.0.24) X-DNSRBL: X-MAIL: twspam01.aspeedtech.com 24O5h54B062557 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.5 at phobos.denx.de X-Virus-Status: Clean >From the HW point of view, the performance of command read mode is greater than user mode slightly. Thus, dirmap read framework is introduced to achieve this goal. In dirmap_create, a specific decoded address area with flash size is assigned to each CS. CPU can thus access the SPI flash as normal memory in dirmap_read function. Signed-off-by: Chin-Ting Kuo --- drivers/spi/spi-aspeed.c | 93 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) diff --git a/drivers/spi/spi-aspeed.c b/drivers/spi/spi-aspeed.c index 9574aff793..e5e348eb7b 100644 --- a/drivers/spi/spi-aspeed.c +++ b/drivers/spi/spi-aspeed.c @@ -85,6 +85,8 @@ struct aspeed_spi_info { static int aspeed_spi_trim_decoded_size(struct udevice *bus, u32 decoded_sz_arr[]); +static int aspeed_spi_decoded_range_config(struct udevice *bus, + u32 decoded_sz_arr[]); static u32 aspeed_spi_get_io_mode(u32 bus_width) { @@ -509,6 +511,95 @@ static int aspeed_spi_exec_op_user_mode(struct spi_slave *slave, return 0; } +static int aspeed_spi_dirmap_create(struct spi_mem_dirmap_desc *desc) +{ + int ret = 0; + struct udevice *dev = desc->slave->dev; + struct udevice *bus = dev->parent; + struct aspeed_spi_plat *plat = dev_get_plat(bus); + struct aspeed_spi_priv *priv = dev_get_priv(bus); + struct dm_spi_slave_plat *slave_plat = dev_get_parent_plat(dev); + const struct aspeed_spi_info *info = priv->info; + struct spi_mem_op op_tmpl = desc->info.op_tmpl; + u32 i; + u32 cs = slave_plat->cs; + u32 decoded_sz_arr[ASPEED_SPI_MAX_CS]; + u32 reg_val; + + if (desc->info.op_tmpl.data.dir == SPI_MEM_DATA_IN) { + for (i = 0; i < priv->num_cs; i++) { + reg_val = readl(plat->ctrl_base + + REG_CE0_DECODED_ADDR_REG + i * 4); + decoded_sz_arr[i] = + info->segment_end(bus, reg_val) - + info->segment_start(bus, reg_val); + } + + decoded_sz_arr[cs] = desc->info.length; + + if (info->adjust_decoded_sz) + info->adjust_decoded_sz(bus, decoded_sz_arr); + + for (i = 0; i < priv->num_cs; i++) { + dev_dbg(dev, "cs: %d, sz: 0x%x\n", i, + decoded_sz_arr[i]); + } + + ret = aspeed_spi_decoded_range_config(bus, decoded_sz_arr); + if (ret) + return ret; + + reg_val = readl(plat->ctrl_base + REG_CE0_CTRL_REG + cs * 4) & + (~info->cmd_io_ctrl_mask); + reg_val |= aspeed_spi_get_io_mode(op_tmpl.data.buswidth) | + op_tmpl.cmd.opcode << 16 | + ((op_tmpl.dummy.nbytes) & 0x3) << 6 | + ((op_tmpl.dummy.nbytes) & 0x4) << 14 | + CTRL_IO_MODE_CMD_READ; + + writel(reg_val, + plat->ctrl_base + REG_CE0_CTRL_REG + cs * 4); + priv->flashes[cs].ce_ctrl_read = reg_val; + + dev_dbg(dev, "read bus width: %d [0x%08x]\n", + op_tmpl.data.buswidth, priv->flashes[cs].ce_ctrl_read); + } else { + /* + * dirmap_write is not supported currently due to a HW + * limitation for command write mode: The written data + * length should be multiple of 4-byte. + */ + return -EOPNOTSUPP; + } + + return ret; +} + +static ssize_t aspeed_spi_dirmap_read(struct spi_mem_dirmap_desc *desc, + u64 offs, size_t len, void *buf) +{ + struct udevice *dev = desc->slave->dev; + struct aspeed_spi_priv *priv = dev_get_priv(dev->parent); + struct dm_spi_slave_plat *slave_plat = dev_get_parent_plat(dev); + u32 cs = slave_plat->cs; + int ret; + + dev_dbg(dev, "read op:0x%x, addr:0x%llx, len:0x%x\n", + desc->info.op_tmpl.cmd.opcode, offs, len); + + if (priv->flashes[cs].ahb_win_sz < offs + len || + (offs + len) % 4 != 0) { + ret = aspeed_spi_exec_op_user_mode(desc->slave, + &desc->info.op_tmpl); + if (ret != 0) + return 0; + } else { + memcpy_fromio(buf, priv->flashes[cs].ahb_base + offs, len); + } + + return len; +} + static struct aspeed_spi_flash *aspeed_spi_get_flash(struct udevice *dev) { struct udevice *bus = dev->parent; @@ -792,6 +883,8 @@ static int aspeed_spi_probe(struct udevice *bus) static const struct spi_controller_mem_ops aspeed_spi_mem_ops = { .supports_op = aspeed_spi_supports_op, .exec_op = aspeed_spi_exec_op_user_mode, + .dirmap_create = aspeed_spi_dirmap_create, + .dirmap_read = aspeed_spi_dirmap_read, }; static const struct dm_spi_ops aspeed_spi_ops = { -- 2.25.1