From patchwork Mon Oct 14 13:27:52 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Raghavendra, Vignesh" X-Patchwork-Id: 1176364 X-Patchwork-Delegate: jagannadh.teki@gmail.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=quarantine dis=none) header.from=ti.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ti.com header.i=@ti.com header.b="yEHB9zn/"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 46sKBy71gpz9sP3 for ; Tue, 15 Oct 2019 00:28:42 +1100 (AEDT) Received: by lists.denx.de (Postfix, from userid 105) id 7E0A8C21E1D; Mon, 14 Oct 2019 13:28:20 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=T_DKIM_INVALID autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id 93AF3C21DD4; Mon, 14 Oct 2019 13:28:02 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 42672C21E36; Mon, 14 Oct 2019 13:27:43 +0000 (UTC) Received: from fllv0015.ext.ti.com (fllv0015.ext.ti.com [198.47.19.141]) by lists.denx.de (Postfix) with ESMTPS id DE72EC21DFD for ; Mon, 14 Oct 2019 13:27:40 +0000 (UTC) Received: from fllv0035.itg.ti.com ([10.64.41.0]) by fllv0015.ext.ti.com (8.15.2/8.15.2) with ESMTP id x9EDRcEt123128; Mon, 14 Oct 2019 08:27:38 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ti.com; s=ti-com-17Q1; t=1571059658; bh=Z/qI3Cim0F0MllTARB3lXGy2UX2EEx4wUWKJYvPRpGY=; h=From:To:CC:Subject:Date:In-Reply-To:References; b=yEHB9zn/RLawzStaY3hBB/bJngrJS13TRW8OrjZfMansfiebTdccbVS7V6GDenyd4 Iz23wx0xwP+Wk9MAqQTBNkwQxvuHaHwVCfXq9H9Pzi1GZl6aKhTsaAkNARBXhufU40 w9gTAFjXNo8q2x8iQgRUUdcLqnNPIBpFk5y57fiE= Received: from DFLE114.ent.ti.com (dfle114.ent.ti.com [10.64.6.35]) by fllv0035.itg.ti.com (8.15.2/8.15.2) with ESMTP id x9EDRcac081947; Mon, 14 Oct 2019 08:27:38 -0500 Received: from DFLE109.ent.ti.com (10.64.6.30) by DFLE114.ent.ti.com (10.64.6.35) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1713.5; Mon, 14 Oct 2019 08:27:38 -0500 Received: from fllv0039.itg.ti.com (10.64.41.19) by DFLE109.ent.ti.com (10.64.6.30) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1713.5 via Frontend Transport; Mon, 14 Oct 2019 08:27:32 -0500 Received: from a0132425.dhcp.ti.com (ileax41-snat.itg.ti.com [10.172.224.153]) by fllv0039.itg.ti.com (8.15.2/8.15.2) with ESMTP id x9EDRV73050987; Mon, 14 Oct 2019 08:27:36 -0500 From: Vignesh Raghavendra To: Jagan Teki Date: Mon, 14 Oct 2019 18:57:52 +0530 Message-ID: <20191014132752.18534-3-vigneshr@ti.com> X-Mailer: git-send-email 2.23.0 In-Reply-To: <20191014132752.18534-1-vigneshr@ti.com> References: <20191014132752.18534-1-vigneshr@ti.com> MIME-Version: 1.0 X-EXCLAIMER-MD-CONFIG: e1e8a2fd-e40a-4ac6-ac9b-f7e9cc9ee180 Cc: u-boot@lists.denx.de, Tom Rini Subject: [U-Boot] [PATCH 2/2] spi: cadence-qspi: Add direct mode support X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 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" Add support for Direct Access Controller mode of Cadence QSPI. This allows MMIO access to SPI NOR flash providing better read performance. Signed-off-by: Vignesh R Signed-off-by: Vignesh Raghavendra --- drivers/spi/cadence_qspi.c | 40 ++++++++++++---------- drivers/spi/cadence_qspi.h | 19 ++++++----- drivers/spi/cadence_qspi_apb.c | 61 +++++++++++++++++++++++++++++----- 3 files changed, 87 insertions(+), 33 deletions(-) diff --git a/drivers/spi/cadence_qspi.c b/drivers/spi/cadence_qspi.c index 673a2e9a6c4c..6c98cbf39ae4 100644 --- a/drivers/spi/cadence_qspi.c +++ b/drivers/spi/cadence_qspi.c @@ -12,12 +12,13 @@ #include #include #include +#include #include "cadence_qspi.h" #define CQSPI_STIG_READ 0 #define CQSPI_STIG_WRITE 1 -#define CQSPI_INDIRECT_READ 2 -#define CQSPI_INDIRECT_WRITE 3 +#define CQSPI_READ 2 +#define CQSPI_WRITE 3 static int cadence_spi_write_speed(struct udevice *bus, uint hz) { @@ -189,6 +190,7 @@ static int cadence_spi_remove(struct udevice *dev) static int cadence_spi_set_mode(struct udevice *bus, uint mode) { + struct cadence_spi_platdata *plat = bus->platdata; struct cadence_spi_priv *priv = dev_get_priv(bus); /* Disable QSPI */ @@ -197,6 +199,10 @@ static int cadence_spi_set_mode(struct udevice *bus, uint mode) /* Set SPI mode */ cadence_qspi_apb_set_clk_mode(priv->regbase, mode); + /* Enable Direct Access Controller */ + if (plat->use_dac_mode) + cadence_qspi_apb_dac_mode_enable(priv->regbase); + /* Enable QSPI */ cadence_qspi_apb_controller_enable(priv->regbase); @@ -221,12 +227,12 @@ static int cadence_spi_mem_exec_op(struct spi_slave *spi, if (!op->addr.nbytes) mode = CQSPI_STIG_READ; else - mode = CQSPI_INDIRECT_READ; + mode = CQSPI_READ; } else { if (!op->addr.nbytes || !op->data.buf.out) mode = CQSPI_STIG_WRITE; else - mode = CQSPI_INDIRECT_WRITE; + mode = CQSPI_WRITE; } switch (mode) { @@ -236,19 +242,15 @@ static int cadence_spi_mem_exec_op(struct spi_slave *spi, case CQSPI_STIG_WRITE: err = cadence_qspi_apb_command_write(base, op); break; - case CQSPI_INDIRECT_READ: - err = cadence_qspi_apb_indirect_read_setup(plat, op); - if (!err) { - err = cadence_qspi_apb_indirect_read_execute - (plat, op->data.nbytes, op->data.buf.in); - } + case CQSPI_READ: + err = cadence_qspi_apb_read_setup(plat, op); + if (!err) + err = cadence_qspi_apb_read_execute(plat, op); break; - case CQSPI_INDIRECT_WRITE: - err = cadence_qspi_apb_indirect_write_setup(plat, op); - if (!err) { - err = cadence_qspi_apb_indirect_write_execute - (plat, op->data.nbytes, op->data.buf.out); - } + case CQSPI_WRITE: + err = cadence_qspi_apb_write_setup(plat, op); + if (!err) + err = cadence_qspi_apb_write_execute(plat, op); break; default: err = -1; @@ -264,13 +266,17 @@ static int cadence_spi_ofdata_to_platdata(struct udevice *bus) ofnode subnode; plat->regbase = (void *)devfdt_get_addr_index(bus, 0); - plat->ahbbase = (void *)devfdt_get_addr_index(bus, 1); + plat->ahbbase = (void *)devfdt_get_addr_size_index(bus, 1, + &plat->ahbsize); plat->is_decoded_cs = dev_read_bool(bus, "cdns,is-decoded-cs"); plat->fifo_depth = dev_read_u32_default(bus, "cdns,fifo-depth", 128); plat->fifo_width = dev_read_u32_default(bus, "cdns,fifo-width", 4); plat->trigger_address = dev_read_u32_default(bus, "cdns,trigger-address", 0); + /* Use DAC mode only when MMIO window is at least 8M wide */ + if (plat->ahbsize >= SZ_8M) + plat->use_dac_mode = true; /* All other paramters are embedded in the child node */ subnode = dev_read_first_subnode(bus); diff --git a/drivers/spi/cadence_qspi.h b/drivers/spi/cadence_qspi.h index e655b027d788..619f0bed8efd 100644 --- a/drivers/spi/cadence_qspi.h +++ b/drivers/spi/cadence_qspi.h @@ -23,6 +23,8 @@ struct cadence_spi_platdata { u32 fifo_depth; u32 fifo_width; u32 trigger_address; + fdt_addr_t ahbsize; + bool use_dac_mode; /* Flash parameters */ u32 page_size; @@ -52,20 +54,21 @@ struct cadence_spi_priv { void cadence_qspi_apb_controller_init(struct cadence_spi_platdata *plat); void cadence_qspi_apb_controller_enable(void *reg_base_addr); void cadence_qspi_apb_controller_disable(void *reg_base_addr); +void cadence_qspi_apb_dac_mode_enable(void *reg_base); int cadence_qspi_apb_command_read(void *reg_base_addr, const struct spi_mem_op *op); int cadence_qspi_apb_command_write(void *reg_base_addr, const struct spi_mem_op *op); -int cadence_qspi_apb_indirect_read_setup(struct cadence_spi_platdata *plat, - const struct spi_mem_op *op); -int cadence_qspi_apb_indirect_read_execute(struct cadence_spi_platdata *plat, - unsigned int rxlen, u8 *rxbuf); -int cadence_qspi_apb_indirect_write_setup(struct cadence_spi_platdata *plat, - const struct spi_mem_op *op); -int cadence_qspi_apb_indirect_write_execute(struct cadence_spi_platdata *plat, - unsigned int txlen, const u8 *txbuf); +int cadence_qspi_apb_read_setup(struct cadence_spi_platdata *plat, + const struct spi_mem_op *op); +int cadence_qspi_apb_read_execute(struct cadence_spi_platdata *plat, + const struct spi_mem_op *op); +int cadence_qspi_apb_write_setup(struct cadence_spi_platdata *plat, + const struct spi_mem_op *op); +int cadence_qspi_apb_write_execute(struct cadence_spi_platdata *plat, + const struct spi_mem_op *op); void cadence_qspi_apb_chipselect(void *reg_base, unsigned int chip_select, unsigned int decoder_enable); diff --git a/drivers/spi/cadence_qspi_apb.c b/drivers/spi/cadence_qspi_apb.c index 8dd0495dfcf4..fd491f2c8104 100644 --- a/drivers/spi/cadence_qspi_apb.c +++ b/drivers/spi/cadence_qspi_apb.c @@ -189,6 +189,15 @@ void cadence_qspi_apb_controller_disable(void *reg_base) writel(reg, reg_base + CQSPI_REG_CONFIG); } +void cadence_qspi_apb_dac_mode_enable(void *reg_base) +{ + unsigned int reg; + + reg = readl(reg_base + CQSPI_REG_CONFIG); + reg |= CQSPI_REG_CONFIG_DIRECT; + writel(reg, reg_base + CQSPI_REG_CONFIG); +} + /* Return 1 if idle, otherwise return 0 (busy). */ static unsigned int cadence_qspi_wait_idle(void *reg_base) { @@ -512,8 +521,8 @@ int cadence_qspi_apb_command_write(void *reg_base, const struct spi_mem_op *op) } /* Opcode + Address (3/4 bytes) + dummy bytes (0-4 bytes) */ -int cadence_qspi_apb_indirect_read_setup(struct cadence_spi_platdata *plat, - const struct spi_mem_op *op) +int cadence_qspi_apb_read_setup(struct cadence_spi_platdata *plat, + const struct spi_mem_op *op) { unsigned int reg; unsigned int rd_reg; @@ -577,8 +586,9 @@ static int cadence_qspi_wait_for_data(struct cadence_spi_platdata *plat) return -ETIMEDOUT; } -int cadence_qspi_apb_indirect_read_execute(struct cadence_spi_platdata *plat, - unsigned int n_rx, u8 *rxbuf) +static int +cadence_qspi_apb_indirect_read_execute(struct cadence_spi_platdata *plat, + unsigned int n_rx, u8 *rxbuf) { unsigned int remaining = n_rx; unsigned int bytes_to_read = 0; @@ -639,9 +649,26 @@ failrd: return ret; } +int cadence_qspi_apb_read_execute(struct cadence_spi_platdata *plat, + const struct spi_mem_op *op) +{ + u32 from = op->addr.val; + void *buf = op->data.buf.in; + size_t len = op->data.nbytes; + + if (plat->use_dac_mode && (from + len < plat->ahbsize)) { + memcpy_fromio(buf, plat->ahbbase + from, len); + if (!cadence_qspi_wait_idle(plat->regbase)) + return -EIO; + return 0; + } + + return cadence_qspi_apb_indirect_read_execute(plat, len, buf); +} + /* Opcode + Address (3/4 bytes) */ -int cadence_qspi_apb_indirect_write_setup(struct cadence_spi_platdata *plat, - const struct spi_mem_op *op) +int cadence_qspi_apb_write_setup(struct cadence_spi_platdata *plat, + const struct spi_mem_op *op) { unsigned int reg; @@ -662,8 +689,9 @@ int cadence_qspi_apb_indirect_write_setup(struct cadence_spi_platdata *plat, return 0; } -int cadence_qspi_apb_indirect_write_execute(struct cadence_spi_platdata *plat, - unsigned int n_tx, const u8 *txbuf) +static int +cadence_qspi_apb_indirect_write_execute(struct cadence_spi_platdata *plat, + unsigned int n_tx, const u8 *txbuf) { unsigned int page_size = plat->page_size; unsigned int remaining = n_tx; @@ -735,6 +763,23 @@ failwr: return ret; } +int cadence_qspi_apb_write_execute(struct cadence_spi_platdata *plat, + const struct spi_mem_op *op) +{ + u32 to = op->addr.val; + const void *buf = op->data.buf.out; + size_t len = op->data.nbytes; + + if (plat->use_dac_mode && (to + len < plat->ahbsize)) { + memcpy_toio(plat->ahbbase + to, buf, len); + if (!cadence_qspi_wait_idle(plat->regbase)) + return -EIO; + return 0; + } + + return cadence_qspi_apb_indirect_write_execute(plat, len, buf); +} + void cadence_qspi_apb_enter_xip(void *reg_base, char xip_dummy) { unsigned int reg;