From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id F0E51C4345F for ; Tue, 23 Apr 2024 10:44:28 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:Content-Type: Content-Transfer-Encoding:List-Subscribe:List-Help:List-Post:List-Archive: List-Unsubscribe:List-Id:In-Reply-To:From:References:Cc:To:Subject: MIME-Version:Date:Message-ID:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=/KaYscORxQF96Qz+PH18/sf9sv4iR6E9mfzvVbaprW0=; b=rh3tCS0BtgG/wE pks6PkPy+Mf+UnnA2VV88p8+r9E4aiyWYTOec+Uh9EJbkxlit5RHiRfAhL7i5DS2IrSBA7lYXCkAa qeRS8HrsFq0It7hqdmuf83JhnxICqQ+tkLXqEmkAfvl6xd5N+aCx3VY1WERziUncrnLschuao3DI8 5PKp0KNOvaEnhbne7ZSf8FMeIQG64zcN8ojThxoAyhd3XDwg9VyiRwJ0lG8iGgB26sr6YiZ82DJGg BrKQoRyuTfATcpG7y19pHc1sausY5/hCBdFcWVDMNpkwmHDya44cvJ/g2syrJykrt/pluqM0E2zlH NWEk/A3e9lt+smi+PIdQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.97.1 #2 (Red Hat Linux)) id 1rzDdE-0000000GtI5-0rfW; Tue, 23 Apr 2024 10:44:12 +0000 Received: from madrid.collaboradmins.com ([2a00:1098:ed:100::25]) by bombadil.infradead.org with esmtps (Exim 4.97.1 #2 (Red Hat Linux)) id 1rzDdB-0000000GtHX-1hf5 for linux-arm-kernel@lists.infradead.org; Tue, 23 Apr 2024 10:44:10 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com; s=mail; t=1713869047; bh=zDJt23fvtClF2RoGc5I6euxTC2BOtp2cbdM4k1tRlpk=; h=Date:Subject:To:Cc:References:From:In-Reply-To:From; b=ZWgwFjAC0CZKxSg8jP2Og1Eov6Avm1tDmmGvSj1woFCU7IpESc6BBle4X1/nsNGly qi0UEull4XwHlPdPBeDOo/PedNt2/ThmOXRgCnT6Qgg4Dt0GWrX4PuBEx18hvJnlwq niTgmA2jSRwUzHf0LmMt3vyxXH1y7MToYuWoZ0y1KZ0sreTz8UxTymHhtgCR/d+Xfd RncRt+v8Cv5Xl4eLlk3rbXy5VAhV4bUNqzx8Q/dqmFsn12VYO5Zu+ptTN4Zf542usD 2gmbqS11PhbJLn5MmSonIifKSGeTmwc9A/5wr0s10qNECQ3hi11nFSRJmysUT8QRPB YodOIIohOJx1A== Received: from [100.113.186.2] (cola.collaboradmins.com [195.201.22.229]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: kholk11) by madrid.collaboradmins.com (Postfix) with ESMTPSA id E525D378208C; Tue, 23 Apr 2024 10:44:06 +0000 (UTC) Message-ID: Date: Tue, 23 Apr 2024 12:44:06 +0200 MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: Re: [PATCH v3 3/3] spi: airoha: add SPI-NAND Flash controller driver To: Lorenzo Bianconi , linux-spi@vger.kernel.org Cc: conor@kernel.org, broonie@kernel.org, lorenzo.bianconi83@gmail.com, linux-arm-kernel@lists.infradead.org, robh+dt@kernel.org, krzysztof.kozlowski+dt@linaro.org, conor+dt@kernel.org, devicetree@vger.kernel.org, nbd@nbd.name, john@phrozen.org, dd@embedd.com, catalin.marinas@arm.com, will@kernel.org, upstream@airoha.com References: <497dc9dad823fcd1403ed62ba164dd7d70f31f90.1713866770.git.lorenzo@kernel.org> From: AngeloGioacchino Del Regno Content-Language: en-US In-Reply-To: <497dc9dad823fcd1403ed62ba164dd7d70f31f90.1713866770.git.lorenzo@kernel.org> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20240423_034409_650355_84A17516 X-CRM114-Status: GOOD ( 28.04 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset="us-ascii"; Format="flowed" Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Il 23/04/24 12:16, Lorenzo Bianconi ha scritto: > Introduce support for SPI-NAND driver of the Airoha NAND Flash Interface > found on Airoha ARM SoCs. > > Tested-by: Rajeev Kumar > Signed-off-by: Lorenzo Bianconi > --- > MAINTAINERS | 9 + > drivers/spi/Kconfig | 10 + > drivers/spi/Makefile | 1 + > drivers/spi/spi-airoha-snfi.c | 1156 +++++++++++++++++++++++++++++++++ > 4 files changed, 1176 insertions(+) > create mode 100644 drivers/spi/spi-airoha-snfi.c > > diff --git a/MAINTAINERS b/MAINTAINERS > index aa3b947fb080..ce9fac46f741 100644 > --- a/MAINTAINERS > +++ b/MAINTAINERS > @@ -653,6 +653,15 @@ S: Supported > F: fs/aio.c > F: include/linux/*aio*.h > > +AIROHA SPI SNFI DRIVER > +M: Lorenzo Bianconi > +M: Ray Liu > +L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) > +L: linux-spi@vger.kernel.org > +S: Maintained > +F: Documentation/devicetree/bindings/spi/airoha,en7581-snand.yaml > +F: drivers/spi/spi-airoha.c > + > AIRSPY MEDIA DRIVER > L: linux-media@vger.kernel.org > S: Orphan > diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig > index bc7021da2fe9..6fa91775f334 100644 > --- a/drivers/spi/Kconfig > +++ b/drivers/spi/Kconfig > @@ -57,6 +57,16 @@ config SPI_MEM > > comment "SPI Master Controller Drivers" > > +config SPI_AIROHA_SNFI > + tristate "Airoha SPI NAND Flash Interface" > + depends on ARCH_AIROHA || COMPILE_TEST > + depends on SPI_MASTER > + select REGMAP_MMIO > + help > + This enables support for SPI-NAND mode on the Airoha NAND > + Flash Interface found on Airoha ARM SoCs. This controller > + is implemented as a SPI-MEM controller. > + > config SPI_ALTERA > tristate "Altera SPI Controller platform driver" > select SPI_ALTERA_CORE > diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile > index 4ff8d725ba5e..e694254dec04 100644 > --- a/drivers/spi/Makefile > +++ b/drivers/spi/Makefile > @@ -14,6 +14,7 @@ obj-$(CONFIG_SPI_SPIDEV) += spidev.o > obj-$(CONFIG_SPI_LOOPBACK_TEST) += spi-loopback-test.o > > # SPI master controller drivers (bus) > +obj-$(CONFIG_SPI_AIROHA_SNFI) += spi-airoha-snfi.o > obj-$(CONFIG_SPI_ALTERA) += spi-altera-platform.o > obj-$(CONFIG_SPI_ALTERA_CORE) += spi-altera-core.o > obj-$(CONFIG_SPI_ALTERA_DFL) += spi-altera-dfl.o > diff --git a/drivers/spi/spi-airoha-snfi.c b/drivers/spi/spi-airoha-snfi.c > new file mode 100644 > index 000000000000..eacb32d6e28e > --- /dev/null > +++ b/drivers/spi/spi-airoha-snfi.c > @@ -0,0 +1,1156 @@ > +// SPDX-License-Identifier: GPL-2.0-only > +/* > + * Copyright (c) 2024 AIROHA Inc > + * Author: Lorenzo Bianconi > + * Author: Ray Liu > + */ > + ..snip... > +static ssize_t airoha_snand_dirmap_read(struct spi_mem_dirmap_desc *desc, > + u64 offs, size_t len, void *buf) > +{ > + struct spi_device *spi = desc->mem->spi; > + struct airoha_snand_dev *as_dev = spi_get_ctldata(spi); > + struct spi_mem_op *op = &desc->info.op_tmpl; > + struct airoha_snand_ctrl *as_ctrl; > + u32 val, rd_mode; > + int err; > + > + if (!as_dev->data_need_update) > + return len; > + > + as_dev->data_need_update = false; > + > + switch (op->cmd.opcode) { > + case SPI_NAND_OP_READ_FROM_CACHE_DUAL: > + rd_mode = 1; > + break; > + case SPI_NAND_OP_READ_FROM_CACHE_QUAD: > + rd_mode = 2; > + break; > + default: > + rd_mode = 0; > + break; > + } > + > + as_ctrl = spi_controller_get_devdata(spi->controller); > + err = airoha_snand_set_mode(as_ctrl, SPI_MODE_DMA); > + if (err < 0) > + return err; > + > + err = airoha_snand_nfi_config(as_ctrl); > + if (err) > + return err; > + > + dma_sync_single_for_device(as_ctrl->dev, as_dev->dma_addr, > + as_dev->buf_len, DMA_BIDIRECTIONAL); > + mb(); Are you sure you need this memory barrier here? P.S.: Just in case... any other write or read will anyway add a barrier ;-) > + > + /* set dma addr */ > + err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_STRADDR, > + as_dev->dma_addr); > + if (err) > + return err; > + ..snip.. > + > +static ssize_t airoha_snand_dirmap_write(struct spi_mem_dirmap_desc *desc, > + u64 offs, size_t len, const void *buf) > +{ > + struct spi_device *spi = desc->mem->spi; > + struct airoha_snand_dev *as_dev = spi_get_ctldata(spi); > + struct spi_mem_op *op = &desc->info.op_tmpl; > + struct airoha_snand_ctrl *as_ctrl; > + u32 wr_mode, val; > + int err; > + > + as_ctrl = spi_controller_get_devdata(spi->controller); > + err = airoha_snand_set_mode(as_ctrl, SPI_MODE_MANUAL); > + if (err < 0) > + return err; > + > + dma_sync_single_for_cpu(as_ctrl->dev, as_dev->dma_addr, > + as_dev->buf_len, DMA_BIDIRECTIONAL); > + memcpy(as_dev->txrx_buf + offs, buf, len); > + dma_sync_single_for_device(as_ctrl->dev, as_dev->dma_addr, > + as_dev->buf_len, DMA_BIDIRECTIONAL); > + mb(); > + > + err = airoha_snand_set_mode(as_ctrl, SPI_MODE_DMA); > + if (err < 0) > + return err; > + > + err = airoha_snand_nfi_config(as_ctrl); > + if (err) > + return err; > + > + if (op->cmd.opcode == SPI_NAND_OP_PROGRAM_LOAD_QUAD || > + op->cmd.opcode == SPI_NAND_OP_PROGRAM_LOAD_RAMDON_QUAD) > + wr_mode = 2; I'm mostly sure that this '2' is supposed to be BIT(1) instead > + else > + wr_mode = 0; > + > + err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_STRADDR, > + as_dev->dma_addr); > + if (err) > + return err; > + > + val = as_ctrl->nfi_cfg.sec_size * as_ctrl->nfi_cfg.sec_num; > + val = FIELD_PREP(SPI_NFI_PROG_LOAD_BYTE_NUM, val); val = FIELD_PREP(SPI_NFI_PROG_LOAD_BYTE_NUM, as_ctrl->nfi_cfg.sec_size * as_ctrl->nfi_cfg.sec_num); Being this 100 cols eventually, you wouldn't even need two lines - but if you don't want to go 100, it's still more readable (imo) like this, even if in two lines. > + err = regmap_update_bits(as_ctrl->regmap_nfi, > + REG_SPI_NFI_SNF_MISC_CTL2, > + SPI_NFI_PROG_LOAD_BYTE_NUM, val); > + if (err) > + return err; > + > + err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_PG_CTL1, > + FIELD_PREP(SPI_NFI_PG_LOAD_CMD, > + op->cmd.opcode)); > + if (err) > + return err; > + > + err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_SNF_MISC_CTL, > + FIELD_PREP(SPI_NFI_DATA_READ_WR_MODE, wr_mode)); > + if (err) > + return err; > + ..snip.. > + > +#define SPI_NAND_CACHE_SIZE (4096 + 256) #include <--- at the beginning #define SPI_NAND_CACHE_SIZE (SZ_4K + SZ_256) ...there are macros for that, might as well use them, right? :-) > + > +static int airoha_snand_setup(struct spi_device *spi) > +{ > + struct airoha_snand_dev *as_dev = spi_get_ctldata(spi); > + struct airoha_snand_ctrl *as_ctrl; > + > + as_dev = kzalloc(sizeof(*as_dev), GFP_KERNEL); > + if (!as_dev) > + return -ENOMEM; > + > + spi_set_ctldata(spi, as_dev); > + as_dev->data_need_update = true; > + > + /* prepare device buffer */ > + as_dev->buf_len = SPI_NAND_CACHE_SIZE; > + as_dev->txrx_buf = kzalloc(as_dev->buf_len, GFP_KERNEL); > + if (!as_dev->txrx_buf) > + goto error_dev_free; > + > + as_ctrl = spi_controller_get_devdata(spi->controller); > + as_dev->dma_addr = dma_map_single(as_ctrl->dev, as_dev->txrx_buf, > + as_dev->buf_len, DMA_BIDIRECTIONAL); > + if (dma_mapping_error(as_ctrl->dev, as_dev->dma_addr)) > + goto error_buf_free; > + > + return 0; > + > +error_buf_free: > + kfree(as_dev->txrx_buf); > +error_dev_free: > + kfree(as_dev); > + > + return -EINVAL; > +} > + > +static void airoha_snand_cleanup(struct spi_device *spi) > +{ > + struct airoha_snand_dev *as_dev = spi_get_ctldata(spi); > + struct airoha_snand_ctrl *as_ctrl; > + > + as_ctrl = spi_controller_get_devdata(spi->controller); > + dma_unmap_single(as_ctrl->dev, as_dev->dma_addr, > + as_dev->buf_len, DMA_BIDIRECTIONAL); > + kfree(as_dev->txrx_buf); > + > + spi_set_ctldata(spi, NULL); > +} > + > +static int airoha_snand_nfi_setup(struct airoha_snand_ctrl *as_ctrl) > +{ > + u32 val, sec_size, sec_num; > + int err; > + > + err = regmap_read(as_ctrl->regmap_nfi, REG_SPI_NFI_CON, &val); > + if (err) > + return err; > + > + sec_num = FIELD_GET(SPI_NFI_SEC_NUM, val); > + > + err = regmap_read(as_ctrl->regmap_nfi, > + REG_SPI_NFI_SECCUS_SIZE, &val); > + if (err) > + return err; > + > + sec_size = FIELD_GET(SPI_NFI_CUS_SEC_SIZE, val); > + > + /* init default value */ > + as_ctrl->nfi_cfg.sec_size = sec_size; > + as_ctrl->nfi_cfg.sec_num = sec_num; > + as_ctrl->nfi_cfg.page_size = rounddown(sec_size * sec_num, 1024); > + as_ctrl->nfi_cfg.spare_size = 16; > + > + err = airoha_snand_nfi_init(as_ctrl); > + if (err) > + return err; > + > + return airoha_snand_nfi_config(as_ctrl); > +} > + > +static const struct regmap_config spi_ctrl_regmap_config = { > + .name = "ctrl", > + .reg_bits = 32, > + .val_bits = 32, > + .reg_stride = 4, > + .max_register = REG_SPI_CTRL_NFI2SPI_EN, > +}; > + > +static const struct regmap_config spi_nfi_regmap_config = { > + .name = "nfi", > + .reg_bits = 32, > + .val_bits = 32, > + .reg_stride = 4, > + .max_register = REG_SPI_NFI_SNF_NFI_CNFG, > +}; > + > +static const struct of_device_id airoha_snand_ids[] = { > + { .compatible = "airoha,en7581-snand" }, > + { } { /* sentinel */ } ...please! > +}; > +MODULE_DEVICE_TABLE(of, airoha_snand_ids); > + Cheers, Angelo _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel