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 -----BEGIN PGP SIGNATURE----- iQEzBAABCgAdFiEE9HuaYnbmDhq/XIDIJWrqGEe9VoQFAmNAOvwACgkQJWrqGEe9 VoRNwQf9EqZu7zW/kWBi7cN9koCk/5YuKeCQi9KJhCf4MC9928BdEy5wwRYPkZPJ N1rTS4Fdx+nLDpULqcE9KYDSJZM09dGEHN7sFYwJR+zKRpBV5awfDvV8gWZp1Afk MLtC+AWO1GkJ/5V0Qmw0RX+0rtM9v+QpH25+nvJImBKt7iTfperpBDmO7S7htxhN xPKLj8A8Ns2LR/JirwHT2DRLwe/1UJwLxNfL/yzyWxekaqmRUNz2rYSQ56ZJAbc4 D9jotFRwdpaMIKkGuruYed2gM7rgbtzSaGLZNYuHzcLMKFocH9vLL7D3EAbovoDL D1l1saZDYsYpXkVwM4uKPWR/B8lgcg== =DvSB -----END PGP SIGNATURE----- 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: Miquel Raynal <miquel.raynal@bootlin.com>
This commit is contained in:
commit
63c30d7044
@ -1,60 +0,0 @@
|
||||
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;
|
||||
};
|
||||
};
|
@ -0,0 +1,93 @@
|
||||
# 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>;
|
||||
};
|
||||
};
|
||||
|
||||
...
|
@ -1,7 +1,7 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%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#
|
||||
|
||||
title: Intel LGM SoC NAND Controller Device Tree Bindings
|
||||
@ -14,7 +14,7 @@ maintainers:
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: intel,lgm-nand
|
||||
const: intel,lgm-ebunand
|
||||
|
||||
reg:
|
||||
maxItems: 6
|
||||
@ -51,7 +51,7 @@ patternProperties:
|
||||
properties:
|
||||
reg:
|
||||
minimum: 0
|
||||
maximum: 7
|
||||
maximum: 1
|
||||
|
||||
nand-ecc-mode: true
|
||||
|
||||
@ -75,7 +75,7 @@ additionalProperties: false
|
||||
examples:
|
||||
- |
|
||||
nand-controller@e0f00000 {
|
||||
compatible = "intel,lgm-nand";
|
||||
compatible = "intel,lgm-ebunand";
|
||||
reg = <0xe0f00000 0x100>,
|
||||
<0xe1000000 0x300>,
|
||||
<0xe1400000 0x8000>,
|
@ -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 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),
|
||||
GFP_KERNEL);
|
||||
nand->bbt.cache = bitmap_zalloc(nblocks * bits_per_block, GFP_KERNEL);
|
||||
if (!nand->bbt.cache)
|
||||
return -ENOMEM;
|
||||
|
||||
@ -44,7 +41,7 @@ EXPORT_SYMBOL_GPL(nanddev_bbt_init);
|
||||
*/
|
||||
void nanddev_bbt_cleanup(struct nand_device *nand)
|
||||
{
|
||||
kfree(nand->bbt.cache);
|
||||
bitmap_free(nand->bbt.cache);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nanddev_bbt_cleanup);
|
||||
|
||||
|
@ -200,27 +200,7 @@ config MTD_NAND_TMIO
|
||||
Support for NAND flash connected to a Toshiba Mobile IO
|
||||
Controller in some PDAs, including the Sharp SL6000x.
|
||||
|
||||
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_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
|
||||
source "drivers/mtd/nand/raw/brcmnand/Kconfig"
|
||||
|
||||
config MTD_NAND_BCM47XXNFLASH
|
||||
tristate "BCM4706 BCMA NAND controller"
|
||||
@ -410,7 +390,7 @@ config MTD_NAND_STM32_FMC2
|
||||
|
||||
config MTD_NAND_MESON
|
||||
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
|
||||
help
|
||||
Enables support for NAND controller on Amlogic's Meson SoCs.
|
||||
|
@ -915,7 +915,7 @@ static int anfc_check_op(struct nand_chip *chip,
|
||||
if (instr->ctx.data.len > ANFC_MAX_CHUNK_SIZE)
|
||||
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;
|
||||
|
||||
break;
|
||||
|
@ -405,6 +405,7 @@ static int atmel_nand_dma_transfer(struct atmel_nand_controller *nc,
|
||||
|
||||
dma_async_issue_pending(nc->dmac);
|
||||
wait_for_completion(&finished);
|
||||
dma_unmap_single(nc->dev, buf_dma, len, dir);
|
||||
|
||||
return 0;
|
||||
|
||||
|
@ -14,7 +14,7 @@
|
||||
#include <linux/bcma/bcma.h>
|
||||
|
||||
/* 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_SECTOR_SIZE 512
|
||||
|
49
drivers/mtd/nand/raw/brcmnand/Kconfig
Normal file
49
drivers/mtd/nand/raw/brcmnand/Kconfig
Normal file
@ -0,0 +1,49 @@
|
||||
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
|
@ -1,10 +1,10 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
# link order matters; don't link the more generic brcmstb_nand.o before the
|
||||
# more specific iproc_nand.o, for instance
|
||||
obj-$(CONFIG_MTD_NAND_BRCMNAND) += iproc_nand.o
|
||||
obj-$(CONFIG_MTD_NAND_BRCMNAND) += bcm63138_nand.o
|
||||
obj-$(CONFIG_MTD_NAND_BRCMNAND) += bcm6368_nand.o
|
||||
obj-$(CONFIG_MTD_NAND_BRCMNAND) += brcmstb_nand.o
|
||||
obj-$(CONFIG_MTD_NAND_BRCMNAND_IPROC) += iproc_nand.o
|
||||
obj-$(CONFIG_MTD_NAND_BRCMNAND_BCMBCA) += bcm63138_nand.o
|
||||
obj-$(CONFIG_MTD_NAND_BRCMNAND_BCM63XX) += bcm6368_nand.o
|
||||
obj-$(CONFIG_MTD_NAND_BRCMNAND_BRCMSTB) += brcmstb_nand.o
|
||||
obj-$(CONFIG_MTD_NAND_BRCMNAND) += brcmnand.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,
|
||||
bool force_8bit)
|
||||
{
|
||||
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
|
||||
@ -1990,9 +1989,7 @@ static int cadence_nand_force_byte_access(struct nand_chip *chip,
|
||||
if (!(chip->options & NAND_BUSWIDTH_16))
|
||||
return 0;
|
||||
|
||||
status = cadence_nand_set_access_width16(cdns_ctrl, !force_8bit);
|
||||
|
||||
return status;
|
||||
return cadence_nand_set_access_width16(cdns_ctrl, !force_8bit);
|
||||
}
|
||||
|
||||
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)
|
||||
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
|
||||
* @buf: buffer to store read data
|
||||
* @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)
|
||||
struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
|
||||
unsigned int al;
|
||||
|
||||
switch (chip->ecc.engine_type) {
|
||||
/*
|
||||
* if ECC was not chosen in DT, decide whether to use HW or SW ECC from
|
||||
* 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 ((in_be32(&lbc->bank[priv->bank].br) & BR_DECC) ==
|
||||
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;
|
||||
mtd_set_ooblayout(mtd, &fsl_elbc_ooblayout_ops);
|
||||
chip->ecc.size = 512;
|
||||
chip->ecc.bytes = 3;
|
||||
chip->ecc.strength = 1;
|
||||
} else {
|
||||
/* otherwise fall back to default software ECC */
|
||||
chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT;
|
||||
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;
|
||||
|
||||
/* 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_ON_DIE:
|
||||
break;
|
||||
|
||||
/* should we also implement *_ECC_ENGINE_CONTROLLER to do as above? */
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -1361,7 +1361,7 @@ error_alloc:
|
||||
/*
|
||||
* Handles block mark swapping.
|
||||
* 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,
|
||||
void *payload, void *auxiliary)
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include <linux/mtd/rawnand.h>
|
||||
#include <linux/mtd/nand.h>
|
||||
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/slab.h>
|
||||
@ -99,15 +100,12 @@
|
||||
|
||||
#define HSNAND_ECC_OFFSET 0x008
|
||||
|
||||
#define NAND_DATA_IFACE_CHECK_ONLY -1
|
||||
|
||||
#define MAX_CS 2
|
||||
|
||||
#define USEC_PER_SEC 1000000L
|
||||
|
||||
struct ebu_nand_cs {
|
||||
void __iomem *chipaddr;
|
||||
dma_addr_t nand_pa;
|
||||
u32 addr_sel;
|
||||
};
|
||||
|
||||
@ -120,7 +118,6 @@ struct ebu_nand_controller {
|
||||
struct dma_chan *dma_tx;
|
||||
struct dma_chan *dma_rx;
|
||||
struct completion dma_access_complete;
|
||||
unsigned long clk_rate;
|
||||
struct clk *clk;
|
||||
u32 nd_para0;
|
||||
u8 cs_num;
|
||||
@ -580,6 +577,7 @@ static int ebu_nand_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct ebu_nand_controller *ebu_host;
|
||||
struct device_node *chip_np;
|
||||
struct nand_chip *nand;
|
||||
struct mtd_info *mtd;
|
||||
struct resource *res;
|
||||
@ -594,17 +592,20 @@ static int ebu_nand_probe(struct platform_device *pdev)
|
||||
ebu_host->dev = dev;
|
||||
nand_controller_init(&ebu_host->controller);
|
||||
|
||||
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ebunand");
|
||||
ebu_host->ebu = devm_ioremap_resource(&pdev->dev, res);
|
||||
ebu_host->ebu = devm_platform_ioremap_resource_byname(pdev, "ebunand");
|
||||
if (IS_ERR(ebu_host->ebu))
|
||||
return PTR_ERR(ebu_host->ebu);
|
||||
|
||||
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "hsnand");
|
||||
ebu_host->hsnand = devm_ioremap_resource(&pdev->dev, res);
|
||||
ebu_host->hsnand = devm_platform_ioremap_resource_byname(pdev, "hsnand");
|
||||
if (IS_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) {
|
||||
dev_err(dev, "failed to get chip select: %d\n", ret);
|
||||
return ret;
|
||||
@ -617,11 +618,10 @@ static int ebu_nand_probe(struct platform_device *pdev)
|
||||
ebu_host->cs_num = 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_ioremap_resource(dev, res);
|
||||
ebu_host->cs[cs].chipaddr = devm_platform_ioremap_resource_byname(pdev,
|
||||
resname);
|
||||
if (IS_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);
|
||||
if (IS_ERR(ebu_host->clk))
|
||||
@ -633,7 +633,6 @@ static int ebu_nand_probe(struct platform_device *pdev)
|
||||
dev_err(dev, "failed to enable clock: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
ebu_host->clk_rate = clk_get_rate(ebu_host->clk);
|
||||
|
||||
ebu_host->dma_tx = dma_request_chan(dev, "tx");
|
||||
if (IS_ERR(ebu_host->dma_tx)) {
|
||||
@ -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,
|
||||
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);
|
||||
if (!mtd->name) {
|
||||
@ -716,7 +715,6 @@ static int ebu_nand_remove(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
static const struct of_device_id ebu_nand_match[] = {
|
||||
{ .compatible = "intel,nand-controller" },
|
||||
{ .compatible = "intel,lgm-ebunand" },
|
||||
{}
|
||||
};
|
||||
|
@ -865,13 +865,19 @@ static int marvell_nfc_xfer_data_dma(struct marvell_nfc *nfc,
|
||||
marvell_nfc_enable_dma(nfc);
|
||||
/* Prepare the DMA transfer */
|
||||
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,
|
||||
direction == DMA_FROM_DEVICE ?
|
||||
DMA_DEV_TO_MEM : DMA_MEM_TO_DEV,
|
||||
DMA_PREP_INTERRUPT);
|
||||
if (!tx) {
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/mtd/rawnand.h>
|
||||
#include <linux/mtd/mtd.h>
|
||||
#include <linux/mfd/syscon.h>
|
||||
@ -56,6 +57,9 @@
|
||||
|
||||
#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) \
|
||||
( \
|
||||
(cmd_dir) | \
|
||||
@ -151,15 +155,15 @@ struct meson_nfc {
|
||||
struct nand_controller controller;
|
||||
struct clk *core_clk;
|
||||
struct clk *device_clk;
|
||||
struct clk *phase_tx;
|
||||
struct clk *phase_rx;
|
||||
struct clk *nand_clk;
|
||||
struct clk_divider nand_divider;
|
||||
|
||||
unsigned long clk_rate;
|
||||
u32 bus_timing;
|
||||
|
||||
struct device *dev;
|
||||
void __iomem *reg_base;
|
||||
struct regmap *reg_clk;
|
||||
void __iomem *reg_clk;
|
||||
struct completion completion;
|
||||
struct list_head chips;
|
||||
const struct meson_nfc_data *data;
|
||||
@ -235,7 +239,7 @@ static void meson_nfc_select_chip(struct nand_chip *nand, int chip)
|
||||
nfc->timing.tbers_max = meson_chip->tbers_max;
|
||||
|
||||
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) {
|
||||
dev_err(nfc->dev, "failed to set clock rate\n");
|
||||
return;
|
||||
@ -454,7 +458,7 @@ static int meson_nfc_ecc_correct(struct nand_chip *nand, u32 *bitflips,
|
||||
if (ECC_ERR_CNT(*info) != ECC_UNCORRECTABLE) {
|
||||
mtd->ecc_stats.corrected += ECC_ERR_CNT(*info);
|
||||
*bitflips = max_t(u32, *bitflips, ECC_ERR_CNT(*info));
|
||||
*correct_bitmap |= 1 >> i;
|
||||
*correct_bitmap |= BIT_ULL(i);
|
||||
continue;
|
||||
}
|
||||
if ((nand->options & NAND_NEED_SCRAMBLING) &&
|
||||
@ -800,7 +804,7 @@ static int meson_nfc_read_page_hwecc(struct nand_chip *nand, u8 *buf,
|
||||
u8 *data = buf + i * ecc->size;
|
||||
u8 *oob = nand->oob_poi + i * (ecc->bytes + 2);
|
||||
|
||||
if (correct_bitmap & (1 << i))
|
||||
if (correct_bitmap & BIT_ULL(i))
|
||||
continue;
|
||||
ret = nand_check_erased_ecc_chunk(data, ecc->size,
|
||||
oob, ecc->bytes + 2,
|
||||
@ -987,6 +991,8 @@ static const struct mtd_ooblayout_ops meson_ooblayout_ops = {
|
||||
|
||||
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;
|
||||
|
||||
/* request core clock */
|
||||
@ -1002,21 +1008,28 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
|
||||
return PTR_ERR(nfc->device_clk);
|
||||
}
|
||||
|
||||
nfc->phase_tx = devm_clk_get(nfc->dev, "tx");
|
||||
if (IS_ERR(nfc->phase_tx)) {
|
||||
dev_err(nfc->dev, "failed to get TX clk\n");
|
||||
return PTR_ERR(nfc->phase_tx);
|
||||
}
|
||||
init.name = devm_kasprintf(nfc->dev,
|
||||
GFP_KERNEL, "%s#div",
|
||||
dev_name(nfc->dev));
|
||||
init.ops = &clk_divider_ops;
|
||||
nfc_divider_parent_data[0].fw_name = "device";
|
||||
init.parent_data = nfc_divider_parent_data;
|
||||
init.num_parents = 1;
|
||||
nfc->nand_divider.reg = nfc->reg_clk;
|
||||
nfc->nand_divider.shift = CLK_DIV_SHIFT;
|
||||
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->phase_rx = devm_clk_get(nfc->dev, "rx");
|
||||
if (IS_ERR(nfc->phase_rx)) {
|
||||
dev_err(nfc->dev, "failed to get RX clk\n");
|
||||
return PTR_ERR(nfc->phase_rx);
|
||||
}
|
||||
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 */
|
||||
regmap_update_bits(nfc->reg_clk,
|
||||
0, CLK_SELECT_NAND, CLK_SELECT_NAND);
|
||||
writel(CLK_SELECT_NAND | readl(nfc->reg_clk),
|
||||
nfc->reg_clk);
|
||||
|
||||
ret = clk_prepare_enable(nfc->core_clk);
|
||||
if (ret) {
|
||||
@ -1030,29 +1043,21 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
|
||||
goto err_device_clk;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(nfc->phase_tx);
|
||||
ret = clk_prepare_enable(nfc->nand_clk);
|
||||
if (ret) {
|
||||
dev_err(nfc->dev, "failed to enable TX clock\n");
|
||||
goto err_phase_tx;
|
||||
dev_err(nfc->dev, "pre enable NFC divider fail\n");
|
||||
goto err_nand_clk;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(nfc->phase_rx);
|
||||
if (ret) {
|
||||
dev_err(nfc->dev, "failed to enable RX clock\n");
|
||||
goto err_phase_rx;
|
||||
}
|
||||
|
||||
ret = clk_set_rate(nfc->device_clk, 24000000);
|
||||
ret = clk_set_rate(nfc->nand_clk, 24000000);
|
||||
if (ret)
|
||||
goto err_disable_rx;
|
||||
goto err_disable_clk;
|
||||
|
||||
return 0;
|
||||
|
||||
err_disable_rx:
|
||||
clk_disable_unprepare(nfc->phase_rx);
|
||||
err_phase_rx:
|
||||
clk_disable_unprepare(nfc->phase_tx);
|
||||
err_phase_tx:
|
||||
err_disable_clk:
|
||||
clk_disable_unprepare(nfc->nand_clk);
|
||||
err_nand_clk:
|
||||
clk_disable_unprepare(nfc->device_clk);
|
||||
err_device_clk:
|
||||
clk_disable_unprepare(nfc->core_clk);
|
||||
@ -1061,8 +1066,7 @@ err_device_clk:
|
||||
|
||||
static void meson_nfc_disable_clk(struct meson_nfc *nfc)
|
||||
{
|
||||
clk_disable_unprepare(nfc->phase_rx);
|
||||
clk_disable_unprepare(nfc->phase_tx);
|
||||
clk_disable_unprepare(nfc->nand_clk);
|
||||
clk_disable_unprepare(nfc->device_clk);
|
||||
clk_disable_unprepare(nfc->core_clk);
|
||||
}
|
||||
@ -1368,7 +1372,6 @@ static int meson_nfc_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct meson_nfc *nfc;
|
||||
struct resource *res;
|
||||
int ret, irq;
|
||||
|
||||
nfc = devm_kzalloc(dev, sizeof(*nfc), GFP_KERNEL);
|
||||
@ -1385,18 +1388,13 @@ static int meson_nfc_probe(struct platform_device *pdev)
|
||||
|
||||
nfc->dev = dev;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
nfc->reg_base = devm_ioremap_resource(dev, res);
|
||||
nfc->reg_base = devm_platform_ioremap_resource_byname(pdev, "nfc");
|
||||
if (IS_ERR(nfc->reg_base))
|
||||
return PTR_ERR(nfc->reg_base);
|
||||
|
||||
nfc->reg_clk =
|
||||
syscon_regmap_lookup_by_phandle(dev->of_node,
|
||||
"amlogic,mmc-syscon");
|
||||
if (IS_ERR(nfc->reg_clk)) {
|
||||
dev_err(dev, "Failed to lookup clock base\n");
|
||||
nfc->reg_clk = devm_platform_ioremap_resource_byname(pdev, "emmc");
|
||||
if (IS_ERR(nfc->reg_clk))
|
||||
return PTR_ERR(nfc->reg_clk);
|
||||
}
|
||||
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq < 0)
|
||||
|
@ -335,8 +335,6 @@ static int nand_isbad_bbm(struct nand_chip *chip, loff_t ofs)
|
||||
* @chip: NAND chip structure
|
||||
*
|
||||
* 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)
|
||||
{
|
||||
@ -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,
|
||||
unsigned int *ncs_array)
|
||||
{
|
||||
struct device_node *np = dev->of_node;
|
||||
struct gpio_desc **descs;
|
||||
int ndescs, i;
|
||||
|
||||
ndescs = of_gpio_named_count(np, "cs-gpios");
|
||||
ndescs = gpiod_count(dev, "cs");
|
||||
if (ndescs < 0) {
|
||||
dev_dbg(dev, "No valid cs-gpios property\n");
|
||||
return 0;
|
||||
|
@ -170,18 +170,11 @@ static int __init orion_nand_probe(struct platform_device *pdev)
|
||||
|
||||
platform_set_drvdata(pdev, info);
|
||||
|
||||
/* Not all platforms can gate the clock, so it is not
|
||||
an error if the clock does not exists. */
|
||||
info->clk = devm_clk_get(&pdev->dev, NULL);
|
||||
if (IS_ERR(info->clk)) {
|
||||
ret = PTR_ERR(info->clk);
|
||||
if (ret == -ENOENT) {
|
||||
info->clk = NULL;
|
||||
} else {
|
||||
dev_err(&pdev->dev, "failed to get clock!\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
/* Not all platforms can gate the clock, so it is optional. */
|
||||
info->clk = devm_clk_get_optional(&pdev->dev, NULL);
|
||||
if (IS_ERR(info->clk))
|
||||
return dev_err_probe(&pdev->dev, PTR_ERR(info->clk),
|
||||
"failed to get clock!\n");
|
||||
|
||||
ret = clk_prepare_enable(info->clk);
|
||||
if (ret) {
|
||||
|
@ -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,
|
||||
eccsteps, dma_data_dir);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (!ret)
|
||||
return -EIO;
|
||||
|
||||
desc_data = dmaengine_prep_slave_sg(dma_ch, nfc->dma_data_sg.sgl,
|
||||
eccsteps, dma_transfer_dir,
|
||||
@ -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,
|
||||
eccsteps, dma_data_dir);
|
||||
if (ret < 0)
|
||||
if (!ret) {
|
||||
ret = -EIO;
|
||||
goto err_unmap_data;
|
||||
}
|
||||
|
||||
desc_ecc = dmaengine_prep_slave_sg(nfc->dma_ecc_ch,
|
||||
nfc->dma_ecc_sg.sgl,
|
||||
@ -1799,9 +1801,8 @@ static int stm32_fmc2_nfc_parse_child(struct stm32_fmc2_nfc *nfc,
|
||||
nand->cs_used[i] = cs;
|
||||
}
|
||||
|
||||
nand->wp_gpio = devm_gpiod_get_from_of_node(nfc->dev, dn,
|
||||
"wp-gpios", 0,
|
||||
GPIOD_OUT_HIGH, "wp");
|
||||
nand->wp_gpio = devm_fwnode_gpiod_get(nfc->dev, of_fwnode_handle(dn),
|
||||
"wp", GPIOD_OUT_HIGH, "wp");
|
||||
if (IS_ERR(nand->wp_gpio)) {
|
||||
ret = PTR_ERR(nand->wp_gpio);
|
||||
if (ret != -ENOENT)
|
||||
|
Loading…
Reference in New Issue
Block a user