From mboxrd@z Thu Jan 1 00:00:00 1970 From: Zhou Wang Subject: Re: [PATCH 2/3] mtd: hisilicon: add a new nand controller driver for hisilicon hip04 Soc Date: Wed, 02 Jul 2014 10:09:43 +0800 Message-ID: <53B369E7.7050202@gmail.com> References: <1404115409-20200-1-git-send-email-wangzhou.bry@gmail.com> <1404115409-20200-3-git-send-email-wangzhou.bry@gmail.com> <53B131AF.2040501@ti.com> Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: QUOTED-PRINTABLE Return-path: In-Reply-To: <53B131AF.2040501@ti.com> Sender: linux-doc-owner@vger.kernel.org To: Ivan Khoronzhuk Cc: Rob Herring , Pawel Moll , Mark Rutland , Ian Campbell , Kumar Gala , Russell King , David Woodhouse , Brian Norris , Grant Likely , Ezequiel Garcia , Pekon Gupta , Artem Bityutskiy , Alexander Shiyan , Jussi Kivilinna , Joern Engel , Randy Dunlap , linux-arm-kernel@lists.infradead.org, devicetree@vger.kernel.org, linux-mtd@lists.infradead.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, wangzhou1@hisilicon.com, caizhiyong@huawei.com List-Id: devicetree@vger.kernel.org On 2014=E5=B9=B406=E6=9C=8830=E6=97=A5 17:45, Ivan Khoronzhuk wrote: > > On 06/30/2014 11:03 AM, Zhou Wang wrote: >> Signed-off-by: Zhou Wang >> --- >> drivers/mtd/nand/Kconfig | 5 + >> drivers/mtd/nand/Makefile | 1 + >> drivers/mtd/nand/hisi_nand.c | 847 >> ++++++++++++++++++++++++++++++++++++++++++ >> 3 files changed, 853 insertions(+) >> create mode 100644 drivers/mtd/nand/hisi_nand.c >> >> diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig >> index 90ff447..253f8c8 100644 >> --- a/drivers/mtd/nand/Kconfig >> +++ b/drivers/mtd/nand/Kconfig >> @@ -510,4 +510,9 @@ config MTD_NAND_XWAY >> Enables support for NAND Flash chips on Lantiq XWAY SoCs. NA= ND >> is attached >> to the External Bus Unit (EBU). >> +config MTD_NAND_HISI >> + tristate "Support for NAND controller on Hisilicon SoC" >> + help >> + Enables support for NAND controller on Hisilicon SoC. >> + >> endif # MTD_NAND >> diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile >> index 542b568..d0881cf 100644 >> --- a/drivers/mtd/nand/Makefile >> +++ b/drivers/mtd/nand/Makefile >> @@ -49,5 +49,6 @@ obj-$(CONFIG_MTD_NAND_JZ4740) +=3D jz4740_n= and.o >> obj-$(CONFIG_MTD_NAND_GPMI_NAND) +=3D gpmi-nand/ >> obj-$(CONFIG_MTD_NAND_XWAY) +=3D xway_nand.o >> obj-$(CONFIG_MTD_NAND_BCM47XXNFLASH) +=3D bcm47xxnflash/ >> +obj-$(CONFIG_MTD_NAND_HISI) +=3D hisi_nand.o >> nand-objs :=3D nand_base.o nand_bbt.o >> diff --git a/drivers/mtd/nand/hisi_nand.c b/drivers/mtd/nand/hisi_na= nd.c >> new file mode 100644 >> index 0000000..fbcb065 >> --- /dev/null >> +++ b/drivers/mtd/nand/hisi_nand.c >> @@ -0,0 +1,847 @@ >> +/* >> + * Hisilicon NAND Flash controller driver >> + * >> + * Copyright =C2=A9 2012-2014 HiSilicon Technologies Co., Ltd. >> + * http://www.hisilicon.com >> + * >> + * Author: Zhou Wang >> + * The initial developer of the original code is Zhiyong Cai >> + * >> + * >> + * This program is free software; you can redistribute it and/or mo= dify >> + * it under the terms of the GNU General Public License as publishe= d by >> + * the Free Software Foundation; either version 2 of the License, o= r >> + * (at your option) any later version. >> + * >> + * This program is distributed in the hope that it will be useful, >> + * but WITHOUT ANY WARRANTY; without even the implied warranty of >> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >> + * GNU General Public License for more details. >> + */ >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> + >> +#define HINFC504_MAX_CHIP (4) >> +#define HINFC504_W_LATCH (5) >> +#define HINFC504_R_LATCH (7) >> +#define HINFC504_RW_LATCH (3) >> + >> +#define HINFC504_NFC_TIMEOUT (2 * HZ) >> +#define HINFC504_NFC_DMA_TIMEOUT (5 * HZ) >> +#define HINFC504_CHIP_DELAY (25) >> + >> +#define HINFC504_REG_BASE_ADDRESS_LEN (0x100) >> +#define HINFC504_BUFFER_BASE_ADDRESS_LEN (2048 + 128) >> + >> +#define HINFC504_ADDR_CYCLE_MASK 0x4 >> + >> +#define HINFC504_CON 0x00 >> +#define HINFC504_CON_OP_MODE_NORMAL (1U << 0) >> +#define HINFC504_CON_PAGEISZE_SHIFT (1) >> +#define HINFC504_CON_PAGESIZE_MASK (0x07) >> +#define HINFC504_CON_BUS_WIDTH (1U << 4) >> +#define HINFC504_CON_READY_BUSY_SEL (1U << 8) >> +#define HINFC504_CON_ECCTYPE_SHIFT (9) >> +#define HINFC504_CON_ECCTYPE_MASK (0x07) >> + >> +#define HINFC504_PWIDTH 0x04 >> +#define SET_HINFC504_PWIDTH(_w_lcnt, _r_lcnt, _rw_hcnt) \ >> + ((_w_lcnt) | (((_r_lcnt) & 0x0F) << 4) | (((_rw_hcnt) & 0x0F) <= < 8)) >> + >> +#define HINFC504_CMD 0x0C >> +#define HINFC504_ADDRL 0x10 >> +#define HINFC504_ADDRH 0x14 >> +#define HINFC504_DATA_NUM 0x18 >> + >> +#define HINFC504_OP 0x1C >> +#define HINFC504_OP_READ_DATA_EN (1U << 1) >> +#define HINFC504_OP_WAIT_READY_EN (1U << 2) >> +#define HINFC504_OP_CMD2_EN (1U << 3) >> +#define HINFC504_OP_WRITE_DATA_EN (1U << 4) >> +#define HINFC504_OP_ADDR_EN (1U << 5) >> +#define HINFC504_OP_CMD1_EN (1U << 6) >> +#define HINFC504_OP_NF_CS_SHIFT (7) >> +#define HINFC504_OP_NF_CS_MASK (3) >> +#define HINFC504_OP_ADDR_CYCLE_SHIFT (9) >> +#define HINFC504_OP_ADDR_CYCLE_MASK (7) >> + >> +#define HINFC504_STATUS 0x20 >> +#define HINFC504_READY (1U << 0) >> + >> +#define HINFC504_INTEN 0x24 >> +#define HINFC504_INTEN_DMA (1U << 9) >> +#define HINFC504_INTEN_UE (1U << 6) >> +#define HINFC504_INTEN_CE (1U << 5) >> + >> +#define HINFC504_INTS 0x28 >> +#define HINFC504_INTS_DMA (1U << 9) >> +#define HINFC504_INTS_UE (1U << 6) >> +#define HINFC504_INTS_CE (1U << 5) >> + >> +#define HINFC504_INTCLR 0x2C >> +#define HINFC504_INTCLR_DMA (1U << 9) >> +#define HINFC504_INTCLR_UE (1U << 6) >> +#define HINFC504_INTCLR_CE (1U << 5) >> + >> +#define HINFC504_ECC_STATUS 0x5C >> +#define HINFC504_ECC_1_BIT_SHIFT 16 >> +#define HINFC504_ECC_16_BIT_SHIFT 12 >> + >> +#define HINFC504_DMA_CTRL 0x60 >> +#define HINFC504_DMA_CTRL_DMA_START (1U << 0) >> +#define HINFC504_DMA_CTRL_WE (1U << 1) >> +#define HINFC504_DMA_CTRL_DATA_AREA_EN (1U << 2) >> +#define HINFC504_DMA_CTRL_OOB_AREA_EN (1U << 3) >> +#define HINFC504_DMA_CTRL_BURST4_EN (1U << 4) >> +#define HINFC504_DMA_CTRL_BURST8_EN (1U << 5) >> +#define HINFC504_DMA_CTRL_BURST16_EN (1U << 6) >> +#define HINFC504_DMA_CTRL_ADDR_NUM_SHIFT (7) >> +#define HINFC504_DMA_CTRL_ADDR_NUM_MASK (1) >> +#define HINFC504_DMA_CTRL_CS_SHIFT (8) >> +#define HINFC504_DMA_CTRL_CS_MASK (0x03) >> + >> +#define HINFC504_DMA_ADDR_DATA 0x64 >> +#define HINFC504_DMA_ADDR_OOB 0x68 >> + >> +#define HINFC504_DMA_LEN 0x6C >> +#define HINFC504_DMA_LEN_OOB_SHIFT (16) >> +#define HINFC504_DMA_LEN_OOB_MASK (0xFFF) >> + >> +#define HINFC504_DMA_PARA 0x70 >> +#define HINFC504_DMA_PARA_DATA_RW_EN (1U << 0) >> +#define HINFC504_DMA_PARA_OOB_RW_EN (1U << 1) >> +#define HINFC504_DMA_PARA_DATA_EDC_EN (1U << 2) >> +#define HINFC504_DMA_PARA_OOB_EDC_EN (1U << 3) >> +#define HINFC504_DMA_PARA_DATA_ECC_EN (1U << 4) >> +#define HINFC504_DMA_PARA_OOB_ECC_EN (1U << 5) >> + >> +#define HINFC_VERSION 0x74 >> +#define HINFC504_LOG_READ_ADDR 0x7C >> +#define HINFC504_LOG_READ_LEN 0x80 >> + >> +#define HINFC504_NANDINFO_LEN 0x10 >> + >> +#define hinfc_read(_host, _reg) readl(_host->iobase + (_reg)) >> +#define hinfc_write(_host, _value, _reg)\ >> + writel((_value), _host->iobase + (_reg)) >> + >> +struct hinfc_host { >> + struct nand_chip *chip; >> + struct mtd_info *mtd; >> + struct device *dev; >> + void __iomem *iobase; >> + struct completion cmd_complete; >> + unsigned int offset; >> + unsigned int command; >> + int chipselect; >> + unsigned int addr_cycle; >> + unsigned int addr_value[2]; >> + unsigned int cache_addr_value[2]; >> + char *buffer; >> + dma_addr_t dma_buffer; >> + dma_addr_t dma_oob; >> + int version; >> + unsigned int ecc_bits; >> + unsigned int irq_status; /* interrupt status */ >> + >> + int (*send_cmd_pageprog)(struct hinfc_host *host); >> + int (*send_cmd_status)(struct hinfc_host *host); >> + int (*send_cmd_readstart)(struct hinfc_host *host); >> + int (*send_cmd_erase)(struct hinfc_host *host); >> + int (*send_cmd_readid)(struct hinfc_host *host); >> + int (*send_cmd_reset)(struct hinfc_host *host, int chipselect); >> +}; >> + >> +void wait_controller_finished(struct hinfc_host *host) >> +{ >> + unsigned long timeout =3D jiffies + HINFC504_NFC_TIMEOUT; >> + int val; >> + >> + while (time_before(jiffies, timeout)) { >> + val =3D hinfc_read(host, HINFC504_STATUS); >> + if (host->command =3D=3D NAND_CMD_ERASE2) { >> + /* nfc is ready */ >> + while (!(val & HINFC504_READY)) { >> + usleep_range(500, 1000); >> + val =3D hinfc_read(host, HINFC504_STATUS); >> + } >> + return; >> + } else { >> + if (val & HINFC504_READY) >> + return; >> + } >> + } >> + >> + /* wait cmd timeout */ >> + dev_err(host->dev, "Wait NAND controller exec cmd timeout.\n"); >> +} >> + >> +static void hisi_nfc_dma_transfer(struct hinfc_host *host, int tode= v) >> +{ >> + struct mtd_info *mtd =3D host->mtd; >> + struct nand_chip *chip =3D mtd->priv; >> + unsigned long val; >> + int ret; >> + >> + hinfc_write(host, host->dma_buffer, HINFC504_DMA_ADDR_DATA); >> + hinfc_write(host, host->dma_oob, HINFC504_DMA_ADDR_OOB); >> + >> + if (chip->ecc.mode =3D=3D NAND_ECC_NONE) { >> + hinfc_write(host, ((mtd->oobsize & HINFC504_DMA_LEN_OOB_MAS= K) >> + << HINFC504_DMA_LEN_OOB_SHIFT), HINFC504_DMA_LEN); >> + >> + hinfc_write(host, HINFC504_DMA_PARA_DATA_RW_EN >> + | HINFC504_DMA_PARA_OOB_RW_EN, HINFC504_DMA_PARA); >> + } else > > Add {} for else also > ./scripts/checkpatch.pl. > ok, I will add them, thanks.