Received: by 2002:a25:1104:0:0:0:0:0 with SMTP id 4csp644982ybr; Fri, 22 May 2020 15:44:07 -0700 (PDT) X-Google-Smtp-Source: ABdhPJwnYKJDQ93e05vOIrPQ6NBfRgcBe4mX6kTEFY5lhiNLvPAMw1AEeKS7Ovl00RZPIz2ZZkvn X-Received: by 2002:a17:906:2c03:: with SMTP id e3mr9950772ejh.206.1590187447193; Fri, 22 May 2020 15:44:07 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1590187447; cv=none; d=google.com; s=arc-20160816; b=v3NHH0IP+u213pa2GdyOKmBRaK8PVgjPWNSCDsUz66Mo1gY7aS5k/9jnZrrPIwQoje 3VBpGrdhXDTxZNXw7D2aI6pH2AEqnRwgwQK/JQeillqqzgmLf2MVlo1pSzJ7B/D5pCCD 9CyuIL+qxwMaxa/M5ObuDM73U1yYP04Q8YgVeMkWOC0eH57PFMND9HhccJq3rlXDG4fP ssZfnnNKgsx/9hLXoSxDxF4G/pwM7v+A/IMRKhxve0JupRRrEiXSAceq+P/aX3oUSMyx Ql6K28QGMnYm6Fway35FYVvjjJCiUDb4vYLQK67gfry8pDMkWm7u3wa5npE4mfO9Iu7x KL/g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=EBSuSKu8E6ZfUxthMZxSUAxK4hljP1NudEiBto9rwgQ=; b=p1wC1HYkeq3QCki/VPsP4cvWs0Vz+gQAVoxRsN3UMc3ajq6AxZeEGhsMRXFwC0EWx4 waVfxUNJGq1Skv5kCSqVHn1/f562xs5U9or86Y/BjV/479YFnqxYJxrWW4QfB9NR6hPF IcQ5UAlLTJAUxpf65fetans1/vIXFuGQLHsJ1P4A697jr9bTTe5eoZqF0DMCBCww/bxW XuCePEPcGYeWnh0dGoHWBITzpW6DYz8Sb2EVJmZ2TTxrKIyw20tyGgzV/NLGEIrK9EA2 EUAONUpzliI64JRetBjfDhH3sp+WH3MepyZZ63ZEu6j6yb6rd4FpPPQcEbn35wWsYMIQ CK8Q== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@ti.com header.s=ti-com-17Q1 header.b=d4Ncexjr; 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=QUARANTINE sp=NONE dis=NONE) header.from=ti.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id sa22si6063500ejb.8.2020.05.22.15.43.44; Fri, 22 May 2020 15:44:07 -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=@ti.com header.s=ti-com-17Q1 header.b=d4Ncexjr; 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=QUARANTINE sp=NONE dis=NONE) header.from=ti.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1731338AbgEVWlw (ORCPT + 99 others); Fri, 22 May 2020 18:41:52 -0400 Received: from lelv0143.ext.ti.com ([198.47.23.248]:54326 "EHLO lelv0143.ext.ti.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1731138AbgEVWlv (ORCPT ); Fri, 22 May 2020 18:41:51 -0400 Received: from lelv0265.itg.ti.com ([10.180.67.224]) by lelv0143.ext.ti.com (8.15.2/8.15.2) with ESMTP id 04MMfaeE061239; Fri, 22 May 2020 17:41:36 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ti.com; s=ti-com-17Q1; t=1590187296; bh=EBSuSKu8E6ZfUxthMZxSUAxK4hljP1NudEiBto9rwgQ=; h=From:To:CC:Subject:Date:In-Reply-To:References; b=d4NcexjrOQ1Alef3pipk3FN3W+ste5Nt8N+VDP7N5sjxQH+EdOgUiXFzV8FcIQRAS hzvl38w2MakflQdZdVxwVs044OkEyavO0cVM5tcVnBG5QX3pOaprml/+N66Q5bHSgQ O5e1mmv/ghOq+/8YsL/DhMW8v3nNmqz/4qhT/2Wo= Received: from DLEE104.ent.ti.com (dlee104.ent.ti.com [157.170.170.34]) by lelv0265.itg.ti.com (8.15.2/8.15.2) with ESMTPS id 04MMfaug079666 (version=TLSv1.2 cipher=AES256-GCM-SHA384 bits=256 verify=FAIL); Fri, 22 May 2020 17:41:36 -0500 Received: from DLEE101.ent.ti.com (157.170.170.31) by DLEE104.ent.ti.com (157.170.170.34) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1979.3; Fri, 22 May 2020 17:41:36 -0500 Received: from lelv0326.itg.ti.com (10.180.67.84) by DLEE101.ent.ti.com (157.170.170.31) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1979.3 via Frontend Transport; Fri, 22 May 2020 17:41:36 -0500 Received: from pratyush-OptiPlex-790.dhcp.ti.com (ileax41-snat.itg.ti.com [10.172.224.153]) by lelv0326.itg.ti.com (8.15.2/8.15.2) with ESMTP id 04MMeh5g044559; Fri, 22 May 2020 17:41:31 -0500 From: Pratyush Yadav To: Tudor Ambarus , Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Mark Brown , Nicolas Ferre , Alexandre Belloni , Ludovic Desroches , Matthias Brugger , Michal Simek , , , , , CC: Pratyush Yadav , Sekhar Nori , Boris Brezillon , Mason Yang Subject: [PATCH v8 09/19] mtd: spi-nor: sfdp: parse xSPI Profile 1.0 table Date: Sat, 23 May 2020 04:10:32 +0530 Message-ID: <20200522224042.29970-10-p.yadav@ti.com> X-Mailer: git-send-email 2.25.0 In-Reply-To: <20200522224042.29970-1-p.yadav@ti.com> References: <20200522224042.29970-1-p.yadav@ti.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Content-Type: text/plain X-EXCLAIMER-MD-CONFIG: e1e8a2fd-e40a-4ac6-ac9b-f7e9cc9ee180 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org This table is indication that the flash is xSPI compliant and hence supports octal DTR mode. Extract information like the fast read opcode, dummy cycles, the number of dummy cycles needed for a Read Status Register command, and the number of address bytes needed for a Read Status Register command. We don't know what speed the controller is running at. Find the fast read dummy cycles for the fastest frequency the flash can run at to be sure we are never short of dummy cycles. If nothing is available, default to 20. Flashes that use a different value should update it in their fixup hooks. Since we want to set read settings, expose spi_nor_set_read_settings() in core.h. Signed-off-by: Pratyush Yadav --- drivers/mtd/spi-nor/core.c | 2 +- drivers/mtd/spi-nor/core.h | 10 ++++ drivers/mtd/spi-nor/sfdp.c | 99 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 110 insertions(+), 1 deletion(-) diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c index 388e695e763f..642e3c07acf9 100644 --- a/drivers/mtd/spi-nor/core.c +++ b/drivers/mtd/spi-nor/core.c @@ -2355,7 +2355,7 @@ static int spi_nor_check(struct spi_nor *nor) return 0; } -static void +void spi_nor_set_read_settings(struct spi_nor_read_command *read, u8 num_mode_clocks, u8 num_wait_states, diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h index de1e3917889f..7e6df8322da0 100644 --- a/drivers/mtd/spi-nor/core.h +++ b/drivers/mtd/spi-nor/core.h @@ -192,6 +192,9 @@ struct spi_nor_locking_ops { * * @size: the flash memory density in bytes. * @page_size: the page size of the SPI NOR flash memory. + * @rdsr_dummy: dummy cycles needed for Read Status Register command. + * @rdsr_addr_nbytes: dummy address bytes needed for Read Status Register + * command. * @hwcaps: describes the read and page program hardware * capabilities. * @reads: read capabilities ordered by priority: the higher index @@ -214,6 +217,8 @@ struct spi_nor_locking_ops { struct spi_nor_flash_parameter { u64 size; u32 page_size; + u8 rdsr_dummy; + u8 rdsr_addr_nbytes; struct spi_nor_hwcaps hwcaps; struct spi_nor_read_command reads[SNOR_CMD_READ_MAX]; @@ -424,6 +429,11 @@ ssize_t spi_nor_write_data(struct spi_nor *nor, loff_t to, size_t len, int spi_nor_hwcaps_read2cmd(u32 hwcaps); u8 spi_nor_convert_3to4_read(u8 opcode); +void spi_nor_set_read_settings(struct spi_nor_read_command *read, + u8 num_mode_clocks, + u8 num_wait_states, + u8 opcode, + enum spi_nor_protocol proto); void spi_nor_set_pp_settings(struct spi_nor_pp_command *pp, u8 opcode, enum spi_nor_protocol proto); diff --git a/drivers/mtd/spi-nor/sfdp.c b/drivers/mtd/spi-nor/sfdp.c index ab086aa4746f..052cabb52df9 100644 --- a/drivers/mtd/spi-nor/sfdp.c +++ b/drivers/mtd/spi-nor/sfdp.c @@ -4,12 +4,15 @@ * Copyright (C) 2014, Freescale Semiconductor, Inc. */ +#include #include #include #include #include "core.h" +#define ROUND_UP_TO(x, y) (((x) + (y) - 1) / (y) * (y)) + #define SFDP_PARAM_HEADER_ID(p) (((p)->id_msb << 8) | (p)->id_lsb) #define SFDP_PARAM_HEADER_PTP(p) \ (((p)->parameter_table_pointer[2] << 16) | \ @@ -19,12 +22,14 @@ #define SFDP_BFPT_ID 0xff00 /* Basic Flash Parameter Table */ #define SFDP_SECTOR_MAP_ID 0xff81 /* Sector Map Table */ #define SFDP_4BAIT_ID 0xff84 /* 4-byte Address Instruction Table */ +#define SFDP_PROFILE1_ID 0xff05 /* xSPI Profile 1.0 table. */ #define SFDP_SIGNATURE 0x50444653U #define SFDP_JESD216_MAJOR 1 #define SFDP_JESD216_MINOR 0 #define SFDP_JESD216A_MINOR 5 #define SFDP_JESD216B_MINOR 6 +#define SFDP_JESD216D_MINOR 8 struct sfdp_header { u32 signature; /* Ox50444653U <=> "SFDP" */ @@ -70,6 +75,16 @@ struct sfdp_bfpt_erase { u32 shift; }; +/* xSPI Profile 1.0 table (from JESD216D.01). */ +#define PROFILE1_DWORD1_RD_FAST_CMD GENMASK(15, 8) +#define PROFILE1_DWORD1_RDSR_DUMMY BIT(28) +#define PROFILE1_DWORD1_RDSR_ADDR_BYTES BIT(29) +#define PROFILE1_DWORD4_DUMMY_200MHZ GENMASK(11, 7) +#define PROFILE1_DWORD5_DUMMY_166MHZ GENMASK(31, 27) +#define PROFILE1_DWORD5_DUMMY_133MHZ GENMASK(21, 17) +#define PROFILE1_DWORD5_DUMMY_100MHZ GENMASK(11, 7) +#define PROFILE1_DUMMY_DEFAULT 20 + #define SMPT_CMD_ADDRESS_LEN_MASK GENMASK(23, 22) #define SMPT_CMD_ADDRESS_LEN_0 (0x0UL << 22) #define SMPT_CMD_ADDRESS_LEN_3 (0x1UL << 22) @@ -1110,6 +1125,86 @@ static int spi_nor_parse_4bait(struct spi_nor *nor, return ret; } +/** + * spi_nor_parse_profile1() - parse the xSPI Profile 1.0 table + * @nor: pointer to a 'struct spi_nor' + * @param_header: pointer to the 'struct sfdp_parameter_header' describing + * the 4-Byte Address Instruction Table length and version. + * @params: pointer to the 'struct spi_nor_flash_parameter' to be. + * + * Return: 0 on success, -errno otherwise. + */ +static int spi_nor_parse_profile1(struct spi_nor *nor, + const struct sfdp_parameter_header *profile1_header, + struct spi_nor_flash_parameter *params) +{ + u32 *table, opcode, addr; + size_t len; + int ret, i; + u8 dummy; + + len = profile1_header->length * sizeof(*table); + table = kmalloc(len, GFP_KERNEL); + if (!table) + return -ENOMEM; + + addr = SFDP_PARAM_HEADER_PTP(profile1_header); + ret = spi_nor_read_sfdp(nor, addr, len, table); + if (ret) + goto out; + + /* Fix endianness of the table DWORDs. */ + for (i = 0; i < profile1_header->length; i++) + table[i] = le32_to_cpu(table[i]); + + /* Get 8D-8D-8D fast read opcode and dummy cycles. */ + opcode = FIELD_GET(PROFILE1_DWORD1_RD_FAST_CMD, table[0]); + + /* + * We don't know what speed the controller is running at. Find the + * dummy cycles for the fastest frequency the flash can run at to be + * sure we are never short of dummy cycles. A value of 0 means the + * frequency is not supported. + * + * Default to PROFILE1_DUMMY_DEFAULT if we don't find anything, and let + * flashes set the correct value if needed in their fixup hooks. + */ + dummy = FIELD_GET(PROFILE1_DWORD4_DUMMY_200MHZ, table[3]); + if (!dummy) + dummy = FIELD_GET(PROFILE1_DWORD5_DUMMY_166MHZ, table[4]); + if (!dummy) + dummy = FIELD_GET(PROFILE1_DWORD5_DUMMY_133MHZ, table[4]); + if (!dummy) + dummy = FIELD_GET(PROFILE1_DWORD5_DUMMY_100MHZ, table[4]); + if (!dummy) + dummy = PROFILE1_DUMMY_DEFAULT; + + /* Round up to an even value to avoid tripping controllers up. */ + dummy = ROUND_UP_TO(dummy, 2); + + /* Update the fast read settings. */ + spi_nor_set_read_settings(¶ms->reads[SNOR_CMD_READ_8_8_8_DTR], + 0, dummy, opcode, + SNOR_PROTO_8_8_8_DTR); + + /* + * Set the Read Status Register dummy cycles and dummy address bytes. + */ + if (table[0] & PROFILE1_DWORD1_RDSR_DUMMY) + params->rdsr_dummy = 8; + else + params->rdsr_dummy = 4; + + if (table[0] & PROFILE1_DWORD1_RDSR_ADDR_BYTES) + params->rdsr_addr_nbytes = 4; + else + params->rdsr_addr_nbytes = 0; + +out: + kfree(table); + return ret; +} + /** * spi_nor_parse_sfdp() - parse the Serial Flash Discoverable Parameters. * @nor: pointer to a 'struct spi_nor' @@ -1211,6 +1306,10 @@ int spi_nor_parse_sfdp(struct spi_nor *nor, err = spi_nor_parse_4bait(nor, param_header, params); break; + case SFDP_PROFILE1_ID: + err = spi_nor_parse_profile1(nor, param_header, params); + break; + default: break; } -- 2.26.2