From patchwork Fri Jun 22 12:14:15 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?C=C3=A9dric_Le_Goater?= X-Patchwork-Id: 933302 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [203.11.71.2]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 41ByRc3ySrz9s19 for ; Fri, 22 Jun 2018 22:24:12 +1000 (AEST) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=kaod.org Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 41ByRc2TvYzF0q0 for ; Fri, 22 Jun 2018 22:24:12 +1000 (AEST) Authentication-Results: lists.ozlabs.org; dmarc=none (p=none dis=none) header.from=kaod.org X-Original-To: linux-aspeed@lists.ozlabs.org Delivered-To: linux-aspeed@lists.ozlabs.org Authentication-Results: lists.ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=kaod.org (client-ip=46.105.61.149; helo=7.mo177.mail-out.ovh.net; envelope-from=clg@kaod.org; receiver=) Authentication-Results: lists.ozlabs.org; dmarc=none (p=none dis=none) header.from=kaod.org X-Greylist: delayed 544 seconds by postgrey-1.36 at bilbo; Fri, 22 Jun 2018 22:24:07 AEST Received: from 7.mo177.mail-out.ovh.net (7.mo177.mail-out.ovh.net [46.105.61.149]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 41ByRW6cBxzDrbK for ; Fri, 22 Jun 2018 22:24:07 +1000 (AEST) Received: from player792.ha.ovh.net (unknown [10.109.108.13]) by mo177.mail-out.ovh.net (Postfix) with ESMTP id 78790B42B3 for ; Fri, 22 Jun 2018 14:14:59 +0200 (CEST) Received: from zorba.kaod.org (LFbn-TOU-1-49-10.w86-201.abo.wanadoo.fr [86.201.141.10]) (Authenticated sender: clg@kaod.org) by player792.ha.ovh.net (Postfix) with ESMTPSA id BD743A00B4; Fri, 22 Jun 2018 14:14:48 +0200 (CEST) From: =?utf-8?q?C=C3=A9dric_Le_Goater?= To: linux-mtd@lists.infradead.org Subject: [PATCH 2/4] mtd: spi-nor: aspeed: add support for SPI dual IO read mode Date: Fri, 22 Jun 2018 14:14:15 +0200 Message-Id: <20180622121417.6762-3-clg@kaod.org> X-Mailer: git-send-email 2.13.6 In-Reply-To: <20180622121417.6762-1-clg@kaod.org> References: <20180622121417.6762-1-clg@kaod.org> MIME-Version: 1.0 X-Ovh-Tracer-Id: 16736220643101739955 X-VR-SPAMSTATE: OK X-VR-SPAMSCORE: -100 X-VR-SPAMCAUSE: gggruggvucftvghtrhhoucdtuddrgedtiedrtdeigdeglecutefuodetggdotefrodftvfcurfhrohhfihhlvgemucfqggfjpdevjffgvefmvefgnecuuegrihhlohhuthemuceftddtnecusecvtfgvtghiphhivghnthhsucdlqddutddtmd X-BeenThere: linux-aspeed@lists.ozlabs.org X-Mailman-Version: 2.1.26 Precedence: list List-Id: Linux ASPEED SoC development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Boris Brezillon , linux-aspeed@lists.ozlabs.org, Richard Weinberger , Marek Vasut , Brian Norris , David Woodhouse Errors-To: linux-aspeed-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "Linux-aspeed" Implements support for the dual IO read mode on aspeed SMC/FMC controllers which uses both MISO and MOSI lines for data during a read to double the read bandwidth. Still to be done SNOR_PROTO_1_2_2 Based on work from Robert Lippert Signed-off-by: Cédric Le Goater Reviewed-by: Joel Stanley --- drivers/mtd/spi-nor/aspeed-smc.c | 56 +++++++++++++++++++++++++++++++--------- 1 file changed, 44 insertions(+), 12 deletions(-) diff --git a/drivers/mtd/spi-nor/aspeed-smc.c b/drivers/mtd/spi-nor/aspeed-smc.c index af84a6fa2360..054614f34698 100644 --- a/drivers/mtd/spi-nor/aspeed-smc.c +++ b/drivers/mtd/spi-nor/aspeed-smc.c @@ -373,18 +373,49 @@ static void aspeed_smc_send_cmd_addr(struct spi_nor *nor, u8 cmd, u32 addr) } } +static int aspeed_smc_get_io_mode(struct aspeed_smc_chip *chip) +{ + switch (chip->nor.read_proto) { + case SNOR_PROTO_1_1_1: + return 0; + case SNOR_PROTO_1_1_2: + return CONTROL_IO_DUAL_DATA; + case SNOR_PROTO_1_2_2: + return CONTROL_IO_DUAL_ADDR_DATA; + default: + dev_err(chip->nor.dev, "unsupported SPI read mode\n"); + return -EINVAL; + } +} + +static void aspeed_smc_set_io_mode(struct aspeed_smc_chip *chip, u32 io_mode) +{ + u32 ctl; + + if (io_mode > 0) { + ctl = readl(chip->ctl) & ~CONTROL_IO_MODE_MASK; + ctl |= io_mode; + writel(ctl, chip->ctl); + } +} + static ssize_t aspeed_smc_read_user(struct spi_nor *nor, loff_t from, size_t len, u_char *read_buf) { struct aspeed_smc_chip *chip = nor->priv; int i; u8 dummy = 0xFF; + int io_mode = aspeed_smc_get_io_mode(chip); aspeed_smc_start_user(nor); aspeed_smc_send_cmd_addr(nor, nor->read_opcode, from); for (i = 0; i < chip->nor.read_dummy / 8; i++) aspeed_smc_write_to_ahb(chip->ahb_base, &dummy, sizeof(dummy)); + /* Set IO mode only for data */ + if (io_mode == CONTROL_IO_DUAL_DATA) + aspeed_smc_set_io_mode(chip, io_mode); + aspeed_smc_read_from_ahb(read_buf, chip->ahb_base, len); aspeed_smc_stop_user(nor); return len; @@ -735,6 +766,7 @@ static int aspeed_smc_chip_setup_finish(struct aspeed_smc_chip *chip) { struct aspeed_smc_controller *controller = chip->controller; const struct aspeed_smc_info *info = controller->info; + int io_mode; u32 cmd; if (chip->nor.addr_width == 4 && info->set_4b) @@ -757,22 +789,21 @@ static int aspeed_smc_chip_setup_finish(struct aspeed_smc_chip *chip) * TODO: Adjust clocks if fast read is supported and interpret * SPI-NOR flags to adjust controller settings. */ - if (chip->nor.read_proto == SNOR_PROTO_1_1_1) { - if (chip->nor.read_dummy == 0) - cmd = CONTROL_COMMAND_MODE_NORMAL; - else - cmd = CONTROL_COMMAND_MODE_FREAD; - } else { - dev_err(chip->nor.dev, "unsupported SPI read mode\n"); - return -EINVAL; - } + io_mode = aspeed_smc_get_io_mode(chip); + if (io_mode < 0) + return io_mode; - chip->ctl_val[smc_read] |= cmd | + if (chip->nor.read_dummy == 0) + cmd = CONTROL_COMMAND_MODE_NORMAL; + else + cmd = CONTROL_COMMAND_MODE_FREAD; + + chip->ctl_val[smc_read] |= cmd | io_mode | chip->nor.read_opcode << CONTROL_COMMAND_SHIFT | CONTROL_IO_DUMMY_SET(chip->nor.read_dummy / 8); - dev_dbg(controller->dev, "base control register: %08x\n", - chip->ctl_val[smc_read]); + dev_info(controller->dev, "read control register: %08x\n", + chip->ctl_val[smc_read]); return 0; } @@ -782,6 +813,7 @@ static int aspeed_smc_setup_flash(struct aspeed_smc_controller *controller, const struct spi_nor_hwcaps hwcaps = { .mask = SNOR_HWCAPS_READ | SNOR_HWCAPS_READ_FAST | + SNOR_HWCAPS_READ_1_1_2 | SNOR_HWCAPS_PP, }; const struct aspeed_smc_info *info = controller->info;