Received: by 2002:a05:6a10:5bc5:0:0:0:0 with SMTP id os5csp2137871pxb; Mon, 11 Oct 2021 23:20:42 -0700 (PDT) X-Google-Smtp-Source: ABdhPJzgc+dDqX2N4FS4zJ6MaGU9rRlfuQbIDlb8pBFfOsTM8Ev2Dxv8nCdbby4niLigu66mXhlI X-Received: by 2002:a50:d8c2:: with SMTP id y2mr47389391edj.360.1634019642441; Mon, 11 Oct 2021 23:20:42 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1634019642; cv=none; d=google.com; s=arc-20160816; b=MrZnfsRCkNYoG//huWzSKu3qGLGfh9jdAvmbfjHM3fWV1EbijHtAn1f+YE0Q5LHUio ktjVfsSsIPyKc63M37fYnqP4KvRJjd9hmHPvuVkpmiZno5Af/jircsTTLdm/ZfF0bZLZ LKzxqgFQQq/HjwKTYqicIBrA0SXkPFk/sT+tKRFJUxlu4ULF9+P3jMjfxdtwzkMfbuKA NHS5SXn0UvRW3zObTq3mGbeZJBlmhq7e54hrP/YyKho3Og0ON59+ryfGtnwlovH9m2YH 0TAwInWB/KAtWuumy0eFaeLR9x9B+fauXCkFkiXw6+OhFbNPpr7OP6JW2GBH5kniQsmn WoNg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature:dkim-signature; bh=L510CHpjo1YY2067LRyVcJ8FsxKVpTHc7AorOe0IHRo=; b=MXMk8uAV63/0TpueeZ0PMmQyUlDcvVOpsQkId9wlvjZpaZu1etfQ9HHW36AGUh+Wcf ToXLcuIsnJDheBgULv2MU7q5cUnwiF2i2Qjc5cRdTIG52sNnLV+/zS7HSYcLyYneaPkz QPs1FqEb14BDqR/KkXUaUlprJOsxGrjHsldg4BkXhizMC20y+dv5btN98gHfMubmHc5P UCDUfCQtKVYhPXvcD4uva0L8pwXe1gTNV62yH2M/5cO2UGQcv7eqk00mwqcejWwe1nnQ /2bpRI27xIxy7NtS2IZH1LAerS7c7rc2v76iWyE4wc9uA4kbTPk9N6vSht4jkMqMVpmE 8AIQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@tq-group.com header.s=key1 header.b=BiNu2CXQ; dkim=pass header.i=@tq-group.com header.s=key1 header.b=lYWtSDbh; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=tq-group.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id o1si26442040ejy.319.2021.10.11.23.20.18; Mon, 11 Oct 2021 23:20:42 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@tq-group.com header.s=key1 header.b=BiNu2CXQ; dkim=pass header.i=@tq-group.com header.s=key1 header.b=lYWtSDbh; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=tq-group.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232931AbhJLGTv (ORCPT + 99 others); Tue, 12 Oct 2021 02:19:51 -0400 Received: from mx1.tq-group.com ([93.104.207.81]:3020 "EHLO mx1.tq-group.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232809AbhJLGTs (ORCPT ); Tue, 12 Oct 2021 02:19:48 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=tq-group.com; i=@tq-group.com; q=dns/txt; s=key1; t=1634019467; x=1665555467; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=L510CHpjo1YY2067LRyVcJ8FsxKVpTHc7AorOe0IHRo=; b=BiNu2CXQ6CGDK76vH2GgqxMPw71hsLMaNF1L5dO+TgZchHIBh42jijnH DXvIBI5N1bzlMmS/Zcj0/d62rtLqLOJpcQvEtiwbO8zwLANDmGRHD6onU 4K4J+XNhnoqTGrb9QHdTXE+OyIL2npPABUHIbzIP0z1pMdfpG0TIvhSyg hB2hnoOObWMUR1Ca16tuFbDu/I8/2TdMOrq9FL2WAa2XsN3EsC3r4JQu9 UpTrn+zDlSpMaYHr8vqogtcJtOLXWuidSo8xGaR1vmTtOO2c4Sp6nAXP9 LfWgog1LKv7CaCvBfa4eYYr/Q6bibAKpg7CITDXVLdgn8S1jrp5O3A2BS A==; X-IronPort-AV: E=Sophos;i="5.85,366,1624312800"; d="scan'208";a="19984098" Received: from unknown (HELO tq-pgp-pr1.tq-net.de) ([192.168.6.15]) by mx1-pgp.tq-group.com with ESMTP; 12 Oct 2021 08:17:45 +0200 Received: from mx1.tq-group.com ([192.168.6.7]) by tq-pgp-pr1.tq-net.de (PGP Universal service); Tue, 12 Oct 2021 08:17:45 +0200 X-PGP-Universal: processed; by tq-pgp-pr1.tq-net.de on Tue, 12 Oct 2021 08:17:45 +0200 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=tq-group.com; i=@tq-group.com; q=dns/txt; s=key1; t=1634019465; x=1665555465; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=L510CHpjo1YY2067LRyVcJ8FsxKVpTHc7AorOe0IHRo=; b=lYWtSDbhLEdIYAa8SlJLQB1tHIrPmI+XYmBIzSnAzFbPiDZll0byHzgF wIDxwfbEdlo2UZMU23pWhggrnCDt/tRczG1bHvTFCzuhu0hlZLuUOX1un UcTGOCktgyZP0T1+pdPUqTjAzXQreI9TipmJXZNkLbBGatd6slX7+O3cl 6l+GuQQtZv7QLpp6irQm9QNRYWX+SoMRhavzx50MsB5bB99sL+VWfPkyS hfYjOlwOXPF6NlQ8lEkoJIivPzavnc0BwlSESOcUFx5C6CnTU1JVEDan2 f6N216bCROHwRqT1Dofcqq7nTv4z8UmJY/t6a5edTNRDURx7gK/fshA8p g==; X-IronPort-AV: E=Sophos;i="5.85,366,1624312800"; d="scan'208";a="19984097" Received: from vtuxmail01.tq-net.de ([10.115.0.20]) by mx1.tq-group.com with ESMTP; 12 Oct 2021 08:17:45 +0200 Received: from steina-w.tq-net.de (unknown [10.123.49.12]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) (No client certificate requested) by vtuxmail01.tq-net.de (Postfix) with ESMTPSA id 802B2280075; Tue, 12 Oct 2021 08:17:45 +0200 (CEST) From: Alexander Stein To: Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Rob Herring , Pratyush Yadav , Michael Walle , Tudor Ambarus Cc: Alexander Stein , linux-mtd@lists.infradead.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v2 2/2] mtd: spi-nor: micron-st: Add support for output-driver-strength for MT25Q Date: Tue, 12 Oct 2021 08:17:04 +0200 Message-Id: <20211012061704.284214-2-alexander.stein@ew.tq-group.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20211012061704.284214-1-alexander.stein@ew.tq-group.com> References: <20211012061704.284214-1-alexander.stein@ew.tq-group.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org MT25Q[UL] Micron flashes support this by the Bits [2:0] in the Enhanced Volatile Configuration Register. Checked datasheet: - mt25t-qljs-L512-xBA-xxT.pdf Signed-off-by: Alexander Stein --- Changes in v2: * Various format fixes * Apply property only to MT25Q devices (e.g. N25Q devices support a different set of impedances) * Use spi_nor_spimem_setup_op() before issuing a command * Add more return code checking * Add a warning if setting drive strength fails at some point * Use GENMASK() drivers/mtd/spi-nor/micron-st.c | 152 ++++++++++++++++++++++++++++++-- 1 file changed, 146 insertions(+), 6 deletions(-) diff --git a/drivers/mtd/spi-nor/micron-st.c b/drivers/mtd/spi-nor/micron-st.c index c224e59820a1..492805a5a278 100644 --- a/drivers/mtd/spi-nor/micron-st.c +++ b/drivers/mtd/spi-nor/micron-st.c @@ -16,6 +16,11 @@ #define SPINOR_MT_OCT_DTR 0xe7 /* Enable Octal DTR. */ #define SPINOR_MT_EXSPI 0xff /* Enable Extended SPI (default) */ +struct micron_drive_strength { + u32 ohms; + u8 val; +}; + static int spi_nor_micron_octal_dtr_enable(struct spi_nor *nor, bool enable) { struct spi_mem_op op; @@ -118,6 +123,135 @@ static struct spi_nor_fixups mt35xu512aba_fixups = { .post_sfdp = mt35xu512aba_post_sfdp_fixup, }; +/* + * Read Micron enhanced volatile configuration register + * Return negative if error occurred or configuration register value + */ +static int micron_read_evcr(struct spi_nor *nor) +{ + int ret; + + if (nor->spimem) { + struct spi_mem_op op = + SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RD_EVCR, 1), + SPI_MEM_OP_NO_ADDR, + SPI_MEM_OP_NO_DUMMY, + SPI_MEM_OP_DATA_IN(1, nor->bouncebuf, 1)); + + spi_nor_spimem_setup_op(nor, &op, nor->reg_proto); + + ret = spi_mem_exec_op(nor->spimem, &op); + } else { + ret = nor->controller_ops->read_reg(nor, SPINOR_OP_RD_EVCR, + nor->bouncebuf, 1); + } + + if (ret < 0) { + dev_err(nor->dev, "error %d reading EVCR\n", ret); + return ret; + } + + return nor->bouncebuf[0]; +} + +/* + * Write Micron enhanced volatile configuration register + * Return negative if error occurred or configuration register value + */ +static int micron_write_evcr(struct spi_nor *nor, u8 evcr) +{ + int ret; + + nor->bouncebuf[0] = evcr; + + ret = spi_nor_write_enable(nor); + if (ret) + return ret; + + if (nor->spimem) { + struct spi_mem_op op = + SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WD_EVCR, 1), + SPI_MEM_OP_NO_ADDR, + SPI_MEM_OP_NO_DUMMY, + SPI_MEM_OP_DATA_OUT(1, nor->bouncebuf, 1)); + + spi_nor_spimem_setup_op(nor, &op, nor->reg_proto); + + return spi_mem_exec_op(nor->spimem, &op); + } + + return nor->controller_ops->write_reg(nor, SPINOR_OP_WD_EVCR, + nor->bouncebuf, 1); +} + +/* + * Supported values from Enahanced Volatile COnfiguration Register (Bits 2:0) + */ +static const struct micron_drive_strength drive_strength_data[] = { + { .ohms = 90, .val = 1 }, + { .ohms = 45, .val = 3 }, + { .ohms = 20, .val = 5 }, + { .ohms = 30, .val = 7 }, +}; + +static const struct micron_drive_strength *micron_st_find_drive_strength_entry(u32 ohms) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(drive_strength_data); i++) { + if (ohms == drive_strength_data[i].ohms) + return &drive_strength_data[i]; + } + return NULL; +} + +static void mt25q_post_sfdp(struct spi_nor *nor) +{ + struct device_node *np = spi_nor_get_flash_node(nor); + u32 ohms; + + if (!np) + return; + + if (!of_property_read_u32(np, "output-driver-strength", &ohms)) { + struct micron_drive_strength const *entry = + micron_st_find_drive_strength_entry(ohms); + + if (entry) { + int evcrr; + int ret; + u8 evcr; + + evcrr = micron_read_evcr(nor); + if (evcrr < 0) { + dev_warn(nor->dev, + "Reading EVCR failed: %d\n", + evcrr); + return; + } + + evcr = (u8)(evcrr & GENMASK(7, 3)) | entry->val; + + ret = micron_write_evcr(nor, evcr); + if (ret) + dev_warn(nor->dev, + "Setting EVCR failed: %d\n", + ret); + + dev_dbg(nor->dev, "%s: EVCR 0x%x\n", __func__, + (u32)micron_read_evcr(nor)); + } else { + dev_warn(nor->dev, + "Invalid output-driver-strength property specified: %u", + ohms); + } + } +} + +static struct spi_nor_fixups mt25q_fixups = { + .post_sfdp = mt25q_post_sfdp, +}; + static const struct flash_info micron_parts[] = { { "mt35xu512aba", INFO(0x2c5b1a, 0, 128 * 1024, 512, SECT_4K | USE_FSR | SPI_NOR_OCTAL_READ | @@ -149,25 +283,29 @@ static const struct flash_info st_parts[] = { SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) }, { "mt25ql256a", INFO6(0x20ba19, 0x104400, 64 * 1024, 512, SECT_4K | USE_FSR | SPI_NOR_DUAL_READ | - SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) }, + SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) + .fixups = &mt25q_fixups }, { "n25q256a", INFO(0x20ba19, 0, 64 * 1024, 512, SECT_4K | USE_FSR | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, { "mt25qu256a", INFO6(0x20bb19, 0x104400, 64 * 1024, 512, SECT_4K | USE_FSR | SPI_NOR_DUAL_READ | - SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) }, + SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) + .fixups = &mt25q_fixups }, { "n25q256ax1", INFO(0x20bb19, 0, 64 * 1024, 512, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) }, { "mt25ql512a", INFO6(0x20ba20, 0x104400, 64 * 1024, 1024, SECT_4K | USE_FSR | SPI_NOR_DUAL_READ | - SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) }, + SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) + .fixups = &mt25q_fixups }, { "n25q512ax3", INFO(0x20ba20, 0, 64 * 1024, 1024, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ | SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | SPI_NOR_4BIT_BP | SPI_NOR_BP3_SR_BIT6) }, { "mt25qu512a", INFO6(0x20bb20, 0x104400, 64 * 1024, 1024, SECT_4K | USE_FSR | SPI_NOR_DUAL_READ | - SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) }, + SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) + .fixups = &mt25q_fixups }, { "n25q512a", INFO(0x20bb20, 0, 64 * 1024, 1024, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ | SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | @@ -182,10 +320,12 @@ static const struct flash_info st_parts[] = { NO_CHIP_ERASE) }, { "mt25ql02g", INFO(0x20ba22, 0, 64 * 1024, 4096, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ | - NO_CHIP_ERASE) }, + NO_CHIP_ERASE) + .fixups = &mt25q_fixups }, { "mt25qu02g", INFO(0x20bb22, 0, 64 * 1024, 4096, SECT_4K | USE_FSR | SPI_NOR_DUAL_READ | - SPI_NOR_QUAD_READ | NO_CHIP_ERASE) }, + SPI_NOR_QUAD_READ | NO_CHIP_ERASE) + .fixups = &mt25q_fixups }, { "m25p05", INFO(0x202010, 0, 32 * 1024, 2, 0) }, { "m25p10", INFO(0x202011, 0, 32 * 1024, 4, 0) }, -- 2.25.1