Raw NAND core changes:
* Fix -Wvoid-pointer-to-enum-cast warning * Export 'nand_exit_status_op()' * dt-bindings: Fix nand-controller.yaml license Raw NAND controller driver changes: * Omap, Omap2, Samsung, Atmel, fsl_upm, lpc32xx_slc, lpc32xx_mlc, STM32_FMC2, sh_ftlctl, MXC, Sunxi: - Use devm_platform_get_and_ioremap_resource() * Orion, vf610_nfc, Sunxi, STM32_FMC2, MTK, mpc5121, lpc32xx_slc, Intel, FSMC, Arasan: - Use helper function devm_clk_get_optional_enabled() * Brcmnand: - Use devm_platform_ioremap_resource_byname() - Propagate init error -EPROBE_DEFER up - Propagate error and simplify ternary operators - Fix mtd oobsize - Fix potential out-of-bounds access in oob write - Fix crash during the panic_write - Fix potential false time out warning - Fix ECC level field setting for v7.2 controller * fsmc: Handle clk prepare error in fsmc_nand_resume() * Marvell: Add support for AC5 SoC * Meson: - Support for 512B ECC step size - Fix build error - Use NAND core API to check status - dt-bindings: * Make ECC properties dependent * Support for 512B ECC step size * Drop unneeded quotes * Oxnas: Remove driver and bindings * Qcom: - Conversion to ->exec_op() - Removal of the legacy interface - Two full series of improvements/misc fixes * Use the BIT() macro * Use u8 instead of uint8_t * Fix alignment with open parenthesis * Fix the spacing * Fix wrong indentation * Fix a typo * Early structure initialization * Fix address parsing within ->exec_op() * Remove superfluous initialization of "ret" * Rename variables in qcom_op_cmd_mapping() * Handle unsupported opcode in qcom_op_cmd_mapping() * Fix the opcode check in qcom_check_op() * Use EOPNOTSUPP instead of ENOTSUPP * Wrap qcom_nand_exec_op() to 80 columns * Unmap sg_list and free desc within submic_descs() * Simplify the call to nand_prog_page_end_op() * Do not override the error no of submit_descs() * Sort includes alphabetically * Clear buf_count and buf_start in raw read * Add read/read_start ops in exec_op path * vf610_nfc: Do not check 0 for platform_get_irq() SPI-NAND changes: * gigadevice: Add support for GD5F1GQ{4,5}RExxH * esmt: Add support for F50D2G41KA * toshiba: Add support for T{C,H}58NYG{0,2}S3HBAI4 and TH58NYG3S0HBAI6 -----BEGIN PGP SIGNATURE----- iQEzBAABCgAdFiEE9HuaYnbmDhq/XIDIJWrqGEe9VoQFAmTsYbAACgkQJWrqGEe9 VoQTsQf+MA+rMfIoyOSLwaFm0Z5UPwIuhleumNgkV2yoC2H42ugz7+Qo4ZS8iHjY qBUWA/PF4s5snF8A/x4uSEUkdT6etuJ58uKy53304C6cx7RXLtfc7qJfs6fQVLqL O6uO/EPdUkmiIbdXcRQRiAUDRHEFMPVEHd5pECB0l/qbiNLWQWRFUsmaP6kBZnm1 y7xPfxJo3GuMKJMWnMg+kcoQ7hhIvd0FRztL6VT4SV/et/nfCYjAVXOpViZ8e3+d tq5yp+WatcBL9tGFSV3IyLW5Z+x1oVDoOIoTk/hWdHsITaHBxXBb8Llc6Eh7GYCD 5mj/renycHEv2Wc2v93z7W3XtnY77Q== =Pp9B -----END PGP SIGNATURE----- Merge tag 'nand/for-6.6' into mtd/next Raw NAND core changes: * Fix -Wvoid-pointer-to-enum-cast warning * Export 'nand_exit_status_op()' * dt-bindings: Fix nand-controller.yaml license Raw NAND controller driver changes: * Omap, Omap2, Samsung, Atmel, fsl_upm, lpc32xx_slc, lpc32xx_mlc, STM32_FMC2, sh_ftlctl, MXC, Sunxi: - Use devm_platform_get_and_ioremap_resource() * Orion, vf610_nfc, Sunxi, STM32_FMC2, MTK, mpc5121, lpc32xx_slc, Intel, FSMC, Arasan: - Use helper function devm_clk_get_optional_enabled() * Brcmnand: - Use devm_platform_ioremap_resource_byname() - Propagate init error -EPROBE_DEFER up - Propagate error and simplify ternary operators - Fix mtd oobsize - Fix potential out-of-bounds access in oob write - Fix crash during the panic_write - Fix potential false time out warning - Fix ECC level field setting for v7.2 controller * fsmc: Handle clk prepare error in fsmc_nand_resume() * Marvell: Add support for AC5 SoC * Meson: - Support for 512B ECC step size - Fix build error - Use NAND core API to check status - dt-bindings: * Make ECC properties dependent * Support for 512B ECC step size * Drop unneeded quotes * Oxnas: Remove driver and bindings * Qcom: - Conversion to ->exec_op() - Removal of the legacy interface - Two full series of improvements/misc fixes * Use the BIT() macro * Use u8 instead of uint8_t * Fix alignment with open parenthesis * Fix the spacing * Fix wrong indentation * Fix a typo * Early structure initialization * Fix address parsing within ->exec_op() * Remove superfluous initialization of "ret" * Rename variables in qcom_op_cmd_mapping() * Handle unsupported opcode in qcom_op_cmd_mapping() * Fix the opcode check in qcom_check_op() * Use EOPNOTSUPP instead of ENOTSUPP * Wrap qcom_nand_exec_op() to 80 columns * Unmap sg_list and free desc within submic_descs() * Simplify the call to nand_prog_page_end_op() * Do not override the error no of submit_descs() * Sort includes alphabetically * Clear buf_count and buf_start in raw read * Add read/read_start ops in exec_op path * vf610_nfc: Do not check 0 for platform_get_irq() SPI-NAND changes: * gigadevice: Add support for GD5F1GQ{4,5}RExxH * esmt: Add support for F50D2G41KA * toshiba: Add support for T{C,H}58NYG{0,2}S3HBAI4 and TH58NYG3S0HBAI6 Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
This commit is contained in:
commit
54a3f6e89f
@ -50,7 +50,7 @@ patternProperties:
|
||||
const: hw
|
||||
|
||||
nand-ecc-step-size:
|
||||
const: 1024
|
||||
enum: [512, 1024]
|
||||
|
||||
nand-ecc-strength:
|
||||
enum: [8, 16, 24, 30, 40, 50, 60]
|
||||
@ -66,6 +66,10 @@ patternProperties:
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
dependencies:
|
||||
nand-ecc-strength: [nand-ecc-step-size]
|
||||
nand-ecc-step-size: [nand-ecc-strength]
|
||||
|
||||
|
||||
required:
|
||||
- compatible
|
||||
|
@ -16,6 +16,7 @@ properties:
|
||||
- const: marvell,armada-8k-nand-controller
|
||||
- const: marvell,armada370-nand-controller
|
||||
- enum:
|
||||
- marvell,ac5-nand-controller
|
||||
- marvell,armada370-nand-controller
|
||||
- marvell,pxa3xx-nand-controller
|
||||
- description: legacy bindings
|
||||
|
@ -1,4 +1,4 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/mtd/nand-controller.yaml#
|
||||
|
@ -1,41 +0,0 @@
|
||||
* Oxford Semiconductor OXNAS NAND Controller
|
||||
|
||||
Please refer to nand-controller.yaml for generic information regarding MTD NAND bindings.
|
||||
|
||||
Required properties:
|
||||
- compatible: "oxsemi,ox820-nand"
|
||||
- reg: Base address and length for NAND mapped memory.
|
||||
|
||||
Optional Properties:
|
||||
- clocks: phandle to the NAND gate clock if needed.
|
||||
- resets: phandle to the NAND reset control if needed.
|
||||
|
||||
Example:
|
||||
|
||||
nandc: nand-controller@41000000 {
|
||||
compatible = "oxsemi,ox820-nand";
|
||||
reg = <0x41000000 0x100000>;
|
||||
clocks = <&stdclk CLK_820_NAND>;
|
||||
resets = <&reset RESET_NAND>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
nand@0 {
|
||||
reg = <0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
nand-ecc-mode = "soft";
|
||||
nand-ecc-algo = "hamming";
|
||||
|
||||
partition@0 {
|
||||
label = "boot";
|
||||
reg = <0x00000000 0x00e00000>;
|
||||
read-only;
|
||||
};
|
||||
|
||||
partition@e00000 {
|
||||
label = "ubi";
|
||||
reg = <0x00e00000 0x07200000>;
|
||||
};
|
||||
};
|
||||
};
|
@ -467,12 +467,6 @@ static int omap2_onenand_probe(struct platform_device *pdev)
|
||||
struct device *dev = &pdev->dev;
|
||||
struct device_node *np = dev->of_node;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!res) {
|
||||
dev_err(dev, "error getting memory resource\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
r = of_property_read_u32(np, "reg", &val);
|
||||
if (r) {
|
||||
dev_err(dev, "reg not found in DT\n");
|
||||
@ -486,11 +480,11 @@ static int omap2_onenand_probe(struct platform_device *pdev)
|
||||
init_completion(&c->irq_done);
|
||||
init_completion(&c->dma_done);
|
||||
c->gpmc_cs = val;
|
||||
c->phys_base = res->start;
|
||||
|
||||
c->onenand.base = devm_ioremap_resource(dev, res);
|
||||
c->onenand.base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
|
||||
if (IS_ERR(c->onenand.base))
|
||||
return PTR_ERR(c->onenand.base);
|
||||
c->phys_base = res->start;
|
||||
|
||||
c->int_gpiod = devm_gpiod_get_optional(dev, "int", GPIOD_IN);
|
||||
if (IS_ERR(c->int_gpiod)) {
|
||||
|
@ -860,8 +860,7 @@ static int s3c_onenand_probe(struct platform_device *pdev)
|
||||
|
||||
s3c_onenand_setup(mtd);
|
||||
|
||||
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
onenand->base = devm_ioremap_resource(&pdev->dev, r);
|
||||
onenand->base = devm_platform_get_and_ioremap_resource(pdev, 0, &r);
|
||||
if (IS_ERR(onenand->base))
|
||||
return PTR_ERR(onenand->base);
|
||||
|
||||
@ -874,8 +873,7 @@ static int s3c_onenand_probe(struct platform_device *pdev)
|
||||
this->options |= ONENAND_SKIP_UNLOCK_CHECK;
|
||||
|
||||
if (onenand->type != TYPE_S5PC110) {
|
||||
r = platform_get_resource(pdev, IORESOURCE_MEM, 1);
|
||||
onenand->ahb_addr = devm_ioremap_resource(&pdev->dev, r);
|
||||
onenand->ahb_addr = devm_platform_ioremap_resource(pdev, 1);
|
||||
if (IS_ERR(onenand->ahb_addr))
|
||||
return PTR_ERR(onenand->ahb_addr);
|
||||
|
||||
@ -895,8 +893,7 @@ static int s3c_onenand_probe(struct platform_device *pdev)
|
||||
this->subpagesize = mtd->writesize;
|
||||
|
||||
} else { /* S5PC110 */
|
||||
r = platform_get_resource(pdev, IORESOURCE_MEM, 1);
|
||||
onenand->dma_addr = devm_ioremap_resource(&pdev->dev, r);
|
||||
onenand->dma_addr = devm_platform_ioremap_resource(pdev, 1);
|
||||
if (IS_ERR(onenand->dma_addr))
|
||||
return PTR_ERR(onenand->dma_addr);
|
||||
|
||||
|
@ -160,7 +160,7 @@ config MTD_NAND_MARVELL
|
||||
including:
|
||||
- PXA3xx processors (NFCv1)
|
||||
- 32-bit Armada platforms (XP, 37x, 38x, 39x) (NFCv2)
|
||||
- 64-bit Aramda platforms (7k, 8k) (NFCv2)
|
||||
- 64-bit Aramda platforms (7k, 8k, ac5) (NFCv2)
|
||||
|
||||
config MTD_NAND_SLC_LPC32XX
|
||||
tristate "NXP LPC32xx SLC NAND controller"
|
||||
@ -204,13 +204,6 @@ config MTD_NAND_BCM47XXNFLASH
|
||||
registered by bcma as platform devices. This enables driver for
|
||||
NAND flash memories. For now only BCM4706 is supported.
|
||||
|
||||
config MTD_NAND_OXNAS
|
||||
tristate "Oxford Semiconductor NAND controller"
|
||||
depends on ARCH_OXNAS || COMPILE_TEST
|
||||
depends on HAS_IOMEM
|
||||
help
|
||||
This enables the NAND flash controller on Oxford Semiconductor SoCs.
|
||||
|
||||
config MTD_NAND_MPC5121_NFC
|
||||
tristate "MPC5121 NAND controller"
|
||||
depends on PPC_MPC512x
|
||||
|
@ -26,7 +26,6 @@ obj-$(CONFIG_MTD_NAND_MARVELL) += marvell_nand.o
|
||||
obj-$(CONFIG_MTD_NAND_PLATFORM) += plat_nand.o
|
||||
obj-$(CONFIG_MTD_NAND_PASEMI) += pasemi_nand.o
|
||||
obj-$(CONFIG_MTD_NAND_ORION) += orion_nand.o
|
||||
obj-$(CONFIG_MTD_NAND_OXNAS) += oxnas_nand.o
|
||||
obj-$(CONFIG_MTD_NAND_FSL_ELBC) += fsl_elbc_nand.o
|
||||
obj-$(CONFIG_MTD_NAND_FSL_IFC) += fsl_ifc_nand.o
|
||||
obj-$(CONFIG_MTD_NAND_FSL_UPM) += fsl_upm.o
|
||||
|
@ -1440,45 +1440,29 @@ static int anfc_probe(struct platform_device *pdev)
|
||||
|
||||
anfc_reset(nfc);
|
||||
|
||||
nfc->controller_clk = devm_clk_get(&pdev->dev, "controller");
|
||||
nfc->controller_clk = devm_clk_get_enabled(&pdev->dev, "controller");
|
||||
if (IS_ERR(nfc->controller_clk))
|
||||
return PTR_ERR(nfc->controller_clk);
|
||||
|
||||
nfc->bus_clk = devm_clk_get(&pdev->dev, "bus");
|
||||
nfc->bus_clk = devm_clk_get_enabled(&pdev->dev, "bus");
|
||||
if (IS_ERR(nfc->bus_clk))
|
||||
return PTR_ERR(nfc->bus_clk);
|
||||
|
||||
ret = clk_prepare_enable(nfc->controller_clk);
|
||||
ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(64));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = clk_prepare_enable(nfc->bus_clk);
|
||||
if (ret)
|
||||
goto disable_controller_clk;
|
||||
|
||||
ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(64));
|
||||
if (ret)
|
||||
goto disable_bus_clk;
|
||||
|
||||
ret = anfc_parse_cs(nfc);
|
||||
if (ret)
|
||||
goto disable_bus_clk;
|
||||
return ret;
|
||||
|
||||
ret = anfc_chips_init(nfc);
|
||||
if (ret)
|
||||
goto disable_bus_clk;
|
||||
return ret;
|
||||
|
||||
platform_set_drvdata(pdev, nfc);
|
||||
|
||||
return 0;
|
||||
|
||||
disable_bus_clk:
|
||||
clk_disable_unprepare(nfc->bus_clk);
|
||||
|
||||
disable_controller_clk:
|
||||
clk_disable_unprepare(nfc->controller_clk);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void anfc_remove(struct platform_device *pdev)
|
||||
@ -1486,9 +1470,6 @@ static void anfc_remove(struct platform_device *pdev)
|
||||
struct arasan_nfc *nfc = platform_get_drvdata(pdev);
|
||||
|
||||
anfc_chips_cleanup(nfc);
|
||||
|
||||
clk_disable_unprepare(nfc->bus_clk);
|
||||
clk_disable_unprepare(nfc->controller_clk);
|
||||
}
|
||||
|
||||
static const struct of_device_id anfc_ids[] = {
|
||||
|
@ -1791,8 +1791,7 @@ atmel_nand_controller_legacy_add_nands(struct atmel_nand_controller *nc)
|
||||
|
||||
nand->numcs = 1;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
nand->cs[0].io.virt = devm_ioremap_resource(dev, res);
|
||||
nand->cs[0].io.virt = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
|
||||
if (IS_ERR(nand->cs[0].io.virt))
|
||||
return PTR_ERR(nand->cs[0].io.virt);
|
||||
|
||||
|
@ -61,15 +61,13 @@ static int bcm63138_nand_probe(struct platform_device *pdev)
|
||||
struct device *dev = &pdev->dev;
|
||||
struct bcm63138_nand_soc *priv;
|
||||
struct brcmnand_soc *soc;
|
||||
struct resource *res;
|
||||
|
||||
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
soc = &priv->soc;
|
||||
|
||||
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "nand-int-base");
|
||||
priv->base = devm_ioremap_resource(dev, res);
|
||||
priv->base = devm_platform_ioremap_resource_byname(pdev, "nand-int-base");
|
||||
if (IS_ERR(priv->base))
|
||||
return PTR_ERR(priv->base);
|
||||
|
||||
|
@ -272,6 +272,7 @@ struct brcmnand_controller {
|
||||
const unsigned int *page_sizes;
|
||||
unsigned int page_size_shift;
|
||||
unsigned int max_oob;
|
||||
u32 ecc_level_shift;
|
||||
u32 features;
|
||||
|
||||
/* for low-power standby/resume only */
|
||||
@ -596,6 +597,34 @@ enum {
|
||||
INTFC_CTLR_READY = BIT(31),
|
||||
};
|
||||
|
||||
/***********************************************************************
|
||||
* NAND ACC CONTROL bitfield
|
||||
*
|
||||
* Some bits have remained constant throughout hardware revision, while
|
||||
* others have shifted around.
|
||||
***********************************************************************/
|
||||
|
||||
/* Constant for all versions (where supported) */
|
||||
enum {
|
||||
/* See BRCMNAND_HAS_CACHE_MODE */
|
||||
ACC_CONTROL_CACHE_MODE = BIT(22),
|
||||
|
||||
/* See BRCMNAND_HAS_PREFETCH */
|
||||
ACC_CONTROL_PREFETCH = BIT(23),
|
||||
|
||||
ACC_CONTROL_PAGE_HIT = BIT(24),
|
||||
ACC_CONTROL_WR_PREEMPT = BIT(25),
|
||||
ACC_CONTROL_PARTIAL_PAGE = BIT(26),
|
||||
ACC_CONTROL_RD_ERASED = BIT(27),
|
||||
ACC_CONTROL_FAST_PGM_RDIN = BIT(28),
|
||||
ACC_CONTROL_WR_ECC = BIT(30),
|
||||
ACC_CONTROL_RD_ECC = BIT(31),
|
||||
};
|
||||
|
||||
#define ACC_CONTROL_ECC_SHIFT 16
|
||||
/* Only for v7.2 */
|
||||
#define ACC_CONTROL_ECC_EXT_SHIFT 13
|
||||
|
||||
static inline bool brcmnand_non_mmio_ops(struct brcmnand_controller *ctrl)
|
||||
{
|
||||
#if IS_ENABLED(CONFIG_MTD_NAND_BRCMNAND_BCMA)
|
||||
@ -737,6 +766,12 @@ static int brcmnand_revision_init(struct brcmnand_controller *ctrl)
|
||||
else if (of_property_read_bool(ctrl->dev->of_node, "brcm,nand-has-wp"))
|
||||
ctrl->features |= BRCMNAND_HAS_WP;
|
||||
|
||||
/* v7.2 has different ecc level shift in the acc register */
|
||||
if (ctrl->nand_version == 0x0702)
|
||||
ctrl->ecc_level_shift = ACC_CONTROL_ECC_EXT_SHIFT;
|
||||
else
|
||||
ctrl->ecc_level_shift = ACC_CONTROL_ECC_SHIFT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -931,30 +966,6 @@ static inline int brcmnand_cmd_shift(struct brcmnand_controller *ctrl)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* NAND ACC CONTROL bitfield
|
||||
*
|
||||
* Some bits have remained constant throughout hardware revision, while
|
||||
* others have shifted around.
|
||||
***********************************************************************/
|
||||
|
||||
/* Constant for all versions (where supported) */
|
||||
enum {
|
||||
/* See BRCMNAND_HAS_CACHE_MODE */
|
||||
ACC_CONTROL_CACHE_MODE = BIT(22),
|
||||
|
||||
/* See BRCMNAND_HAS_PREFETCH */
|
||||
ACC_CONTROL_PREFETCH = BIT(23),
|
||||
|
||||
ACC_CONTROL_PAGE_HIT = BIT(24),
|
||||
ACC_CONTROL_WR_PREEMPT = BIT(25),
|
||||
ACC_CONTROL_PARTIAL_PAGE = BIT(26),
|
||||
ACC_CONTROL_RD_ERASED = BIT(27),
|
||||
ACC_CONTROL_FAST_PGM_RDIN = BIT(28),
|
||||
ACC_CONTROL_WR_ECC = BIT(30),
|
||||
ACC_CONTROL_RD_ECC = BIT(31),
|
||||
};
|
||||
|
||||
static inline u32 brcmnand_spare_area_mask(struct brcmnand_controller *ctrl)
|
||||
{
|
||||
if (ctrl->nand_version == 0x0702)
|
||||
@ -967,18 +978,15 @@ static inline u32 brcmnand_spare_area_mask(struct brcmnand_controller *ctrl)
|
||||
return GENMASK(4, 0);
|
||||
}
|
||||
|
||||
#define NAND_ACC_CONTROL_ECC_SHIFT 16
|
||||
#define NAND_ACC_CONTROL_ECC_EXT_SHIFT 13
|
||||
|
||||
static inline u32 brcmnand_ecc_level_mask(struct brcmnand_controller *ctrl)
|
||||
{
|
||||
u32 mask = (ctrl->nand_version >= 0x0600) ? 0x1f : 0x0f;
|
||||
|
||||
mask <<= NAND_ACC_CONTROL_ECC_SHIFT;
|
||||
mask <<= ACC_CONTROL_ECC_SHIFT;
|
||||
|
||||
/* v7.2 includes additional ECC levels */
|
||||
if (ctrl->nand_version >= 0x0702)
|
||||
mask |= 0x7 << NAND_ACC_CONTROL_ECC_EXT_SHIFT;
|
||||
if (ctrl->nand_version == 0x0702)
|
||||
mask |= 0x7 << ACC_CONTROL_ECC_EXT_SHIFT;
|
||||
|
||||
return mask;
|
||||
}
|
||||
@ -992,8 +1000,8 @@ static void brcmnand_set_ecc_enabled(struct brcmnand_host *host, int en)
|
||||
|
||||
if (en) {
|
||||
acc_control |= ecc_flags; /* enable RD/WR ECC */
|
||||
acc_control |= host->hwcfg.ecc_level
|
||||
<< NAND_ACC_CONTROL_ECC_SHIFT;
|
||||
acc_control &= ~brcmnand_ecc_level_mask(ctrl);
|
||||
acc_control |= host->hwcfg.ecc_level << ctrl->ecc_level_shift;
|
||||
} else {
|
||||
acc_control &= ~ecc_flags; /* disable RD/WR ECC */
|
||||
acc_control &= ~brcmnand_ecc_level_mask(ctrl);
|
||||
@ -1072,6 +1080,14 @@ static int bcmnand_ctrl_poll_status(struct brcmnand_controller *ctrl,
|
||||
cpu_relax();
|
||||
} while (time_after(limit, jiffies));
|
||||
|
||||
/*
|
||||
* do a final check after time out in case the CPU was busy and the driver
|
||||
* did not get enough time to perform the polling to avoid false alarms
|
||||
*/
|
||||
val = brcmnand_read_reg(ctrl, BRCMNAND_INTFC_STATUS);
|
||||
if ((val & mask) == expected_val)
|
||||
return 0;
|
||||
|
||||
dev_warn(ctrl->dev, "timeout on status poll (expected %x got %x)\n",
|
||||
expected_val, val & mask);
|
||||
|
||||
@ -1461,19 +1477,33 @@ static int write_oob_to_regs(struct brcmnand_controller *ctrl, int i,
|
||||
const u8 *oob, int sas, int sector_1k)
|
||||
{
|
||||
int tbytes = sas << sector_1k;
|
||||
int j;
|
||||
int j, k = 0;
|
||||
u32 last = 0xffffffff;
|
||||
u8 *plast = (u8 *)&last;
|
||||
|
||||
/* Adjust OOB values for 1K sector size */
|
||||
if (sector_1k && (i & 0x01))
|
||||
tbytes = max(0, tbytes - (int)ctrl->max_oob);
|
||||
tbytes = min_t(int, tbytes, ctrl->max_oob);
|
||||
|
||||
for (j = 0; j < tbytes; j += 4)
|
||||
/*
|
||||
* tbytes may not be multiple of words. Make sure we don't read out of
|
||||
* the boundary and stop at last word.
|
||||
*/
|
||||
for (j = 0; (j + 3) < tbytes; j += 4)
|
||||
oob_reg_write(ctrl, j,
|
||||
(oob[j + 0] << 24) |
|
||||
(oob[j + 1] << 16) |
|
||||
(oob[j + 2] << 8) |
|
||||
(oob[j + 3] << 0));
|
||||
|
||||
/* handle the remaing bytes */
|
||||
while (j < tbytes)
|
||||
plast[k++] = oob[j++];
|
||||
|
||||
if (tbytes & 0x3)
|
||||
oob_reg_write(ctrl, (tbytes & ~0x3), (__force u32)cpu_to_be32(last));
|
||||
|
||||
return tbytes;
|
||||
}
|
||||
|
||||
@ -1592,7 +1622,17 @@ static void brcmnand_send_cmd(struct brcmnand_host *host, int cmd)
|
||||
|
||||
dev_dbg(ctrl->dev, "send native cmd %d addr 0x%llx\n", cmd, cmd_addr);
|
||||
|
||||
BUG_ON(ctrl->cmd_pending != 0);
|
||||
/*
|
||||
* If we came here through _panic_write and there is a pending
|
||||
* command, try to wait for it. If it times out, rather than
|
||||
* hitting BUG_ON, just return so we don't crash while crashing.
|
||||
*/
|
||||
if (oops_in_progress) {
|
||||
if (ctrl->cmd_pending &&
|
||||
bcmnand_ctrl_poll_status(ctrl, NAND_CTRL_RDY, NAND_CTRL_RDY, 0))
|
||||
return;
|
||||
} else
|
||||
BUG_ON(ctrl->cmd_pending != 0);
|
||||
ctrl->cmd_pending = cmd;
|
||||
|
||||
ret = bcmnand_ctrl_poll_status(ctrl, NAND_CTRL_RDY, NAND_CTRL_RDY, 0);
|
||||
@ -1626,13 +1666,13 @@ static bool brcmstb_nand_wait_for_completion(struct nand_chip *chip)
|
||||
disable_ctrl_irqs(ctrl);
|
||||
sts = bcmnand_ctrl_poll_status(ctrl, NAND_CTRL_RDY,
|
||||
NAND_CTRL_RDY, 0);
|
||||
err = (sts < 0) ? true : false;
|
||||
err = sts < 0;
|
||||
} else {
|
||||
unsigned long timeo = msecs_to_jiffies(
|
||||
NAND_POLL_STATUS_TIMEOUT_MS);
|
||||
/* wait for completion interrupt */
|
||||
sts = wait_for_completion_timeout(&ctrl->done, timeo);
|
||||
err = (sts <= 0) ? true : false;
|
||||
err = !sts;
|
||||
}
|
||||
|
||||
return err;
|
||||
@ -1648,6 +1688,7 @@ static int brcmnand_waitfunc(struct nand_chip *chip)
|
||||
if (ctrl->cmd_pending)
|
||||
err = brcmstb_nand_wait_for_completion(chip);
|
||||
|
||||
ctrl->cmd_pending = 0;
|
||||
if (err) {
|
||||
u32 cmd = brcmnand_read_reg(ctrl, BRCMNAND_CMD_START)
|
||||
>> brcmnand_cmd_shift(ctrl);
|
||||
@ -1656,8 +1697,8 @@ static int brcmnand_waitfunc(struct nand_chip *chip)
|
||||
"timeout waiting for command %#02x\n", cmd);
|
||||
dev_err_ratelimited(ctrl->dev, "intfc status %08x\n",
|
||||
brcmnand_read_reg(ctrl, BRCMNAND_INTFC_STATUS));
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
ctrl->cmd_pending = 0;
|
||||
return brcmnand_read_reg(ctrl, BRCMNAND_INTFC_STATUS) &
|
||||
INTFC_FLASH_STATUS;
|
||||
}
|
||||
@ -2561,7 +2602,7 @@ static int brcmnand_set_cfg(struct brcmnand_host *host,
|
||||
tmp &= ~brcmnand_ecc_level_mask(ctrl);
|
||||
tmp &= ~brcmnand_spare_area_mask(ctrl);
|
||||
if (ctrl->nand_version >= 0x0302) {
|
||||
tmp |= cfg->ecc_level << NAND_ACC_CONTROL_ECC_SHIFT;
|
||||
tmp |= cfg->ecc_level << ctrl->ecc_level_shift;
|
||||
tmp |= cfg->spare_area_size;
|
||||
}
|
||||
nand_writereg(ctrl, acc_control_offs, tmp);
|
||||
@ -2612,6 +2653,8 @@ static int brcmnand_setup_dev(struct brcmnand_host *host)
|
||||
struct nand_chip *chip = &host->chip;
|
||||
const struct nand_ecc_props *requirements =
|
||||
nanddev_get_ecc_requirements(&chip->base);
|
||||
struct nand_memory_organization *memorg =
|
||||
nanddev_get_memorg(&chip->base);
|
||||
struct brcmnand_controller *ctrl = host->ctrl;
|
||||
struct brcmnand_cfg *cfg = &host->hwcfg;
|
||||
char msg[128];
|
||||
@ -2633,10 +2676,11 @@ static int brcmnand_setup_dev(struct brcmnand_host *host)
|
||||
if (cfg->spare_area_size > ctrl->max_oob)
|
||||
cfg->spare_area_size = ctrl->max_oob;
|
||||
/*
|
||||
* Set oobsize to be consistent with controller's spare_area_size, as
|
||||
* the rest is inaccessible.
|
||||
* Set mtd and memorg oobsize to be consistent with controller's
|
||||
* spare_area_size, as the rest is inaccessible.
|
||||
*/
|
||||
mtd->oobsize = cfg->spare_area_size * (mtd->writesize >> FC_SHIFT);
|
||||
memorg->oobsize = mtd->oobsize;
|
||||
|
||||
cfg->device_size = mtd->size;
|
||||
cfg->block_size = mtd->erasesize;
|
||||
@ -3202,6 +3246,10 @@ int brcmnand_probe(struct platform_device *pdev, struct brcmnand_soc *soc)
|
||||
|
||||
ret = brcmnand_init_cs(host, NULL);
|
||||
if (ret) {
|
||||
if (ret == -EPROBE_DEFER) {
|
||||
of_node_put(child);
|
||||
goto err;
|
||||
}
|
||||
devm_kfree(dev, host);
|
||||
continue; /* Try all chip-selects */
|
||||
}
|
||||
|
@ -103,7 +103,6 @@ static int iproc_nand_probe(struct platform_device *pdev)
|
||||
struct device *dev = &pdev->dev;
|
||||
struct iproc_nand_soc *priv;
|
||||
struct brcmnand_soc *soc;
|
||||
struct resource *res;
|
||||
|
||||
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv)
|
||||
@ -112,13 +111,11 @@ static int iproc_nand_probe(struct platform_device *pdev)
|
||||
|
||||
spin_lock_init(&priv->idm_lock);
|
||||
|
||||
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "iproc-idm");
|
||||
priv->idm_base = devm_ioremap_resource(dev, res);
|
||||
priv->idm_base = devm_platform_ioremap_resource_byname(pdev, "iproc-idm");
|
||||
if (IS_ERR(priv->idm_base))
|
||||
return PTR_ERR(priv->idm_base);
|
||||
|
||||
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "iproc-ext");
|
||||
priv->ext_base = devm_ioremap_resource(dev, res);
|
||||
priv->ext_base = devm_platform_ioremap_resource_byname(pdev, "iproc-ext");
|
||||
if (IS_ERR(priv->ext_base))
|
||||
return PTR_ERR(priv->ext_base);
|
||||
|
||||
|
@ -173,8 +173,7 @@ static int fun_probe(struct platform_device *ofdev)
|
||||
if (!fun)
|
||||
return -ENOMEM;
|
||||
|
||||
io_res = platform_get_resource(ofdev, IORESOURCE_MEM, 0);
|
||||
fun->io_base = devm_ioremap_resource(&ofdev->dev, io_res);
|
||||
fun->io_base = devm_platform_get_and_ioremap_resource(ofdev, 0, &io_res);
|
||||
if (IS_ERR(fun->io_base))
|
||||
return PTR_ERR(fun->io_base);
|
||||
|
||||
|
@ -1066,16 +1066,12 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
|
||||
host->regs_va = base + FSMC_NOR_REG_SIZE +
|
||||
(host->bank * FSMC_NAND_BANK_SZ);
|
||||
|
||||
host->clk = devm_clk_get(&pdev->dev, NULL);
|
||||
host->clk = devm_clk_get_enabled(&pdev->dev, NULL);
|
||||
if (IS_ERR(host->clk)) {
|
||||
dev_err(&pdev->dev, "failed to fetch block clock\n");
|
||||
return PTR_ERR(host->clk);
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(host->clk);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* This device ID is actually a common AMBA ID as used on the
|
||||
* AMBA PrimeCell bus. However it is not a PrimeCell.
|
||||
@ -1111,7 +1107,7 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
|
||||
if (!host->read_dma_chan) {
|
||||
dev_err(&pdev->dev, "Unable to get read dma channel\n");
|
||||
ret = -ENODEV;
|
||||
goto disable_clk;
|
||||
goto disable_fsmc;
|
||||
}
|
||||
host->write_dma_chan = dma_request_channel(mask, filter, NULL);
|
||||
if (!host->write_dma_chan) {
|
||||
@ -1155,9 +1151,8 @@ release_dma_write_chan:
|
||||
release_dma_read_chan:
|
||||
if (host->mode == USE_DMA_ACCESS)
|
||||
dma_release_channel(host->read_dma_chan);
|
||||
disable_clk:
|
||||
disable_fsmc:
|
||||
fsmc_nand_disable(host);
|
||||
clk_disable_unprepare(host->clk);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -1182,7 +1177,6 @@ static void fsmc_nand_remove(struct platform_device *pdev)
|
||||
dma_release_channel(host->write_dma_chan);
|
||||
dma_release_channel(host->read_dma_chan);
|
||||
}
|
||||
clk_disable_unprepare(host->clk);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1200,9 +1194,14 @@ static int fsmc_nand_suspend(struct device *dev)
|
||||
static int fsmc_nand_resume(struct device *dev)
|
||||
{
|
||||
struct fsmc_nand_data *host = dev_get_drvdata(dev);
|
||||
int ret;
|
||||
|
||||
if (host) {
|
||||
clk_prepare_enable(host->clk);
|
||||
ret = clk_prepare_enable(host->clk);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to enable clk\n");
|
||||
return ret;
|
||||
}
|
||||
if (host->dev_timings)
|
||||
fsmc_nand_setup(host, host->dev_timings);
|
||||
nand_reset(&host->nand, 0);
|
||||
|
@ -626,16 +626,10 @@ static int ebu_nand_probe(struct platform_device *pdev)
|
||||
goto err_of_node_put;
|
||||
}
|
||||
|
||||
ebu_host->clk = devm_clk_get(dev, NULL);
|
||||
ebu_host->clk = devm_clk_get_enabled(dev, NULL);
|
||||
if (IS_ERR(ebu_host->clk)) {
|
||||
ret = dev_err_probe(dev, PTR_ERR(ebu_host->clk),
|
||||
"failed to get clock\n");
|
||||
goto err_of_node_put;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(ebu_host->clk);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to enable clock: %d\n", ret);
|
||||
"failed to get and enable clock\n");
|
||||
goto err_of_node_put;
|
||||
}
|
||||
|
||||
@ -643,7 +637,7 @@ static int ebu_nand_probe(struct platform_device *pdev)
|
||||
if (IS_ERR(ebu_host->dma_tx)) {
|
||||
ret = dev_err_probe(dev, PTR_ERR(ebu_host->dma_tx),
|
||||
"failed to request DMA tx chan!.\n");
|
||||
goto err_disable_unprepare_clk;
|
||||
goto err_of_node_put;
|
||||
}
|
||||
|
||||
ebu_host->dma_rx = dma_request_chan(dev, "rx");
|
||||
@ -698,8 +692,6 @@ err_clean_nand:
|
||||
nand_cleanup(&ebu_host->chip);
|
||||
err_cleanup_dma:
|
||||
ebu_dma_cleanup(ebu_host);
|
||||
err_disable_unprepare_clk:
|
||||
clk_disable_unprepare(ebu_host->clk);
|
||||
err_of_node_put:
|
||||
of_node_put(chip_np);
|
||||
|
||||
@ -716,7 +708,6 @@ static void ebu_nand_remove(struct platform_device *pdev)
|
||||
nand_cleanup(&ebu_host->chip);
|
||||
ebu_nand_disable(&ebu_host->chip);
|
||||
ebu_dma_cleanup(ebu_host);
|
||||
clk_disable_unprepare(ebu_host->clk);
|
||||
}
|
||||
|
||||
static const struct of_device_id ebu_nand_match[] = {
|
||||
|
@ -695,8 +695,7 @@ static int lpc32xx_nand_probe(struct platform_device *pdev)
|
||||
|
||||
host->pdev = pdev;
|
||||
|
||||
rc = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
host->io_base = devm_ioremap_resource(&pdev->dev, rc);
|
||||
host->io_base = devm_platform_get_and_ioremap_resource(pdev, 0, &rc);
|
||||
if (IS_ERR(host->io_base))
|
||||
return PTR_ERR(host->io_base);
|
||||
|
||||
|
@ -836,8 +836,7 @@ static int lpc32xx_nand_probe(struct platform_device *pdev)
|
||||
if (!host)
|
||||
return -ENOMEM;
|
||||
|
||||
rc = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
host->io_base = devm_ioremap_resource(&pdev->dev, rc);
|
||||
host->io_base = devm_platform_get_and_ioremap_resource(pdev, 0, &rc);
|
||||
if (IS_ERR(host->io_base))
|
||||
return PTR_ERR(host->io_base);
|
||||
|
||||
@ -872,15 +871,12 @@ static int lpc32xx_nand_probe(struct platform_device *pdev)
|
||||
mtd->dev.parent = &pdev->dev;
|
||||
|
||||
/* Get NAND clock */
|
||||
host->clk = devm_clk_get(&pdev->dev, NULL);
|
||||
host->clk = devm_clk_get_enabled(&pdev->dev, NULL);
|
||||
if (IS_ERR(host->clk)) {
|
||||
dev_err(&pdev->dev, "Clock failure\n");
|
||||
res = -ENOENT;
|
||||
goto enable_wp;
|
||||
}
|
||||
res = clk_prepare_enable(host->clk);
|
||||
if (res)
|
||||
goto enable_wp;
|
||||
|
||||
/* Set NAND IO addresses and command/ready functions */
|
||||
chip->legacy.IO_ADDR_R = SLC_DATA(host->io_base);
|
||||
@ -908,13 +904,13 @@ static int lpc32xx_nand_probe(struct platform_device *pdev)
|
||||
GFP_KERNEL);
|
||||
if (host->data_buf == NULL) {
|
||||
res = -ENOMEM;
|
||||
goto unprepare_clk;
|
||||
goto enable_wp;
|
||||
}
|
||||
|
||||
res = lpc32xx_nand_dma_setup(host);
|
||||
if (res) {
|
||||
res = -EIO;
|
||||
goto unprepare_clk;
|
||||
goto enable_wp;
|
||||
}
|
||||
|
||||
/* Find NAND device */
|
||||
@ -935,8 +931,6 @@ cleanup_nand:
|
||||
nand_cleanup(chip);
|
||||
release_dma:
|
||||
dma_release_channel(host->dma_chan);
|
||||
unprepare_clk:
|
||||
clk_disable_unprepare(host->clk);
|
||||
enable_wp:
|
||||
lpc32xx_wp_enable(host);
|
||||
|
||||
@ -963,7 +957,6 @@ static void lpc32xx_nand_remove(struct platform_device *pdev)
|
||||
tmp &= ~SLCCFG_CE_LOW;
|
||||
writel(tmp, SLC_CTRL(host->io_base));
|
||||
|
||||
clk_disable_unprepare(host->clk);
|
||||
lpc32xx_wp_enable(host);
|
||||
}
|
||||
|
||||
|
@ -376,6 +376,7 @@ static inline struct marvell_nand_chip_sel *to_nand_sel(struct marvell_nand_chip
|
||||
* BCH error detection and correction algorithm,
|
||||
* NDCB3 register has been added
|
||||
* @use_dma: Use dma for data transfers
|
||||
* @max_mode_number: Maximum timing mode supported by the controller
|
||||
*/
|
||||
struct marvell_nfc_caps {
|
||||
unsigned int max_cs_nb;
|
||||
@ -384,6 +385,7 @@ struct marvell_nfc_caps {
|
||||
bool legacy_of_bindings;
|
||||
bool is_nfcv2;
|
||||
bool use_dma;
|
||||
unsigned int max_mode_number;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -2377,6 +2379,9 @@ static int marvell_nfc_setup_interface(struct nand_chip *chip, int chipnr,
|
||||
if (IS_ERR(sdr))
|
||||
return PTR_ERR(sdr);
|
||||
|
||||
if (nfc->caps->max_mode_number && nfc->caps->max_mode_number < conf->timings.mode)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
/*
|
||||
* SDR timings are given in pico-seconds while NFC timings must be
|
||||
* expressed in NAND controller clock cycles, which is half of the
|
||||
@ -3074,6 +3079,13 @@ static const struct marvell_nfc_caps marvell_armada_8k_nfc_caps = {
|
||||
.is_nfcv2 = true,
|
||||
};
|
||||
|
||||
static const struct marvell_nfc_caps marvell_ac5_caps = {
|
||||
.max_cs_nb = 2,
|
||||
.max_rb_nb = 1,
|
||||
.is_nfcv2 = true,
|
||||
.max_mode_number = 3,
|
||||
};
|
||||
|
||||
static const struct marvell_nfc_caps marvell_armada370_nfc_caps = {
|
||||
.max_cs_nb = 4,
|
||||
.max_rb_nb = 2,
|
||||
@ -3122,6 +3134,10 @@ static const struct of_device_id marvell_nfc_of_ids[] = {
|
||||
.compatible = "marvell,armada-8k-nand-controller",
|
||||
.data = &marvell_armada_8k_nfc_caps,
|
||||
},
|
||||
{
|
||||
.compatible = "marvell,ac5-nand-controller",
|
||||
.data = &marvell_ac5_caps,
|
||||
},
|
||||
{
|
||||
.compatible = "marvell,armada370-nand-controller",
|
||||
.data = &marvell_armada370_nfc_caps,
|
||||
|
@ -134,6 +134,7 @@ struct meson_nfc_nand_chip {
|
||||
struct meson_nand_ecc {
|
||||
u32 bch;
|
||||
u32 strength;
|
||||
u32 size;
|
||||
};
|
||||
|
||||
struct meson_nfc_data {
|
||||
@ -189,7 +190,8 @@ struct meson_nfc {
|
||||
};
|
||||
|
||||
enum {
|
||||
NFC_ECC_BCH8_1K = 2,
|
||||
NFC_ECC_BCH8_512 = 1,
|
||||
NFC_ECC_BCH8_1K,
|
||||
NFC_ECC_BCH24_1K,
|
||||
NFC_ECC_BCH30_1K,
|
||||
NFC_ECC_BCH40_1K,
|
||||
@ -197,15 +199,16 @@ enum {
|
||||
NFC_ECC_BCH60_1K,
|
||||
};
|
||||
|
||||
#define MESON_ECC_DATA(b, s) { .bch = (b), .strength = (s)}
|
||||
#define MESON_ECC_DATA(b, s, sz) { .bch = (b), .strength = (s), .size = (sz) }
|
||||
|
||||
static struct meson_nand_ecc meson_ecc[] = {
|
||||
MESON_ECC_DATA(NFC_ECC_BCH8_1K, 8),
|
||||
MESON_ECC_DATA(NFC_ECC_BCH24_1K, 24),
|
||||
MESON_ECC_DATA(NFC_ECC_BCH30_1K, 30),
|
||||
MESON_ECC_DATA(NFC_ECC_BCH40_1K, 40),
|
||||
MESON_ECC_DATA(NFC_ECC_BCH50_1K, 50),
|
||||
MESON_ECC_DATA(NFC_ECC_BCH60_1K, 60),
|
||||
MESON_ECC_DATA(NFC_ECC_BCH8_512, 8, 512),
|
||||
MESON_ECC_DATA(NFC_ECC_BCH8_1K, 8, 1024),
|
||||
MESON_ECC_DATA(NFC_ECC_BCH24_1K, 24, 1024),
|
||||
MESON_ECC_DATA(NFC_ECC_BCH30_1K, 30, 1024),
|
||||
MESON_ECC_DATA(NFC_ECC_BCH40_1K, 40, 1024),
|
||||
MESON_ECC_DATA(NFC_ECC_BCH50_1K, 50, 1024),
|
||||
MESON_ECC_DATA(NFC_ECC_BCH60_1K, 60, 1024),
|
||||
};
|
||||
|
||||
static int meson_nand_calc_ecc_bytes(int step_size, int strength)
|
||||
@ -223,8 +226,27 @@ static int meson_nand_calc_ecc_bytes(int step_size, int strength)
|
||||
|
||||
NAND_ECC_CAPS_SINGLE(meson_gxl_ecc_caps,
|
||||
meson_nand_calc_ecc_bytes, 1024, 8, 24, 30, 40, 50, 60);
|
||||
NAND_ECC_CAPS_SINGLE(meson_axg_ecc_caps,
|
||||
meson_nand_calc_ecc_bytes, 1024, 8);
|
||||
|
||||
static const int axg_stepinfo_strengths[] = { 8 };
|
||||
|
||||
static const struct nand_ecc_step_info axg_stepinfo[] = {
|
||||
{
|
||||
.stepsize = 1024,
|
||||
.strengths = axg_stepinfo_strengths,
|
||||
.nstrengths = ARRAY_SIZE(axg_stepinfo_strengths)
|
||||
},
|
||||
{
|
||||
.stepsize = 512,
|
||||
.strengths = axg_stepinfo_strengths,
|
||||
.nstrengths = ARRAY_SIZE(axg_stepinfo_strengths)
|
||||
},
|
||||
};
|
||||
|
||||
static const struct nand_ecc_caps meson_axg_ecc_caps = {
|
||||
.stepinfos = axg_stepinfo,
|
||||
.nstepinfos = ARRAY_SIZE(axg_stepinfo),
|
||||
.calc_ecc_bytes = meson_nand_calc_ecc_bytes,
|
||||
};
|
||||
|
||||
static struct meson_nfc_nand_chip *to_meson_nand(struct nand_chip *nand)
|
||||
{
|
||||
@ -399,9 +421,10 @@ static void meson_nfc_set_data_oob(struct nand_chip *nand,
|
||||
}
|
||||
}
|
||||
|
||||
static int meson_nfc_wait_no_rb_pin(struct meson_nfc *nfc, int timeout_ms,
|
||||
static int meson_nfc_wait_no_rb_pin(struct nand_chip *nand, int timeout_ms,
|
||||
bool need_cmd_read0)
|
||||
{
|
||||
struct meson_nfc *nfc = nand_get_controller_data(nand);
|
||||
u32 cmd, cfg;
|
||||
|
||||
meson_nfc_cmd_idle(nfc, nfc->timing.twb);
|
||||
@ -413,8 +436,7 @@ static int meson_nfc_wait_no_rb_pin(struct meson_nfc *nfc, int timeout_ms,
|
||||
writel(cfg, nfc->reg_base + NFC_REG_CFG);
|
||||
|
||||
reinit_completion(&nfc->completion);
|
||||
cmd = nfc->param.chip_select | NFC_CMD_CLE | NAND_CMD_STATUS;
|
||||
writel(cmd, nfc->reg_base + NFC_REG_CMD);
|
||||
nand_status_op(nand, NULL);
|
||||
|
||||
/* use the max erase time as the maximum clock for waiting R/B */
|
||||
cmd = NFC_CMD_RB | NFC_CMD_RB_INT_NO_PIN | nfc->timing.tbers_max;
|
||||
@ -424,12 +446,8 @@ static int meson_nfc_wait_no_rb_pin(struct meson_nfc *nfc, int timeout_ms,
|
||||
msecs_to_jiffies(timeout_ms)))
|
||||
return -ETIMEDOUT;
|
||||
|
||||
if (need_cmd_read0) {
|
||||
cmd = nfc->param.chip_select | NFC_CMD_CLE | NAND_CMD_READ0;
|
||||
writel(cmd, nfc->reg_base + NFC_REG_CMD);
|
||||
meson_nfc_drain_cmd(nfc);
|
||||
meson_nfc_wait_cmd_finish(nfc, CMD_FIFO_EMPTY_TIMEOUT);
|
||||
}
|
||||
if (need_cmd_read0)
|
||||
nand_exit_status_op(nand);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -462,9 +480,11 @@ static int meson_nfc_wait_rb_pin(struct meson_nfc *nfc, int timeout_ms)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int meson_nfc_queue_rb(struct meson_nfc *nfc, int timeout_ms,
|
||||
static int meson_nfc_queue_rb(struct nand_chip *nand, int timeout_ms,
|
||||
bool need_cmd_read0)
|
||||
{
|
||||
struct meson_nfc *nfc = nand_get_controller_data(nand);
|
||||
|
||||
if (nfc->no_rb_pin) {
|
||||
/* This mode is used when there is no wired R/B pin.
|
||||
* It works like 'nand_soft_waitrdy()', but instead of
|
||||
@ -476,7 +496,7 @@ static int meson_nfc_queue_rb(struct meson_nfc *nfc, int timeout_ms,
|
||||
* needed (for all cases except page programming - this
|
||||
* is reason of 'need_cmd_read0' flag).
|
||||
*/
|
||||
return meson_nfc_wait_no_rb_pin(nfc, timeout_ms,
|
||||
return meson_nfc_wait_no_rb_pin(nand, timeout_ms,
|
||||
need_cmd_read0);
|
||||
} else {
|
||||
return meson_nfc_wait_rb_pin(nfc, timeout_ms);
|
||||
@ -686,7 +706,7 @@ static int meson_nfc_rw_cmd_prepare_and_execute(struct nand_chip *nand,
|
||||
if (in) {
|
||||
nfc->cmdfifo.rw.cmd1 = cs | NFC_CMD_CLE | NAND_CMD_READSTART;
|
||||
writel(nfc->cmdfifo.rw.cmd1, nfc->reg_base + NFC_REG_CMD);
|
||||
meson_nfc_queue_rb(nfc, PSEC_TO_MSEC(sdr->tR_max), true);
|
||||
meson_nfc_queue_rb(nand, PSEC_TO_MSEC(sdr->tR_max), true);
|
||||
} else {
|
||||
meson_nfc_cmd_idle(nfc, nfc->timing.tadl);
|
||||
}
|
||||
@ -732,7 +752,7 @@ static int meson_nfc_write_page_sub(struct nand_chip *nand,
|
||||
|
||||
cmd = nfc->param.chip_select | NFC_CMD_CLE | NAND_CMD_PAGEPROG;
|
||||
writel(cmd, nfc->reg_base + NFC_REG_CMD);
|
||||
meson_nfc_queue_rb(nfc, PSEC_TO_MSEC(sdr->tPROG_max), false);
|
||||
meson_nfc_queue_rb(nand, PSEC_TO_MSEC(sdr->tPROG_max), false);
|
||||
|
||||
meson_nfc_dma_buffer_release(nand, data_len, info_len, DMA_TO_DEVICE);
|
||||
|
||||
@ -1048,7 +1068,7 @@ static int meson_nfc_exec_op(struct nand_chip *nand,
|
||||
break;
|
||||
|
||||
case NAND_OP_WAITRDY_INSTR:
|
||||
meson_nfc_queue_rb(nfc, instr->ctx.waitrdy.timeout_ms,
|
||||
meson_nfc_queue_rb(nand, instr->ctx.waitrdy.timeout_ms,
|
||||
true);
|
||||
if (instr->delay_ns)
|
||||
meson_nfc_cmd_idle(nfc, delay_idle);
|
||||
@ -1258,7 +1278,8 @@ static int meson_nand_bch_mode(struct nand_chip *nand)
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(meson_ecc); i++) {
|
||||
if (meson_ecc[i].strength == nand->ecc.strength) {
|
||||
if (meson_ecc[i].strength == nand->ecc.strength &&
|
||||
meson_ecc[i].size == nand->ecc.size) {
|
||||
meson_chip->bch_mode = meson_ecc[i].bch;
|
||||
return 0;
|
||||
}
|
||||
|
@ -595,8 +595,6 @@ static void mpc5121_nfc_free(struct device *dev, struct mtd_info *mtd)
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct mpc5121_nfc_prv *prv = nand_get_controller_data(chip);
|
||||
|
||||
clk_disable_unprepare(prv->clk);
|
||||
|
||||
if (prv->csreg)
|
||||
iounmap(prv->csreg);
|
||||
}
|
||||
@ -717,17 +715,12 @@ static int mpc5121_nfc_probe(struct platform_device *op)
|
||||
}
|
||||
|
||||
/* Enable NFC clock */
|
||||
clk = devm_clk_get(dev, "ipg");
|
||||
clk = devm_clk_get_enabled(dev, "ipg");
|
||||
if (IS_ERR(clk)) {
|
||||
dev_err(dev, "Unable to acquire NFC clock!\n");
|
||||
dev_err(dev, "Unable to acquire and enable NFC clock!\n");
|
||||
retval = PTR_ERR(clk);
|
||||
goto error;
|
||||
}
|
||||
retval = clk_prepare_enable(clk);
|
||||
if (retval) {
|
||||
dev_err(dev, "Unable to enable NFC clock!\n");
|
||||
goto error;
|
||||
}
|
||||
prv->clk = clk;
|
||||
|
||||
/* Reset NAND Flash controller */
|
||||
|
@ -1118,32 +1118,6 @@ static irqreturn_t mtk_nfc_irq(int irq, void *id)
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int mtk_nfc_enable_clk(struct device *dev, struct mtk_nfc_clk *clk)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = clk_prepare_enable(clk->nfi_clk);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to enable nfi clk\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(clk->pad_clk);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to enable pad clk\n");
|
||||
clk_disable_unprepare(clk->nfi_clk);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mtk_nfc_disable_clk(struct mtk_nfc_clk *clk)
|
||||
{
|
||||
clk_disable_unprepare(clk->nfi_clk);
|
||||
clk_disable_unprepare(clk->pad_clk);
|
||||
}
|
||||
|
||||
static int mtk_nfc_ooblayout_free(struct mtd_info *mtd, int section,
|
||||
struct mtd_oob_region *oob_region)
|
||||
{
|
||||
@ -1545,40 +1519,36 @@ static int mtk_nfc_probe(struct platform_device *pdev)
|
||||
goto release_ecc;
|
||||
}
|
||||
|
||||
nfc->clk.nfi_clk = devm_clk_get(dev, "nfi_clk");
|
||||
nfc->clk.nfi_clk = devm_clk_get_enabled(dev, "nfi_clk");
|
||||
if (IS_ERR(nfc->clk.nfi_clk)) {
|
||||
dev_err(dev, "no clk\n");
|
||||
ret = PTR_ERR(nfc->clk.nfi_clk);
|
||||
goto release_ecc;
|
||||
}
|
||||
|
||||
nfc->clk.pad_clk = devm_clk_get(dev, "pad_clk");
|
||||
nfc->clk.pad_clk = devm_clk_get_enabled(dev, "pad_clk");
|
||||
if (IS_ERR(nfc->clk.pad_clk)) {
|
||||
dev_err(dev, "no pad clk\n");
|
||||
ret = PTR_ERR(nfc->clk.pad_clk);
|
||||
goto release_ecc;
|
||||
}
|
||||
|
||||
ret = mtk_nfc_enable_clk(dev, &nfc->clk);
|
||||
if (ret)
|
||||
goto release_ecc;
|
||||
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq < 0) {
|
||||
ret = -EINVAL;
|
||||
goto clk_disable;
|
||||
goto release_ecc;
|
||||
}
|
||||
|
||||
ret = devm_request_irq(dev, irq, mtk_nfc_irq, 0x0, "mtk-nand", nfc);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to request nfi irq\n");
|
||||
goto clk_disable;
|
||||
goto release_ecc;
|
||||
}
|
||||
|
||||
ret = dma_set_mask(dev, DMA_BIT_MASK(32));
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to set dma mask\n");
|
||||
goto clk_disable;
|
||||
goto release_ecc;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, nfc);
|
||||
@ -1586,14 +1556,11 @@ static int mtk_nfc_probe(struct platform_device *pdev)
|
||||
ret = mtk_nfc_nand_chips_init(dev, nfc);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to init nand chips\n");
|
||||
goto clk_disable;
|
||||
goto release_ecc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
clk_disable:
|
||||
mtk_nfc_disable_clk(&nfc->clk);
|
||||
|
||||
release_ecc:
|
||||
mtk_ecc_release(nfc->ecc);
|
||||
|
||||
@ -1618,7 +1585,6 @@ static void mtk_nfc_remove(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
mtk_ecc_release(nfc->ecc);
|
||||
mtk_nfc_disable_clk(&nfc->clk);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
@ -1626,7 +1592,8 @@ static int mtk_nfc_suspend(struct device *dev)
|
||||
{
|
||||
struct mtk_nfc *nfc = dev_get_drvdata(dev);
|
||||
|
||||
mtk_nfc_disable_clk(&nfc->clk);
|
||||
clk_disable_unprepare(nfc->clk.nfi_clk);
|
||||
clk_disable_unprepare(nfc->clk.pad_clk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1641,9 +1608,18 @@ static int mtk_nfc_resume(struct device *dev)
|
||||
|
||||
udelay(200);
|
||||
|
||||
ret = mtk_nfc_enable_clk(dev, &nfc->clk);
|
||||
if (ret)
|
||||
ret = clk_prepare_enable(nfc->clk.nfi_clk);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to enable nfi clk\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(nfc->clk.pad_clk);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to enable pad clk\n");
|
||||
clk_disable_unprepare(nfc->clk.nfi_clk);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* reset NAND chip if VCC was powered off */
|
||||
list_for_each_entry(chip, &nfc->chips, node) {
|
||||
|
@ -1695,7 +1695,6 @@ static int mxcnd_probe(struct platform_device *pdev)
|
||||
struct nand_chip *this;
|
||||
struct mtd_info *mtd;
|
||||
struct mxc_nand_host *host;
|
||||
struct resource *res;
|
||||
int err = 0;
|
||||
|
||||
/* Allocate memory for MTD device structure and private data */
|
||||
@ -1739,17 +1738,15 @@ static int mxcnd_probe(struct platform_device *pdev)
|
||||
this->options |= NAND_KEEP_TIMINGS;
|
||||
|
||||
if (host->devtype_data->needs_ip) {
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
host->regs_ip = devm_ioremap_resource(&pdev->dev, res);
|
||||
host->regs_ip = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(host->regs_ip))
|
||||
return PTR_ERR(host->regs_ip);
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
|
||||
host->base = devm_platform_ioremap_resource(pdev, 1);
|
||||
} else {
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
host->base = devm_platform_ioremap_resource(pdev, 0);
|
||||
}
|
||||
|
||||
host->base = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(host->base))
|
||||
return PTR_ERR(host->base);
|
||||
|
||||
|
@ -1885,6 +1885,7 @@ int nand_exit_status_op(struct nand_chip *chip)
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nand_exit_status_op);
|
||||
|
||||
/**
|
||||
* nand_erase_op - Do an erase operation
|
||||
|
@ -2219,8 +2219,7 @@ static int omap_nand_probe(struct platform_device *pdev)
|
||||
}
|
||||
}
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
vaddr = devm_ioremap_resource(&pdev->dev, res);
|
||||
vaddr = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
|
||||
if (IS_ERR(vaddr))
|
||||
return PTR_ERR(vaddr);
|
||||
|
||||
|
@ -169,16 +169,10 @@ 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 optional. */
|
||||
info->clk = devm_clk_get_optional(&pdev->dev, NULL);
|
||||
info->clk = devm_clk_get_optional_enabled(&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) {
|
||||
dev_err(&pdev->dev, "failed to prepare clock!\n");
|
||||
return ret;
|
||||
}
|
||||
"failed to get and enable clock!\n");
|
||||
|
||||
/*
|
||||
* This driver assumes that the default ECC engine should be TYPE_SOFT.
|
||||
@ -189,19 +183,13 @@ static int __init orion_nand_probe(struct platform_device *pdev)
|
||||
|
||||
ret = nand_scan(nc, 1);
|
||||
if (ret)
|
||||
goto no_dev;
|
||||
return ret;
|
||||
|
||||
mtd->name = "orion_nand";
|
||||
ret = mtd_device_register(mtd, board->parts, board->nr_parts);
|
||||
if (ret) {
|
||||
if (ret)
|
||||
nand_cleanup(nc);
|
||||
goto no_dev;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
no_dev:
|
||||
clk_disable_unprepare(info->clk);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -215,8 +203,6 @@ static void orion_nand_remove(struct platform_device *pdev)
|
||||
WARN_ON(ret);
|
||||
|
||||
nand_cleanup(chip);
|
||||
|
||||
clk_disable_unprepare(info->clk);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
|
@ -1,209 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Oxford Semiconductor OXNAS NAND driver
|
||||
|
||||
* Copyright (C) 2016 Neil Armstrong <narmstrong@baylibre.com>
|
||||
* Heavily based on plat_nand.c :
|
||||
* Author: Vitaly Wool <vitalywool@gmail.com>
|
||||
* Copyright (C) 2013 Ma Haijun <mahaijuns@gmail.com>
|
||||
* Copyright (C) 2012 John Crispin <blogic@openwrt.org>
|
||||
*/
|
||||
|
||||
#include <linux/err.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/reset.h>
|
||||
#include <linux/mtd/mtd.h>
|
||||
#include <linux/mtd/rawnand.h>
|
||||
#include <linux/mtd/partitions.h>
|
||||
#include <linux/of.h>
|
||||
|
||||
/* Nand commands */
|
||||
#define OXNAS_NAND_CMD_ALE BIT(18)
|
||||
#define OXNAS_NAND_CMD_CLE BIT(19)
|
||||
|
||||
#define OXNAS_NAND_MAX_CHIPS 1
|
||||
|
||||
struct oxnas_nand_ctrl {
|
||||
struct nand_controller base;
|
||||
void __iomem *io_base;
|
||||
struct clk *clk;
|
||||
struct nand_chip *chips[OXNAS_NAND_MAX_CHIPS];
|
||||
unsigned int nchips;
|
||||
};
|
||||
|
||||
static uint8_t oxnas_nand_read_byte(struct nand_chip *chip)
|
||||
{
|
||||
struct oxnas_nand_ctrl *oxnas = nand_get_controller_data(chip);
|
||||
|
||||
return readb(oxnas->io_base);
|
||||
}
|
||||
|
||||
static void oxnas_nand_read_buf(struct nand_chip *chip, u8 *buf, int len)
|
||||
{
|
||||
struct oxnas_nand_ctrl *oxnas = nand_get_controller_data(chip);
|
||||
|
||||
ioread8_rep(oxnas->io_base, buf, len);
|
||||
}
|
||||
|
||||
static void oxnas_nand_write_buf(struct nand_chip *chip, const u8 *buf,
|
||||
int len)
|
||||
{
|
||||
struct oxnas_nand_ctrl *oxnas = nand_get_controller_data(chip);
|
||||
|
||||
iowrite8_rep(oxnas->io_base, buf, len);
|
||||
}
|
||||
|
||||
/* Single CS command control */
|
||||
static void oxnas_nand_cmd_ctrl(struct nand_chip *chip, int cmd,
|
||||
unsigned int ctrl)
|
||||
{
|
||||
struct oxnas_nand_ctrl *oxnas = nand_get_controller_data(chip);
|
||||
|
||||
if (ctrl & NAND_CLE)
|
||||
writeb(cmd, oxnas->io_base + OXNAS_NAND_CMD_CLE);
|
||||
else if (ctrl & NAND_ALE)
|
||||
writeb(cmd, oxnas->io_base + OXNAS_NAND_CMD_ALE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Probe for the NAND device.
|
||||
*/
|
||||
static int oxnas_nand_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
struct device_node *nand_np;
|
||||
struct oxnas_nand_ctrl *oxnas;
|
||||
struct nand_chip *chip;
|
||||
struct mtd_info *mtd;
|
||||
int count = 0;
|
||||
int err = 0;
|
||||
int i;
|
||||
|
||||
/* Allocate memory for the device structure (and zero it) */
|
||||
oxnas = devm_kzalloc(&pdev->dev, sizeof(*oxnas),
|
||||
GFP_KERNEL);
|
||||
if (!oxnas)
|
||||
return -ENOMEM;
|
||||
|
||||
nand_controller_init(&oxnas->base);
|
||||
|
||||
oxnas->io_base = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(oxnas->io_base))
|
||||
return PTR_ERR(oxnas->io_base);
|
||||
|
||||
oxnas->clk = devm_clk_get(&pdev->dev, NULL);
|
||||
if (IS_ERR(oxnas->clk))
|
||||
oxnas->clk = NULL;
|
||||
|
||||
/* Only a single chip node is supported */
|
||||
count = of_get_child_count(np);
|
||||
if (count > 1)
|
||||
return -EINVAL;
|
||||
|
||||
err = clk_prepare_enable(oxnas->clk);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
device_reset_optional(&pdev->dev);
|
||||
|
||||
for_each_child_of_node(np, nand_np) {
|
||||
chip = devm_kzalloc(&pdev->dev, sizeof(struct nand_chip),
|
||||
GFP_KERNEL);
|
||||
if (!chip) {
|
||||
err = -ENOMEM;
|
||||
goto err_release_child;
|
||||
}
|
||||
|
||||
chip->controller = &oxnas->base;
|
||||
|
||||
nand_set_flash_node(chip, nand_np);
|
||||
nand_set_controller_data(chip, oxnas);
|
||||
|
||||
mtd = nand_to_mtd(chip);
|
||||
mtd->dev.parent = &pdev->dev;
|
||||
mtd->priv = chip;
|
||||
|
||||
chip->legacy.cmd_ctrl = oxnas_nand_cmd_ctrl;
|
||||
chip->legacy.read_buf = oxnas_nand_read_buf;
|
||||
chip->legacy.read_byte = oxnas_nand_read_byte;
|
||||
chip->legacy.write_buf = oxnas_nand_write_buf;
|
||||
chip->legacy.chip_delay = 30;
|
||||
|
||||
/* Scan to find existence of the device */
|
||||
err = nand_scan(chip, 1);
|
||||
if (err)
|
||||
goto err_release_child;
|
||||
|
||||
err = mtd_device_register(mtd, NULL, 0);
|
||||
if (err)
|
||||
goto err_cleanup_nand;
|
||||
|
||||
oxnas->chips[oxnas->nchips++] = chip;
|
||||
}
|
||||
|
||||
/* Exit if no chips found */
|
||||
if (!oxnas->nchips) {
|
||||
err = -ENODEV;
|
||||
goto err_clk_unprepare;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, oxnas);
|
||||
|
||||
return 0;
|
||||
|
||||
err_cleanup_nand:
|
||||
nand_cleanup(chip);
|
||||
err_release_child:
|
||||
of_node_put(nand_np);
|
||||
|
||||
for (i = 0; i < oxnas->nchips; i++) {
|
||||
chip = oxnas->chips[i];
|
||||
WARN_ON(mtd_device_unregister(nand_to_mtd(chip)));
|
||||
nand_cleanup(chip);
|
||||
}
|
||||
|
||||
err_clk_unprepare:
|
||||
clk_disable_unprepare(oxnas->clk);
|
||||
return err;
|
||||
}
|
||||
|
||||
static void oxnas_nand_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct oxnas_nand_ctrl *oxnas = platform_get_drvdata(pdev);
|
||||
struct nand_chip *chip;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < oxnas->nchips; i++) {
|
||||
chip = oxnas->chips[i];
|
||||
WARN_ON(mtd_device_unregister(nand_to_mtd(chip)));
|
||||
nand_cleanup(chip);
|
||||
}
|
||||
|
||||
clk_disable_unprepare(oxnas->clk);
|
||||
}
|
||||
|
||||
static const struct of_device_id oxnas_nand_match[] = {
|
||||
{ .compatible = "oxsemi,ox820-nand" },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, oxnas_nand_match);
|
||||
|
||||
static struct platform_driver oxnas_nand_driver = {
|
||||
.probe = oxnas_nand_probe,
|
||||
.remove_new = oxnas_nand_remove,
|
||||
.driver = {
|
||||
.name = "oxnas_nand",
|
||||
.of_match_table = oxnas_nand_match,
|
||||
},
|
||||
};
|
||||
|
||||
module_platform_driver(oxnas_nand_driver);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>");
|
||||
MODULE_DESCRIPTION("Oxnas NAND driver");
|
||||
MODULE_ALIAS("platform:oxnas_nand");
|
File diff suppressed because it is too large
Load Diff
@ -1123,8 +1123,7 @@ static int flctl_probe(struct platform_device *pdev)
|
||||
if (!flctl)
|
||||
return -ENOMEM;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
flctl->reg = devm_ioremap_resource(&pdev->dev, res);
|
||||
flctl->reg = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
|
||||
if (IS_ERR(flctl->reg))
|
||||
return PTR_ERR(flctl->reg);
|
||||
flctl->fifo = res->start + 0x24; /* FLDTFIFO */
|
||||
|
@ -1922,8 +1922,8 @@ static int stm32_fmc2_nfc_probe(struct platform_device *pdev)
|
||||
if (!(nfc->cs_assigned & BIT(chip_cs)))
|
||||
continue;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, mem_region);
|
||||
nfc->data_base[chip_cs] = devm_ioremap_resource(dev, res);
|
||||
nfc->data_base[chip_cs] = devm_platform_get_and_ioremap_resource(pdev,
|
||||
mem_region, &res);
|
||||
if (IS_ERR(nfc->data_base[chip_cs]))
|
||||
return PTR_ERR(nfc->data_base[chip_cs]);
|
||||
|
||||
@ -1951,21 +1951,17 @@ static int stm32_fmc2_nfc_probe(struct platform_device *pdev)
|
||||
|
||||
init_completion(&nfc->complete);
|
||||
|
||||
nfc->clk = devm_clk_get(nfc->cdev, NULL);
|
||||
if (IS_ERR(nfc->clk))
|
||||
nfc->clk = devm_clk_get_enabled(nfc->cdev, NULL);
|
||||
if (IS_ERR(nfc->clk)) {
|
||||
dev_err(dev, "can not get and enable the clock\n");
|
||||
return PTR_ERR(nfc->clk);
|
||||
|
||||
ret = clk_prepare_enable(nfc->clk);
|
||||
if (ret) {
|
||||
dev_err(dev, "can not enable the clock\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
rstc = devm_reset_control_get(dev, NULL);
|
||||
if (IS_ERR(rstc)) {
|
||||
ret = PTR_ERR(rstc);
|
||||
if (ret == -EPROBE_DEFER)
|
||||
goto err_clk_disable;
|
||||
return ret;
|
||||
} else {
|
||||
reset_control_assert(rstc);
|
||||
reset_control_deassert(rstc);
|
||||
@ -2018,9 +2014,6 @@ err_release_dma:
|
||||
sg_free_table(&nfc->dma_data_sg);
|
||||
sg_free_table(&nfc->dma_ecc_sg);
|
||||
|
||||
err_clk_disable:
|
||||
clk_disable_unprepare(nfc->clk);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -2045,8 +2038,6 @@ static void stm32_fmc2_nfc_remove(struct platform_device *pdev)
|
||||
sg_free_table(&nfc->dma_data_sg);
|
||||
sg_free_table(&nfc->dma_ecc_sg);
|
||||
|
||||
clk_disable_unprepare(nfc->clk);
|
||||
|
||||
stm32_fmc2_nfc_wp_enable(nand);
|
||||
}
|
||||
|
||||
|
@ -2086,8 +2086,7 @@ static int sunxi_nfc_probe(struct platform_device *pdev)
|
||||
nand_controller_init(&nfc->controller);
|
||||
INIT_LIST_HEAD(&nfc->chips);
|
||||
|
||||
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
nfc->regs = devm_ioremap_resource(dev, r);
|
||||
nfc->regs = devm_platform_get_and_ioremap_resource(pdev, 0, &r);
|
||||
if (IS_ERR(nfc->regs))
|
||||
return PTR_ERR(nfc->regs);
|
||||
|
||||
@ -2095,37 +2094,26 @@ static int sunxi_nfc_probe(struct platform_device *pdev)
|
||||
if (irq < 0)
|
||||
return irq;
|
||||
|
||||
nfc->ahb_clk = devm_clk_get(dev, "ahb");
|
||||
nfc->ahb_clk = devm_clk_get_enabled(dev, "ahb");
|
||||
if (IS_ERR(nfc->ahb_clk)) {
|
||||
dev_err(dev, "failed to retrieve ahb clk\n");
|
||||
return PTR_ERR(nfc->ahb_clk);
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(nfc->ahb_clk);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
nfc->mod_clk = devm_clk_get(dev, "mod");
|
||||
nfc->mod_clk = devm_clk_get_enabled(dev, "mod");
|
||||
if (IS_ERR(nfc->mod_clk)) {
|
||||
dev_err(dev, "failed to retrieve mod clk\n");
|
||||
ret = PTR_ERR(nfc->mod_clk);
|
||||
goto out_ahb_clk_unprepare;
|
||||
return PTR_ERR(nfc->mod_clk);
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(nfc->mod_clk);
|
||||
if (ret)
|
||||
goto out_ahb_clk_unprepare;
|
||||
|
||||
nfc->reset = devm_reset_control_get_optional_exclusive(dev, "ahb");
|
||||
if (IS_ERR(nfc->reset)) {
|
||||
ret = PTR_ERR(nfc->reset);
|
||||
goto out_mod_clk_unprepare;
|
||||
}
|
||||
if (IS_ERR(nfc->reset))
|
||||
return PTR_ERR(nfc->reset);
|
||||
|
||||
ret = reset_control_deassert(nfc->reset);
|
||||
if (ret) {
|
||||
dev_err(dev, "reset err %d\n", ret);
|
||||
goto out_mod_clk_unprepare;
|
||||
return ret;
|
||||
}
|
||||
|
||||
nfc->caps = of_device_get_match_data(&pdev->dev);
|
||||
@ -2164,10 +2152,6 @@ out_release_dmac:
|
||||
dma_release_channel(nfc->dmac);
|
||||
out_ahb_reset_reassert:
|
||||
reset_control_assert(nfc->reset);
|
||||
out_mod_clk_unprepare:
|
||||
clk_disable_unprepare(nfc->mod_clk);
|
||||
out_ahb_clk_unprepare:
|
||||
clk_disable_unprepare(nfc->ahb_clk);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -2182,8 +2166,6 @@ static void sunxi_nfc_remove(struct platform_device *pdev)
|
||||
|
||||
if (nfc->dmac)
|
||||
dma_release_channel(nfc->dmac);
|
||||
clk_disable_unprepare(nfc->mod_clk);
|
||||
clk_disable_unprepare(nfc->ahb_clk);
|
||||
}
|
||||
|
||||
static const struct sunxi_nfc_caps sunxi_nfc_a10_caps = {
|
||||
|
@ -827,30 +827,24 @@ static int vf610_nfc_probe(struct platform_device *pdev)
|
||||
mtd->name = DRV_NAME;
|
||||
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq <= 0)
|
||||
return -EINVAL;
|
||||
if (irq < 0)
|
||||
return irq;
|
||||
|
||||
nfc->regs = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(nfc->regs))
|
||||
return PTR_ERR(nfc->regs);
|
||||
|
||||
nfc->clk = devm_clk_get(&pdev->dev, NULL);
|
||||
if (IS_ERR(nfc->clk))
|
||||
nfc->clk = devm_clk_get_enabled(&pdev->dev, NULL);
|
||||
if (IS_ERR(nfc->clk)) {
|
||||
dev_err(nfc->dev, "Unable to get and enable clock!\n");
|
||||
return PTR_ERR(nfc->clk);
|
||||
|
||||
err = clk_prepare_enable(nfc->clk);
|
||||
if (err) {
|
||||
dev_err(nfc->dev, "Unable to enable clock!\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
of_id = of_match_device(vf610_nfc_dt_ids, &pdev->dev);
|
||||
if (!of_id) {
|
||||
err = -ENODEV;
|
||||
goto err_disable_clk;
|
||||
}
|
||||
if (!of_id)
|
||||
return -ENODEV;
|
||||
|
||||
nfc->variant = (enum vf610_nfc_variant)of_id->data;
|
||||
nfc->variant = (uintptr_t)of_id->data;
|
||||
|
||||
for_each_available_child_of_node(nfc->dev->of_node, child) {
|
||||
if (of_device_is_compatible(child, "fsl,vf610-nfc-nandcs")) {
|
||||
@ -858,9 +852,8 @@ static int vf610_nfc_probe(struct platform_device *pdev)
|
||||
if (nand_get_flash_node(chip)) {
|
||||
dev_err(nfc->dev,
|
||||
"Only one NAND chip supported!\n");
|
||||
err = -EINVAL;
|
||||
of_node_put(child);
|
||||
goto err_disable_clk;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
nand_set_flash_node(chip, child);
|
||||
@ -869,8 +862,7 @@ static int vf610_nfc_probe(struct platform_device *pdev)
|
||||
|
||||
if (!nand_get_flash_node(chip)) {
|
||||
dev_err(nfc->dev, "NAND chip sub-node missing!\n");
|
||||
err = -ENODEV;
|
||||
goto err_disable_clk;
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
chip->options |= NAND_NO_SUBPAGE_WRITE;
|
||||
@ -880,7 +872,7 @@ static int vf610_nfc_probe(struct platform_device *pdev)
|
||||
err = devm_request_irq(nfc->dev, irq, vf610_nfc_irq, 0, DRV_NAME, nfc);
|
||||
if (err) {
|
||||
dev_err(nfc->dev, "Error requesting IRQ!\n");
|
||||
goto err_disable_clk;
|
||||
return err;
|
||||
}
|
||||
|
||||
vf610_nfc_preinit_controller(nfc);
|
||||
@ -892,7 +884,7 @@ static int vf610_nfc_probe(struct platform_device *pdev)
|
||||
/* Scan the NAND chip */
|
||||
err = nand_scan(chip, 1);
|
||||
if (err)
|
||||
goto err_disable_clk;
|
||||
return err;
|
||||
|
||||
platform_set_drvdata(pdev, nfc);
|
||||
|
||||
@ -904,8 +896,6 @@ static int vf610_nfc_probe(struct platform_device *pdev)
|
||||
|
||||
err_cleanup_nand:
|
||||
nand_cleanup(chip);
|
||||
err_disable_clk:
|
||||
clk_disable_unprepare(nfc->clk);
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -918,7 +908,6 @@ static void vf610_nfc_remove(struct platform_device *pdev)
|
||||
ret = mtd_device_unregister(nand_to_mtd(chip));
|
||||
WARN_ON(ret);
|
||||
nand_cleanup(chip);
|
||||
clk_disable_unprepare(nfc->clk);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
|
@ -121,6 +121,15 @@ static const struct spinand_info esmt_c8_spinand_table[] = {
|
||||
&update_cache_variants),
|
||||
0,
|
||||
SPINAND_ECCINFO(&f50l1g41lb_ooblayout, NULL)),
|
||||
SPINAND_INFO("F50D2G41KA",
|
||||
SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x51),
|
||||
NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),
|
||||
NAND_ECCREQ(8, 512),
|
||||
SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
|
||||
&write_cache_variants,
|
||||
&update_cache_variants),
|
||||
0,
|
||||
SPINAND_ECCINFO(&f50l1g41lb_ooblayout, NULL)),
|
||||
};
|
||||
|
||||
static const struct spinand_manufacturer_ops esmt_spinand_manuf_ops = {
|
||||
|
@ -511,6 +511,26 @@ static const struct spinand_info gigadevice_spinand_table[] = {
|
||||
SPINAND_HAS_QE_BIT,
|
||||
SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
|
||||
gd5fxgq4uexxg_ecc_get_status)),
|
||||
SPINAND_INFO("GD5F1GQ5RExxH",
|
||||
SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x21),
|
||||
NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
|
||||
NAND_ECCREQ(4, 512),
|
||||
SPINAND_INFO_OP_VARIANTS(&read_cache_variants_1gq5,
|
||||
&write_cache_variants,
|
||||
&update_cache_variants),
|
||||
SPINAND_HAS_QE_BIT,
|
||||
SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
|
||||
gd5fxgq4uexxg_ecc_get_status)),
|
||||
SPINAND_INFO("GD5F1GQ4RExxH",
|
||||
SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xc9),
|
||||
NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
|
||||
NAND_ECCREQ(4, 512),
|
||||
SPINAND_INFO_OP_VARIANTS(&read_cache_variants_1gq5,
|
||||
&write_cache_variants,
|
||||
&update_cache_variants),
|
||||
SPINAND_HAS_QE_BIT,
|
||||
SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
|
||||
gd5fxgq4uexxg_ecc_get_status)),
|
||||
};
|
||||
|
||||
static const struct spinand_manufacturer_ops gigadevice_spinand_manuf_ops = {
|
||||
|
@ -266,6 +266,39 @@ static const struct spinand_info toshiba_spinand_table[] = {
|
||||
SPINAND_HAS_QE_BIT,
|
||||
SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
|
||||
tx58cxgxsxraix_ecc_get_status)),
|
||||
/* 1.8V 1Gb (1st generation) */
|
||||
SPINAND_INFO("TC58NYG0S3HBAI4",
|
||||
SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xA1),
|
||||
NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
|
||||
NAND_ECCREQ(8, 512),
|
||||
SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
|
||||
&write_cache_variants,
|
||||
&update_cache_variants),
|
||||
0,
|
||||
SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
|
||||
tx58cxgxsxraix_ecc_get_status)),
|
||||
/* 1.8V 4Gb (1st generation) */
|
||||
SPINAND_INFO("TH58NYG2S3HBAI4",
|
||||
SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xAC),
|
||||
NAND_MEMORG(1, 2048, 128, 64, 4096, 80, 1, 2, 1),
|
||||
NAND_ECCREQ(8, 512),
|
||||
SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
|
||||
&write_cache_x4_variants,
|
||||
&update_cache_x4_variants),
|
||||
SPINAND_HAS_QE_BIT,
|
||||
SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
|
||||
tx58cxgxsxraix_ecc_get_status)),
|
||||
/* 1.8V 8Gb (1st generation) */
|
||||
SPINAND_INFO("TH58NYG3S0HBAI6",
|
||||
SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xA3),
|
||||
NAND_MEMORG(1, 4096, 256, 64, 4096, 80, 1, 1, 1),
|
||||
NAND_ECCREQ(8, 512),
|
||||
SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
|
||||
&write_cache_x4_variants,
|
||||
&update_cache_x4_variants),
|
||||
SPINAND_HAS_QE_BIT,
|
||||
SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
|
||||
tx58cxgxsxraix_ecc_get_status)),
|
||||
};
|
||||
|
||||
static const struct spinand_manufacturer_ops toshiba_spinand_manuf_ops = {
|
||||
|
@ -1540,6 +1540,7 @@ int nand_reset_op(struct nand_chip *chip);
|
||||
int nand_readid_op(struct nand_chip *chip, u8 addr, void *buf,
|
||||
unsigned int len);
|
||||
int nand_status_op(struct nand_chip *chip, u8 *status);
|
||||
int nand_exit_status_op(struct nand_chip *chip);
|
||||
int nand_erase_op(struct nand_chip *chip, unsigned int eraseblock);
|
||||
int nand_read_page_op(struct nand_chip *chip, unsigned int page,
|
||||
unsigned int offset_in_page, void *buf, unsigned int len);
|
||||
|
Loading…
x
Reference in New Issue
Block a user