From patchwork Tue Feb 12 07:12:54 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Masahiro Yamada X-Patchwork-Id: 158125 Delivered-To: patch@linaro.org Received: by 2002:a02:48:0:0:0:0:0 with SMTP id 69csp3510770jaa; Mon, 11 Feb 2019 23:15:22 -0800 (PST) X-Google-Smtp-Source: AHgI3IadTpqyVuMzTBWTwt3HCn82MuD+TUvNHieSK2go62htb2OhZE2vjBt/aELiFA9pNU7Dckwi X-Received: by 2002:a62:178f:: with SMTP id 137mr2522370pfx.226.1549955721999; Mon, 11 Feb 2019 23:15:21 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1549955721; cv=none; d=google.com; s=arc-20160816; b=o6MXuXps+x64zL3fq6K0GLjzizloqGq5OLcwdrqPmagfY17eVZDLf14fFdBw+Y12la WNoVGdmNiZO8zaXs9c1pfuUTKWni9joD0RWqJP2EuNEFcH/yPuV7Zr0j23OBobqvdIPy o3jjKy4kkTQAXDmMqSeeYiKFi6nLxSVlkrmk3ALj3E2Y6OD28DCBMBtMQoFkk/rhku/n wr/Q1jDCxl09DwbkyHc3MbslRPBpdAoFdLcLgCr+r11ZUSFOLkULrRGG5nLmRKi6y3Rr lkmtGcuwLgoATNhxaITNtwGp91pE4wqtsP499etS23xvWvJZm9CEQRCNYCDkt+Krg2U3 v0dg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:dkim-filter; bh=ihNbLBMtgE/zJu/k8HCGhdOaZjsPbiFnKTP5gCB7XuY=; b=rPPER32pzgMoBqr2nVyQVbo2nBY4bFlBOFROsTFg92sgeuDvUirHLWxQ+OU4TvzEb7 HTNkuJJ15hAWw6YsWyQ/0p1vbZ9dEbUNDkievXCYUKHypduJFB3dRVuGnJIFLG+89btJ ojBuq5D2KhaRjcgyHLhS0LWmju467D9DzMyW3MlOSFAW2tIdjogCKkkUtxQBS6C8Az9T wTO0AKws2mYSVadd8olP9i9AL80WlWx5wyieqBdsBay/PzKcKKNLaoqxbr70cS++ct2i 2woFBIJHLbkymQsZ4BrKHGCMgKWwUM+74R6KdntENmILgi8IxwDMvDvPAbLA9e2CFCih JUsg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@nifty.com header.s=dec2015msa header.b=wzJS7IgE; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id l61si13465175plb.6.2019.02.11.23.15.20; Mon, 11 Feb 2019 23:15:21 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@nifty.com header.s=dec2015msa header.b=wzJS7IgE; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728260AbfBLHPT (ORCPT + 31 others); Tue, 12 Feb 2019 02:15:19 -0500 Received: from conuserg-09.nifty.com ([210.131.2.76]:37649 "EHLO conuserg-09.nifty.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726864AbfBLHOk (ORCPT ); Tue, 12 Feb 2019 02:14:40 -0500 Received: from pug.e01.socionext.com (p14092-ipngnfx01kyoto.kyoto.ocn.ne.jp [153.142.97.92]) (authenticated) by conuserg-09.nifty.com with ESMTP id x1C7DPdQ019269; Tue, 12 Feb 2019 16:13:27 +0900 DKIM-Filter: OpenDKIM Filter v2.10.3 conuserg-09.nifty.com x1C7DPdQ019269 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nifty.com; s=dec2015msa; t=1549955608; bh=ihNbLBMtgE/zJu/k8HCGhdOaZjsPbiFnKTP5gCB7XuY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=wzJS7IgEHpXoyyUyx4hkJ4XFkZ90FNdm1QPP6/lrY38h0B+Zmf/QMjaxUR7AaJVU4 rYkYBo7OYzUo12abe+rjckymZvS8Ypku/IppoBbt69l7mzN9U4GuXl350nIfrT/MKJ 521RElPveetp/YawBhDlQA/5KfOkZkdqhvTBuRpLhR02ey4MVO7igbT9rfs0zJFR5C UPuiiJR2errII0t2HwhhMWdCOAwOXI09YNfrAnWpldSbv+R3t6HhJCRRkn9nSGmank YzgSpRDPXYmVAV6ap8SKxQqumWZeWszWUD331FdGi6ssRyg6Y+K2lwgAAM7CUG0IZO QzdKE7X6fKVOA== X-Nifty-SrcIP: [153.142.97.92] From: Masahiro Yamada To: linux-mtd@lists.infradead.org, Miquel Raynal Cc: Boris Brezillon , Masahiro Yamada , Brian Norris , linux-kernel@vger.kernel.org, Marek Vasut , Richard Weinberger , David Woodhouse Subject: [PATCH v2 02/10] mtd: rawnand: denali: refactor syndrome layout handling for raw access Date: Tue, 12 Feb 2019 16:12:54 +0900 Message-Id: <1549955582-30346-3-git-send-email-yamada.masahiro@socionext.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1549955582-30346-1-git-send-email-yamada.masahiro@socionext.com> References: <1549955582-30346-1-git-send-email-yamada.masahiro@socionext.com> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org The Denali IP adopts the syndrome page layout (payload and ECC are interleaved). The *_page_raw() and *_oob() callbacks are complicated because they must hide the underlying layout used by the hardware, and always return contiguous in-band and out-of-band data. Currently, similar code is duplicated to reorganize the data layout. For example, denali_read_page_raw() and denali_write_page_raw() look almost the same. The idea for refactoring is to split the code into two parts: [1] conversion of page layout [2] what to do at every ECC chunk boundary For [1], I wrote denali_raw_payload_op() and denali_raw_oob_op(). They manipulate data for the Denali controller's specific page layout of in-band, out-of-band, respectively. The difference between write and read is just the operation at ECC chunk boundaries. For example, denali_read_oob() calls nand_change_read_column_op(), whereas denali_write_oob() calls nand_change_write_column_op(). So, I implemented [2] as a callback passed into [1]. Signed-off-by: Masahiro Yamada --- Changes in v2: None drivers/mtd/nand/raw/denali.c | 354 +++++++++++++++++++----------------------- 1 file changed, 163 insertions(+), 191 deletions(-) -- 2.7.4 diff --git a/drivers/mtd/nand/raw/denali.c b/drivers/mtd/nand/raw/denali.c index 4ac1314..9287f4f 100644 --- a/drivers/mtd/nand/raw/denali.c +++ b/drivers/mtd/nand/raw/denali.c @@ -608,159 +608,210 @@ static int denali_data_xfer(struct nand_chip *chip, void *buf, size_t size, return denali_pio_xfer(denali, buf, size, page, write); } -static void denali_oob_xfer(struct mtd_info *mtd, struct nand_chip *chip, - int page, int write) +typedef int denali_change_column_callback(void *buf, unsigned int offset, + unsigned int len, void *priv); + +static int denali_raw_payload_op(struct nand_chip *chip, void *buf, + denali_change_column_callback *cb, void *priv) { - struct denali_nand_info *denali = mtd_to_denali(mtd); + struct denali_nand_info *denali = to_denali(chip); + struct mtd_info *mtd = nand_to_mtd(chip); + struct nand_ecc_ctrl *ecc = &chip->ecc; + int writesize = mtd->writesize; + int oob_skip = denali->oob_skip_bytes; + int ret, i, pos, len; + + for (i = 0; i < ecc->steps; i++) { + pos = i * (ecc->size + ecc->bytes); + len = ecc->size; + + if (pos >= writesize) { + pos += oob_skip; + } else if (pos + len > writesize) { + /* This chunk overwraps the BBM area. Must be split */ + ret = cb(buf, pos, writesize - pos, priv); + if (ret) + return ret; + + buf += writesize - pos; + len -= writesize - pos; + pos = writesize + oob_skip; + } + + ret = cb(buf, pos, len, priv); + if (ret) + return ret; + + buf += len; + } + + return 0; +} + +static int denali_raw_oob_op(struct nand_chip *chip, void *buf, + denali_change_column_callback *cb, void *priv) +{ + struct denali_nand_info *denali = to_denali(chip); + struct mtd_info *mtd = nand_to_mtd(chip); + struct nand_ecc_ctrl *ecc = &chip->ecc; int writesize = mtd->writesize; int oobsize = mtd->oobsize; - uint8_t *bufpoi = chip->oob_poi; - int ecc_steps = chip->ecc.steps; - int ecc_size = chip->ecc.size; - int ecc_bytes = chip->ecc.bytes; int oob_skip = denali->oob_skip_bytes; - size_t size = writesize + oobsize; - int i, pos, len; + int ret, i, pos, len; /* BBM at the beginning of the OOB area */ - if (write) - nand_prog_page_begin_op(chip, page, writesize, bufpoi, - oob_skip); - else - nand_read_page_op(chip, page, writesize, bufpoi, oob_skip); - bufpoi += oob_skip; + ret = cb(buf, writesize, oob_skip, priv); + if (ret) + return ret; - /* OOB ECC */ - for (i = 0; i < ecc_steps; i++) { - pos = ecc_size + i * (ecc_size + ecc_bytes); - len = ecc_bytes; + buf += oob_skip; - if (pos >= writesize) - pos += oob_skip; - else if (pos + len > writesize) - len = writesize - pos; + for (i = 0; i < ecc->steps; i++) { + pos = ecc->size + i * (ecc->size + ecc->bytes); - if (write) - nand_change_write_column_op(chip, pos, bufpoi, len, - false); + if (i == ecc->steps - 1) + /* The last chunk includes OOB free */ + len = writesize + oobsize - pos - oob_skip; else - nand_change_read_column_op(chip, pos, bufpoi, len, - false); - bufpoi += len; - if (len < ecc_bytes) { - len = ecc_bytes - len; - if (write) - nand_change_write_column_op(chip, writesize + - oob_skip, bufpoi, - len, false); - else - nand_change_read_column_op(chip, writesize + - oob_skip, bufpoi, - len, false); - bufpoi += len; + len = ecc->bytes; + + if (pos >= writesize) { + pos += oob_skip; + } else if (pos + len > writesize) { + /* This chunk overwraps the BBM area. Must be split */ + ret = cb(buf, pos, writesize - pos, priv); + if (ret) + return ret; + + buf += writesize - pos; + len -= writesize - pos; + pos = writesize + oob_skip; } + + ret = cb(buf, pos, len, priv); + if (ret) + return ret; + + buf += len; } - /* OOB free */ - len = oobsize - (bufpoi - chip->oob_poi); - if (write) - nand_change_write_column_op(chip, size - len, bufpoi, len, - false); - else - nand_change_read_column_op(chip, size - len, bufpoi, len, - false); + return 0; +} + +static int denali_memcpy_in(void *buf, unsigned int offset, unsigned int len, + void *priv) +{ + memcpy(buf, priv + offset, len); + return 0; } static int denali_read_page_raw(struct nand_chip *chip, uint8_t *buf, int oob_required, int page) { + struct denali_nand_info *denali = to_denali(chip); struct mtd_info *mtd = nand_to_mtd(chip); - struct denali_nand_info *denali = mtd_to_denali(mtd); - int writesize = mtd->writesize; - int oobsize = mtd->oobsize; - int ecc_steps = chip->ecc.steps; - int ecc_size = chip->ecc.size; - int ecc_bytes = chip->ecc.bytes; void *tmp_buf = denali->buf; - int oob_skip = denali->oob_skip_bytes; - size_t size = writesize + oobsize; - int ret, i, pos, len; + size_t size = mtd->writesize + mtd->oobsize; + int ret; + + if (!buf) + return -EINVAL; ret = denali_data_xfer(chip, tmp_buf, size, page, 1, 0); if (ret) return ret; - /* Arrange the buffer for syndrome payload/ecc layout */ - if (buf) { - for (i = 0; i < ecc_steps; i++) { - pos = i * (ecc_size + ecc_bytes); - len = ecc_size; - - if (pos >= writesize) - pos += oob_skip; - else if (pos + len > writesize) - len = writesize - pos; - - memcpy(buf, tmp_buf + pos, len); - buf += len; - if (len < ecc_size) { - len = ecc_size - len; - memcpy(buf, tmp_buf + writesize + oob_skip, - len); - buf += len; - } - } - } + ret = denali_raw_payload_op(chip, buf, denali_memcpy_in, tmp_buf); + if (ret) + return ret; if (oob_required) { - uint8_t *oob = chip->oob_poi; - - /* BBM at the beginning of the OOB area */ - memcpy(oob, tmp_buf + writesize, oob_skip); - oob += oob_skip; - - /* OOB ECC */ - for (i = 0; i < ecc_steps; i++) { - pos = ecc_size + i * (ecc_size + ecc_bytes); - len = ecc_bytes; - - if (pos >= writesize) - pos += oob_skip; - else if (pos + len > writesize) - len = writesize - pos; - - memcpy(oob, tmp_buf + pos, len); - oob += len; - if (len < ecc_bytes) { - len = ecc_bytes - len; - memcpy(oob, tmp_buf + writesize + oob_skip, - len); - oob += len; - } - } - - /* OOB free */ - len = oobsize - (oob - chip->oob_poi); - memcpy(oob, tmp_buf + size - len, len); + ret = denali_raw_oob_op(chip, chip->oob_poi, denali_memcpy_in, + tmp_buf); + if (ret) + return ret; } return 0; } -static int denali_read_oob(struct nand_chip *chip, int page) +static int denali_memcpy_out(void *buf, unsigned int offset, unsigned int len, + void *priv) +{ + memcpy(priv + offset, buf, len); + return 0; +} + +static int denali_write_page_raw(struct nand_chip *chip, const uint8_t *buf, + int oob_required, int page) { + struct denali_nand_info *denali = to_denali(chip); struct mtd_info *mtd = nand_to_mtd(chip); + void *tmp_buf = denali->buf; + size_t size = mtd->writesize + mtd->oobsize; + int ret; - denali_oob_xfer(mtd, chip, page, 0); + if (!buf) + return -EINVAL; - return 0; + /* + * Fill the buffer with 0xff first except the full page transfer. + * This simplifies the logic. + */ + if (!oob_required) + memset(tmp_buf, 0xff, size); + + ret = denali_raw_payload_op(chip, (void *)buf, denali_memcpy_out, + tmp_buf); + if (ret) + return ret; + + if (oob_required) { + ret = denali_raw_oob_op(chip, chip->oob_poi, denali_memcpy_out, + tmp_buf); + if (ret) + return ret; + } + + return denali_data_xfer(chip, tmp_buf, size, page, 1, 1); +} + +static int denali_change_read_column_op(void *buf, unsigned int offset, + unsigned int len, void *priv) +{ + return nand_change_read_column_op(priv, offset, buf, len, false); +} + +static int denali_read_oob(struct nand_chip *chip, int page) +{ + int ret; + + ret = nand_read_page_op(chip, page, 0, NULL, 0); + if (ret) + return ret; + + return denali_raw_oob_op(chip, chip->oob_poi, + denali_change_read_column_op, chip); +} + +static int denali_change_write_column_op(void *buf, unsigned int offset, + unsigned int len, void *priv) +{ + return nand_change_write_column_op(priv, offset, buf, len, false); } static int denali_write_oob(struct nand_chip *chip, int page) { - struct mtd_info *mtd = nand_to_mtd(chip); + int ret; - denali_oob_xfer(mtd, chip, page, 1); + ret = nand_prog_page_begin_op(chip, page, 0, NULL, 0); + if (ret) + return ret; + + ret = denali_raw_oob_op(chip, chip->oob_poi, + denali_change_write_column_op, chip); + if (ret) + return ret; return nand_prog_page_end_op(chip); } @@ -798,85 +849,6 @@ static int denali_read_page(struct nand_chip *chip, uint8_t *buf, return stat; } -static int denali_write_page_raw(struct nand_chip *chip, const uint8_t *buf, - int oob_required, int page) -{ - struct mtd_info *mtd = nand_to_mtd(chip); - struct denali_nand_info *denali = mtd_to_denali(mtd); - int writesize = mtd->writesize; - int oobsize = mtd->oobsize; - int ecc_steps = chip->ecc.steps; - int ecc_size = chip->ecc.size; - int ecc_bytes = chip->ecc.bytes; - void *tmp_buf = denali->buf; - int oob_skip = denali->oob_skip_bytes; - size_t size = writesize + oobsize; - int i, pos, len; - - /* - * Fill the buffer with 0xff first except the full page transfer. - * This simplifies the logic. - */ - if (!buf || !oob_required) - memset(tmp_buf, 0xff, size); - - /* Arrange the buffer for syndrome payload/ecc layout */ - if (buf) { - for (i = 0; i < ecc_steps; i++) { - pos = i * (ecc_size + ecc_bytes); - len = ecc_size; - - if (pos >= writesize) - pos += oob_skip; - else if (pos + len > writesize) - len = writesize - pos; - - memcpy(tmp_buf + pos, buf, len); - buf += len; - if (len < ecc_size) { - len = ecc_size - len; - memcpy(tmp_buf + writesize + oob_skip, buf, - len); - buf += len; - } - } - } - - if (oob_required) { - const uint8_t *oob = chip->oob_poi; - - /* BBM at the beginning of the OOB area */ - memcpy(tmp_buf + writesize, oob, oob_skip); - oob += oob_skip; - - /* OOB ECC */ - for (i = 0; i < ecc_steps; i++) { - pos = ecc_size + i * (ecc_size + ecc_bytes); - len = ecc_bytes; - - if (pos >= writesize) - pos += oob_skip; - else if (pos + len > writesize) - len = writesize - pos; - - memcpy(tmp_buf + pos, oob, len); - oob += len; - if (len < ecc_bytes) { - len = ecc_bytes - len; - memcpy(tmp_buf + writesize + oob_skip, oob, - len); - oob += len; - } - } - - /* OOB free */ - len = oobsize - (oob - chip->oob_poi); - memcpy(tmp_buf + size - len, oob, len); - } - - return denali_data_xfer(chip, tmp_buf, size, page, 1, 1); -} - static int denali_write_page(struct nand_chip *chip, const uint8_t *buf, int oob_required, int page) { From patchwork Tue Feb 12 07:12:56 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Masahiro Yamada X-Patchwork-Id: 158124 Delivered-To: patch@linaro.org Received: by 2002:a02:48:0:0:0:0:0 with SMTP id 69csp3510679jaa; Mon, 11 Feb 2019 23:15:15 -0800 (PST) X-Google-Smtp-Source: AHgI3Iaa90ylREMkLWpcztUsLXzi8wog5r6dHY9zU/Wp+qTZEveGOIO0ASY1yrwCVVYPIrW02eAT X-Received: by 2002:a63:4618:: with SMTP id t24mr2362886pga.316.1549955715365; Mon, 11 Feb 2019 23:15:15 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1549955715; cv=none; d=google.com; s=arc-20160816; b=fEqImEKMpg5dzDxqmj0ySs0xTvsyHpWcnonIFFIMJthFhZFtuo3mw6ZGa2ZNy4y0zE jtzzaJ+6yzhYMPVDz/rdmzKca99AC19h+org2k+TclVMJYjMHLYwbHsQfPOFks55+4OP tiGzHvRV4cBRPY7626WQR5YGjfftiYTXX/p15Umk3idXrRHPASwS3iNQ+VPyvYsqQWcj 0jg1Z1RjVN0HJFSBClfFiOIZ8xc5y0xDfTclAyXDiLWjUvyKOADrqZMkafS8NWhOm6jK 5vHUyj1eBcXF0cF9y2lIJ+C32N8RllNJKDk1ezZt1Ujlwa7XXLUxTUcxdF2TylZqyXtY 6uRg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:dkim-filter; bh=hYC0Lc/1kY7sze/Gf1zTbIllRohqLxgfC98eG37YG2k=; b=IhM6xLzQM43YAooAFDFY1FXrLwtSP/cLl/BtlSeSqZxlMcVUbzUY0tjMLg3yzYqPm8 hLsRssXfDPGwLUZOmzfYbyC9KqcP2YSSwm4bLch10s7NfA1mz7X6yeql3V9MwXDLdMW3 NQxdjbuN9wn0aU+BjaMLqa31vA+ImhiqB6SrGPeXGbw26+5cMqFrMQww3R6dvADbuGuZ JhhVeujP1FprPDYgBejpHNdjMhRW9hURO4YoE9Hbikzpsr1ANR7aRsXaggTRgL8Fk5jR pzw3BTql5NHoMrtH4GjFf1dJjT//fFdAG5BBAAaOK+uoYljfNmPUITaBRxTmcCd930Kk vnnQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@nifty.com header.s=dec2015msa header.b="t51k/HGP"; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id f23si10804381plr.151.2019.02.11.23.15.15; Mon, 11 Feb 2019 23:15:15 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@nifty.com header.s=dec2015msa header.b="t51k/HGP"; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728002AbfBLHPC (ORCPT + 31 others); Tue, 12 Feb 2019 02:15:02 -0500 Received: from conuserg-09.nifty.com ([210.131.2.76]:37709 "EHLO conuserg-09.nifty.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728095AbfBLHOl (ORCPT ); Tue, 12 Feb 2019 02:14:41 -0500 Received: from pug.e01.socionext.com (p14092-ipngnfx01kyoto.kyoto.ocn.ne.jp [153.142.97.92]) (authenticated) by conuserg-09.nifty.com with ESMTP id x1C7DPdS019269; Tue, 12 Feb 2019 16:13:29 +0900 DKIM-Filter: OpenDKIM Filter v2.10.3 conuserg-09.nifty.com x1C7DPdS019269 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nifty.com; s=dec2015msa; t=1549955610; bh=hYC0Lc/1kY7sze/Gf1zTbIllRohqLxgfC98eG37YG2k=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=t51k/HGP9AypqmsY/BVk79jeKcXr0/r6R1N8kbGmVf7P8GYl37wtTO1VajhF14gC1 7VCcKHWsLTYLMbKuHwt8GM5rcQHvuPfJKoFJgk4GqWoKXYPEGAizQG89ckKrukn8hu TPx4/AjRRPhp8cn2r0FTuZWXCh09R6nW5a/PqP8v2RbXmjKAuNdk02xjNdgKK7FvRG qg33ta3UDGW7HQtwswHXUOnCI2MkKJniyHdadtqBLVaE1cCvcjQac4r98AVhCH4Zq5 EH6P1/8fIxiXnhF0/SAFdCaoVPIeF4Dncu1X6mtfvnPG7U3RE3cZr2p8P2iYGn6Ku9 0RcHfQwNVk1+g== X-Nifty-SrcIP: [153.142.97.92] From: Masahiro Yamada To: linux-mtd@lists.infradead.org, Miquel Raynal Cc: Boris Brezillon , Masahiro Yamada , Brian Norris , linux-kernel@vger.kernel.org, Marek Vasut , Richard Weinberger , David Woodhouse Subject: [PATCH v2 04/10] mtd: rawnand: denali: switch over to ->exec_op() from legacy hooks Date: Tue, 12 Feb 2019 16:12:56 +0900 Message-Id: <1549955582-30346-5-git-send-email-yamada.masahiro@socionext.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1549955582-30346-1-git-send-email-yamada.masahiro@socionext.com> References: <1549955582-30346-1-git-send-email-yamada.masahiro@socionext.com> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Implement ->exec_op(), and remove the deprecated hooks. Signed-off-by: Masahiro Yamada --- Changes in v2: None drivers/mtd/nand/raw/denali.c | 234 +++++++++++++++++++++++------------------- 1 file changed, 126 insertions(+), 108 deletions(-) -- 2.7.4 diff --git a/drivers/mtd/nand/raw/denali.c b/drivers/mtd/nand/raw/denali.c index a2fe2ff..bd7df25 100644 --- a/drivers/mtd/nand/raw/denali.c +++ b/drivers/mtd/nand/raw/denali.c @@ -206,85 +206,11 @@ static uint32_t denali_wait_for_irq(struct denali_nand_info *denali, return denali->irq_status; } -static void denali_read_buf(struct nand_chip *chip, uint8_t *buf, int len) +static void denali_select_target(struct nand_chip *chip, int cs) { - struct mtd_info *mtd = nand_to_mtd(chip); - struct denali_nand_info *denali = mtd_to_denali(mtd); - u32 addr = DENALI_MAP11_DATA | DENALI_BANK(denali); - int i; - - for (i = 0; i < len; i++) - buf[i] = denali->host_read(denali, addr); -} - -static void denali_write_buf(struct nand_chip *chip, const uint8_t *buf, - int len) -{ - struct denali_nand_info *denali = mtd_to_denali(nand_to_mtd(chip)); - u32 addr = DENALI_MAP11_DATA | DENALI_BANK(denali); - int i; - - for (i = 0; i < len; i++) - denali->host_write(denali, addr, buf[i]); -} - -static void denali_read_buf16(struct nand_chip *chip, uint8_t *buf, int len) -{ - struct denali_nand_info *denali = mtd_to_denali(nand_to_mtd(chip)); - u32 addr = DENALI_MAP11_DATA | DENALI_BANK(denali); - uint16_t *buf16 = (uint16_t *)buf; - int i; - - for (i = 0; i < len / 2; i++) - buf16[i] = denali->host_read(denali, addr); -} - -static void denali_write_buf16(struct nand_chip *chip, const uint8_t *buf, - int len) -{ - struct denali_nand_info *denali = mtd_to_denali(nand_to_mtd(chip)); - u32 addr = DENALI_MAP11_DATA | DENALI_BANK(denali); - const uint16_t *buf16 = (const uint16_t *)buf; - int i; - - for (i = 0; i < len / 2; i++) - denali->host_write(denali, addr, buf16[i]); -} - -static uint8_t denali_read_byte(struct nand_chip *chip) -{ - uint8_t byte; - - denali_read_buf(chip, &byte, 1); - - return byte; -} - -static void denali_write_byte(struct nand_chip *chip, uint8_t byte) -{ - denali_write_buf(chip, &byte, 1); -} - -static void denali_cmd_ctrl(struct nand_chip *chip, int dat, unsigned int ctrl) -{ - struct denali_nand_info *denali = mtd_to_denali(nand_to_mtd(chip)); - uint32_t type; - - if (ctrl & NAND_CLE) - type = DENALI_MAP11_CMD; - else if (ctrl & NAND_ALE) - type = DENALI_MAP11_ADDR; - else - return; - - /* - * Some commands are followed by chip->legacy.waitfunc. - * irq_status must be cleared here to catch the R/B# interrupt later. - */ - if (ctrl & NAND_CTRL_CHANGE) - denali_reset_irq(denali); + struct denali_nand_info *denali = to_denali(chip); - denali->host_write(denali, DENALI_BANK(denali) | type, dat); + denali->active_bank = cs; } static int denali_check_erased_page(struct nand_chip *chip, @@ -596,6 +522,8 @@ static int denali_data_xfer(struct nand_chip *chip, void *buf, size_t size, { struct denali_nand_info *denali = to_denali(chip); + denali_select_target(chip, chip->cur_cs); + iowrite32(raw ? 0 : ECC_ENABLE__FLAG, denali->reg + ECC_ENABLE); iowrite32(raw ? TRANSFER_SPARE_REG__FLAG : 0, denali->reg + TRANSFER_SPARE_REG); @@ -856,24 +784,6 @@ static int denali_write_page(struct nand_chip *chip, const uint8_t *buf, 0, 1); } -static void denali_select_chip(struct nand_chip *chip, int cs) -{ - struct denali_nand_info *denali = mtd_to_denali(nand_to_mtd(chip)); - - denali->active_bank = cs; -} - -static int denali_waitfunc(struct nand_chip *chip) -{ - struct denali_nand_info *denali = mtd_to_denali(nand_to_mtd(chip)); - uint32_t irq_status; - - /* R/B# pin transitioned from low to high? */ - irq_status = denali_wait_for_irq(denali, INTR__INT_ACT); - - return irq_status & INTR__INT_ACT ? 0 : NAND_STATUS_FAIL; -} - static int denali_setup_data_interface(struct nand_chip *chip, int chipnr, const struct nand_data_interface *conf) { @@ -1185,13 +1095,6 @@ static int denali_attach_chip(struct nand_chip *chip) mtd_set_ooblayout(mtd, &denali_ooblayout_ops); - if (chip->options & NAND_BUSWIDTH_16) { - chip->legacy.read_buf = denali_read_buf16; - chip->legacy.write_buf = denali_write_buf16; - } else { - chip->legacy.read_buf = denali_read_buf; - chip->legacy.write_buf = denali_write_buf; - } chip->ecc.read_page = denali_read_page; chip->ecc.read_page_raw = denali_read_page_raw; chip->ecc.write_page = denali_write_page; @@ -1223,9 +1126,130 @@ static void denali_detach_chip(struct nand_chip *chip) kfree(denali->buf); } +static void denali_exec_in8(struct denali_nand_info *denali, u32 type, + u8 *buf, unsigned int len) +{ + int i; + + for (i = 0; i < len; i++) + buf[i] = denali->host_read(denali, type | DENALI_BANK(denali)); +} + +static void denali_exec_in16(struct denali_nand_info *denali, u32 type, + u8 *buf, unsigned int len) +{ + u32 data; + int i; + + for (i = 0; i < len; i += 2) { + data = denali->host_read(denali, type | DENALI_BANK(denali)); + /* bit 31:24 and 15:8 are used for DDR */ + buf[i] = data >> 16; + buf[i + 1] = data; + } +} + +static void denali_exec_out8(struct denali_nand_info *denali, u32 type, + const u8 *buf, unsigned int len) +{ + int i; + + for (i = 0; i < len; i++) + denali->host_write(denali, type | DENALI_BANK(denali), buf[i]); +} + +static void denali_exec_out16(struct denali_nand_info *denali, u32 type, + const u8 *buf, unsigned int len) +{ + int i; + + for (i = 0; i < len; i += 2) + denali->host_write(denali, type | DENALI_BANK(denali), + buf[i + 1] << 16 | buf[i]); +} + +static int denali_exec_waitrdy(struct denali_nand_info *denali) +{ + u32 irq_stat; + + /* R/B# pin transitioned from low to high? */ + irq_stat = denali_wait_for_irq(denali, INTR__INT_ACT); + + /* Just in case nand_operation has multiple NAND_OP_WAITRDY_INSTR. */ + denali_reset_irq(denali); + + return irq_stat & INTR__INT_ACT ? 0 : -EIO; +} + +static int denali_exec_instr(struct nand_chip *chip, + const struct nand_op_instr *instr) +{ + struct denali_nand_info *denali = to_denali(chip); + bool width16 = chip->options & NAND_BUSWIDTH_16; + + switch (instr->type) { + case NAND_OP_CMD_INSTR: + denali_exec_out8(denali, DENALI_MAP11_CMD, + &instr->ctx.cmd.opcode, 1); + return 0; + case NAND_OP_ADDR_INSTR: + denali_exec_out8(denali, DENALI_MAP11_ADDR, + instr->ctx.addr.addrs, + instr->ctx.addr.naddrs); + return 0; + case NAND_OP_DATA_IN_INSTR: + (!instr->ctx.data.force_8bit && width16 ? + denali_exec_in16 : + denali_exec_in8)(denali, DENALI_MAP11_DATA, + instr->ctx.data.buf.in, + instr->ctx.data.len); + return 0; + case NAND_OP_DATA_OUT_INSTR: + (!instr->ctx.data.force_8bit && width16 ? + denali_exec_out16 : + denali_exec_out8)(denali, DENALI_MAP11_DATA, + instr->ctx.data.buf.out, + instr->ctx.data.len); + return 0; + case NAND_OP_WAITRDY_INSTR: + return denali_exec_waitrdy(denali); + default: + WARN_ONCE(1, "unsupported NAND instruction type: %d\n", + instr->type); + + return -EINVAL; + } +} + +static int denali_exec_op(struct nand_chip *chip, + const struct nand_operation *op, bool check_only) +{ + int i, ret; + + if (check_only) + return 0; + + denali_select_target(chip, op->cs); + + /* + * Some commands contain NAND_OP_WAITRDY_INSTR. + * irq must be cleared here to catch the R/B# interrupt there. + */ + denali_reset_irq(to_denali(chip)); + + for (i = 0; i < op->ninstrs; i++) { + ret = denali_exec_instr(chip, &op->instrs[i]); + if (ret) + return ret; + } + + return 0; +} + static const struct nand_controller_ops denali_controller_ops = { .attach_chip = denali_attach_chip, .detach_chip = denali_detach_chip, + .exec_op = denali_exec_op, .setup_data_interface = denali_setup_data_interface, }; @@ -1260,12 +1284,6 @@ int denali_init(struct denali_nand_info *denali) if (!mtd->name) mtd->name = "denali-nand"; - chip->legacy.select_chip = denali_select_chip; - chip->legacy.read_byte = denali_read_byte; - chip->legacy.write_byte = denali_write_byte; - chip->legacy.cmd_ctrl = denali_cmd_ctrl; - chip->legacy.waitfunc = denali_waitfunc; - if (features & FEATURES__INDEX_ADDR) { denali->host_read = denali_indexed_read; denali->host_write = denali_indexed_write; From patchwork Tue Feb 12 07:12:57 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Masahiro Yamada X-Patchwork-Id: 158122 Delivered-To: patch@linaro.org Received: by 2002:a02:48:0:0:0:0:0 with SMTP id 69csp3510542jaa; Mon, 11 Feb 2019 23:15:05 -0800 (PST) X-Google-Smtp-Source: AHgI3IZGzPa3RrJkkGyHOY98Y55555Wicw6dInf+MW+VKgOmnGBoX9uFVLxxtNATW5LHfLmIHPcF X-Received: by 2002:a17:902:f20a:: with SMTP id gn10mr2552748plb.105.1549955704942; Mon, 11 Feb 2019 23:15:04 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1549955704; cv=none; d=google.com; s=arc-20160816; b=wxXvCdJQetql/LTutT9DZA6BpPsPwzQRAhhxVCNtuuFr3+QKr+Q2RoWnsUSQUoCgns G89nm3HlChIxiM65BImr2GKFpscGnPOs/2P5is2pE+OjDUawvUeLyhufUYXVEYaNgp2+ 7ePMx+X1aSX55jO7Ssh7Rrv9N78cw73SG97npizYIuOd7ol4vYnD19aGGNZY7H75fPQw WHwKcZ8fIS7NVKWQD9Gb+FqOu0tHdqCJNYhTpK2ypLQBg51p3ATRaqwm4LSzqmqE+Rm3 OZMI4Bc1b5XcmTQdUlYm23sfjD2pBC8wtqv9D+0QAG0BN2jMtAWNfxxgw7PgT6uZngxe BQ6g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:dkim-filter; bh=8Izt7+M0GIMZcso6VHsMqkgTh6a7EcMPGS4x0G6xF04=; b=dshiyxkqCUx+xTxDfTFUe3+sF1zN8x8WVJ47UOtAyZ7kC4oFQIGrnGRmP0z6HmUVoz lKY931FGs/4mWw8LOc1fRxF1A73oCxUgcj7bD+347NtqrrpFg5dvs744Cj+1BheroId7 wdkj6Qk2WE4b992EM2oqywFN8epOPuFbIgSiFv3hhMbrrJbcXYzlhaCbxGiEbryUnaPr /Gf9j4YCgQWYVznhK0571pfN88mXDIx+MBACHOJ1aET5Uu2NEmB0wRZFIkQMzytAVYBP PN9iQmgCGdUIApQeu62UegfTcoEVK37oPUWYqEg02A2wHmtg6d5HhEC+ThHph6FwnHCD QDBQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@nifty.com header.s=dec2015msa header.b=I7fuUbRO; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id k13si4553704pgo.502.2019.02.11.23.15.04; Mon, 11 Feb 2019 23:15:04 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@nifty.com header.s=dec2015msa header.b=I7fuUbRO; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728223AbfBLHPD (ORCPT + 31 others); Tue, 12 Feb 2019 02:15:03 -0500 Received: from conuserg-09.nifty.com ([210.131.2.76]:37683 "EHLO conuserg-09.nifty.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728077AbfBLHOl (ORCPT ); Tue, 12 Feb 2019 02:14:41 -0500 Received: from pug.e01.socionext.com (p14092-ipngnfx01kyoto.kyoto.ocn.ne.jp [153.142.97.92]) (authenticated) by conuserg-09.nifty.com with ESMTP id x1C7DPdT019269; Tue, 12 Feb 2019 16:13:30 +0900 DKIM-Filter: OpenDKIM Filter v2.10.3 conuserg-09.nifty.com x1C7DPdT019269 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nifty.com; s=dec2015msa; t=1549955610; bh=8Izt7+M0GIMZcso6VHsMqkgTh6a7EcMPGS4x0G6xF04=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=I7fuUbROclvtxjHgSQM1T5JfMt/0sk1vB5Eopd7FuVNPMZxoHeUvaBKW1bleLZ5Jv ZpPjejoCnRDtwscbzsVrw7UAcYi0ey0fD1NwBieYM94U+KK3n2r4CPT+sZYov8Y+ko gOqXyTvLvPK16ycyyvc8WMWddu6uYeTqe6XA0ket347uuMUyUZQSna7Ib3ae32bOs0 LSlSvBgOcc3w1uLVKHswDjh/s7JpJh/qcp/Q5PTdSIvx0UTlhgaTSs25x7E7eVOsJQ 0/3OAVkOvusdumLKmlNIFRscQeyqq5ctueMcXfaqerRf+LXBOvJXGdoBz76bb7JC5d XZQsf8r0oI/cw== X-Nifty-SrcIP: [153.142.97.92] From: Masahiro Yamada To: linux-mtd@lists.infradead.org, Miquel Raynal Cc: Boris Brezillon , Masahiro Yamada , Brian Norris , linux-kernel@vger.kernel.org, Marek Vasut , Richard Weinberger , David Woodhouse Subject: [PATCH v2 05/10] mtd: rawnand: denali: use more precise timeout for NAND_OP_WAITRDT_INSTR Date: Tue, 12 Feb 2019 16:12:57 +0900 Message-Id: <1549955582-30346-6-git-send-email-yamada.masahiro@socionext.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1549955582-30346-1-git-send-email-yamada.masahiro@socionext.com> References: <1549955582-30346-1-git-send-email-yamada.masahiro@socionext.com> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Currently, wait_for_completion_timeout() is always passed in the hard-coded msec_to_jiffies(1000). There is no specific reason for 1000 msec, but it was chosen to be long enough. With the exec_op() conversion, NAND_OP_WAITRDY_INSTR provides more precise timeout value, depending on the preceding command. Let's use it (+ 100 msec) to bail out earlier in error case. The 100 msec extra is in case the heavy load on the system. I am still keeping the hard-coded values for other higher level hooks such as page_read, page_write, etc. We know the value of tR, tPROG, but we have unknowledge about the data transfer speed of the DMA engine. Signed-off-by: Masahiro Yamada --- Changes in v2: - Add extra 100 msec to the wait-period in case the system is under load drivers/mtd/nand/raw/denali.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) -- 2.7.4 diff --git a/drivers/mtd/nand/raw/denali.c b/drivers/mtd/nand/raw/denali.c index bd7df25..7050b1f 100644 --- a/drivers/mtd/nand/raw/denali.c +++ b/drivers/mtd/nand/raw/denali.c @@ -176,7 +176,7 @@ static void denali_reset_irq(struct denali_nand_info *denali) } static uint32_t denali_wait_for_irq(struct denali_nand_info *denali, - uint32_t irq_mask) + u32 irq_mask, unsigned int timeout_ms) { unsigned long time_left, flags; uint32_t irq_status; @@ -195,8 +195,11 @@ static uint32_t denali_wait_for_irq(struct denali_nand_info *denali, reinit_completion(&denali->complete); spin_unlock_irqrestore(&denali->irq_lock, flags); + /* Prolong the IRQ wait time in case the system is under heavy load. */ + timeout_ms += 100; + time_left = wait_for_completion_timeout(&denali->complete, - msecs_to_jiffies(1000)); + msecs_to_jiffies(timeout_ms)); if (!time_left) { dev_err(denali->dev, "timeout while waiting for irq 0x%x\n", irq_mask); @@ -349,7 +352,7 @@ static int denali_sw_ecc_fixup(struct nand_chip *chip, * Once handle all ECC errors, controller will trigger an * ECC_TRANSACTION_DONE interrupt. */ - irq_status = denali_wait_for_irq(denali, INTR__ECC_TRANSACTION_DONE); + irq_status = denali_wait_for_irq(denali, INTR__ECC_TRANSACTION_DONE, 1); if (!(irq_status & INTR__ECC_TRANSACTION_DONE)) return -EIO; @@ -421,7 +424,7 @@ static int denali_pio_read(struct denali_nand_info *denali, u32 *buf, for (i = 0; i < size / 4; i++) buf[i] = denali->host_read(denali, addr); - irq_status = denali_wait_for_irq(denali, INTR__PAGE_XFER_INC); + irq_status = denali_wait_for_irq(denali, INTR__PAGE_XFER_INC, 1); if (!(irq_status & INTR__PAGE_XFER_INC)) return -EIO; @@ -444,7 +447,9 @@ static int denali_pio_write(struct denali_nand_info *denali, const u32 *buf, denali->host_write(denali, addr, buf[i]); irq_status = denali_wait_for_irq(denali, - INTR__PROGRAM_COMP | INTR__PROGRAM_FAIL); + INTR__PROGRAM_COMP | + INTR__PROGRAM_FAIL, + 1000); if (!(irq_status & INTR__PROGRAM_COMP)) return -EIO; @@ -501,7 +506,7 @@ static int denali_dma_xfer(struct denali_nand_info *denali, void *buf, denali_reset_irq(denali); denali->setup_dma(denali, dma_addr, page, write); - irq_status = denali_wait_for_irq(denali, irq_mask); + irq_status = denali_wait_for_irq(denali, irq_mask, 1000); if (!(irq_status & INTR__DMA_CMD_COMP)) ret = -EIO; else if (irq_status & ecc_err_mask) @@ -1168,12 +1173,13 @@ static void denali_exec_out16(struct denali_nand_info *denali, u32 type, buf[i + 1] << 16 | buf[i]); } -static int denali_exec_waitrdy(struct denali_nand_info *denali) +static int denali_exec_waitrdy(struct denali_nand_info *denali, + unsigned int timeout_ms) { u32 irq_stat; /* R/B# pin transitioned from low to high? */ - irq_stat = denali_wait_for_irq(denali, INTR__INT_ACT); + irq_stat = denali_wait_for_irq(denali, INTR__INT_ACT, timeout_ms); /* Just in case nand_operation has multiple NAND_OP_WAITRDY_INSTR. */ denali_reset_irq(denali); @@ -1212,7 +1218,8 @@ static int denali_exec_instr(struct nand_chip *chip, instr->ctx.data.len); return 0; case NAND_OP_WAITRDY_INSTR: - return denali_exec_waitrdy(denali); + return denali_exec_waitrdy(denali, + instr->ctx.waitrdy.timeout_ms); default: WARN_ONCE(1, "unsupported NAND instruction type: %d\n", instr->type); From patchwork Tue Feb 12 07:12:58 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Masahiro Yamada X-Patchwork-Id: 158119 Delivered-To: patch@linaro.org Received: by 2002:a02:48:0:0:0:0:0 with SMTP id 69csp3510255jaa; Mon, 11 Feb 2019 23:14:42 -0800 (PST) X-Google-Smtp-Source: AHgI3Iaj1M7Q1yX7tx6WJ3ul09tEaH2GSZAJp574jeIj9dYQWH1Qm+/hXoCNZeQCdP/1ItHolo4A X-Received: by 2002:a17:902:7598:: with SMTP id j24mr2581932pll.7.1549955682671; Mon, 11 Feb 2019 23:14:42 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1549955682; cv=none; d=google.com; s=arc-20160816; b=PjKcoTZyc5/CV+uEXXDXexzz4RDyPXSnIWOakW7OtsBWwO0YtMmbSv0lkecOLwjBtR 12Dei96UyRw/DSGPBZCsMEP7tce8hBbDNyyY2AceIa3mWNHuXRSHY4YzNIaYkV4kdaun 49EOx+/XZ/wvmZF6tnt7d+a3P8g5zGdTr4DFMF0E+jDj9v1w9F8y67is+/1DtBnejBh/ oMmaA2puRZe5jxUM3hZsmJ4qxZKmPpk7OdY+XsYHW9wBmzggpMTDO/46rIs5NZtc7Ywr s0a6iE2PSU6fUVMtZQedDmXk+i/swFYrHG4T+8oQZ7tc5l8rMUxDp1Dl4UZ2mx1qRzyP q+SQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:dkim-filter; bh=0G9g6BzHFdBZ8N7j/ak6EoadsuEhODUjvRjxPSQclEk=; b=ROqy62nHrPU+ribx+IeaehRAL/BejkAGF+jmPhAZtpbXvLhMNGBdRt+megKJIWmkoV RbVPMgho/Kjg+FlxFrPmzszoKRMYXHqeoPAKed6n+cGggvJbOBhBNmUEdEoE+vUBtUd3 gS5HL1f2koaYbVwe9HoVYHszjDXk3AqxPP3Edz88eV2KtG9j8cCPYvFfAGSebr6dXtQw +LPns5U0rkCs3oxW4YCJXfZ92dJWgQPdEtvNJ999PsWfqSJFAVqzciwAO+EEsncfzcbp IBGaYhbo+DGWQnB9Vb2YLcoHLMhNQWcplk/zEGaWCmijrDzykfrGj6dNVMeRKRAjYcDT Ws6Q== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@nifty.com header.s=dec2015msa header.b=F13MjZmx; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id r8si8639198plo.203.2019.02.11.23.14.42; Mon, 11 Feb 2019 23:14:42 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@nifty.com header.s=dec2015msa header.b=F13MjZmx; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728110AbfBLHOl (ORCPT + 31 others); Tue, 12 Feb 2019 02:14:41 -0500 Received: from conuserg-09.nifty.com ([210.131.2.76]:37568 "EHLO conuserg-09.nifty.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726044AbfBLHOg (ORCPT ); Tue, 12 Feb 2019 02:14:36 -0500 Received: from pug.e01.socionext.com (p14092-ipngnfx01kyoto.kyoto.ocn.ne.jp [153.142.97.92]) (authenticated) by conuserg-09.nifty.com with ESMTP id x1C7DPdU019269; Tue, 12 Feb 2019 16:13:31 +0900 DKIM-Filter: OpenDKIM Filter v2.10.3 conuserg-09.nifty.com x1C7DPdU019269 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nifty.com; s=dec2015msa; t=1549955611; bh=0G9g6BzHFdBZ8N7j/ak6EoadsuEhODUjvRjxPSQclEk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=F13MjZmxcDB0wIv0YOF6QVzKcYPLcLW3dKltOEAEG5zjRg+4uGCw3oOLACge8hb2s EJBlzD0lZ3ly4JSOiYsryNak9NH9uL1RlTO/U3sEDj854668OUAUGEWBZ/SBLZMO4F Cbl+JMX20vHpeqjUX4jW/sZ6We+NpU2h8z6slLQQ59upMd0aEZX7ILHbufPmrAD0ky vphw5cHQGCK7xycABUOeBP6gSYzKPBBVpoQudLjcPJYTu5N/LIzhOl0O8VdNEUvtji BPW68xUOmk57AayVHOTlkxUGNHNd+YFcMQgcs0nE00iyQV8PzzTDmvh/tFaXmv/Qq9 /FSewYcWg3X5g== X-Nifty-SrcIP: [153.142.97.92] From: Masahiro Yamada To: linux-mtd@lists.infradead.org, Miquel Raynal Cc: Boris Brezillon , Masahiro Yamada , Brian Norris , linux-kernel@vger.kernel.org, Marek Vasut , Richard Weinberger , David Woodhouse Subject: [PATCH v2 06/10] mtd: rawnand: denali: use bool type instead of int where appropriate Date: Tue, 12 Feb 2019 16:12:58 +0900 Message-Id: <1549955582-30346-7-git-send-email-yamada.masahiro@socionext.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1549955582-30346-1-git-send-email-yamada.masahiro@socionext.com> References: <1549955582-30346-1-git-send-email-yamada.masahiro@socionext.com> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Use 'bool' type for the following boolean parameters. - write (write or read?) - raw (raw access or not?) - dma_avail (DMA engine available or not?) Signed-off-by: Masahiro Yamada --- Changes in v2: - Use bool for dma_avail as well drivers/mtd/nand/raw/denali.c | 27 ++++++++++++++------------- drivers/mtd/nand/raw/denali.h | 4 ++-- 2 files changed, 16 insertions(+), 15 deletions(-) -- 2.7.4 diff --git a/drivers/mtd/nand/raw/denali.c b/drivers/mtd/nand/raw/denali.c index 7050b1f..f539731 100644 --- a/drivers/mtd/nand/raw/denali.c +++ b/drivers/mtd/nand/raw/denali.c @@ -360,7 +360,7 @@ static int denali_sw_ecc_fixup(struct nand_chip *chip, } static void denali_setup_dma64(struct denali_nand_info *denali, - dma_addr_t dma_addr, int page, int write) + dma_addr_t dma_addr, int page, bool write) { uint32_t mode; const int page_count = 1; @@ -374,7 +374,8 @@ static void denali_setup_dma64(struct denali_nand_info *denali, * burst len = 64 bytes, the number of pages */ denali->host_write(denali, mode, - 0x01002000 | (64 << 16) | (write << 8) | page_count); + 0x01002000 | (64 << 16) | + (write ? BIT(8) : 0) | page_count); /* 2. set memory low address */ denali->host_write(denali, mode, lower_32_bits(dma_addr)); @@ -384,7 +385,7 @@ static void denali_setup_dma64(struct denali_nand_info *denali, } static void denali_setup_dma32(struct denali_nand_info *denali, - dma_addr_t dma_addr, int page, int write) + dma_addr_t dma_addr, int page, bool write) { uint32_t mode; const int page_count = 1; @@ -395,7 +396,7 @@ static void denali_setup_dma32(struct denali_nand_info *denali, /* 1. setup transfer type and # of pages */ denali->host_write(denali, mode | page, - 0x2000 | (write << 8) | page_count); + 0x2000 | (write ? BIT(8) : 0) | page_count); /* 2. set memory high address bits 23:8 */ denali->host_write(denali, mode | ((dma_addr >> 16) << 8), 0x2200); @@ -457,7 +458,7 @@ static int denali_pio_write(struct denali_nand_info *denali, const u32 *buf, } static int denali_pio_xfer(struct denali_nand_info *denali, void *buf, - size_t size, int page, int write) + size_t size, int page, bool write) { if (write) return denali_pio_write(denali, buf, size, page); @@ -466,7 +467,7 @@ static int denali_pio_xfer(struct denali_nand_info *denali, void *buf, } static int denali_dma_xfer(struct denali_nand_info *denali, void *buf, - size_t size, int page, int write) + size_t size, int page, bool write) { dma_addr_t dma_addr; uint32_t irq_mask, irq_status, ecc_err_mask; @@ -523,7 +524,7 @@ static int denali_dma_xfer(struct denali_nand_info *denali, void *buf, } static int denali_data_xfer(struct nand_chip *chip, void *buf, size_t size, - int page, int raw, int write) + int page, bool raw, bool write) { struct denali_nand_info *denali = to_denali(chip); @@ -648,7 +649,7 @@ static int denali_read_page_raw(struct nand_chip *chip, uint8_t *buf, if (!buf) return -EINVAL; - ret = denali_data_xfer(chip, tmp_buf, size, page, 1, 0); + ret = denali_data_xfer(chip, tmp_buf, size, page, true, false); if (ret) return ret; @@ -704,7 +705,7 @@ static int denali_write_page_raw(struct nand_chip *chip, const uint8_t *buf, return ret; } - return denali_data_xfer(chip, tmp_buf, size, page, 1, 1); + return denali_data_xfer(chip, tmp_buf, size, page, true, true); } static int denali_change_read_column_op(void *buf, unsigned int offset, @@ -756,7 +757,7 @@ static int denali_read_page(struct nand_chip *chip, uint8_t *buf, int stat = 0; int ret; - ret = denali_data_xfer(chip, buf, mtd->writesize, page, 0, 0); + ret = denali_data_xfer(chip, buf, mtd->writesize, page, false, false); if (ret && ret != -EBADMSG) return ret; @@ -786,7 +787,7 @@ static int denali_write_page(struct nand_chip *chip, const uint8_t *buf, struct mtd_info *mtd = nand_to_mtd(chip); return denali_data_xfer(chip, (void *)buf, mtd->writesize, page, - 0, 1); + false, true); } static int denali_setup_data_interface(struct nand_chip *chip, int chipnr, @@ -1042,7 +1043,7 @@ static int denali_attach_chip(struct nand_chip *chip) int ret; if (ioread32(denali->reg + FEATURES) & FEATURES__DMA) - denali->dma_avail = 1; + denali->dma_avail = true; if (denali->dma_avail) { int dma_bit = denali->caps & DENALI_CAP_DMA_64BIT ? 64 : 32; @@ -1051,7 +1052,7 @@ static int denali_attach_chip(struct nand_chip *chip) if (ret) { dev_info(denali->dev, "Failed to set DMA mask. Disabling DMA.\n"); - denali->dma_avail = 0; + denali->dma_avail = false; } } diff --git a/drivers/mtd/nand/raw/denali.h b/drivers/mtd/nand/raw/denali.h index c8c2620..8552b3f 100644 --- a/drivers/mtd/nand/raw/denali.h +++ b/drivers/mtd/nand/raw/denali.h @@ -304,7 +304,7 @@ struct denali_nand_info { u32 irq_status; /* interrupts that have happened */ int irq; void *buf; /* for syndrome layout conversion */ - int dma_avail; /* can support DMA? */ + bool dma_avail; /* can support DMA? */ int devs_per_cs; /* devices connected in parallel */ int oob_skip_bytes; /* number of bytes reserved for BBM */ int max_banks; @@ -314,7 +314,7 @@ struct denali_nand_info { u32 (*host_read)(struct denali_nand_info *denali, u32 addr); void (*host_write)(struct denali_nand_info *denali, u32 addr, u32 data); void (*setup_dma)(struct denali_nand_info *denali, dma_addr_t dma_addr, - int page, int write); + int page, bool write); }; #define DENALI_CAP_HW_ECC_FIXUP BIT(0) From patchwork Tue Feb 12 07:12:59 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Masahiro Yamada X-Patchwork-Id: 158121 Delivered-To: patch@linaro.org Received: by 2002:a02:48:0:0:0:0:0 with SMTP id 69csp3510479jaa; Mon, 11 Feb 2019 23:14:59 -0800 (PST) X-Google-Smtp-Source: AHgI3IZUQWcKu0uUx20sWj0K7WjPW8rQwjvNheIYnXOh+TB1OhjcQxUUB04bZGqzw/sSWQuChoGL X-Received: by 2002:a17:902:e990:: with SMTP id ct16mr2577218plb.201.1549955699015; Mon, 11 Feb 2019 23:14:59 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1549955699; cv=none; d=google.com; s=arc-20160816; b=IAVmL73JJ1Q+NJBj57HvqkuUWAVvKhBrQ8Ez6BHl29FNRR2cZpmfrSTG1nop2q2QNr E2t6yGSYVVgP0d8LNrNg8o1yJipn5PMiC8w1P+5uf7hYgmDGwCRMVY5gIDOig7Xb97Ym lBRrP8TrOQoiMwLW23Yf7/IbkJMpRgNAWkuOEd01s0mDgZmpan/iJTi5BbSaOB4zre7W G1TqqJYEjRXbMHWvOTicUY1hoQZRq7CTuUxQmo2ZdnfxQBqb7v/eRipn7Ap3+kNhjQuC aO6I2/TY4UjSKYMlLzKyMiirfMSsjiM7y6HJujjbjZi1aNK4DbLnz+di3XfvH0IyFg6J OLzg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:dkim-filter; bh=Cxo+nXTM0mDOF2OjW40lPL0MRI8BxhjckTRFkxa+L8M=; b=zU1XNXnxGittNp3TMYeAZB87s1bBMsjf1FbXQ/UVt5HXcwwwyUCjBHnbR2ilh9mKo5 4Y+TUnwAWVuVy2JcKDHAWh8rcqoGsegns5JmzUnIOedVlDMHa2LZcrZWnywsOD5HWX8j fthbOTgoUB4K3+d5A+LN693hWH+tlhE6OjEUs8rJsHh9/IC0le6380/aVf34PyufcRdK h4MZtPh2nSAfqbjPMebdVN8qsYR1uAbZm8iQHeC06XO5ADPT3MHhnI7v6/cuPxyd1e3K YO8u7GWNkFf9wCBBP+sc3wbMbudSFKrJtBLJWXeFiNF6eaUzHNJTiZT0eU1ZfTdv6IPh 7pFg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@nifty.com header.s=dec2015msa header.b=M4k0TZjP; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id x23si11955435pgk.272.2019.02.11.23.14.58; Mon, 11 Feb 2019 23:14:59 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@nifty.com header.s=dec2015msa header.b=M4k0TZjP; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728134AbfBLHOn (ORCPT + 31 others); Tue, 12 Feb 2019 02:14:43 -0500 Received: from conuserg-09.nifty.com ([210.131.2.76]:37564 "EHLO conuserg-09.nifty.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726179AbfBLHOg (ORCPT ); Tue, 12 Feb 2019 02:14:36 -0500 Received: from pug.e01.socionext.com (p14092-ipngnfx01kyoto.kyoto.ocn.ne.jp [153.142.97.92]) (authenticated) by conuserg-09.nifty.com with ESMTP id x1C7DPdV019269; Tue, 12 Feb 2019 16:13:32 +0900 DKIM-Filter: OpenDKIM Filter v2.10.3 conuserg-09.nifty.com x1C7DPdV019269 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nifty.com; s=dec2015msa; t=1549955612; bh=Cxo+nXTM0mDOF2OjW40lPL0MRI8BxhjckTRFkxa+L8M=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=M4k0TZjPOGPdeO/Yk6e3L38TJi6a9WG84ecuAVW3uGmjmCk2GEZpj1sqsXQCpokb+ yg0RHjtXos4agwU0AbO91MTpdgMc65ml0f8y3h5TRZ7Nv/KwLukmCYVTsXIvEfw2aB Kvz8gzZfjnWsWtHdwhSX/MIN49ADGBdZ5xFh2PBTAlV5HhtUO72DZh3R+jXHu7iUFs e9YJ3r+Z1e29c02v3M9F8OrO76d5He7AuDuQDdvx5qIcV9dztkS56g49O1EFwJPiQ3 ygQvl/zPGYlOqjuR7yY/uQbtjASGv6ZNbdEH7FGz3AIaLCyIXTYrM6r5oMkasi7hs8 aoPyjE3mQxk6w== X-Nifty-SrcIP: [153.142.97.92] From: Masahiro Yamada To: linux-mtd@lists.infradead.org, Miquel Raynal Cc: Boris Brezillon , Masahiro Yamada , Brian Norris , linux-kernel@vger.kernel.org, Marek Vasut , Richard Weinberger , David Woodhouse Subject: [PATCH v2 07/10] mtd: rawnand: denali_pci: rename goto labels Date: Tue, 12 Feb 2019 16:12:59 +0900 Message-Id: <1549955582-30346-8-git-send-email-yamada.masahiro@socionext.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1549955582-30346-1-git-send-email-yamada.masahiro@socionext.com> References: <1549955582-30346-1-git-send-email-yamada.masahiro@socionext.com> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org As Documentation/process/coding-style.rst says, choose label names which say what the goto does. The out_ label style is already used in denali_dt.c. Rename likewise for denali_pci.c Signed-off-by: Masahiro Yamada --- Changes in v2: None drivers/mtd/nand/raw/denali_pci.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) -- 2.7.4 diff --git a/drivers/mtd/nand/raw/denali_pci.c b/drivers/mtd/nand/raw/denali_pci.c index 48e9ac5..02eb599 100644 --- a/drivers/mtd/nand/raw/denali_pci.c +++ b/drivers/mtd/nand/raw/denali_pci.c @@ -84,20 +84,20 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) if (!denali->host) { dev_err(&dev->dev, "Spectra: ioremap_nocache failed!"); ret = -ENOMEM; - goto failed_remap_reg; + goto out_unmap_reg; } ret = denali_init(denali); if (ret) - goto failed_remap_mem; + goto out_unmap_host; pci_set_drvdata(dev, denali); return 0; -failed_remap_mem: +out_unmap_host: iounmap(denali->host); -failed_remap_reg: +out_unmap_reg: iounmap(denali->reg); return ret; } From patchwork Tue Feb 12 07:13:00 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Masahiro Yamada X-Patchwork-Id: 158123 Delivered-To: patch@linaro.org Received: by 2002:a02:48:0:0:0:0:0 with SMTP id 69csp3510595jaa; Mon, 11 Feb 2019 23:15:09 -0800 (PST) X-Google-Smtp-Source: AHgI3IYjwaPHfNVDrqkNH+4S+DJmT6XBYuN5GwFNxJ98Vecsnu4ZbmfGKqBayf2wPgkMbNMJN5Gt X-Received: by 2002:a62:1112:: with SMTP id z18mr2518704pfi.173.1549955709014; Mon, 11 Feb 2019 23:15:09 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1549955709; cv=none; d=google.com; s=arc-20160816; b=Hqblw1KPMYq1nKaxVlpO5VhaHnjNnIDfmSeaH/yH4NHxi/feKe66dDZQMZKWRXSY6B Xk3/Joe5WuTUgQZnI0QYN0NLKN/Mrrjcs93w8e9hp5YB2AAAgwb4+YgrDNEbp6QCvqOD 6wssmA0Jp6AFbb0xLtiHhhNXCR94GzqpbkhfbXibU9NPQPZHwrqHPvetvquP6tI8XwW2 23qSWUtHat2NI/FEabJqibz23aCNAI3mhfAEB5+2OJyHVGciZMDS5bnsts9KZaJdtyxG MysNI0VACzpwWC2z/bc2QJGL9wI0P3wg60v0ZX+USkF0qbglkvrRsXvq1cQY66CQXy1D H9DA== 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:dkim-filter; bh=ATDUB4CCbbUxonof29OSwvyuYnv94PssJs+AQLLfess=; b=FM4rjKrNxcQKKHu7Y49UcaDbZf+VrHOZSZi1/9vtZKxxA1DQrVcGJeep+GQQ2kHJkE 3T6i9osRnhCc2KHN/062g7c0M4w4n0KXDxvVA6mP0Q0AzXp+l0lN2chECQLr4DJEgNIb Yw2mGLbLeAORhdEaYIvFUOpJ3TIuADbtp2d9uTdBJWJ+y6LTt4JPmWfqDDRCh1fG+cE9 n7ohCmXWqRbG02vQa/53BlU5xqosj6HwDuDRuOM2zT7Sg9k5nL2j7IeAMQur4cyBO7pw LLQzz/fabKuthOAfJw6ChBHyR0rbpWNDLdYNlBJmHqKWVhuzeV+HCZE0ou2RjqBevGVx B60Q== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@nifty.com header.s=dec2015msa header.b=p7WLI738; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id k13si4553704pgo.502.2019.02.11.23.15.08; Mon, 11 Feb 2019 23:15:08 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@nifty.com header.s=dec2015msa header.b=p7WLI738; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728245AbfBLHPG (ORCPT + 31 others); Tue, 12 Feb 2019 02:15:06 -0500 Received: from conuserg-09.nifty.com ([210.131.2.76]:38279 "EHLO conuserg-09.nifty.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725916AbfBLHPE (ORCPT ); Tue, 12 Feb 2019 02:15:04 -0500 Received: from pug.e01.socionext.com (p14092-ipngnfx01kyoto.kyoto.ocn.ne.jp [153.142.97.92]) (authenticated) by conuserg-09.nifty.com with ESMTP id x1C7DPdW019269; Tue, 12 Feb 2019 16:13:32 +0900 DKIM-Filter: OpenDKIM Filter v2.10.3 conuserg-09.nifty.com x1C7DPdW019269 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nifty.com; s=dec2015msa; t=1549955613; bh=ATDUB4CCbbUxonof29OSwvyuYnv94PssJs+AQLLfess=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=p7WLI738sVSbfgHC/3MFU4aN/sqP1h2OsnLTghCHIyLRWRoWeSkD8yjGrrfkvcPfo C5wTp3ZCPQCr1DC9W4P/a5S9OzUWgVcWpAjmLDVmSovOnHaomtdoXM7JOND97aqdNS 5GqvCHo2EvAsjORmBQWjSPA1S9H9ZoyG430gFgCaCcpYO8Yfok2jHHsRnUtsfxFEp8 Q5GPuY96iGAHKOfhM2IuTxhbRDrzfC42+dBVth+6u+cdt2wQQyhk0KjR27YmRlS2T6 YtXfIZfe4PfHd7COj+McxhcJcls311nWlkGbn1iFUF7EU+TR4gtc8ltLWPRpfcjf4H WtW1MJdc26RYQ== X-Nifty-SrcIP: [153.142.97.92] From: Masahiro Yamada To: linux-mtd@lists.infradead.org, Miquel Raynal Cc: Boris Brezillon , Masahiro Yamada , devicetree@vger.kernel.org, Brian Norris , linux-kernel@vger.kernel.org, Marek Vasut , Richard Weinberger , David Woodhouse , Rob Herring , Mark Rutland Subject: [PATCH v2 08/10] mtd: rawnand: denali: decouple controller and NAND chips Date: Tue, 12 Feb 2019 16:13:00 +0900 Message-Id: <1549955582-30346-9-git-send-email-yamada.masahiro@socionext.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1549955582-30346-1-git-send-email-yamada.masahiro@socionext.com> References: <1549955582-30346-1-git-send-email-yamada.masahiro@socionext.com> MIME-Version: 1.0 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Currently, this driver sticks to the legacy NAND model because it was upstreamed before commit 2d472aba15ff ("mtd: nand: document the NAND controller/NAND chip DT representation"). However, relying on the dummy_controller is already deprecated. Switch over to the new controller/chip representation. The struct denali_nand_info has been split into denali_controller and denali_chip, to contain the controller data, per-chip data, respectively. One problem is, this commit changes the DT binding. So, as always, the backward compatibility must be taken into consideration. In the new binding, the controller node expects #address-cells = <1>; #size-cells = <0>; ... since the child nodes represent NAND chips. In the old binding, the controller node may have subnodes, but they are MTD partitions. The denali_dt_is_legacy_binding() exploits it to distinguish old/new platforms. Going forward, the old binding is only allowed for existing DT files. I updated the binding document. Signed-off-by: Masahiro Yamada --- Changes in v2: None .../devicetree/bindings/mtd/denali-nand.txt | 39 +- drivers/mtd/nand/raw/denali.c | 453 ++++++++++++--------- drivers/mtd/nand/raw/denali.h | 117 +++++- drivers/mtd/nand/raw/denali_dt.c | 98 ++++- drivers/mtd/nand/raw/denali_pci.c | 30 +- 5 files changed, 500 insertions(+), 237 deletions(-) -- 2.7.4 Acked-by: Rob Herring diff --git a/Documentation/devicetree/bindings/mtd/denali-nand.txt b/Documentation/devicetree/bindings/mtd/denali-nand.txt index f33da87..de4ddff 100644 --- a/Documentation/devicetree/bindings/mtd/denali-nand.txt +++ b/Documentation/devicetree/bindings/mtd/denali-nand.txt @@ -7,34 +7,47 @@ Required properties: "socionext,uniphier-denali-nand-v5b" - for Socionext UniPhier (v5b) - reg : should contain registers location and length for data and reg. - reg-names: Should contain the reg names "nand_data" and "denali_reg" + - #address-cells: should be 1. The cell encodes the chip select connection. + - #size-cells : should be 0. - interrupts : The interrupt number. - clocks: should contain phandle of the controller core clock, the bus interface clock, and the ECC circuit clock. - clock-names: should contain "nand", "nand_x", "ecc" -Optional properties: - - nand-ecc-step-size: see nand.txt for details. If present, the value must be - 512 for "altr,socfpga-denali-nand" - 1024 for "socionext,uniphier-denali-nand-v5a" - 1024 for "socionext,uniphier-denali-nand-v5b" - - nand-ecc-strength: see nand.txt for details. Valid values are: - 8, 15 for "altr,socfpga-denali-nand" - 8, 16, 24 for "socionext,uniphier-denali-nand-v5a" - 8, 16 for "socionext,uniphier-denali-nand-v5b" - - nand-ecc-maximize: see nand.txt for details - -The device tree may optionally contain sub-nodes describing partitions of the +Sub-nodes: + Sub-nodes represent available NAND chips. + + Required properties: + - reg: should contain the bank ID of the controller to which each chip + select is connected. + + Optional properties: + - nand-ecc-step-size: see nand.txt for details. If present, the value must be + 512 for "altr,socfpga-denali-nand" + 1024 for "socionext,uniphier-denali-nand-v5a" + 1024 for "socionext,uniphier-denali-nand-v5b" + - nand-ecc-strength: see nand.txt for details. Valid values are: + 8, 15 for "altr,socfpga-denali-nand" + 8, 16, 24 for "socionext,uniphier-denali-nand-v5a" + 8, 16 for "socionext,uniphier-denali-nand-v5b" + - nand-ecc-maximize: see nand.txt for details + +The chip nodes may optionally contain sub-nodes describing partitions of the address space. See partition.txt for more detail. Examples: nand: nand@ff900000 { #address-cells = <1>; - #size-cells = <1>; + #size-cells = <0>; compatible = "altr,socfpga-denali-nand"; reg = <0xff900000 0x20>, <0xffb80000 0x1000>; reg-names = "nand_data", "denali_reg"; clocks = <&nand_clk>, <&nand_x_clk>, <&nand_ecc_clk>; clock-names = "nand", "nand_x", "ecc"; interrupts = <0 144 4>; + + nand@0 { + reg = <0>; + } }; diff --git a/drivers/mtd/nand/raw/denali.c b/drivers/mtd/nand/raw/denali.c index f539731..a162bd1 100644 --- a/drivers/mtd/nand/raw/denali.c +++ b/drivers/mtd/nand/raw/denali.c @@ -3,7 +3,7 @@ * NAND Flash Controller Device Driver * Copyright © 2009-2010, Intel Corporation and its suppliers. * - * Copyright (c) 2017 Socionext Inc. + * Copyright (c) 2017-2019 Socionext Inc. * Reworked by Masahiro Yamada */ @@ -42,14 +42,15 @@ #define DENALI_INVALID_BANK -1 #define DENALI_NR_BANKS 4 -static inline struct denali_nand_info *mtd_to_denali(struct mtd_info *mtd) +static struct denali_chip *to_denali_chip(struct nand_chip *chip) { - return container_of(mtd_to_nand(mtd), struct denali_nand_info, nand); + return container_of(chip, struct denali_chip, chip); } -static struct denali_nand_info *to_denali(struct nand_chip *chip) +static struct denali_controller *to_denali_controller(struct nand_chip *chip) { - return container_of(chip, struct denali_nand_info, nand); + return container_of(chip->controller, struct denali_controller, + controller); } /* @@ -57,12 +58,12 @@ static struct denali_nand_info *to_denali(struct nand_chip *chip) * type, bank, block, and page address). The slave data is the actual data to * be transferred. This mode requires 28 bits of address region allocated. */ -static u32 denali_direct_read(struct denali_nand_info *denali, u32 addr) +static u32 denali_direct_read(struct denali_controller *denali, u32 addr) { return ioread32(denali->host + addr); } -static void denali_direct_write(struct denali_nand_info *denali, u32 addr, +static void denali_direct_write(struct denali_controller *denali, u32 addr, u32 data) { iowrite32(data, denali->host + addr); @@ -74,35 +75,20 @@ static void denali_direct_write(struct denali_nand_info *denali, u32 addr, * control information and transferred data are latched by the registers in * the translation module. */ -static u32 denali_indexed_read(struct denali_nand_info *denali, u32 addr) +static u32 denali_indexed_read(struct denali_controller *denali, u32 addr) { iowrite32(addr, denali->host + DENALI_INDEXED_CTRL); return ioread32(denali->host + DENALI_INDEXED_DATA); } -static void denali_indexed_write(struct denali_nand_info *denali, u32 addr, +static void denali_indexed_write(struct denali_controller *denali, u32 addr, u32 data) { iowrite32(addr, denali->host + DENALI_INDEXED_CTRL); iowrite32(data, denali->host + DENALI_INDEXED_DATA); } -/* - * Use the configuration feature register to determine the maximum number of - * banks that the hardware supports. - */ -static void denali_detect_max_banks(struct denali_nand_info *denali) -{ - uint32_t features = ioread32(denali->reg + FEATURES); - - denali->max_banks = 1 << FIELD_GET(FEATURES__N_BANKS, features); - - /* the encoding changed from rev 5.0 to 5.1 */ - if (denali->revision < 0x0501) - denali->max_banks <<= 1; -} - -static void denali_enable_irq(struct denali_nand_info *denali) +static void denali_enable_irq(struct denali_controller *denali) { int i; @@ -111,7 +97,7 @@ static void denali_enable_irq(struct denali_nand_info *denali) iowrite32(GLOBAL_INT_EN_FLAG, denali->reg + GLOBAL_INT_ENABLE); } -static void denali_disable_irq(struct denali_nand_info *denali) +static void denali_disable_irq(struct denali_controller *denali) { int i; @@ -120,14 +106,14 @@ static void denali_disable_irq(struct denali_nand_info *denali) iowrite32(0, denali->reg + GLOBAL_INT_ENABLE); } -static void denali_clear_irq(struct denali_nand_info *denali, +static void denali_clear_irq(struct denali_controller *denali, int bank, uint32_t irq_status) { /* write one to clear bits */ iowrite32(irq_status, denali->reg + INTR_STATUS(bank)); } -static void denali_clear_irq_all(struct denali_nand_info *denali) +static void denali_clear_irq_all(struct denali_controller *denali) { int i; @@ -137,7 +123,7 @@ static void denali_clear_irq_all(struct denali_nand_info *denali) static irqreturn_t denali_isr(int irq, void *dev_id) { - struct denali_nand_info *denali = dev_id; + struct denali_controller *denali = dev_id; irqreturn_t ret = IRQ_NONE; uint32_t irq_status; int i; @@ -165,7 +151,7 @@ static irqreturn_t denali_isr(int irq, void *dev_id) return ret; } -static void denali_reset_irq(struct denali_nand_info *denali) +static void denali_reset_irq(struct denali_controller *denali) { unsigned long flags; @@ -175,8 +161,8 @@ static void denali_reset_irq(struct denali_nand_info *denali) spin_unlock_irqrestore(&denali->irq_lock, flags); } -static uint32_t denali_wait_for_irq(struct denali_nand_info *denali, - u32 irq_mask, unsigned int timeout_ms) +static u32 denali_wait_for_irq(struct denali_controller *denali, u32 irq_mask, + unsigned int timeout_ms) { unsigned long time_left, flags; uint32_t irq_status; @@ -211,13 +197,45 @@ static uint32_t denali_wait_for_irq(struct denali_nand_info *denali, static void denali_select_target(struct nand_chip *chip, int cs) { - struct denali_nand_info *denali = to_denali(chip); + struct denali_controller *denali = to_denali_controller(chip); + struct denali_chip_sel *sel = &to_denali_chip(chip)->sels[cs]; + struct mtd_info *mtd = nand_to_mtd(chip); - denali->active_bank = cs; + denali->active_bank = sel->bank; + + iowrite32(1 << (chip->phys_erase_shift - chip->page_shift), + denali->reg + PAGES_PER_BLOCK); + iowrite32(chip->options & NAND_BUSWIDTH_16 ? 1 : 0, + denali->reg + DEVICE_WIDTH); + iowrite32(mtd->writesize, denali->reg + DEVICE_MAIN_AREA_SIZE); + iowrite32(mtd->oobsize, denali->reg + DEVICE_SPARE_AREA_SIZE); + iowrite32(chip->options & NAND_ROW_ADDR_3 ? + 0 : TWO_ROW_ADDR_CYCLES__FLAG, + denali->reg + TWO_ROW_ADDR_CYCLES); + iowrite32(FIELD_PREP(ECC_CORRECTION__ERASE_THRESHOLD, 1) | + FIELD_PREP(ECC_CORRECTION__VALUE, chip->ecc.strength), + denali->reg + ECC_CORRECTION); + iowrite32(chip->ecc.size, denali->reg + CFG_DATA_BLOCK_SIZE); + iowrite32(chip->ecc.size, denali->reg + CFG_LAST_DATA_BLOCK_SIZE); + iowrite32(chip->ecc.steps, denali->reg + CFG_NUM_DATA_BLOCKS); + + if (chip->options & NAND_KEEP_TIMINGS) + return; + + /* update timing registers unless NAND_KEEP_TIMINGS is set */ + iowrite32(sel->hwhr2_and_we_2_re, denali->reg + TWHR2_AND_WE_2_RE); + iowrite32(sel->tcwaw_and_addr_2_data, + denali->reg + TCWAW_AND_ADDR_2_DATA); + iowrite32(sel->re_2_we, denali->reg + RE_2_WE); + iowrite32(sel->acc_clks, denali->reg + ACC_CLKS); + iowrite32(sel->rdwr_en_lo_cnt, denali->reg + RDWR_EN_LO_CNT); + iowrite32(sel->rdwr_en_hi_cnt, denali->reg + RDWR_EN_HI_CNT); + iowrite32(sel->cs_setup_cnt, denali->reg + CS_SETUP_CNT); + iowrite32(sel->re_2_re, denali->reg + RE_2_RE); } static int denali_check_erased_page(struct nand_chip *chip, - struct denali_nand_info *denali, u8 *buf, + struct denali_controller *denali, u8 *buf, unsigned long uncor_ecc_flags, unsigned int max_bitflips) { @@ -251,7 +269,7 @@ static int denali_check_erased_page(struct nand_chip *chip, } static int denali_hw_ecc_fixup(struct nand_chip *chip, - struct denali_nand_info *denali, + struct denali_controller *denali, unsigned long *uncor_ecc_flags) { struct mtd_ecc_stats *ecc_stats = &nand_to_mtd(chip)->ecc_stats; @@ -286,7 +304,7 @@ static int denali_hw_ecc_fixup(struct nand_chip *chip, } static int denali_sw_ecc_fixup(struct nand_chip *chip, - struct denali_nand_info *denali, + struct denali_controller *denali, unsigned long *uncor_ecc_flags, uint8_t *buf) { struct mtd_ecc_stats *ecc_stats = &nand_to_mtd(chip)->ecc_stats; @@ -359,7 +377,7 @@ static int denali_sw_ecc_fixup(struct nand_chip *chip, return max_bitflips; } -static void denali_setup_dma64(struct denali_nand_info *denali, +static void denali_setup_dma64(struct denali_controller *denali, dma_addr_t dma_addr, int page, bool write) { uint32_t mode; @@ -384,7 +402,7 @@ static void denali_setup_dma64(struct denali_nand_info *denali, denali->host_write(denali, mode, upper_32_bits(dma_addr)); } -static void denali_setup_dma32(struct denali_nand_info *denali, +static void denali_setup_dma32(struct denali_controller *denali, dma_addr_t dma_addr, int page, bool write) { uint32_t mode; @@ -408,7 +426,7 @@ static void denali_setup_dma32(struct denali_nand_info *denali, denali->host_write(denali, mode | 0x14000, 0x2400); } -static int denali_pio_read(struct denali_nand_info *denali, u32 *buf, +static int denali_pio_read(struct denali_controller *denali, u32 *buf, size_t size, int page) { u32 addr = DENALI_MAP01 | DENALI_BANK(denali) | page; @@ -435,7 +453,7 @@ static int denali_pio_read(struct denali_nand_info *denali, u32 *buf, return irq_status & ecc_err_mask ? -EBADMSG : 0; } -static int denali_pio_write(struct denali_nand_info *denali, const u32 *buf, +static int denali_pio_write(struct denali_controller *denali, const u32 *buf, size_t size, int page) { u32 addr = DENALI_MAP01 | DENALI_BANK(denali) | page; @@ -457,7 +475,7 @@ static int denali_pio_write(struct denali_nand_info *denali, const u32 *buf, return 0; } -static int denali_pio_xfer(struct denali_nand_info *denali, void *buf, +static int denali_pio_xfer(struct denali_controller *denali, void *buf, size_t size, int page, bool write) { if (write) @@ -466,7 +484,7 @@ static int denali_pio_xfer(struct denali_nand_info *denali, void *buf, return denali_pio_read(denali, buf, size, page); } -static int denali_dma_xfer(struct denali_nand_info *denali, void *buf, +static int denali_dma_xfer(struct denali_controller *denali, void *buf, size_t size, int page, bool write) { dma_addr_t dma_addr; @@ -526,7 +544,7 @@ static int denali_dma_xfer(struct denali_nand_info *denali, void *buf, static int denali_data_xfer(struct nand_chip *chip, void *buf, size_t size, int page, bool raw, bool write) { - struct denali_nand_info *denali = to_denali(chip); + struct denali_controller *denali = to_denali_controller(chip); denali_select_target(chip, chip->cur_cs); @@ -546,7 +564,7 @@ typedef int denali_change_column_callback(void *buf, unsigned int offset, static int denali_raw_payload_op(struct nand_chip *chip, void *buf, denali_change_column_callback *cb, void *priv) { - struct denali_nand_info *denali = to_denali(chip); + struct denali_controller *denali = to_denali_controller(chip); struct mtd_info *mtd = nand_to_mtd(chip); struct nand_ecc_ctrl *ecc = &chip->ecc; int writesize = mtd->writesize; @@ -583,7 +601,7 @@ static int denali_raw_payload_op(struct nand_chip *chip, void *buf, static int denali_raw_oob_op(struct nand_chip *chip, void *buf, denali_change_column_callback *cb, void *priv) { - struct denali_nand_info *denali = to_denali(chip); + struct denali_controller *denali = to_denali_controller(chip); struct mtd_info *mtd = nand_to_mtd(chip); struct nand_ecc_ctrl *ecc = &chip->ecc; int writesize = mtd->writesize; @@ -640,9 +658,9 @@ static int denali_memcpy_in(void *buf, unsigned int offset, unsigned int len, static int denali_read_page_raw(struct nand_chip *chip, uint8_t *buf, int oob_required, int page) { - struct denali_nand_info *denali = to_denali(chip); + struct denali_chip *dchip = to_denali_chip(chip); struct mtd_info *mtd = nand_to_mtd(chip); - void *tmp_buf = denali->buf; + void *tmp_buf = dchip->buf; size_t size = mtd->writesize + mtd->oobsize; int ret; @@ -677,9 +695,9 @@ static int denali_memcpy_out(void *buf, unsigned int offset, unsigned int len, static int denali_write_page_raw(struct nand_chip *chip, const uint8_t *buf, int oob_required, int page) { - struct denali_nand_info *denali = to_denali(chip); + struct denali_chip *dchip = to_denali_chip(chip); struct mtd_info *mtd = nand_to_mtd(chip); - void *tmp_buf = denali->buf; + void *tmp_buf = dchip->buf; size_t size = mtd->writesize + mtd->oobsize; int ret; @@ -751,8 +769,8 @@ static int denali_write_oob(struct nand_chip *chip, int page) static int denali_read_page(struct nand_chip *chip, uint8_t *buf, int oob_required, int page) { + struct denali_controller *denali = to_denali_controller(chip); struct mtd_info *mtd = nand_to_mtd(chip); - struct denali_nand_info *denali = mtd_to_denali(mtd); unsigned long uncor_ecc_flags = 0; int stat = 0; int ret; @@ -793,7 +811,8 @@ static int denali_write_page(struct nand_chip *chip, const uint8_t *buf, static int denali_setup_data_interface(struct nand_chip *chip, int chipnr, const struct nand_data_interface *conf) { - struct denali_nand_info *denali = mtd_to_denali(nand_to_mtd(chip)); + struct denali_controller *denali = to_denali_controller(chip); + struct denali_chip_sel *sel; const struct nand_sdr_timings *timings; unsigned long t_x, mult_x; int acc_clks, re_2_we, re_2_re, we_2_re, addr_2_data; @@ -822,6 +841,8 @@ static int denali_setup_data_interface(struct nand_chip *chip, int chipnr, if (chipnr == NAND_DATA_IFACE_CHECK_ONLY) return 0; + sel = &to_denali_chip(chip)->sels[chipnr]; + /* tREA -> ACC_CLKS */ acc_clks = DIV_ROUND_UP(timings->tREA_max, t_x); acc_clks = min_t(int, acc_clks, ACC_CLKS__VALUE); @@ -829,7 +850,7 @@ static int denali_setup_data_interface(struct nand_chip *chip, int chipnr, tmp = ioread32(denali->reg + ACC_CLKS); tmp &= ~ACC_CLKS__VALUE; tmp |= FIELD_PREP(ACC_CLKS__VALUE, acc_clks); - iowrite32(tmp, denali->reg + ACC_CLKS); + sel->acc_clks = tmp; /* tRWH -> RE_2_WE */ re_2_we = DIV_ROUND_UP(timings->tRHW_min, t_x); @@ -838,7 +859,7 @@ static int denali_setup_data_interface(struct nand_chip *chip, int chipnr, tmp = ioread32(denali->reg + RE_2_WE); tmp &= ~RE_2_WE__VALUE; tmp |= FIELD_PREP(RE_2_WE__VALUE, re_2_we); - iowrite32(tmp, denali->reg + RE_2_WE); + sel->re_2_we = tmp; /* tRHZ -> RE_2_RE */ re_2_re = DIV_ROUND_UP(timings->tRHZ_max, t_x); @@ -847,7 +868,7 @@ static int denali_setup_data_interface(struct nand_chip *chip, int chipnr, tmp = ioread32(denali->reg + RE_2_RE); tmp &= ~RE_2_RE__VALUE; tmp |= FIELD_PREP(RE_2_RE__VALUE, re_2_re); - iowrite32(tmp, denali->reg + RE_2_RE); + sel->re_2_re = tmp; /* * tCCS, tWHR -> WE_2_RE @@ -861,7 +882,7 @@ static int denali_setup_data_interface(struct nand_chip *chip, int chipnr, tmp = ioread32(denali->reg + TWHR2_AND_WE_2_RE); tmp &= ~TWHR2_AND_WE_2_RE__WE_2_RE; tmp |= FIELD_PREP(TWHR2_AND_WE_2_RE__WE_2_RE, we_2_re); - iowrite32(tmp, denali->reg + TWHR2_AND_WE_2_RE); + sel->hwhr2_and_we_2_re = tmp; /* tADL -> ADDR_2_DATA */ @@ -876,7 +897,7 @@ static int denali_setup_data_interface(struct nand_chip *chip, int chipnr, tmp = ioread32(denali->reg + TCWAW_AND_ADDR_2_DATA); tmp &= ~TCWAW_AND_ADDR_2_DATA__ADDR_2_DATA; tmp |= FIELD_PREP(TCWAW_AND_ADDR_2_DATA__ADDR_2_DATA, addr_2_data); - iowrite32(tmp, denali->reg + TCWAW_AND_ADDR_2_DATA); + sel->tcwaw_and_addr_2_data = tmp; /* tREH, tWH -> RDWR_EN_HI_CNT */ rdwr_en_hi = DIV_ROUND_UP(max(timings->tREH_min, timings->tWH_min), @@ -886,7 +907,7 @@ static int denali_setup_data_interface(struct nand_chip *chip, int chipnr, tmp = ioread32(denali->reg + RDWR_EN_HI_CNT); tmp &= ~RDWR_EN_HI_CNT__VALUE; tmp |= FIELD_PREP(RDWR_EN_HI_CNT__VALUE, rdwr_en_hi); - iowrite32(tmp, denali->reg + RDWR_EN_HI_CNT); + sel->rdwr_en_hi_cnt = tmp; /* tRP, tWP -> RDWR_EN_LO_CNT */ rdwr_en_lo = DIV_ROUND_UP(max(timings->tRP_min, timings->tWP_min), t_x); @@ -899,7 +920,7 @@ static int denali_setup_data_interface(struct nand_chip *chip, int chipnr, tmp = ioread32(denali->reg + RDWR_EN_LO_CNT); tmp &= ~RDWR_EN_LO_CNT__VALUE; tmp |= FIELD_PREP(RDWR_EN_LO_CNT__VALUE, rdwr_en_lo); - iowrite32(tmp, denali->reg + RDWR_EN_LO_CNT); + sel->rdwr_en_lo_cnt = tmp; /* tCS, tCEA -> CS_SETUP_CNT */ cs_setup = max3((int)DIV_ROUND_UP(timings->tCS_min, t_x) - rdwr_en_lo, @@ -910,39 +931,11 @@ static int denali_setup_data_interface(struct nand_chip *chip, int chipnr, tmp = ioread32(denali->reg + CS_SETUP_CNT); tmp &= ~CS_SETUP_CNT__VALUE; tmp |= FIELD_PREP(CS_SETUP_CNT__VALUE, cs_setup); - iowrite32(tmp, denali->reg + CS_SETUP_CNT); + sel->cs_setup_cnt = tmp; return 0; } -static void denali_hw_init(struct denali_nand_info *denali) -{ - /* - * The REVISION register may not be reliable. Platforms are allowed to - * override it. - */ - if (!denali->revision) - denali->revision = swab16(ioread32(denali->reg + REVISION)); - - /* - * Set how many bytes should be skipped before writing data in OOB. - * If a non-zero value has already been set (by firmware or something), - * just use it. Otherwise, set the driver default. - */ - denali->oob_skip_bytes = ioread32(denali->reg + SPARE_AREA_SKIP_BYTES); - if (!denali->oob_skip_bytes) { - denali->oob_skip_bytes = DENALI_DEFAULT_OOB_SKIP_BYTES; - iowrite32(denali->oob_skip_bytes, - denali->reg + SPARE_AREA_SKIP_BYTES); - } - - denali_detect_max_banks(denali); - iowrite32(0x0F, denali->reg + RB_PIN_ENABLED); - iowrite32(CHIP_EN_DONT_CARE__FLAG, denali->reg + CHIP_ENABLE_DONT_CARE); - - iowrite32(0xffff, denali->reg + SPARE_AREA_MARKER); -} - int denali_calc_ecc_bytes(int step_size, int strength) { /* BCH code. Denali requires ecc.bytes to be multiple of 2 */ @@ -953,10 +946,10 @@ EXPORT_SYMBOL(denali_calc_ecc_bytes); static int denali_ooblayout_ecc(struct mtd_info *mtd, int section, struct mtd_oob_region *oobregion) { - struct denali_nand_info *denali = mtd_to_denali(mtd); struct nand_chip *chip = mtd_to_nand(mtd); + struct denali_controller *denali = to_denali_controller(chip); - if (section) + if (section > 0) return -ERANGE; oobregion->offset = denali->oob_skip_bytes; @@ -968,10 +961,10 @@ static int denali_ooblayout_ecc(struct mtd_info *mtd, int section, static int denali_ooblayout_free(struct mtd_info *mtd, int section, struct mtd_oob_region *oobregion) { - struct denali_nand_info *denali = mtd_to_denali(mtd); struct nand_chip *chip = mtd_to_nand(mtd); + struct denali_controller *denali = to_denali_controller(chip); - if (section) + if (section > 0) return -ERANGE; oobregion->offset = chip->ecc.total + denali->oob_skip_bytes; @@ -987,7 +980,7 @@ static const struct mtd_ooblayout_ops denali_ooblayout_ops = { static int denali_multidev_fixup(struct nand_chip *chip) { - struct denali_nand_info *denali = to_denali(chip); + struct denali_controller *denali = to_denali_controller(chip); struct mtd_info *mtd = nand_to_mtd(chip); /* @@ -1038,38 +1031,11 @@ static int denali_multidev_fixup(struct nand_chip *chip) static int denali_attach_chip(struct nand_chip *chip) { + struct denali_controller *denali = to_denali_controller(chip); + struct denali_chip *dchip = to_denali_chip(chip); struct mtd_info *mtd = nand_to_mtd(chip); - struct denali_nand_info *denali = mtd_to_denali(mtd); int ret; - if (ioread32(denali->reg + FEATURES) & FEATURES__DMA) - denali->dma_avail = true; - - if (denali->dma_avail) { - int dma_bit = denali->caps & DENALI_CAP_DMA_64BIT ? 64 : 32; - - ret = dma_set_mask(denali->dev, DMA_BIT_MASK(dma_bit)); - if (ret) { - dev_info(denali->dev, - "Failed to set DMA mask. Disabling DMA.\n"); - denali->dma_avail = false; - } - } - - if (denali->dma_avail) { - chip->options |= NAND_USE_BOUNCE_BUFFER; - chip->buf_align = 16; - if (denali->caps & DENALI_CAP_DMA_64BIT) - denali->setup_dma = denali_setup_dma64; - else - denali->setup_dma = denali_setup_dma32; - } - - chip->bbt_options |= NAND_BBT_USE_FLASH; - chip->bbt_options |= NAND_BBT_NO_OOB; - chip->ecc.mode = NAND_ECC_HW_SYNDROME; - chip->options |= NAND_NO_SUBPAGE_WRITE; - ret = nand_ecc_choose_conf(chip, denali->ecc_caps, mtd->oobsize - denali->oob_skip_bytes); if (ret) { @@ -1081,33 +1047,6 @@ static int denali_attach_chip(struct nand_chip *chip) "chosen ECC settings: step=%d, strength=%d, bytes=%d\n", chip->ecc.size, chip->ecc.strength, chip->ecc.bytes); - iowrite32(FIELD_PREP(ECC_CORRECTION__ERASE_THRESHOLD, 1) | - FIELD_PREP(ECC_CORRECTION__VALUE, chip->ecc.strength), - denali->reg + ECC_CORRECTION); - iowrite32(mtd->erasesize / mtd->writesize, - denali->reg + PAGES_PER_BLOCK); - iowrite32(chip->options & NAND_BUSWIDTH_16 ? 1 : 0, - denali->reg + DEVICE_WIDTH); - iowrite32(chip->options & NAND_ROW_ADDR_3 ? 0 : TWO_ROW_ADDR_CYCLES__FLAG, - denali->reg + TWO_ROW_ADDR_CYCLES); - iowrite32(mtd->writesize, denali->reg + DEVICE_MAIN_AREA_SIZE); - iowrite32(mtd->oobsize, denali->reg + DEVICE_SPARE_AREA_SIZE); - - iowrite32(chip->ecc.size, denali->reg + CFG_DATA_BLOCK_SIZE); - iowrite32(chip->ecc.size, denali->reg + CFG_LAST_DATA_BLOCK_SIZE); - /* chip->ecc.steps is set by nand_scan_tail(); not available here */ - iowrite32(mtd->writesize / chip->ecc.size, - denali->reg + CFG_NUM_DATA_BLOCKS); - - mtd_set_ooblayout(mtd, &denali_ooblayout_ops); - - chip->ecc.read_page = denali_read_page; - chip->ecc.read_page_raw = denali_read_page_raw; - chip->ecc.write_page = denali_write_page; - chip->ecc.write_page_raw = denali_write_page_raw; - chip->ecc.read_oob = denali_read_oob; - chip->ecc.write_oob = denali_write_oob; - ret = denali_multidev_fixup(chip); if (ret) return ret; @@ -1117,8 +1056,8 @@ static int denali_attach_chip(struct nand_chip *chip) * use devm_kmalloc() because the memory allocated by devm_ does not * guarantee DMA-safe alignment. */ - denali->buf = kmalloc(mtd->writesize + mtd->oobsize, GFP_KERNEL); - if (!denali->buf) + dchip->buf = kmalloc(mtd->writesize + mtd->oobsize, GFP_KERNEL); + if (!dchip->buf) return -ENOMEM; return 0; @@ -1126,13 +1065,12 @@ static int denali_attach_chip(struct nand_chip *chip) static void denali_detach_chip(struct nand_chip *chip) { - struct mtd_info *mtd = nand_to_mtd(chip); - struct denali_nand_info *denali = mtd_to_denali(mtd); + struct denali_chip *dchip = to_denali_chip(chip); - kfree(denali->buf); + kfree(dchip->buf); } -static void denali_exec_in8(struct denali_nand_info *denali, u32 type, +static void denali_exec_in8(struct denali_controller *denali, u32 type, u8 *buf, unsigned int len) { int i; @@ -1141,7 +1079,7 @@ static void denali_exec_in8(struct denali_nand_info *denali, u32 type, buf[i] = denali->host_read(denali, type | DENALI_BANK(denali)); } -static void denali_exec_in16(struct denali_nand_info *denali, u32 type, +static void denali_exec_in16(struct denali_controller *denali, u32 type, u8 *buf, unsigned int len) { u32 data; @@ -1155,7 +1093,7 @@ static void denali_exec_in16(struct denali_nand_info *denali, u32 type, } } -static void denali_exec_out8(struct denali_nand_info *denali, u32 type, +static void denali_exec_out8(struct denali_controller *denali, u32 type, const u8 *buf, unsigned int len) { int i; @@ -1164,7 +1102,7 @@ static void denali_exec_out8(struct denali_nand_info *denali, u32 type, denali->host_write(denali, type | DENALI_BANK(denali), buf[i]); } -static void denali_exec_out16(struct denali_nand_info *denali, u32 type, +static void denali_exec_out16(struct denali_controller *denali, u32 type, const u8 *buf, unsigned int len) { int i; @@ -1174,7 +1112,7 @@ static void denali_exec_out16(struct denali_nand_info *denali, u32 type, buf[i + 1] << 16 | buf[i]); } -static int denali_exec_waitrdy(struct denali_nand_info *denali, +static int denali_exec_waitrdy(struct denali_controller *denali, unsigned int timeout_ms) { u32 irq_stat; @@ -1191,7 +1129,7 @@ static int denali_exec_waitrdy(struct denali_nand_info *denali, static int denali_exec_instr(struct nand_chip *chip, const struct nand_op_instr *instr) { - struct denali_nand_info *denali = to_denali(chip); + struct denali_controller *denali = to_denali_controller(chip); bool width16 = chip->options & NAND_BUSWIDTH_16; switch (instr->type) { @@ -1243,7 +1181,7 @@ static int denali_exec_op(struct nand_chip *chip, * Some commands contain NAND_OP_WAITRDY_INSTR. * irq must be cleared here to catch the R/B# interrupt there. */ - denali_reset_irq(to_denali(chip)); + denali_reset_irq(to_denali_controller(chip)); for (i = 0; i < op->ninstrs; i++) { ret = denali_exec_instr(chip, &op->instrs[i]); @@ -1261,53 +1199,91 @@ static const struct nand_controller_ops denali_controller_ops = { .setup_data_interface = denali_setup_data_interface, }; -int denali_init(struct denali_nand_info *denali) +int denali_chip_init(struct denali_controller *denali, + struct denali_chip *dchip) { - struct nand_chip *chip = &denali->nand; + struct nand_chip *chip = &dchip->chip; struct mtd_info *mtd = nand_to_mtd(chip); - u32 features = ioread32(denali->reg + FEATURES); - int ret; + struct denali_chip *dchip2; + unsigned int chip_cnt = 0; + int i, j, ret; - mtd->dev.parent = denali->dev; - denali_hw_init(denali); + chip->controller = &denali->controller; - init_completion(&denali->complete); - spin_lock_init(&denali->irq_lock); + /* sanity checks for bank numbers */ + for (i = 0; i < dchip->nsels; i++) { + unsigned int bank = dchip->sels[i].bank; - denali_clear_irq_all(denali); + if (bank >= denali->nbanks) { + dev_err(denali->dev, "unsupported bank %d\n", bank); + return -EINVAL; + } - ret = devm_request_irq(denali->dev, denali->irq, denali_isr, - IRQF_SHARED, DENALI_NAND_NAME, denali); - if (ret) { - dev_err(denali->dev, "Unable to request IRQ\n"); - return ret; - } + for (j = 0; j < i; j++) { + if (bank == dchip->sels[j].bank) { + dev_err(denali->dev, + "bank %d is assigned twice in the same chip\n", + bank); + return -EINVAL; + } + } - denali_enable_irq(denali); + list_for_each_entry(dchip2, &denali->chips, node) { + chip_cnt++; + for (j = 0; j < dchip2->nsels; j++) { + if (bank == dchip2->sels[j].bank) { + dev_err(denali->dev, + "bank %d is already used\n", + bank); + return -EINVAL; + } + } + } + } - denali->active_bank = DENALI_INVALID_BANK; + mtd->dev.parent = denali->dev; - nand_set_flash_node(chip, denali->dev->of_node); /* Fallback to the default name if DT did not give "label" property */ - if (!mtd->name) - mtd->name = "denali-nand"; + if (!mtd->name) { + if (chip_cnt) { + mtd->name = devm_kasprintf(denali->dev, GFP_KERNEL, + "denali-nand%d", chip_cnt); + if (!mtd->name) + return -ENOMEM; + } else { + /* + * "denali-nand" instead of "denali-nand0" + * for backward compatibility + */ + mtd->name = "denali-nand"; + } + } - if (features & FEATURES__INDEX_ADDR) { - denali->host_read = denali_indexed_read; - denali->host_write = denali_indexed_write; - } else { - denali->host_read = denali_direct_read; - denali->host_write = denali_direct_write; + if (denali->dma_avail) { + chip->options |= NAND_USE_BOUNCE_BUFFER; + chip->buf_align = 16; } /* clk rate info is needed for setup_data_interface */ if (!denali->clk_rate || !denali->clk_x_rate) chip->options |= NAND_KEEP_TIMINGS; - chip->legacy.dummy_controller.ops = &denali_controller_ops; - ret = nand_scan(chip, denali->max_banks); + chip->bbt_options |= NAND_BBT_USE_FLASH; + chip->bbt_options |= NAND_BBT_NO_OOB; + chip->options |= NAND_NO_SUBPAGE_WRITE; + chip->ecc.mode = NAND_ECC_HW_SYNDROME; + chip->ecc.read_page = denali_read_page; + chip->ecc.write_page = denali_write_page; + chip->ecc.read_page_raw = denali_read_page_raw; + chip->ecc.write_page_raw = denali_write_page_raw; + chip->ecc.read_oob = denali_read_oob; + chip->ecc.write_oob = denali_write_oob; + + mtd_set_ooblayout(mtd, &denali_ooblayout_ops); + + ret = nand_scan(chip, dchip->nsels); if (ret) - goto disable_irq; + return ret; ret = mtd_device_register(mtd, NULL, 0); if (ret) { @@ -1315,20 +1291,109 @@ int denali_init(struct denali_nand_info *denali) goto cleanup_nand; } + list_add_tail(&dchip->node, &denali->chips); + return 0; cleanup_nand: nand_cleanup(chip); -disable_irq: - denali_disable_irq(denali); return ret; } +EXPORT_SYMBOL_GPL(denali_chip_init); + +int denali_init(struct denali_controller *denali) +{ + u32 features = ioread32(denali->reg + FEATURES); + int ret; + + nand_controller_init(&denali->controller); + denali->controller.ops = &denali_controller_ops; + init_completion(&denali->complete); + spin_lock_init(&denali->irq_lock); + INIT_LIST_HEAD(&denali->chips); + denali->active_bank = DENALI_INVALID_BANK; + + /* + * The REVISION register may not be reliable. Platforms are allowed to + * override it. + */ + if (!denali->revision) + denali->revision = swab16(ioread32(denali->reg + REVISION)); + + denali->nbanks = 1 << FIELD_GET(FEATURES__N_BANKS, features); + + /* the encoding changed from rev 5.0 to 5.1 */ + if (denali->revision < 0x0501) + denali->nbanks <<= 1; + + if (features & FEATURES__DMA) + denali->dma_avail = true; + + if (denali->dma_avail) { + int dma_bit = denali->caps & DENALI_CAP_DMA_64BIT ? 64 : 32; + + ret = dma_set_mask(denali->dev, DMA_BIT_MASK(dma_bit)); + if (ret) { + dev_info(denali->dev, + "Failed to set DMA mask. Disabling DMA.\n"); + denali->dma_avail = false; + } + } + + if (denali->dma_avail) { + if (denali->caps & DENALI_CAP_DMA_64BIT) + denali->setup_dma = denali_setup_dma64; + else + denali->setup_dma = denali_setup_dma32; + } + + if (features & FEATURES__INDEX_ADDR) { + denali->host_read = denali_indexed_read; + denali->host_write = denali_indexed_write; + } else { + denali->host_read = denali_direct_read; + denali->host_write = denali_direct_write; + } + + /* + * Set how many bytes should be skipped before writing data in OOB. + * If a non-zero value has already been set (by firmware or something), + * just use it. Otherwise, set the driver's default. + */ + denali->oob_skip_bytes = ioread32(denali->reg + SPARE_AREA_SKIP_BYTES); + if (!denali->oob_skip_bytes) { + denali->oob_skip_bytes = DENALI_DEFAULT_OOB_SKIP_BYTES; + iowrite32(denali->oob_skip_bytes, + denali->reg + SPARE_AREA_SKIP_BYTES); + } + + iowrite32(GENMASK(denali->nbanks - 1, 0), denali->reg + RB_PIN_ENABLED); + iowrite32(CHIP_EN_DONT_CARE__FLAG, denali->reg + CHIP_ENABLE_DONT_CARE); + iowrite32(0xffff, denali->reg + SPARE_AREA_MARKER); + + denali_clear_irq_all(denali); + + ret = devm_request_irq(denali->dev, denali->irq, denali_isr, + IRQF_SHARED, DENALI_NAND_NAME, denali); + if (ret) { + dev_err(denali->dev, "Unable to request IRQ\n"); + return ret; + } + + denali_enable_irq(denali); + + return 0; +} EXPORT_SYMBOL(denali_init); -void denali_remove(struct denali_nand_info *denali) +void denali_remove(struct denali_controller *denali) { - nand_release(&denali->nand); + struct denali_chip *dchip; + + list_for_each_entry(dchip, &denali->chips, node) + nand_release(&dchip->chip); + denali_disable_irq(denali); } EXPORT_SYMBOL(denali_remove); diff --git a/drivers/mtd/nand/raw/denali.h b/drivers/mtd/nand/raw/denali.h index 8552b3f..138b239 100644 --- a/drivers/mtd/nand/raw/denali.h +++ b/drivers/mtd/nand/raw/denali.h @@ -9,6 +9,7 @@ #include #include +#include #include #include #include @@ -290,30 +291,100 @@ #define CHNL_ACTIVE__CHANNEL2 BIT(2) #define CHNL_ACTIVE__CHANNEL3 BIT(3) -struct denali_nand_info { - struct nand_chip nand; - unsigned long clk_rate; /* core clock rate */ - unsigned long clk_x_rate; /* bus interface clock rate */ - int active_bank; /* currently selected bank */ +/** + * struct denali_chip_sel - per-CS data of Denali NAND + * + * @bank: bank id of the controller this CS is connected to + * @hwhr2_and_we_2_re: value of timing register HWHR2_AND_WE_2_RE + * @tcwaw_and_addr_2_data: value of timing register TCWAW_AND_ADDR_2_DATA + * @re_2_we: value of timing register RE_2_WE + * @acc_clks: value of timing register ACC_CLKS + * @rdwr_en_lo_cnt: value of timing register RDWR_EN_LO_CNT + * @rdwr_en_hi_cnt: value of timing register RDWR_EN_HI_CNT + * @cs_setup_cnt: value of timing register CS_SETUP_CNT + * @re_2_re: value of timing register RE_2_RE + */ +struct denali_chip_sel { + int bank; + u32 hwhr2_and_we_2_re; + u32 tcwaw_and_addr_2_data; + u32 re_2_we; + u32 acc_clks; + u32 rdwr_en_lo_cnt; + u32 rdwr_en_hi_cnt; + u32 cs_setup_cnt; + u32 re_2_re; +}; + +/** + * struct denali_chip - per-chip data of Denali NAND + * + * @chip: base NAND chip structure + * @buf: internal buffer for syndrome layout conversion + * @node: node to be used to associate this chip with the controller + * @nsels: the number of CS lines of this chip + * @sels: the array of per-cs data + */ +struct denali_chip { + struct nand_chip chip; + void *buf; + struct list_head node; + unsigned int nsels; + struct denali_chip_sel sels[0]; +}; + +/** + * struct denali_controller - Denali NAND controller data + * + * @controller: base NAND controller structure + * @dev: device + * @chips: the list of chips attached to this controller + * @clk_rate: frequency of core clock + * @clk_x_rate: frequency of bus interface clock + * @reg: base of Register Interface + * @host: base of Host Data/Command interface + * @complete: completion used to wait for interrupts + * @irq: interrupt number + * @irq_mask: interrupt bits the controller is waiting for + * @irq_status: interrupt bits of events that have happened + * @irq_lock: lock to protect @irq_mask and @irq_status + * @dma_avail: set if DMA engine is available + * @devs_per_cs: number of devices connected in parallel + * @oob_skip_bytes: number of bytes in OOB skipped by the ECC engine + * @active_bank: active bank id + * @nbanks: the number of banks supported by this controller + * @revision: IP revision + * @caps: controller capabilities that cannot be detected run-time + * @ecc_caps: ECC engine capabilities + * @host_read: callback for read access of Host Data/Command Interface + * @host_write: callback for write access of Host Data/Command Interface + * @setup_dma: callback for setup of the Data DMA + */ +struct denali_controller { + struct nand_controller controller; struct device *dev; - void __iomem *reg; /* Register Interface */ - void __iomem *host; /* Host Data/Command Interface */ + struct list_head chips; + unsigned long clk_rate; + unsigned long clk_x_rate; + void __iomem *reg; + void __iomem *host; struct completion complete; - spinlock_t irq_lock; /* protect irq_mask and irq_status */ - u32 irq_mask; /* interrupts we are waiting for */ - u32 irq_status; /* interrupts that have happened */ int irq; - void *buf; /* for syndrome layout conversion */ - bool dma_avail; /* can support DMA? */ - int devs_per_cs; /* devices connected in parallel */ - int oob_skip_bytes; /* number of bytes reserved for BBM */ - int max_banks; - unsigned int revision; /* IP revision */ - unsigned int caps; /* IP capability (or quirk) */ + u32 irq_mask; + u32 irq_status; + spinlock_t irq_lock; + bool dma_avail; + int devs_per_cs; + int oob_skip_bytes; + int active_bank; + int nbanks; + unsigned int revision; + unsigned int caps; const struct nand_ecc_caps *ecc_caps; - u32 (*host_read)(struct denali_nand_info *denali, u32 addr); - void (*host_write)(struct denali_nand_info *denali, u32 addr, u32 data); - void (*setup_dma)(struct denali_nand_info *denali, dma_addr_t dma_addr, + u32 (*host_read)(struct denali_controller *denali, u32 addr); + void (*host_write)(struct denali_controller *denali, u32 addr, + u32 data); + void (*setup_dma)(struct denali_controller *denali, dma_addr_t dma_addr, int page, bool write); }; @@ -321,7 +392,9 @@ struct denali_nand_info { #define DENALI_CAP_DMA_64BIT BIT(1) int denali_calc_ecc_bytes(int step_size, int strength); -int denali_init(struct denali_nand_info *denali); -void denali_remove(struct denali_nand_info *denali); +int denali_chip_init(struct denali_controller *denali, + struct denali_chip *dchip); +int denali_init(struct denali_controller *denali); +void denali_remove(struct denali_controller *denali); #endif /* __DENALI_H__ */ diff --git a/drivers/mtd/nand/raw/denali_dt.c b/drivers/mtd/nand/raw/denali_dt.c index 0b5ae24..5e14836 100644 --- a/drivers/mtd/nand/raw/denali_dt.c +++ b/drivers/mtd/nand/raw/denali_dt.c @@ -18,7 +18,7 @@ #include "denali.h" struct denali_dt { - struct denali_nand_info denali; + struct denali_controller controller; struct clk *clk; /* core clock */ struct clk *clk_x; /* bus interface clock */ struct clk *clk_ecc; /* ECC circuit clock */ @@ -71,19 +71,92 @@ static const struct of_device_id denali_nand_dt_ids[] = { }; MODULE_DEVICE_TABLE(of, denali_nand_dt_ids); +static int denali_dt_chip_init(struct denali_controller *denali, + struct device_node *chip_np) +{ + struct denali_chip *dchip; + u32 bank; + int nsels, i, ret; + + nsels = of_property_count_u32_elems(chip_np, "reg"); + if (nsels < 0) + return nsels; + + dchip = devm_kzalloc(denali->dev, struct_size(dchip, sels, nsels), + GFP_KERNEL); + if (!dchip) + return -ENOMEM; + + dchip->nsels = nsels; + + for (i = 0; i < nsels; i++) { + ret = of_property_read_u32_index(chip_np, "reg", i, &bank); + if (ret) + return ret; + + dchip->sels[i].bank = bank; + + nand_set_flash_node(&dchip->chip, chip_np); + } + + return denali_chip_init(denali, dchip); +} + +/* Backward compatibility for old platforms */ +static int denali_dt_legacy_chip_init(struct denali_controller *denali) +{ + struct denali_chip *dchip; + int nsels, i; + + nsels = denali->nbanks; + + dchip = devm_kzalloc(denali->dev, struct_size(dchip, sels, nsels), + GFP_KERNEL); + if (!dchip) + return -ENOMEM; + + dchip->nsels = nsels; + + for (i = 0; i < nsels; i++) + dchip->sels[i].bank = i; + + nand_set_flash_node(&dchip->chip, denali->dev->of_node); + + return denali_chip_init(denali, dchip); +} + +/* + * Check the DT binding. + * The new binding expects chip subnodes in the controller node. + * So, #address-cells = <1>; #size-cells = <0>; are required. + * Check the #size-cells to distinguish the binding. + */ +static bool denali_dt_is_legacy_binding(struct device_node *np) +{ + u32 cells; + int ret; + + ret = of_property_read_u32(np, "#size-cells", &cells); + if (ret) + return true; + + return cells != 0; +} + static int denali_dt_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct resource *res; struct denali_dt *dt; const struct denali_dt_data *data; - struct denali_nand_info *denali; + struct denali_controller *denali; + struct device_node *np; int ret; dt = devm_kzalloc(dev, sizeof(*dt), GFP_KERNEL); if (!dt) return -ENOMEM; - denali = &dt->denali; + denali = &dt->controller; data = of_device_get_match_data(dev); if (data) { @@ -140,9 +213,26 @@ static int denali_dt_probe(struct platform_device *pdev) if (ret) goto out_disable_clk_ecc; + if (denali_dt_is_legacy_binding(dev->of_node)) { + ret = denali_dt_legacy_chip_init(denali); + if (ret) + goto out_remove_denali; + } else { + for_each_child_of_node(dev->of_node, np) { + ret = denali_dt_chip_init(denali, np); + if (ret) { + of_node_put(np); + goto out_remove_denali; + } + } + } + platform_set_drvdata(pdev, dt); + return 0; +out_remove_denali: + denali_remove(denali); out_disable_clk_ecc: clk_disable_unprepare(dt->clk_ecc); out_disable_clk_x: @@ -157,7 +247,7 @@ static int denali_dt_remove(struct platform_device *pdev) { struct denali_dt *dt = platform_get_drvdata(pdev); - denali_remove(&dt->denali); + denali_remove(&dt->controller); clk_disable_unprepare(dt->clk_ecc); clk_disable_unprepare(dt->clk_x); clk_disable_unprepare(dt->clk); diff --git a/drivers/mtd/nand/raw/denali_pci.c b/drivers/mtd/nand/raw/denali_pci.c index 02eb599..d62aa52 100644 --- a/drivers/mtd/nand/raw/denali_pci.c +++ b/drivers/mtd/nand/raw/denali_pci.c @@ -29,10 +29,11 @@ NAND_ECC_CAPS_SINGLE(denali_pci_ecc_caps, denali_calc_ecc_bytes, 512, 8, 15); static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) { - int ret; resource_size_t csr_base, mem_base; unsigned long csr_len, mem_len; - struct denali_nand_info *denali; + struct denali_controller *denali; + struct denali_chip *dchip; + int nsels, ret, i; denali = devm_kzalloc(&dev->dev, sizeof(*denali), GFP_KERNEL); if (!denali) @@ -64,7 +65,6 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) denali->dev = &dev->dev; denali->irq = dev->irq; denali->ecc_caps = &denali_pci_ecc_caps; - denali->nand.ecc.options |= NAND_ECC_MAXIMIZE; denali->clk_rate = 50000000; /* 50 MHz */ denali->clk_x_rate = 200000000; /* 200 MHz */ @@ -91,10 +91,32 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) if (ret) goto out_unmap_host; + nsels = denali->nbanks; + + dchip = devm_kzalloc(denali->dev, struct_size(dchip, sels, nsels), + GFP_KERNEL); + if (!dchip) { + ret = -ENOMEM; + goto out_remove_denali; + } + + dchip->chip.ecc.options |= NAND_ECC_MAXIMIZE; + + dchip->nsels = nsels; + + for (i = 0; i < nsels; i++) + dchip->sels[i].bank = i; + + ret = denali_chip_init(denali, dchip); + if (ret) + goto out_remove_denali; + pci_set_drvdata(dev, denali); return 0; +out_remove_denali: + denali_remove(denali); out_unmap_host: iounmap(denali->host); out_unmap_reg: @@ -104,7 +126,7 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) static void denali_pci_remove(struct pci_dev *dev) { - struct denali_nand_info *denali = pci_get_drvdata(dev); + struct denali_controller *denali = pci_get_drvdata(dev); denali_remove(denali); iounmap(denali->reg); From patchwork Tue Feb 12 07:13:02 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Masahiro Yamada X-Patchwork-Id: 158120 Delivered-To: patch@linaro.org Received: by 2002:a02:48:0:0:0:0:0 with SMTP id 69csp3510326jaa; Mon, 11 Feb 2019 23:14:47 -0800 (PST) X-Google-Smtp-Source: AHgI3IYBOBbPMPP5DGOGRxsqTL/Qf1+Hl01FYl2DDDlZNzYOQGm9wcoeXgQ3HtuCeM9idpyGDQ5d X-Received: by 2002:a63:c42:: with SMTP id 2mr2341096pgm.372.1549955687593; Mon, 11 Feb 2019 23:14:47 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1549955687; cv=none; d=google.com; s=arc-20160816; b=WJgrnDNjmgmVkustGEICpLW2NQ38MAZq9sUUqa56jWKp0eK3y7d8PljrWvtFeK9pJ8 rKIGLKpP7DeWE79ti1DkR7Bvmwy7sHroNSnq3fzjMrpw/YPQQPJxSyZ9usYi3cA4or4Q rEyK0wLOMKyDS4ppprlGQ+t/wZOJIQWtS2We4hGIX9wdksPEU0urqu0oYx/7OqrMTxZV I6kCAR/n1JrkFe1apE9ZS9DY3Auo3mYoc9OmHTe7m7QDDVLBANinTyQ1XaJMxamkHIRN ypMLH2yQ8VBCUCt2QITrwZMfBHcD5B+CQUyhKEjm5AjHlr2If4fG02t9DQURR0HAhyhx CTvQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:dkim-filter; bh=XGysdmS4tbl7yrVBNgBANjU9bQoRzs2DxSH9clfygmc=; b=mihmeJmNnzR1ouup8yv6SpP2bvcUyejUANdL/cru8VUCD2e6bhV21Tk0TmlRypQxZP qPW80g5INL82naKETwdjY/sOHxDCb0pbqO3fdMG1IdPLvLAWKtXVSAFKkT6QSU0KELQP +sfZOC2hXiZYWXpSsZYIs1xmsGPwWPn378FSY4l+QBq4dw3Zs6V103sOfmZ5BiZaMvor /+ML+2KJQHLNfPk/TOx/VkHw2fFrzE0S1bSCcqMwauBK5caKJrceGiLaewgnQ05UXrX/ HPML6AKiIcKL+/T6XzIld6hLJt6hW1A+BP3vtkqb0la9dtMWDyibh7gMe5oGS+0VwSWu 6vng== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@nifty.com header.s=dec2015msa header.b=bYe38x01; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id k123si5526601pgc.280.2019.02.11.23.14.47; Mon, 11 Feb 2019 23:14:47 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@nifty.com header.s=dec2015msa header.b=bYe38x01; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728206AbfBLHOp (ORCPT + 31 others); Tue, 12 Feb 2019 02:14:45 -0500 Received: from conuserg-09.nifty.com ([210.131.2.76]:37708 "EHLO conuserg-09.nifty.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728096AbfBLHOl (ORCPT ); Tue, 12 Feb 2019 02:14:41 -0500 Received: from pug.e01.socionext.com (p14092-ipngnfx01kyoto.kyoto.ocn.ne.jp [153.142.97.92]) (authenticated) by conuserg-09.nifty.com with ESMTP id x1C7DPdY019269; Tue, 12 Feb 2019 16:13:34 +0900 DKIM-Filter: OpenDKIM Filter v2.10.3 conuserg-09.nifty.com x1C7DPdY019269 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nifty.com; s=dec2015msa; t=1549955615; bh=XGysdmS4tbl7yrVBNgBANjU9bQoRzs2DxSH9clfygmc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=bYe38x01hE39o4/AA/qy9v5uFm01SpfgMRed/PfTpIuoWqEDDky/wMEE4sI5Q4+YO qifHPgOBUo03n0dpxvyCjVBy29/TTB6YVlROGLw0rJufHUCYd2/rwXP3HQ2xaVe2ZE F6pDqLAIzlR7LbI1um3q87r/JAaYlY6TknA+fYnsrXo47WBnIGZm4pPnMWx2E3qa6Y OAsO7T5SvUe6ZhfluOoB3evVhyorFkZdZQs0cA78miGWb5Z5cHAP53guWKoyzDa+Zw b89k6KY3JTDW7+Hzoeir8VXAgXsYZuKfpauNXLB9Q4qVomu+cUoPRbY7Dzyx8kAbmk WqDJrxq8/CDfQ== X-Nifty-SrcIP: [153.142.97.92] From: Masahiro Yamada To: linux-mtd@lists.infradead.org, Miquel Raynal Cc: Boris Brezillon , Masahiro Yamada , Brian Norris , linux-kernel@vger.kernel.org, Marek Vasut , Richard Weinberger , David Woodhouse Subject: [PATCH v2 10/10] mtd: rawnand: denali: clean up coding style Date: Tue, 12 Feb 2019 16:13:02 +0900 Message-Id: <1549955582-30346-11-git-send-email-yamada.masahiro@socionext.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1549955582-30346-1-git-send-email-yamada.masahiro@socionext.com> References: <1549955582-30346-1-git-send-email-yamada.masahiro@socionext.com> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Eliminate the following reports from 'scripts/checkpatch.pl --strict'. CHECK: Prefer kernel type 'u8' over 'uint8_t' CHECK: Prefer kernel type 'u32' over 'uint32_t' CHECK: Alignment should match open parenthesis I slightly changed denali_check_erased_page() to make it shorter. Signed-off-by: Masahiro Yamada --- Changes in v2: None drivers/mtd/nand/raw/denali.c | 53 ++++++++++++++++++++----------------------- 1 file changed, 25 insertions(+), 28 deletions(-) -- 2.7.4 diff --git a/drivers/mtd/nand/raw/denali.c b/drivers/mtd/nand/raw/denali.c index eb58136..82b2b8e 100644 --- a/drivers/mtd/nand/raw/denali.c +++ b/drivers/mtd/nand/raw/denali.c @@ -124,7 +124,7 @@ static irqreturn_t denali_isr(int irq, void *dev_id) { struct denali_controller *denali = dev_id; irqreturn_t ret = IRQ_NONE; - uint32_t irq_status; + u32 irq_status; int i; spin_lock(&denali->irq_lock); @@ -164,7 +164,7 @@ static u32 denali_wait_for_irq(struct denali_controller *denali, u32 irq_mask, unsigned int timeout_ms) { unsigned long time_left, flags; - uint32_t irq_status; + u32 irq_status; spin_lock_irqsave(&denali->irq_lock, flags); @@ -239,20 +239,17 @@ static int denali_check_erased_page(struct nand_chip *chip, unsigned int max_bitflips) { struct mtd_ecc_stats *ecc_stats = &nand_to_mtd(chip)->ecc_stats; - uint8_t *ecc_code = chip->oob_poi + denali->oob_skip_bytes; - int ecc_steps = chip->ecc.steps; - int ecc_size = chip->ecc.size; - int ecc_bytes = chip->ecc.bytes; + struct nand_ecc_ctrl *ecc = &chip->ecc; + u8 *ecc_code = chip->oob_poi + denali->oob_skip_bytes; int i, stat; - for (i = 0; i < ecc_steps; i++) { + for (i = 0; i < ecc->steps; i++) { if (!(uncor_ecc_flags & BIT(i))) continue; - stat = nand_check_erased_ecc_chunk(buf, ecc_size, - ecc_code, ecc_bytes, - NULL, 0, - chip->ecc.strength); + stat = nand_check_erased_ecc_chunk(buf, ecc->size, ecc_code, + ecc->bytes, NULL, 0, + ecc->strength); if (stat < 0) { ecc_stats->failed++; } else { @@ -260,8 +257,8 @@ static int denali_check_erased_page(struct nand_chip *chip, max_bitflips = max_t(unsigned int, max_bitflips, stat); } - buf += ecc_size; - ecc_code += ecc_bytes; + buf += ecc->size; + ecc_code += ecc->bytes; } return max_bitflips; @@ -273,7 +270,7 @@ static int denali_hw_ecc_fixup(struct nand_chip *chip, { struct mtd_ecc_stats *ecc_stats = &nand_to_mtd(chip)->ecc_stats; int bank = denali->active_bank; - uint32_t ecc_cor; + u32 ecc_cor; unsigned int max_bitflips; ecc_cor = ioread32(denali->reg + ECC_COR_INFO(bank)); @@ -304,17 +301,17 @@ static int denali_hw_ecc_fixup(struct nand_chip *chip, static int denali_sw_ecc_fixup(struct nand_chip *chip, struct denali_controller *denali, - unsigned long *uncor_ecc_flags, uint8_t *buf) + unsigned long *uncor_ecc_flags, u8 *buf) { struct mtd_ecc_stats *ecc_stats = &nand_to_mtd(chip)->ecc_stats; unsigned int ecc_size = chip->ecc.size; unsigned int bitflips = 0; unsigned int max_bitflips = 0; - uint32_t err_addr, err_cor_info; + u32 err_addr, err_cor_info; unsigned int err_byte, err_sector, err_device; - uint8_t err_cor_value; + u8 err_cor_value; unsigned int prev_sector = 0; - uint32_t irq_status; + u32 irq_status; denali_reset_irq(denali); @@ -379,7 +376,7 @@ static int denali_sw_ecc_fixup(struct nand_chip *chip, static void denali_setup_dma64(struct denali_controller *denali, dma_addr_t dma_addr, int page, bool write) { - uint32_t mode; + u32 mode; const int page_count = 1; mode = DENALI_MAP10 | DENALI_BANK(denali) | page; @@ -404,7 +401,7 @@ static void denali_setup_dma64(struct denali_controller *denali, static void denali_setup_dma32(struct denali_controller *denali, dma_addr_t dma_addr, int page, bool write) { - uint32_t mode; + u32 mode; const int page_count = 1; mode = DENALI_MAP10 | DENALI_BANK(denali); @@ -429,7 +426,7 @@ static int denali_pio_read(struct denali_controller *denali, u32 *buf, size_t size, int page) { u32 addr = DENALI_MAP01 | DENALI_BANK(denali) | page; - uint32_t irq_status, ecc_err_mask; + u32 irq_status, ecc_err_mask; int i; if (denali->caps & DENALI_CAP_HW_ECC_FIXUP) @@ -456,7 +453,7 @@ static int denali_pio_write(struct denali_controller *denali, const u32 *buf, size_t size, int page) { u32 addr = DENALI_MAP01 | DENALI_BANK(denali) | page; - uint32_t irq_status; + u32 irq_status; int i; denali_reset_irq(denali); @@ -487,7 +484,7 @@ static int denali_dma_xfer(struct denali_controller *denali, void *buf, size_t size, int page, bool write) { dma_addr_t dma_addr; - uint32_t irq_mask, irq_status, ecc_err_mask; + u32 irq_mask, irq_status, ecc_err_mask; enum dma_data_direction dir = write ? DMA_TO_DEVICE : DMA_FROM_DEVICE; int ret = 0; @@ -654,7 +651,7 @@ static int denali_memcpy_in(void *buf, unsigned int offset, unsigned int len, return 0; } -static int denali_read_page_raw(struct nand_chip *chip, uint8_t *buf, +static int denali_read_page_raw(struct nand_chip *chip, u8 *buf, int oob_required, int page) { struct denali_chip *dchip = to_denali_chip(chip); @@ -691,7 +688,7 @@ static int denali_memcpy_out(void *buf, unsigned int offset, unsigned int len, return 0; } -static int denali_write_page_raw(struct nand_chip *chip, const uint8_t *buf, +static int denali_write_page_raw(struct nand_chip *chip, const u8 *buf, int oob_required, int page) { struct denali_chip *dchip = to_denali_chip(chip); @@ -765,7 +762,7 @@ static int denali_write_oob(struct nand_chip *chip, int page) return nand_prog_page_end_op(chip); } -static int denali_read_page(struct nand_chip *chip, uint8_t *buf, +static int denali_read_page(struct nand_chip *chip, u8 *buf, int oob_required, int page) { struct denali_controller *denali = to_denali_controller(chip); @@ -798,7 +795,7 @@ static int denali_read_page(struct nand_chip *chip, uint8_t *buf, return stat; } -static int denali_write_page(struct nand_chip *chip, const uint8_t *buf, +static int denali_write_page(struct nand_chip *chip, const u8 *buf, int oob_required, int page) { struct mtd_info *mtd = nand_to_mtd(chip); @@ -817,7 +814,7 @@ static int denali_setup_data_interface(struct nand_chip *chip, int chipnr, int acc_clks, re_2_we, re_2_re, we_2_re, addr_2_data; int rdwr_en_lo, rdwr_en_hi, rdwr_en_lo_hi, cs_setup; int addr_2_data_mask; - uint32_t tmp; + u32 tmp; timings = nand_get_sdr_timings(conf); if (IS_ERR(timings))