Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932835AbbHZG1w (ORCPT ); Wed, 26 Aug 2015 02:27:52 -0400 Received: from mail-bn1bon0066.outbound.protection.outlook.com ([157.56.111.66]:45248 "EHLO na01-bn1-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1751951AbbHZG1G (ORCPT ); Wed, 26 Aug 2015 02:27:06 -0400 Authentication-Results: spf=pass (sender IP is 149.199.60.83) smtp.mailfrom=xilinx.com; vger.kernel.org; dkim=none (message not signed) header.d=none; From: Ranjit Waghmode To: , , , , , , , , , , , CC: , , , , , , Ranjit Waghmode Subject: [LINUX RFC v2 3/4] spi-nor: add dual parallel mode support Date: Wed, 26 Aug 2015 11:56:06 +0530 Message-ID: <1440570367-22569-4-git-send-email-ranjit.waghmode@xilinx.com> X-Mailer: git-send-email 2.1.2 In-Reply-To: <1440570367-22569-1-git-send-email-ranjit.waghmode@xilinx.com> References: <1440570367-22569-1-git-send-email-ranjit.waghmode@xilinx.com> X-RCIS-Action: ALLOW X-TM-AS-Product-Ver: IMSS-7.1.0.1224-8.0.0.1202-21768.005 X-TM-AS-User-Approved-Sender: Yes;Yes X-EOPAttributedMessage: 0 X-Microsoft-Exchange-Diagnostics: 1;BY2FFO11FD023;1:6WDJLFRkPwY/OFP9zYsa+QInvWySsqx/K1Quoh+OLRliGs5JkAdf9MIroK/WDF+WzcwVoOKUvZPCvWQ8GyzFCIAAoV3Lt1gPuBnV7xcyJl4+nePa27cc5/co3VVsq3gM8Gaj/PNSQFOAZtezw1z+kuQds0/cdkg58B+oVS6jzPKVbrkehoMK7+jNLuNIYzhenWk8yZ4c8TyxNPprxcMWk9BBjqfZNComXq+d3mFnyVBCeYIUiCZNdHvztto6hHCNudN3M71hup6zSRtMT0vaaoLZZSlsVfpzyRlWoYBttyR8PjKvb/c9BdMQSdnLmDRlD3TL8AoF5yuLGQSrnQ/cZv6bEKAlJyD48NfgrxTrXhkeF/AD5MfDEIxWMsurSiNPH3DNxCHV81LGMY2UMA2G5A== X-Forefront-Antispam-Report: CIP:149.199.60.83;CTRY:US;IPV:NLI;EFV:NLI;SFV:NSPM;SFS:(10009020)(6009001)(2980300002)(438002)(3050300001)(199003)(189002)(47776003)(2950100001)(64706001)(48376002)(50466002)(5007970100001)(77156002)(62966003)(6806004)(19580405001)(19580395003)(36386004)(229853001)(45336002)(46386002)(5003940100001)(92566002)(5001860100001)(5001770100001)(33646002)(5001830100001)(81156007)(4001540100001)(42186005)(52956003)(107886002)(189998001)(5001960100002)(86362001)(2201001)(76176999)(36756003)(50226001)(50986999)(63266004)(46102003)(106466001)(87936001)(103686003)(7059030)(107986001)(921003)(90966001)(4001430100001)(1121003)(217873001);DIR:OUT;SFP:1101;SCL:1;SRVR:BY2FFO11HUB055;H:xsj-pvapsmtpgw01;FPR:;SPF:Pass;PTR:unknown-60-83.xilinx.com;A:1;MX:1;LANG:en; MIME-Version: 1.0 Content-Type: text/plain X-Microsoft-Exchange-Diagnostics: 1;BY2FFO11HUB055;2:VgtFp8N62jvlP8OwkUzkYradGIEHv9m277AjqT/LFoEeNlP3Ua43+v5ERDcXULyPF9HwJHi70DWCfatOQIQfXW9vjgEPb2M45x6MVPCOKUvpd1V5GzR5fg+c0Rfd11uTSow01tO1QwgkXge1gYk+DvhQ5p+9ubreQYFseaheuIA=;3:91hkijpaVhKD8WZMByt5D+ZNc/xVUoWl/MFVjvj0BPXKHW6xQjYRlF5flEKsBrodCfJDlgCLdxlCtKRNJscsm9cDD2fJfQdh4YCpSHRR9XdXrlyPaxJ+qj+droRVuQ4ll+9571NCEufUvsnExDTGScLoqd1Zo7vMvG4wQXnj9XxFeAq0keaOvQHhW6Cl67f3uMe6+ODcgJnqoCTmZSQDBlYa5K9xVma7rIrLGQgcqLA=;25:I7UiQJrGydBgazCYtRPkqbA071ORq+U4EMol5W5Eeth1N40wKx7cBNYeCWm/pLA1F4CjJy+iPX8K62dfWoYVccRjzg4y9/c7ds01mMYLw5BR7hSUocn0N+6Ygip1rfS8W11NaqN+3+ed6kFqvmKorqEYAGAy8a+FUwiAFwSWgxFXJaQLFOrYC54jTnUft+bUAB7mBWJUKky2SvvApxsaWC8y0tUmV+ntSML6QwN9XPucLC+pFMTt6nUZvZayNSiI X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:;SRVR:BY2FFO11HUB055; X-Microsoft-Exchange-Diagnostics: 1;BY2FFO11HUB055;20:ZyZ0RnKoyyxDFU9Q5cq9LNQ3Hn29UZrnX9B7r8F5FzbPB16QNyRXZtqoGpUY2sEpnL/sMtBDYDoLEQuKT16T3eVq/LHmxdx01vTYQHSEL8dva0TduF69rf3iazeg5vwYFT0ysYrMxftBRJxRRxYRz9mmtB2mD3j36hg7Y3A6Zbpi7HjeL+aCpO8Vv+jXjw+X9p14YI4ndaUfY4qoOuy//cFvC5gU4e+uyNbLvDff/UkEYOtY2Yr8iw0jszoK5UFuoJ92rCcHO9SeQkYsNC2m7LK920X8ZFxCEzSRygHNjbZ8sAJCrfIQGalDJbJiE2zBYANn8gma8EHchm94IkraNFP0476uxjhEbyiWbWsnJrEQ1MeTMjQQ2ka0QmvE4mkHLvSQ4QGDHjtUXYeU5PEKSXoKAoTG/73zIyNuVWzD+2IPzbyHg6eWaS7dHq8Ryg5gJUe4PwBFIJ3slimW2tlKK2hCtCzGyRgpMjeKPd5vamsA3WfqoxRYTR9rhTYOQZqB;4:LZmjfdn2/1979H27pBd2eR5/YUVA57lZ4lsQ1MKixpbI4Lo6MFy+2IobrryUP/7DOSgXXZO0D8+Mds5YIIJIRKPVaRFwKJwGODhry+OVOFNQ1K7yGEjvbqFCgtWNiPv9xIHmBpZW+uIiOZm0KSvp7aJwoOIrfo3afA7Y/byqc/o6F5SQsNUKbuFMdCrGcib0Tdr5RiQgkTII0VywcjQQpXuJQf6Bf5rgi5+W8fjGCAw3VVnowY32Fh8kDHG7T7DbcJhl3CjcAoYkiQzzkytM0a5cHTJOEu2r5S3sjM75iSlaeGeh6x0njBma6difIDIi X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:; X-Exchange-Antispam-Report-CFA-Test: BCL:0;PCL:0;RULEID:(601004)(5005006)(8121501046)(3002001);SRVR:BY2FFO11HUB055;BCL:0;PCL:0;RULEID:;SRVR:BY2FFO11HUB055; X-Forefront-PRVS: 0680FADD48 X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1;BY2FFO11HUB055;23:4STeRImb26arcskgoVxhwkBEHrDssUG974UIzYS9?= =?us-ascii?Q?MBVpnnhwZ6f4KoBx0fyu1mE+azP1ALF+h+IWuPJqcgBd2TxhISG/6IEszVVR?= =?us-ascii?Q?AH9VlyeZs55hPZegpHLBHlC4erBYXjyAuW704LLUArIO5oHmPwT1QFOMvZel?= =?us-ascii?Q?zOiNNLNy7IPvY5vndAmnSkyw9dSavm5Uvi65tQn8mvKCYm9bqug0XQyAUfZM?= =?us-ascii?Q?bu+ej454H3qNKTKdpreqljJUt3zVLJmpwVJkq5niS+hzsyQ5Dzlf2pJMP88I?= =?us-ascii?Q?xicFf2tf2X3T/usXRDIoMyud49gqqsw9MI9TWkoRMsr4VBGRrSx9+gVuskfY?= =?us-ascii?Q?u/IgApcJb1DMNVYnQVAOKddqLJutH6I5Qct1buwe50eZrp0BaQk0ZfLp1L1V?= =?us-ascii?Q?xusIMeTESxRD69AKxwdNrX+dlwmeyJDE7GCfNKzdPfUppOVX+zbHAHwFgZl/?= =?us-ascii?Q?RwkUbSq9WGaE96tjFznn8E2ygJo7/rseORTTIGtxkzG/qiVqJttZAII2FUF7?= =?us-ascii?Q?C5JDDZ3TI3k51xGEruPWqJqZFv8m0+QzdkF28RqueDysRx0VeUWjNMMRN6kV?= =?us-ascii?Q?1LrJN6SXM+LquYcwWSuO8RHLCqMWM0wCpg7GWbxXZG196blCsg3xlXLVAcoS?= =?us-ascii?Q?MqPlhM8Def+q5fIMtOYsdqsg+FWaUZlSd5orlkmg/GbthLdhT7kKAF8V0CeG?= =?us-ascii?Q?NIQwr/lj0kMS1Jvco6P1x6kgQT3CpfMQRi3GpNc1FmyOCdle6zD5UYzpN8ad?= =?us-ascii?Q?qYIVWiAlbeOJnFeQFAGxU6oTCNvmU7rn6YggkJUenNChdtSTnGppc1k+6uTL?= =?us-ascii?Q?UsshXY0dNOi4S7g4tTN4Cm/hZauH5sddfqg+IOA87/C2d2B9CU2LT3xX57rZ?= =?us-ascii?Q?rA6fT/fi/gdgilgQTpazBmzugOH4lksRriUrpTxvPXNVz1XSgD8Z47E8udtN?= =?us-ascii?Q?PF7yR3/6cM0YyfAlN8QfMhIXbaExcfp2zR79RV8mlKqeDOKM5/jVGeZAC2+/?= =?us-ascii?Q?o86fRW2JqjmO2iyIttlQjp9E4kSaC0wrHmVv9/+vZ+Mnw4T0DWngkE1Eepqw?= =?us-ascii?Q?5Z5Bl4NHI3l6dCDNbjEhKInFhvgVYNIQZuz19NOPiIx0s49NEFdCbq5n3/i5?= =?us-ascii?Q?G9Sm+rGea9fd3A8G4K/ztYK+CIELpagraXxgE/Uscv69T4jwJYB7EfGHtE9I?= =?us-ascii?Q?EFZzq/Yq9dJctuzVNZJkT4urAi/gbdTmlKd+juj8gnJJIHHcRvU/9uHxaFWY?= =?us-ascii?Q?UAwkyNWIpDEpW7hkk2J/244JTp6fPWjfGt8vQvrQLvAyfzqtd3WUhq+/kQn4?= =?us-ascii?Q?ogPfehG+1Ok6NhlV/vgluXIdWjdwqx9dDvybjHYXLrzx3W/DdfrmKvN4B19I?= =?us-ascii?Q?ZH8wnA=3D=3D?= X-Microsoft-Exchange-Diagnostics: 1;BY2FFO11HUB055;5:OnbKjv/DjN3Yj2Z1cK0P3f3MttV96g09zhO1RuCOcnlTT7rRvyKmzVbci55Xgs7hS+v4np7eNBTuwLz3T+JEWe9eVirg5/NkSouX9Nj/V88OBxn0z0xdrqYe/doDJD+PVIZDsl0go+MHjqYbBf1NHA==;24:cA/m0v9vbbtGLOnuUILnV1//5stuAWu90caTvwop6inpizvZ6hzcJ3uynlc6QBQ966FwFpHh5UlkNinet8OoCr5k7dOQSzTMsr4YOUcaVgo= SpamDiagnosticOutput: 1:23 SpamDiagnosticMetadata: NSPM X-OriginatorOrg: xilinx.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 26 Aug 2015 06:27:02.2940 (UTC) X-MS-Exchange-CrossTenant-Id: 657af505-d5df-48d0-8300-c31994686c5c X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=657af505-d5df-48d0-8300-c31994686c5c;Ip=[149.199.60.83];Helo=[xsj-pvapsmtpgw01] X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: BY2FFO11HUB055 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 7633 Lines: 263 This patch adds support for dual parallel configuration by: - Adding required parameters like isparallel and shift to spi_nor structure. - Initializing all added parameters in spi_nor_scan() - Updating read_sr() and read_fsr() for getting status of both flashes - Increasing page_size, sector_size, erase_size and toatal flash size as and when required. - Dividing address by 2 - Updating spi->master->flags for qspi driver to change CS Signed-off-by: Ranjit Waghmode --- V2 Changes: Splitted to separate MTD layer changes from SPI core changes --- drivers/mtd/spi-nor/spi-nor.c | 91 ++++++++++++++++++++++++++++++++++--------- include/linux/mtd/spi-nor.h | 2 + 2 files changed, 74 insertions(+), 19 deletions(-) diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index d78831b..6a2e80b 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -22,6 +22,7 @@ #include #include #include +#include /* Define max times to check status register before we give up. */ #define MAX_READY_WAIT_JIFFIES (40 * HZ) /* M25P16 specs 40s max chip erase */ @@ -69,15 +70,24 @@ static const struct spi_device_id *spi_nor_match_id(const char *name); static int read_sr(struct spi_nor *nor) { int ret; - u8 val; + u8 val[2]; - ret = nor->read_reg(nor, SPINOR_OP_RDSR, &val, 1); - if (ret < 0) { - pr_err("error %d reading SR\n", (int) ret); - return ret; + if (nor->isparallel) { + ret = nor->read_reg(nor, SPINOR_OP_RDSR, &val[0], 2); + if (ret < 0) { + pr_err("error %d reading SR\n", (int) ret); + return ret; + } + val[0] |= val[1]; + } else { + ret = nor->read_reg(nor, SPINOR_OP_RDSR, &val[0], 1); + if (ret < 0) { + pr_err("error %d reading SR\n", (int) ret); + return ret; + } } - return val; + return val[0]; } /* @@ -87,16 +97,24 @@ static int read_sr(struct spi_nor *nor) */ static int read_fsr(struct spi_nor *nor) { - int ret; - u8 val; + int ret, size; + u8 val[2]; + + size = 1; + val[1] = 0xff; + + if (nor->isparallel) + size = 2; - ret = nor->read_reg(nor, SPINOR_OP_RDFSR, &val, 1); + ret = nor->read_reg(nor, SPINOR_OP_RDFSR, &val[0], size); if (ret < 0) { pr_err("error %d reading FSR\n", ret); return ret; } - return val; + val[0] &= val[1]; + + return val[0]; } /* @@ -317,6 +335,9 @@ static int spi_nor_erase(struct mtd_info *mtd, struct erase_info *instr) if (ret) return ret; + if (nor->isparallel) + nor->spi->master->flags |= SPI_MASTER_DATA_STRIPE; + /* whole-chip erase? */ if (len == mtd->size) { write_enable(nor); @@ -340,6 +361,8 @@ static int spi_nor_erase(struct mtd_info *mtd, struct erase_info *instr) while (len) { write_enable(nor); + addr = addr >> nor->shift; + if (nor->erase(nor, addr)) { ret = -EIO; goto erase_err; @@ -360,19 +383,22 @@ static int spi_nor_erase(struct mtd_info *mtd, struct erase_info *instr) instr->state = MTD_ERASE_DONE; mtd_erase_callback(instr); - + if (nor->isparallel) + nor->spi->master->flags &= ~SPI_MASTER_DATA_STRIPE; return ret; erase_err: spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_ERASE); instr->state = MTD_ERASE_FAILED; + if (nor->isparallel) + nor->spi->master->flags &= ~SPI_MASTER_DATA_STRIPE; return ret; } static int stm_lock(struct spi_nor *nor, loff_t ofs, uint64_t len) { struct mtd_info *mtd = nor->mtd; - uint32_t offset = ofs; + uint32_t offset = ofs >> nor->shift; uint8_t status_old, status_new; int ret = 0; @@ -406,7 +432,7 @@ static int stm_lock(struct spi_nor *nor, loff_t ofs, uint64_t len) static int stm_unlock(struct spi_nor *nor, loff_t ofs, uint64_t len) { struct mtd_info *mtd = nor->mtd; - uint32_t offset = ofs; + uint32_t offset = ofs >> nor->shift; uint8_t status_old, status_new; int ret = 0; @@ -446,6 +472,8 @@ static int spi_nor_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len) if (ret) return ret; + ofs = ofs >> nor->shift; + ret = nor->flash_lock(nor, ofs, len); spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_UNLOCK); @@ -461,6 +489,8 @@ static int spi_nor_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len) if (ret) return ret; + ofs = ofs >> nor->shift; + ret = nor->flash_unlock(nor, ofs, len); spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_LOCK); @@ -738,7 +768,13 @@ static int spi_nor_read(struct mtd_info *mtd, loff_t from, size_t len, if (ret) return ret; - ret = nor->read(nor, from, len, retlen, buf); + if (nor->isparallel) + nor->spi->master->flags |= SPI_MASTER_DATA_STRIPE; + + ret = nor->read(nor, from >> nor->shift, len, retlen, buf); + + if (nor->isparallel) + nor->spi->master->flags &= ~SPI_MASTER_DATA_STRIPE; spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_READ); return ret; @@ -834,11 +870,11 @@ static int spi_nor_write(struct mtd_info *mtd, loff_t to, size_t len, /* do all the bytes fit onto one page? */ if (page_offset + len <= nor->page_size) { - nor->write(nor, to, len, retlen, buf); + nor->write(nor, to >> nor->shift, len, retlen, buf); } else { /* the size of data remaining on the first page */ page_size = nor->page_size - page_offset; - nor->write(nor, to, page_size, retlen, buf); + nor->write(nor, to >> nor->shift, page_size, retlen, buf); /* write everything in nor->page_size chunks */ for (i = page_size; i < len; i += page_size) { @@ -852,12 +888,15 @@ static int spi_nor_write(struct mtd_info *mtd, loff_t to, size_t len, write_enable(nor); - nor->write(nor, to + i, page_size, retlen, buf + i); + nor->write(nor, (to + i) >> nor->shift, page_size, + retlen, buf + i); } } ret = spi_nor_wait_till_ready(nor); write_err: + if (nor->isparallel) + nor->spi->master->flags &= ~SPI_MASTER_DATA_STRIPE; spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_WRITE); return ret; } @@ -1073,6 +1112,20 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode) mtd->_erase = spi_nor_erase; mtd->_read = spi_nor_read; +#ifdef CONFIG_OF + struct device_node *np_spi = of_get_next_parent(np); + u32 is_dual; + + if (of_property_read_u32(np_spi, "is-dual", &is_dual) > 0) { + nor->shift = 1; + info->sector_size <<= nor->shift; + info->page_size <<= nor->shift; + mtd->size <<= nor->shift; + nor->isparallel = 1; + nor->spi->master->flags |= SPI_MASTER_BOTH_CS; + } +#endif + /* nor protection support for STmicro chips */ if (JEDEC_MFR(info) == CFI_MFR_ST) { nor->flash_lock = stm_lock; @@ -1097,10 +1150,10 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode) /* prefer "small sector" erase if possible */ if (info->flags & SECT_4K) { nor->erase_opcode = SPINOR_OP_BE_4K; - mtd->erasesize = 4096; + mtd->erasesize = 4096 << nor->shift; } else if (info->flags & SECT_4K_PMC) { nor->erase_opcode = SPINOR_OP_BE_4K_PMC; - mtd->erasesize = 4096; + mtd->erasesize = 4096 << nor->shift; } else #endif { diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h index 1705dc3..6ef25a8 100644 --- a/include/linux/mtd/spi-nor.h +++ b/include/linux/mtd/spi-nor.h @@ -171,6 +171,8 @@ struct spi_nor { u8 read_dummy; u8 program_opcode; enum read_mode flash_read; + bool shift; + bool isparallel; bool sst_write_second; u32 flags; struct spi_nor_xfer_cfg cfg; -- 2.1.2 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/