Commit 63c30d70 authored by Miquel Raynal's avatar Miquel Raynal

Merge tag 'nand/for-6.1' into mtd/next

Raw NAND core changes:
* Replace of_gpio_named_count() by gpiod_count()
  - Remove misguided comment of nand_get_device()
  - bbt: Use the bitmap API to allocate bitmaps

Raw NAND controller drivers changes:
* Meson:
  - Stop supporting legacy clocks
  - Refine resource getting in probe
  - Convert bindings to yaml
  - Fix clock handling and update the bindings accordingly
  - Fix bit map use in meson_nfc_ecc_correct()
* bcm47xx:
  - Fix spelling typo in comment
* STM32 FMC2:
  - Switch to using devm_fwnode_gpiod_get()
  - Fix dma_map_sg error check
* Cadence:
  - Remove an unneeded result variable
* Marvell:
  - Fix error handle regarding dma_map_sg
* Orion:
  - Use devm_clk_get_optional()
* Cafe:
  - Use correct function name in comment block
* Atmel:
  - Unmap streaming DMA mappings
* Arasan:
  - Stop using 0 as NULL pointer
* GPMI:
  - Fix typo 'the the' in comment
* BRCM:
  - Add individual glue driver selection
  - Move Kconfig to driver folder
* FSL: Fix none ECC mode
* Intel:
  - Use devm_platform_ioremap_resource_byname()
  - Remove unused clk_rate member from struct ebu_nand
  - Remove unused nand_pa member from ebu_nand_cs
  - Don't re-define NAND_DATA_IFACE_CHECK_ONLY
  - Remove undocumented compatible string
  - Fix compatible string in the bindings
  - Read the chip-select line from the correct OF node
  - Fix maximum chip select value in the bindings
Signed-off-by: default avatarMiquel Raynal <miquel.raynal@bootlin.com>
parents 095bb6e4 ba47a6ac
Amlogic NAND Flash Controller (NFC) for GXBB/GXL/AXG family SoCs
This file documents the properties in addition to those available in
the MTD NAND bindings.
Required properties:
- compatible : contains one of:
- "amlogic,meson-gxl-nfc"
- "amlogic,meson-axg-nfc"
- clocks :
A list of phandle + clock-specifier pairs for the clocks listed
in clock-names.
- clock-names: Should contain the following:
"core" - NFC module gate clock
"device" - device clock from eMMC sub clock controller
"rx" - rx clock phase
"tx" - tx clock phase
- amlogic,mmc-syscon : Required for NAND clocks, it's shared with SD/eMMC
controller port C
Optional children nodes:
Children nodes represent the available nand chips.
Other properties:
see Documentation/devicetree/bindings/mtd/nand-controller.yaml for generic bindings.
Example demonstrate on AXG SoC:
sd_emmc_c_clkc: mmc@7000 {
compatible = "amlogic,meson-axg-mmc-clkc", "syscon";
reg = <0x0 0x7000 0x0 0x800>;
};
nand-controller@7800 {
compatible = "amlogic,meson-axg-nfc";
reg = <0x0 0x7800 0x0 0x100>;
#address-cells = <1>;
#size-cells = <0>;
interrupts = <GIC_SPI 34 IRQ_TYPE_EDGE_RISING>;
clocks = <&clkc CLKID_SD_EMMC_C>,
<&sd_emmc_c_clkc CLKID_MMC_DIV>,
<&sd_emmc_c_clkc CLKID_MMC_PHASE_RX>,
<&sd_emmc_c_clkc CLKID_MMC_PHASE_TX>;
clock-names = "core", "device", "rx", "tx";
amlogic,mmc-syscon = <&sd_emmc_c_clkc>;
pinctrl-names = "default";
pinctrl-0 = <&nand_pins>;
nand@0 {
reg = <0>;
#address-cells = <1>;
#size-cells = <1>;
nand-on-flash-bbt;
};
};
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/mtd/amlogic,meson-nand.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Amlogic NAND Flash Controller (NFC) for GXBB/GXL/AXG family SoCs
allOf:
- $ref: nand-controller.yaml
maintainers:
- liang.yang@amlogic.com
properties:
compatible:
enum:
- amlogic,meson-gxl-nfc
- amlogic,meson-axg-nfc
reg:
maxItems: 2
reg-names:
items:
- const: nfc
- const: emmc
interrupts:
maxItems: 1
clocks:
minItems: 2
clock-names:
items:
- const: core
- const: device
patternProperties:
"^nand@[0-7]$":
type: object
properties:
reg:
minimum: 0
maximum: 1
nand-ecc-mode:
const: hw
nand-ecc-step-size:
const: 1024
nand-ecc-strength:
enum: [8, 16, 24, 30, 40, 50, 60]
description: |
The ECC configurations that can be supported are as follows.
meson-gxl-nfc 8, 16, 24, 30, 40, 50, 60
meson-axg-nfc 8
required:
- compatible
- reg
- interrupts
- clocks
- clock-names
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/clock/axg-clkc.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
nand-controller@ffe07800 {
compatible = "amlogic,meson-axg-nfc";
reg = <0xffe07800 0x100>, <0xffe07000 0x800>;
reg-names = "nfc", "emmc";
interrupts = <GIC_SPI 34 IRQ_TYPE_EDGE_RISING>;
clocks = <&clkc CLKID_SD_EMMC_C>, <&clkc CLKID_FCLK_DIV2>;
clock-names = "core", "device";
pinctrl-0 = <&nand_pins>;
pinctrl-names = "default";
#address-cells = <1>;
#size-cells = <0>;
nand@0 {
reg = <0>;
};
};
...
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) # SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2 %YAML 1.2
--- ---
$id: http://devicetree.org/schemas/mtd/intel,lgm-nand.yaml# $id: http://devicetree.org/schemas/mtd/intel,lgm-ebunand.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml# $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Intel LGM SoC NAND Controller Device Tree Bindings title: Intel LGM SoC NAND Controller Device Tree Bindings
...@@ -14,7 +14,7 @@ maintainers: ...@@ -14,7 +14,7 @@ maintainers:
properties: properties:
compatible: compatible:
const: intel,lgm-nand const: intel,lgm-ebunand
reg: reg:
maxItems: 6 maxItems: 6
...@@ -51,7 +51,7 @@ patternProperties: ...@@ -51,7 +51,7 @@ patternProperties:
properties: properties:
reg: reg:
minimum: 0 minimum: 0
maximum: 7 maximum: 1
nand-ecc-mode: true nand-ecc-mode: true
...@@ -75,7 +75,7 @@ additionalProperties: false ...@@ -75,7 +75,7 @@ additionalProperties: false
examples: examples:
- | - |
nand-controller@e0f00000 { nand-controller@e0f00000 {
compatible = "intel,lgm-nand"; compatible = "intel,lgm-ebunand";
reg = <0xe0f00000 0x100>, reg = <0xe0f00000 0x100>,
<0xe1000000 0x300>, <0xe1000000 0x300>,
<0xe1400000 0x8000>, <0xe1400000 0x8000>,
......
...@@ -24,11 +24,8 @@ int nanddev_bbt_init(struct nand_device *nand) ...@@ -24,11 +24,8 @@ int nanddev_bbt_init(struct nand_device *nand)
{ {
unsigned int bits_per_block = fls(NAND_BBT_BLOCK_NUM_STATUS); unsigned int bits_per_block = fls(NAND_BBT_BLOCK_NUM_STATUS);
unsigned int nblocks = nanddev_neraseblocks(nand); unsigned int nblocks = nanddev_neraseblocks(nand);
unsigned int nwords = DIV_ROUND_UP(nblocks * bits_per_block,
BITS_PER_LONG);
nand->bbt.cache = kcalloc(nwords, sizeof(*nand->bbt.cache), nand->bbt.cache = bitmap_zalloc(nblocks * bits_per_block, GFP_KERNEL);
GFP_KERNEL);
if (!nand->bbt.cache) if (!nand->bbt.cache)
return -ENOMEM; return -ENOMEM;
...@@ -44,7 +41,7 @@ EXPORT_SYMBOL_GPL(nanddev_bbt_init); ...@@ -44,7 +41,7 @@ EXPORT_SYMBOL_GPL(nanddev_bbt_init);
*/ */
void nanddev_bbt_cleanup(struct nand_device *nand) void nanddev_bbt_cleanup(struct nand_device *nand)
{ {
kfree(nand->bbt.cache); bitmap_free(nand->bbt.cache);
} }
EXPORT_SYMBOL_GPL(nanddev_bbt_cleanup); EXPORT_SYMBOL_GPL(nanddev_bbt_cleanup);
......
...@@ -200,27 +200,7 @@ config MTD_NAND_TMIO ...@@ -200,27 +200,7 @@ config MTD_NAND_TMIO
Support for NAND flash connected to a Toshiba Mobile IO Support for NAND flash connected to a Toshiba Mobile IO
Controller in some PDAs, including the Sharp SL6000x. Controller in some PDAs, including the Sharp SL6000x.
config MTD_NAND_BRCMNAND source "drivers/mtd/nand/raw/brcmnand/Kconfig"
tristate "Broadcom STB NAND controller"
depends on ARM || ARM64 || MIPS || COMPILE_TEST
depends on HAS_IOMEM
help
Enables the Broadcom NAND controller driver. The controller was
originally designed for Set-Top Box but is used on various BCM7xxx,
BCM3xxx, BCM63xxx, iProc/Cygnus and more.
if MTD_NAND_BRCMNAND
config MTD_NAND_BRCMNAND_BCMA
tristate "Broadcom BCMA NAND controller"
depends on BCMA_NFLASH
depends on BCMA
help
Enables the BRCMNAND controller over BCMA on BCM47186/BCM5358 SoCs.
The glue driver will take care of performing the low-level I/O
operations to interface the BRCMNAND controller over the BCMA bus.
endif # MTD_NAND_BRCMNAND
config MTD_NAND_BCM47XXNFLASH config MTD_NAND_BCM47XXNFLASH
tristate "BCM4706 BCMA NAND controller" tristate "BCM4706 BCMA NAND controller"
...@@ -410,7 +390,7 @@ config MTD_NAND_STM32_FMC2 ...@@ -410,7 +390,7 @@ config MTD_NAND_STM32_FMC2
config MTD_NAND_MESON config MTD_NAND_MESON
tristate "Support for NAND controller on Amlogic's Meson SoCs" tristate "Support for NAND controller on Amlogic's Meson SoCs"
depends on ARCH_MESON || COMPILE_TEST depends on COMMON_CLK && (ARCH_MESON || COMPILE_TEST)
select MFD_SYSCON select MFD_SYSCON
help help
Enables support for NAND controller on Amlogic's Meson SoCs. Enables support for NAND controller on Amlogic's Meson SoCs.
......
...@@ -915,7 +915,7 @@ static int anfc_check_op(struct nand_chip *chip, ...@@ -915,7 +915,7 @@ static int anfc_check_op(struct nand_chip *chip,
if (instr->ctx.data.len > ANFC_MAX_CHUNK_SIZE) if (instr->ctx.data.len > ANFC_MAX_CHUNK_SIZE)
return -ENOTSUPP; return -ENOTSUPP;
if (anfc_pkt_len_config(instr->ctx.data.len, 0, 0)) if (anfc_pkt_len_config(instr->ctx.data.len, NULL, NULL))
return -ENOTSUPP; return -ENOTSUPP;
break; break;
......
...@@ -405,6 +405,7 @@ static int atmel_nand_dma_transfer(struct atmel_nand_controller *nc, ...@@ -405,6 +405,7 @@ static int atmel_nand_dma_transfer(struct atmel_nand_controller *nc,
dma_async_issue_pending(nc->dmac); dma_async_issue_pending(nc->dmac);
wait_for_completion(&finished); wait_for_completion(&finished);
dma_unmap_single(nc->dev, buf_dma, len, dir);
return 0; return 0;
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
#include <linux/bcma/bcma.h> #include <linux/bcma/bcma.h>
/* Broadcom uses 1'000'000 but it seems to be too many. Tests on WNDR4500 has /* Broadcom uses 1'000'000 but it seems to be too many. Tests on WNDR4500 has
* shown ~1000 retries as maxiumum. */ * shown ~1000 retries as maximum. */
#define NFLASH_READY_RETRIES 10000 #define NFLASH_READY_RETRIES 10000
#define NFLASH_SECTOR_SIZE 512 #define NFLASH_SECTOR_SIZE 512
......
config MTD_NAND_BRCMNAND
tristate "Broadcom STB NAND controller"
depends on ARM || ARM64 || MIPS || COMPILE_TEST
depends on HAS_IOMEM
help
Enables the Broadcom NAND controller driver. The controller was
originally designed for Set-Top Box but is used on various BCM7xxx,
BCM3xxx, BCM63xxx, iProc/Cygnus and more.
if MTD_NAND_BRCMNAND
config MTD_NAND_BRCMNAND_BCM63XX
tristate "Broadcom BCM63xx NAND controller glue"
default BCM63XX
help
Enables the BRCMNAND glue driver to register the NAND controller
on Broadcom BCM63xx MIPS-based DSL platforms.
config MTD_NAND_BRCMNAND_BCMA
tristate "Broadcom BCMA NAND controller"
depends on BCMA_NFLASH
depends on BCMA
help
Enables the BRCMNAND controller over BCMA on BCM47186/BCM5358 SoCs.
The glue driver will take care of performing the low-level I/O
operations to interface the BRCMNAND controller over the BCMA bus.
config MTD_NAND_BRCMNAND_BCMBCA
tristate "Broadcom BCMBCA NAND controller glue"
default ARCH_BCMBCA
help
Enables the BRCMNAND glue driver to register the NAND controller
on Broadcom BCA platforms.
config MTD_NAND_BRCMNAND_BRCMSTB
tristate "Broadcom STB Nand controller glue"
default ARCH_BRCMSTB
help
Enables the BRCMNAND glue driver to register the NAND controller
on Broadcom STB platforms.
config MTD_NAND_BRCMNAND_IPROC
tristate "Broadcom iProc NAND controller glue"
default ARCH_BCM_IPROC
help
Enables the BRCMNAND controller glue driver to register the NAND
controller on Broadcom iProc platforms.
endif # MTD_NAND_BRCMNAND
# SPDX-License-Identifier: GPL-2.0 # SPDX-License-Identifier: GPL-2.0
# link order matters; don't link the more generic brcmstb_nand.o before the # link order matters; don't link the more generic brcmstb_nand.o before the
# more specific iproc_nand.o, for instance # more specific iproc_nand.o, for instance
obj-$(CONFIG_MTD_NAND_BRCMNAND) += iproc_nand.o obj-$(CONFIG_MTD_NAND_BRCMNAND_IPROC) += iproc_nand.o
obj-$(CONFIG_MTD_NAND_BRCMNAND) += bcm63138_nand.o obj-$(CONFIG_MTD_NAND_BRCMNAND_BCMBCA) += bcm63138_nand.o
obj-$(CONFIG_MTD_NAND_BRCMNAND) += bcm6368_nand.o obj-$(CONFIG_MTD_NAND_BRCMNAND_BCM63XX) += bcm6368_nand.o
obj-$(CONFIG_MTD_NAND_BRCMNAND) += brcmstb_nand.o obj-$(CONFIG_MTD_NAND_BRCMNAND_BRCMSTB) += brcmstb_nand.o
obj-$(CONFIG_MTD_NAND_BRCMNAND) += brcmnand.o obj-$(CONFIG_MTD_NAND_BRCMNAND) += brcmnand.o
obj-$(CONFIG_MTD_NAND_BRCMNAND_BCMA) += bcma_nand.o obj-$(CONFIG_MTD_NAND_BRCMNAND_BCMA) += bcma_nand.o
...@@ -1979,7 +1979,6 @@ static int cadence_nand_force_byte_access(struct nand_chip *chip, ...@@ -1979,7 +1979,6 @@ static int cadence_nand_force_byte_access(struct nand_chip *chip,
bool force_8bit) bool force_8bit)
{ {
struct cdns_nand_ctrl *cdns_ctrl = to_cdns_nand_ctrl(chip->controller); struct cdns_nand_ctrl *cdns_ctrl = to_cdns_nand_ctrl(chip->controller);
int status;
/* /*
* Callers of this function do not verify if the NAND is using a 16-bit * Callers of this function do not verify if the NAND is using a 16-bit
...@@ -1990,9 +1989,7 @@ static int cadence_nand_force_byte_access(struct nand_chip *chip, ...@@ -1990,9 +1989,7 @@ static int cadence_nand_force_byte_access(struct nand_chip *chip,
if (!(chip->options & NAND_BUSWIDTH_16)) if (!(chip->options & NAND_BUSWIDTH_16))
return 0; return 0;
status = cadence_nand_set_access_width16(cdns_ctrl, !force_8bit); return cadence_nand_set_access_width16(cdns_ctrl, !force_8bit);
return status;
} }
static int cadence_nand_cmd_opcode(struct nand_chip *chip, static int cadence_nand_cmd_opcode(struct nand_chip *chip,
......
...@@ -358,7 +358,7 @@ static int cafe_nand_read_oob(struct nand_chip *chip, int page) ...@@ -358,7 +358,7 @@ static int cafe_nand_read_oob(struct nand_chip *chip, int page)
return nand_read_oob_op(chip, page, 0, chip->oob_poi, mtd->oobsize); return nand_read_oob_op(chip, page, 0, chip->oob_poi, mtd->oobsize);
} }
/** /**
* cafe_nand_read_page_syndrome - [REPLACEABLE] hardware ecc syndrome based page read * cafe_nand_read_page - [REPLACEABLE] hardware ecc syndrome based page read
* @chip: nand chip info structure * @chip: nand chip info structure
* @buf: buffer to store read data * @buf: buffer to store read data
* @oob_required: caller expects OOB data read to chip->oob_poi * @oob_required: caller expects OOB data read to chip->oob_poi
......
...@@ -726,36 +726,40 @@ static int fsl_elbc_attach_chip(struct nand_chip *chip) ...@@ -726,36 +726,40 @@ static int fsl_elbc_attach_chip(struct nand_chip *chip)
struct fsl_lbc_regs __iomem *lbc = ctrl->regs; struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
unsigned int al; unsigned int al;
switch (chip->ecc.engine_type) {
/* /*
* if ECC was not chosen in DT, decide whether to use HW or SW ECC from * if ECC was not chosen in DT, decide whether to use HW or SW ECC from
* CS Base Register * CS Base Register
*/ */
case NAND_ECC_ENGINE_TYPE_NONE: if (chip->ecc.engine_type == NAND_ECC_ENGINE_TYPE_INVALID) {
/* If CS Base Register selects full hardware ECC then use it */ /* If CS Base Register selects full hardware ECC then use it */
if ((in_be32(&lbc->bank[priv->bank].br) & BR_DECC) == if ((in_be32(&lbc->bank[priv->bank].br) & BR_DECC) ==
BR_DECC_CHK_GEN) { BR_DECC_CHK_GEN) {
chip->ecc.read_page = fsl_elbc_read_page;
chip->ecc.write_page = fsl_elbc_write_page;
chip->ecc.write_subpage = fsl_elbc_write_subpage;
chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_ON_HOST; chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_ON_HOST;
mtd_set_ooblayout(mtd, &fsl_elbc_ooblayout_ops);
chip->ecc.size = 512;
chip->ecc.bytes = 3;
chip->ecc.strength = 1;
} else { } else {
/* otherwise fall back to default software ECC */ /* otherwise fall back to default software ECC */
chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT; chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT;
chip->ecc.algo = NAND_ECC_ALGO_HAMMING; chip->ecc.algo = NAND_ECC_ALGO_HAMMING;
} }
}
switch (chip->ecc.engine_type) {
/* if HW ECC was chosen, setup ecc and oob layout */
case NAND_ECC_ENGINE_TYPE_ON_HOST:
chip->ecc.read_page = fsl_elbc_read_page;
chip->ecc.write_page = fsl_elbc_write_page;
chip->ecc.write_subpage = fsl_elbc_write_subpage;
mtd_set_ooblayout(mtd, &fsl_elbc_ooblayout_ops);
chip->ecc.size = 512;
chip->ecc.bytes = 3;
chip->ecc.strength = 1;
break; break;
/* if SW ECC was chosen in DT, we do not need to set anything here */ /* if none or SW ECC was chosen, we do not need to set anything here */
case NAND_ECC_ENGINE_TYPE_NONE:
case NAND_ECC_ENGINE_TYPE_SOFT: case NAND_ECC_ENGINE_TYPE_SOFT:
case NAND_ECC_ENGINE_TYPE_ON_DIE:
break; break;
/* should we also implement *_ECC_ENGINE_CONTROLLER to do as above? */
default: default:
return -EINVAL; return -EINVAL;
} }
......
...@@ -1361,7 +1361,7 @@ static int gpmi_alloc_dma_buffer(struct gpmi_nand_data *this) ...@@ -1361,7 +1361,7 @@ static int gpmi_alloc_dma_buffer(struct gpmi_nand_data *this)
/* /*
* Handles block mark swapping. * Handles block mark swapping.
* It can be called in swapping the block mark, or swapping it back, * It can be called in swapping the block mark, or swapping it back,
* because the the operations are the same. * because the operations are the same.
*/ */
static void block_mark_swapping(struct gpmi_nand_data *this, static void block_mark_swapping(struct gpmi_nand_data *this,
void *payload, void *auxiliary) void *payload, void *auxiliary)
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include <linux/mtd/rawnand.h> #include <linux/mtd/rawnand.h>
#include <linux/mtd/nand.h> #include <linux/mtd/nand.h>
#include <linux/of.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/slab.h> #include <linux/slab.h>
...@@ -99,15 +100,12 @@ ...@@ -99,15 +100,12 @@
#define HSNAND_ECC_OFFSET 0x008 #define HSNAND_ECC_OFFSET 0x008
#define NAND_DATA_IFACE_CHECK_ONLY -1
#define MAX_CS 2 #define MAX_CS 2
#define USEC_PER_SEC 1000000L #define USEC_PER_SEC 1000000L
struct ebu_nand_cs { struct ebu_nand_cs {
void __iomem *chipaddr; void __iomem *chipaddr;
dma_addr_t nand_pa;
u32 addr_sel; u32 addr_sel;
}; };
...@@ -120,7 +118,6 @@ struct ebu_nand_controller { ...@@ -120,7 +118,6 @@ struct ebu_nand_controller {
struct dma_chan *dma_tx; struct dma_chan *dma_tx;
struct dma_chan *dma_rx; struct dma_chan *dma_rx;
struct completion dma_access_complete; struct completion dma_access_complete;
unsigned long clk_rate;
struct clk *clk; struct clk *clk;
u32 nd_para0; u32 nd_para0;
u8 cs_num; u8 cs_num;
...@@ -580,6 +577,7 @@ static int ebu_nand_probe(struct platform_device *pdev) ...@@ -580,6 +577,7 @@ static int ebu_nand_probe(struct platform_device *pdev)
{ {
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct ebu_nand_controller *ebu_host; struct ebu_nand_controller *ebu_host;
struct device_node *chip_np;
struct nand_chip *nand; struct nand_chip *nand;
struct mtd_info *mtd; struct mtd_info *mtd;
struct resource *res; struct resource *res;
...@@ -594,17 +592,20 @@ static int ebu_nand_probe(struct platform_device *pdev) ...@@ -594,17 +592,20 @@ static int ebu_nand_probe(struct platform_device *pdev)
ebu_host->dev = dev; ebu_host->dev = dev;
nand_controller_init(&ebu_host->controller); nand_controller_init(&ebu_host->controller);
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ebunand"); ebu_host->ebu = devm_platform_ioremap_resource_byname(pdev, "ebunand");
ebu_host->ebu = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(ebu_host->ebu)) if (IS_ERR(ebu_host->ebu))
return PTR_ERR(ebu_host->ebu); return PTR_ERR(ebu_host->ebu);
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "hsnand"); ebu_host->hsnand = devm_platform_ioremap_resource_byname(pdev, "hsnand");
ebu_host->hsnand = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(ebu_host->hsnand)) if (IS_ERR(ebu_host->hsnand))
return PTR_ERR(ebu_host->hsnand); return PTR_ERR(ebu_host->hsnand);
ret = device_property_read_u32(dev, "reg", &cs); chip_np = of_get_next_child(dev->of_node, NULL);
if (!chip_np)
return dev_err_probe(dev, -EINVAL,
"Could not find child node for the NAND chip\n");
ret = of_property_read_u32(chip_np, "reg", &cs);
if (ret) { if (ret) {
dev_err(dev, "failed to get chip select: %d\n", ret); dev_err(dev, "failed to get chip select: %d\n", ret);
return ret; return ret;
...@@ -617,11 +618,10 @@ static int ebu_nand_probe(struct platform_device *pdev) ...@@ -617,11 +618,10 @@ static int ebu_nand_probe(struct platform_device *pdev)
ebu_host->cs_num = cs; ebu_host->cs_num = cs;
resname = devm_kasprintf(dev, GFP_KERNEL, "nand_cs%d", cs); resname = devm_kasprintf(dev, GFP_KERNEL, "nand_cs%d", cs);
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, resname); ebu_host->cs[cs].chipaddr = devm_platform_ioremap_resource_byname(pdev,
ebu_host->cs[cs].chipaddr = devm_ioremap_resource(dev, res); resname);
if (IS_ERR(ebu_host->cs[cs].chipaddr)) if (IS_ERR(ebu_host->cs[cs].chipaddr))
return PTR_ERR(ebu_host->cs[cs].chipaddr); return PTR_ERR(ebu_host->cs[cs].chipaddr);
ebu_host->cs[cs].nand_pa = res->start;
ebu_host->clk = devm_clk_get(dev, NULL); ebu_host->clk = devm_clk_get(dev, NULL);
if (IS_ERR(ebu_host->clk)) if (IS_ERR(ebu_host->clk))
...@@ -633,7 +633,6 @@ static int ebu_nand_probe(struct platform_device *pdev) ...@@ -633,7 +633,6 @@ static int ebu_nand_probe(struct platform_device *pdev)
dev_err(dev, "failed to enable clock: %d\n", ret); dev_err(dev, "failed to enable clock: %d\n", ret);
return ret; return ret;
} }
ebu_host->clk_rate = clk_get_rate(ebu_host->clk);
ebu_host->dma_tx = dma_request_chan(dev, "tx"); ebu_host->dma_tx = dma_request_chan(dev, "tx");
if (IS_ERR(ebu_host->dma_tx)) { if (IS_ERR(ebu_host->dma_tx)) {
...@@ -660,7 +659,7 @@ static int ebu_nand_probe(struct platform_device *pdev) ...@@ -660,7 +659,7 @@ static int ebu_nand_probe(struct platform_device *pdev)
writel(ebu_host->cs[cs].addr_sel | EBU_ADDR_MASK(5) | EBU_ADDR_SEL_REGEN, writel(ebu_host->cs[cs].addr_sel | EBU_ADDR_MASK(5) | EBU_ADDR_SEL_REGEN,
ebu_host->ebu + EBU_ADDR_SEL(cs)); ebu_host->ebu + EBU_ADDR_SEL(cs));
nand_set_flash_node(&ebu_host->chip, dev->of_node); nand_set_flash_node(&ebu_host->chip, chip_np);
mtd = nand_to_mtd(&ebu_host->chip); mtd = nand_to_mtd(&ebu_host->chip);
if (!mtd->name) { if (!mtd->name) {
...@@ -716,7 +715,6 @@ static int ebu_nand_remove(struct platform_device *pdev) ...@@ -716,7 +715,6 @@ static int ebu_nand_remove(struct platform_device *pdev)
} }
static const struct of_device_id ebu_nand_match[] = { static const struct of_device_id ebu_nand_match[] = {
{ .compatible = "intel,nand-controller" },
{ .compatible = "intel,lgm-ebunand" }, { .compatible = "intel,lgm-ebunand" },
{} {}
}; };
......
...@@ -865,13 +865,19 @@ static int marvell_nfc_xfer_data_dma(struct marvell_nfc *nfc, ...@@ -865,13 +865,19 @@ static int marvell_nfc_xfer_data_dma(struct marvell_nfc *nfc,
marvell_nfc_enable_dma(nfc); marvell_nfc_enable_dma(nfc);
/* Prepare the DMA transfer */ /* Prepare the DMA transfer */
sg_init_one(&sg, nfc->dma_buf, dma_len); sg_init_one(&sg, nfc->dma_buf, dma_len);
dma_map_sg(nfc->dma_chan->device->dev, &sg, 1, direction); ret = dma_map_sg(nfc->dma_chan->device->dev, &sg, 1, direction);
if (!ret) {
dev_err(nfc->dev, "Could not map DMA S/G list\n");
return -ENXIO;
}
tx = dmaengine_prep_slave_sg(nfc->dma_chan, &sg, 1, tx = dmaengine_prep_slave_sg(nfc->dma_chan, &sg, 1,
direction == DMA_FROM_DEVICE ? direction == DMA_FROM_DEVICE ?
DMA_DEV_TO_MEM : DMA_MEM_TO_DEV, DMA_DEV_TO_MEM : DMA_MEM_TO_DEV,
DMA_PREP_INTERRUPT); DMA_PREP_INTERRUPT);
if (!tx) { if (!tx) {
dev_err(nfc->dev, "Could not prepare DMA S/G list\n"); dev_err(nfc->dev, "Could not prepare DMA S/G list\n");
dma_unmap_sg(nfc->dma_chan->device->dev, &sg, 1, direction);
return -ENXIO; return -ENXIO;
} }
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/mtd/rawnand.h> #include <linux/mtd/rawnand.h>
#include <linux/mtd/mtd.h> #include <linux/mtd/mtd.h>
#include <linux/mfd/syscon.h> #include <linux/mfd/syscon.h>
...@@ -56,6 +57,9 @@ ...@@ -56,6 +57,9 @@
#define NFC_RB_IRQ_EN BIT(21) #define NFC_RB_IRQ_EN BIT(21)
#define CLK_DIV_SHIFT 0
#define CLK_DIV_WIDTH 6
#define CMDRWGEN(cmd_dir, ran, bch, short_mode, page_size, pages) \ #define CMDRWGEN(cmd_dir, ran, bch, short_mode, page_size, pages) \
( \ ( \
(cmd_dir) | \ (cmd_dir) | \
...@@ -151,15 +155,15 @@ struct meson_nfc { ...@@ -151,15 +155,15 @@ struct meson_nfc {
struct nand_controller controller; struct nand_controller controller;
struct clk *core_clk; struct clk *core_clk;
struct clk *device_clk; struct clk *device_clk;
struct clk *phase_tx; struct clk *nand_clk;
struct clk *phase_rx; struct clk_divider nand_divider;
unsigned long clk_rate; unsigned long clk_rate;
u32 bus_timing; u32 bus_timing;
struct device *dev; struct device *dev;
void __iomem *reg_base; void __iomem *reg_base;
struct regmap *reg_clk; void __iomem *reg_clk;
struct completion completion; struct completion completion;
struct list_head chips; struct list_head chips;
const struct meson_nfc_data *data; const struct meson_nfc_data *data;
...@@ -235,7 +239,7 @@ static void meson_nfc_select_chip(struct nand_chip *nand, int chip) ...@@ -235,7 +239,7 @@ static void meson_nfc_select_chip(struct nand_chip *nand, int chip)
nfc->timing.tbers_max = meson_chip->tbers_max; nfc->timing.tbers_max = meson_chip->tbers_max;
if (nfc->clk_rate != meson_chip->clk_rate) { if (nfc->clk_rate != meson_chip->clk_rate) {
ret = clk_set_rate(nfc->device_clk, meson_chip->clk_rate); ret = clk_set_rate(nfc->nand_clk, meson_chip->clk_rate);
if (ret) { if (ret) {
dev_err(nfc->dev, "failed to set clock rate\n"); dev_err(nfc->dev, "failed to set clock rate\n");
return; return;
...@@ -454,7 +458,7 @@ static int meson_nfc_ecc_correct(struct nand_chip *nand, u32 *bitflips, ...@@ -454,7 +458,7 @@ static int meson_nfc_ecc_correct(struct nand_chip *nand, u32 *bitflips,
if (ECC_ERR_CNT(*info) != ECC_UNCORRECTABLE) { if (ECC_ERR_CNT(*info) != ECC_UNCORRECTABLE) {
mtd->ecc_stats.corrected += ECC_ERR_CNT(*info); mtd->ecc_stats.corrected += ECC_ERR_CNT(*info);
*bitflips = max_t(u32, *bitflips, ECC_ERR_CNT(*info)); *bitflips = max_t(u32, *bitflips, ECC_ERR_CNT(*info));
*correct_bitmap |= 1 >> i; *correct_bitmap |= BIT_ULL(i);
continue; continue;
} }
if ((nand->options & NAND_NEED_SCRAMBLING) && if ((nand->options & NAND_NEED_SCRAMBLING) &&
...@@ -800,7 +804,7 @@ static int meson_nfc_read_page_hwecc(struct nand_chip *nand, u8 *buf, ...@@ -800,7 +804,7 @@ static int meson_nfc_read_page_hwecc(struct nand_chip *nand, u8 *buf,
u8 *data = buf + i * ecc->size; u8 *data = buf + i * ecc->size;
u8 *oob = nand->oob_poi + i * (ecc->bytes + 2); u8 *oob = nand->oob_poi + i * (ecc->bytes + 2);
if (correct_bitmap & (1 << i)) if (correct_bitmap & BIT_ULL(i))
continue; continue;
ret = nand_check_erased_ecc_chunk(data, ecc->size, ret = nand_check_erased_ecc_chunk(data, ecc->size,
oob, ecc->bytes + 2, oob, ecc->bytes + 2,
...@@ -987,6 +991,8 @@ static const struct mtd_ooblayout_ops meson_ooblayout_ops = { ...@@ -987,6 +991,8 @@ static const struct mtd_ooblayout_ops meson_ooblayout_ops = {
static int meson_nfc_clk_init(struct meson_nfc *nfc) static int meson_nfc_clk_init(struct meson_nfc *nfc)
{ {
struct clk_parent_data nfc_divider_parent_data[1];
struct clk_init_data init = {0};
int ret; int ret;
/* request core clock */ /* request core clock */
...@@ -1002,21 +1008,28 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc) ...@@ -1002,21 +1008,28 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
return PTR_ERR(nfc->device_clk); return PTR_ERR(nfc->device_clk);
} }
nfc->phase_tx = devm_clk_get(nfc->dev, "tx"); init.name = devm_kasprintf(nfc->dev,
if (IS_ERR(nfc->phase_tx)) { GFP_KERNEL, "%s#div",
dev_err(nfc->dev, "failed to get TX clk\n"); dev_name(nfc->dev));
return PTR_ERR(nfc->phase_tx); init.ops = &clk_divider_ops;
} nfc_divider_parent_data[0].fw_name = "device";
init.parent_data = nfc_divider_parent_data;
nfc->phase_rx = devm_clk_get(nfc->dev, "rx"); init.num_parents = 1;
if (IS_ERR(nfc->phase_rx)) { nfc->nand_divider.reg = nfc->reg_clk;
dev_err(nfc->dev, "failed to get RX clk\n"); nfc->nand_divider.shift = CLK_DIV_SHIFT;
return PTR_ERR(nfc->phase_rx); nfc->nand_divider.width = CLK_DIV_WIDTH;
} nfc->nand_divider.hw.init = &init;
nfc->nand_divider.flags = CLK_DIVIDER_ONE_BASED |
CLK_DIVIDER_ROUND_CLOSEST |
CLK_DIVIDER_ALLOW_ZERO;
nfc->nand_clk = devm_clk_register(nfc->dev, &nfc->nand_divider.hw);
if (IS_ERR(nfc->nand_clk))
return PTR_ERR(nfc->nand_clk);
/* init SD_EMMC_CLOCK to sane defaults w/min clock rate */ /* init SD_EMMC_CLOCK to sane defaults w/min clock rate */
regmap_update_bits(nfc->reg_clk, writel(CLK_SELECT_NAND | readl(nfc->reg_clk),
0, CLK_SELECT_NAND, CLK_SELECT_NAND); nfc->reg_clk);
ret = clk_prepare_enable(nfc->core_clk); ret = clk_prepare_enable(nfc->core_clk);
if (ret) { if (ret) {
...@@ -1030,29 +1043,21 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc) ...@@ -1030,29 +1043,21 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
goto err_device_clk; goto err_device_clk;
} }
ret = clk_prepare_enable(nfc->phase_tx); ret = clk_prepare_enable(nfc->nand_clk);
if (ret) { if (ret) {
dev_err(nfc->dev, "failed to enable TX clock\n"); dev_err(nfc->dev, "pre enable NFC divider fail\n");
goto err_phase_tx; goto err_nand_clk;
} }
ret = clk_prepare_enable(nfc->phase_rx); ret = clk_set_rate(nfc->nand_clk, 24000000);
if (ret) {
dev_err(nfc->dev, "failed to enable RX clock\n");
goto err_phase_rx;
}
ret = clk_set_rate(nfc->device_clk, 24000000);
if (ret) if (ret)
goto err_disable_rx; goto err_disable_clk;
return 0; return 0;
err_disable_rx: err_disable_clk:
clk_disable_unprepare(nfc->phase_rx); clk_disable_unprepare(nfc->nand_clk);
err_phase_rx: err_nand_clk:
clk_disable_unprepare(nfc->phase_tx);
err_phase_tx:
clk_disable_unprepare(nfc->device_clk); clk_disable_unprepare(nfc->device_clk);
err_device_clk: err_device_clk:
clk_disable_unprepare(nfc->core_clk); clk_disable_unprepare(nfc->core_clk);
...@@ -1061,8 +1066,7 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc) ...@@ -1061,8 +1066,7 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
static void meson_nfc_disable_clk(struct meson_nfc *nfc) static void meson_nfc_disable_clk(struct meson_nfc *nfc)
{ {
clk_disable_unprepare(nfc->phase_rx); clk_disable_unprepare(nfc->nand_clk);
clk_disable_unprepare(nfc->phase_tx);
clk_disable_unprepare(nfc->device_clk); clk_disable_unprepare(nfc->device_clk);
clk_disable_unprepare(nfc->core_clk); clk_disable_unprepare(nfc->core_clk);
} }
...@@ -1368,7 +1372,6 @@ static int meson_nfc_probe(struct platform_device *pdev) ...@@ -1368,7 +1372,6 @@ static int meson_nfc_probe(struct platform_device *pdev)
{ {
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct meson_nfc *nfc; struct meson_nfc *nfc;
struct resource *res;
int ret, irq; int ret, irq;
nfc = devm_kzalloc(dev, sizeof(*nfc), GFP_KERNEL); nfc = devm_kzalloc(dev, sizeof(*nfc), GFP_KERNEL);
...@@ -1385,18 +1388,13 @@ static int meson_nfc_probe(struct platform_device *pdev) ...@@ -1385,18 +1388,13 @@ static int meson_nfc_probe(struct platform_device *pdev)
nfc->dev = dev; nfc->dev = dev;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); nfc->reg_base = devm_platform_ioremap_resource_byname(pdev, "nfc");
nfc->reg_base = devm_ioremap_resource(dev, res);
if (IS_ERR(nfc->reg_base)) if (IS_ERR(nfc->reg_base))
return PTR_ERR(nfc->reg_base); return PTR_ERR(nfc->reg_base);
nfc->reg_clk = nfc->reg_clk = devm_platform_ioremap_resource_byname(pdev, "emmc");
syscon_regmap_lookup_by_phandle(dev->of_node, if (IS_ERR(nfc->reg_clk))
"amlogic,mmc-syscon");
if (IS_ERR(nfc->reg_clk)) {
dev_err(dev, "Failed to lookup clock base\n");
return PTR_ERR(nfc->reg_clk); return PTR_ERR(nfc->reg_clk);
}
irq = platform_get_irq(pdev, 0); irq = platform_get_irq(pdev, 0);
if (irq < 0) if (irq < 0)
......
...@@ -335,8 +335,6 @@ static int nand_isbad_bbm(struct nand_chip *chip, loff_t ofs) ...@@ -335,8 +335,6 @@ static int nand_isbad_bbm(struct nand_chip *chip, loff_t ofs)
* @chip: NAND chip structure * @chip: NAND chip structure
* *
* Lock the device and its controller for exclusive access * Lock the device and its controller for exclusive access
*
* Return: -EBUSY if the chip has been suspended, 0 otherwise
*/ */
static void nand_get_device(struct nand_chip *chip) static void nand_get_device(struct nand_chip *chip)
{ {
...@@ -5341,11 +5339,10 @@ static int of_get_nand_secure_regions(struct nand_chip *chip) ...@@ -5341,11 +5339,10 @@ static int of_get_nand_secure_regions(struct nand_chip *chip)
int rawnand_dt_parse_gpio_cs(struct device *dev, struct gpio_desc ***cs_array, int rawnand_dt_parse_gpio_cs(struct device *dev, struct gpio_desc ***cs_array,
unsigned int *ncs_array) unsigned int *ncs_array)
{ {
struct device_node *np = dev->of_node;
struct gpio_desc **descs; struct gpio_desc **descs;
int ndescs, i; int ndescs, i;
ndescs = of_gpio_named_count(np, "cs-gpios"); ndescs = gpiod_count(dev, "cs");
if (ndescs < 0) { if (ndescs < 0) {
dev_dbg(dev, "No valid cs-gpios property\n"); dev_dbg(dev, "No valid cs-gpios property\n");
return 0; return 0;
......
...@@ -170,18 +170,11 @@ static int __init orion_nand_probe(struct platform_device *pdev) ...@@ -170,18 +170,11 @@ static int __init orion_nand_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, info); platform_set_drvdata(pdev, info);
/* Not all platforms can gate the clock, so it is not /* Not all platforms can gate the clock, so it is optional. */
an error if the clock does not exists. */ info->clk = devm_clk_get_optional(&pdev->dev, NULL);
info->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(info->clk))
if (IS_ERR(info->clk)) { return dev_err_probe(&pdev->dev, PTR_ERR(info->clk),
ret = PTR_ERR(info->clk); "failed to get clock!\n");
if (ret == -ENOENT) {
info->clk = NULL;
} else {
dev_err(&pdev->dev, "failed to get clock!\n");
return ret;
}
}
ret = clk_prepare_enable(info->clk); ret = clk_prepare_enable(info->clk);
if (ret) { if (ret) {
......
...@@ -862,8 +862,8 @@ static int stm32_fmc2_nfc_xfer(struct nand_chip *chip, const u8 *buf, ...@@ -862,8 +862,8 @@ static int stm32_fmc2_nfc_xfer(struct nand_chip *chip, const u8 *buf,
ret = dma_map_sg(nfc->dev, nfc->dma_data_sg.sgl, ret = dma_map_sg(nfc->dev, nfc->dma_data_sg.sgl,
eccsteps, dma_data_dir); eccsteps, dma_data_dir);
if (ret < 0) if (!ret)
return ret; return -EIO;
desc_data = dmaengine_prep_slave_sg(dma_ch, nfc->dma_data_sg.sgl, desc_data = dmaengine_prep_slave_sg(dma_ch, nfc->dma_data_sg.sgl,
eccsteps, dma_transfer_dir, eccsteps, dma_transfer_dir,
...@@ -893,8 +893,10 @@ static int stm32_fmc2_nfc_xfer(struct nand_chip *chip, const u8 *buf, ...@@ -893,8 +893,10 @@ static int stm32_fmc2_nfc_xfer(struct nand_chip *chip, const u8 *buf,
ret = dma_map_sg(nfc->dev, nfc->dma_ecc_sg.sgl, ret = dma_map_sg(nfc->dev, nfc->dma_ecc_sg.sgl,
eccsteps, dma_data_dir); eccsteps, dma_data_dir);
if (ret < 0) if (!ret) {
ret = -EIO;
goto err_unmap_data; goto err_unmap_data;
}
desc_ecc = dmaengine_prep_slave_sg(nfc->dma_ecc_ch, desc_ecc = dmaengine_prep_slave_sg(nfc->dma_ecc_ch,
nfc->dma_ecc_sg.sgl, nfc->dma_ecc_sg.sgl,
...@@ -1799,9 +1801,8 @@ static int stm32_fmc2_nfc_parse_child(struct stm32_fmc2_nfc *nfc, ...@@ -1799,9 +1801,8 @@ static int stm32_fmc2_nfc_parse_child(struct stm32_fmc2_nfc *nfc,
nand->cs_used[i] = cs; nand->cs_used[i] = cs;
} }
nand->wp_gpio = devm_gpiod_get_from_of_node(nfc->dev, dn, nand->wp_gpio = devm_fwnode_gpiod_get(nfc->dev, of_fwnode_handle(dn),
"wp-gpios", 0, "wp", GPIOD_OUT_HIGH, "wp");
GPIOD_OUT_HIGH, "wp");
if (IS_ERR(nand->wp_gpio)) { if (IS_ERR(nand->wp_gpio)) {
ret = PTR_ERR(nand->wp_gpio); ret = PTR_ERR(nand->wp_gpio);
if (ret != -ENOENT) if (ret != -ENOENT)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment