From 653c57c7da087be6448f63430e077dd9eae06188 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Sun, 11 Nov 2018 08:55:20 +0100 Subject: mtd: rawnand: vf610: Stop implementing ->select_chip() Now that the CS to be selected is kept in chip->cur_cs and passed in nand_operation->cs, we can get rid of the ->select_chip() implementation and replace it by an internal function which is called from the chip->exec_op() and chip->ecc.read/write_xxx() hooks. Signed-off-by: Boris Brezillon Signed-off-by: Miquel Raynal --- drivers/mtd/nand/raw/vf610_nfc.c | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) (limited to 'drivers/mtd/nand/raw/vf610_nfc.c') diff --git a/drivers/mtd/nand/raw/vf610_nfc.c b/drivers/mtd/nand/raw/vf610_nfc.c index 9814fd4a84cf..49a174e30211 100644 --- a/drivers/mtd/nand/raw/vf610_nfc.c +++ b/drivers/mtd/nand/raw/vf610_nfc.c @@ -487,36 +487,35 @@ static const struct nand_op_parser vf610_nfc_op_parser = NAND_OP_PARSER( NAND_OP_PARSER_PAT_DATA_IN_ELEM(true, PAGE_2K + OOB_MAX)), ); -static int vf610_nfc_exec_op(struct nand_chip *chip, - const struct nand_operation *op, - bool check_only) -{ - return nand_op_parser_exec_op(chip, &vf610_nfc_op_parser, op, - check_only); -} - /* * This function supports Vybrid only (MPC5125 would have full RB and four CS) */ -static void vf610_nfc_select_chip(struct nand_chip *chip, int cs) +static void vf610_nfc_select_target(struct nand_chip *chip, unsigned int cs) { struct vf610_nfc *nfc = mtd_to_nfc(nand_to_mtd(chip)); - u32 tmp = vf610_nfc_read(nfc, NFC_ROW_ADDR); + u32 tmp; /* Vybrid only (MPC5125 would have full RB and four CS) */ if (nfc->variant != NFC_VFC610) return; + tmp = vf610_nfc_read(nfc, NFC_ROW_ADDR); tmp &= ~(ROW_ADDR_CHIP_SEL_RB_MASK | ROW_ADDR_CHIP_SEL_MASK); - - if (cs >= 0) { - tmp |= 1 << ROW_ADDR_CHIP_SEL_RB_SHIFT; - tmp |= BIT(cs) << ROW_ADDR_CHIP_SEL_SHIFT; - } + tmp |= 1 << ROW_ADDR_CHIP_SEL_RB_SHIFT; + tmp |= BIT(cs) << ROW_ADDR_CHIP_SEL_SHIFT; vf610_nfc_write(nfc, NFC_ROW_ADDR, tmp); } +static int vf610_nfc_exec_op(struct nand_chip *chip, + const struct nand_operation *op, + bool check_only) +{ + vf610_nfc_select_target(chip, op->cs); + return nand_op_parser_exec_op(chip, &vf610_nfc_op_parser, op, + check_only); +} + static inline int vf610_nfc_correct_data(struct mtd_info *mtd, uint8_t *dat, uint8_t *oob, int page) { @@ -566,6 +565,8 @@ static int vf610_nfc_read_page(struct nand_chip *chip, uint8_t *buf, u32 row = 0, cmd1 = 0, cmd2 = 0, code = 0; int stat; + vf610_nfc_select_target(chip, chip->cur_cs); + cmd2 |= NAND_CMD_READ0 << CMD_BYTE1_SHIFT; code |= COMMAND_CMD_BYTE1 | COMMAND_CAR_BYTE1 | COMMAND_CAR_BYTE2; @@ -613,6 +614,8 @@ static int vf610_nfc_write_page(struct nand_chip *chip, const uint8_t *buf, u8 status; int ret; + vf610_nfc_select_target(chip, chip->cur_cs); + cmd2 |= NAND_CMD_SEQIN << CMD_BYTE1_SHIFT; code |= COMMAND_CMD_BYTE1 | COMMAND_CAR_BYTE1 | COMMAND_CAR_BYTE2; @@ -877,7 +880,6 @@ static int vf610_nfc_probe(struct platform_device *pdev) } chip->exec_op = vf610_nfc_exec_op; - chip->select_chip = vf610_nfc_select_chip; chip->options |= NAND_NO_SUBPAGE_WRITE; -- cgit v1.2.3 From f2abfeb2078b9682bfeb77f91816fcf2177b3051 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Sun, 11 Nov 2018 08:55:23 +0100 Subject: mtd: rawnand: Move the ->exec_op() method to nand_controller_ops ->exec_op() is a controller method and has nothing to do in the nand_chip struct. Let's move it to the nand_controller_ops struct and adjust the core and drivers accordingly. Signed-off-by: Boris Brezillon Tested-by: Janusz Krzysztofik Signed-off-by: Miquel Raynal --- drivers/mtd/nand/raw/ams-delta.c | 7 ++- drivers/mtd/nand/raw/fsmc_nand.c | 2 +- drivers/mtd/nand/raw/internals.h | 13 ++++- drivers/mtd/nand/raw/marvell_nand.c | 2 +- drivers/mtd/nand/raw/nand_base.c | 51 +++++++++---------- drivers/mtd/nand/raw/nand_hynix.c | 4 +- drivers/mtd/nand/raw/nand_legacy.c | 4 +- drivers/mtd/nand/raw/tegra_nand.c | 2 +- drivers/mtd/nand/raw/vf610_nfc.c | 4 +- include/linux/mtd/rawnand.h | 99 ++++++++++++++++++------------------- 10 files changed, 100 insertions(+), 88 deletions(-) (limited to 'drivers/mtd/nand/raw/vf610_nfc.c') diff --git a/drivers/mtd/nand/raw/ams-delta.c b/drivers/mtd/nand/raw/ams-delta.c index 611c822e967f..f8eb4a419e77 100644 --- a/drivers/mtd/nand/raw/ams-delta.c +++ b/drivers/mtd/nand/raw/ams-delta.c @@ -176,6 +176,10 @@ static int ams_delta_exec_op(struct nand_chip *this, return ret; } +static const struct nand_controller_ops ams_delta_ops = { + .exec_op = ams_delta_exec_op, +}; + /* * Main initialization routine */ @@ -216,8 +220,6 @@ static int ams_delta_init(struct platform_device *pdev) priv->io_base = io_base; nand_set_controller_data(this, priv); - this->exec_op = ams_delta_exec_op; - priv->gpiod_rdy = devm_gpiod_get_optional(&pdev->dev, "rdy", GPIOD_IN); if (IS_ERR(priv->gpiod_rdy)) { err = PTR_ERR(priv->gpiod_rdy); @@ -277,6 +279,7 @@ static int ams_delta_init(struct platform_device *pdev) ams_delta_dir_input(priv, true); /* Initialize the NAND controller object embedded in ams_delta_nand. */ + priv->base.ops = &ams_delta_ops; nand_controller_init(&priv->base); this->controller = &priv->base; diff --git a/drivers/mtd/nand/raw/fsmc_nand.c b/drivers/mtd/nand/raw/fsmc_nand.c index ea69ac6e6d7a..1eb5008e7453 100644 --- a/drivers/mtd/nand/raw/fsmc_nand.c +++ b/drivers/mtd/nand/raw/fsmc_nand.c @@ -995,6 +995,7 @@ static int fsmc_nand_attach_chip(struct nand_chip *nand) static const struct nand_controller_ops fsmc_nand_controller_ops = { .attach_chip = fsmc_nand_attach_chip, + .exec_op = fsmc_exec_op, }; /* @@ -1082,7 +1083,6 @@ static int __init fsmc_nand_probe(struct platform_device *pdev) nand_set_flash_node(nand, pdev->dev.of_node); mtd->dev.parent = &pdev->dev; - nand->exec_op = fsmc_exec_op; /* * Setup default ECC mode. nand_dt_init() called from nand_scan_ident() diff --git a/drivers/mtd/nand/raw/internals.h b/drivers/mtd/nand/raw/internals.h index b62728d5884b..ac66b458566f 100644 --- a/drivers/mtd/nand/raw/internals.h +++ b/drivers/mtd/nand/raw/internals.h @@ -95,16 +95,25 @@ void nand_decode_ext_id(struct nand_chip *chip); void panic_nand_wait(struct nand_chip *chip, unsigned long timeo); void sanitize_string(uint8_t *s, size_t len); +static inline bool nand_has_exec_op(struct nand_chip *chip) +{ + if (!chip->controller || !chip->controller->ops || + !chip->controller->ops->exec_op) + return false; + + return true; +} + static inline int nand_exec_op(struct nand_chip *chip, const struct nand_operation *op) { - if (!chip->exec_op) + if (!nand_has_exec_op(chip)) return -ENOTSUPP; if (WARN_ON(op->cs >= chip->numchips)) return -EINVAL; - return chip->exec_op(chip, op, false); + return chip->controller->ops->exec_op(chip, op, false); } /* BBT functions */ diff --git a/drivers/mtd/nand/raw/marvell_nand.c b/drivers/mtd/nand/raw/marvell_nand.c index ba7a45fb1905..2e8257fe7d00 100644 --- a/drivers/mtd/nand/raw/marvell_nand.c +++ b/drivers/mtd/nand/raw/marvell_nand.c @@ -2505,6 +2505,7 @@ static int marvell_nand_attach_chip(struct nand_chip *chip) static const struct nand_controller_ops marvell_nand_controller_ops = { .attach_chip = marvell_nand_attach_chip, + .exec_op = marvell_nfc_exec_op, }; static int marvell_nand_chip_init(struct device *dev, struct marvell_nfc *nfc, @@ -2627,7 +2628,6 @@ static int marvell_nand_chip_init(struct device *dev, struct marvell_nfc *nfc, chip->controller = &nfc->controller; nand_set_flash_node(chip, np); - chip->exec_op = marvell_nfc_exec_op; if (!of_property_read_bool(np, "marvell,nand-keep-config")) chip->setup_data_interface = marvell_nfc_setup_data_interface; diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c index cef6633fdce9..eabef6a3857e 100644 --- a/drivers/mtd/nand/raw/nand_base.c +++ b/drivers/mtd/nand/raw/nand_base.c @@ -678,7 +678,7 @@ int nand_soft_waitrdy(struct nand_chip *chip, unsigned long timeout_ms) u8 status = 0; int ret; - if (!chip->exec_op) + if (!nand_has_exec_op(chip)) return -ENOTSUPP; /* Wait tWB before polling the STATUS reg. */ @@ -1117,7 +1117,7 @@ int nand_read_page_op(struct nand_chip *chip, unsigned int page, if (offset_in_page + len > mtd->writesize + mtd->oobsize) return -EINVAL; - if (chip->exec_op) { + if (nand_has_exec_op(chip)) { if (mtd->writesize > 512) return nand_lp_exec_read_page_op(chip, page, offset_in_page, buf, @@ -1156,7 +1156,7 @@ int nand_read_param_page_op(struct nand_chip *chip, u8 page, void *buf, if (len && !buf) return -EINVAL; - if (chip->exec_op) { + if (nand_has_exec_op(chip)) { const struct nand_sdr_timings *sdr = nand_get_sdr_timings(&chip->data_interface); struct nand_op_instr instrs[] = { @@ -1211,7 +1211,7 @@ int nand_change_read_column_op(struct nand_chip *chip, if (mtd->writesize <= 512) return -ENOTSUPP; - if (chip->exec_op) { + if (nand_has_exec_op(chip)) { const struct nand_sdr_timings *sdr = nand_get_sdr_timings(&chip->data_interface); u8 addrs[2] = {}; @@ -1270,7 +1270,7 @@ int nand_read_oob_op(struct nand_chip *chip, unsigned int page, if (offset_in_oob + len > mtd->oobsize) return -EINVAL; - if (chip->exec_op) + if (nand_has_exec_op(chip)) return nand_read_page_op(chip, page, mtd->writesize + offset_in_oob, buf, len); @@ -1383,7 +1383,7 @@ int nand_prog_page_begin_op(struct nand_chip *chip, unsigned int page, if (offset_in_page + len > mtd->writesize + mtd->oobsize) return -EINVAL; - if (chip->exec_op) + if (nand_has_exec_op(chip)) return nand_exec_prog_page_op(chip, page, offset_in_page, buf, len, false); @@ -1410,7 +1410,7 @@ int nand_prog_page_end_op(struct nand_chip *chip) int ret; u8 status; - if (chip->exec_op) { + if (nand_has_exec_op(chip)) { const struct nand_sdr_timings *sdr = nand_get_sdr_timings(&chip->data_interface); struct nand_op_instr instrs[] = { @@ -1469,7 +1469,7 @@ int nand_prog_page_op(struct nand_chip *chip, unsigned int page, if (offset_in_page + len > mtd->writesize + mtd->oobsize) return -EINVAL; - if (chip->exec_op) { + if (nand_has_exec_op(chip)) { status = nand_exec_prog_page_op(chip, page, offset_in_page, buf, len, true); } else { @@ -1517,7 +1517,7 @@ int nand_change_write_column_op(struct nand_chip *chip, if (mtd->writesize <= 512) return -ENOTSUPP; - if (chip->exec_op) { + if (nand_has_exec_op(chip)) { const struct nand_sdr_timings *sdr = nand_get_sdr_timings(&chip->data_interface); u8 addrs[2]; @@ -1572,7 +1572,7 @@ int nand_readid_op(struct nand_chip *chip, u8 addr, void *buf, if (len && !buf) return -EINVAL; - if (chip->exec_op) { + if (nand_has_exec_op(chip)) { const struct nand_sdr_timings *sdr = nand_get_sdr_timings(&chip->data_interface); struct nand_op_instr instrs[] = { @@ -1611,7 +1611,7 @@ EXPORT_SYMBOL_GPL(nand_readid_op); */ int nand_status_op(struct nand_chip *chip, u8 *status) { - if (chip->exec_op) { + if (nand_has_exec_op(chip)) { const struct nand_sdr_timings *sdr = nand_get_sdr_timings(&chip->data_interface); struct nand_op_instr instrs[] = { @@ -1648,7 +1648,7 @@ EXPORT_SYMBOL_GPL(nand_status_op); */ int nand_exit_status_op(struct nand_chip *chip) { - if (chip->exec_op) { + if (nand_has_exec_op(chip)) { struct nand_op_instr instrs[] = { NAND_OP_CMD(NAND_CMD_READ0, 0), }; @@ -1680,7 +1680,7 @@ int nand_erase_op(struct nand_chip *chip, unsigned int eraseblock) int ret; u8 status; - if (chip->exec_op) { + if (nand_has_exec_op(chip)) { const struct nand_sdr_timings *sdr = nand_get_sdr_timings(&chip->data_interface); u8 addrs[3] = { page, page >> 8, page >> 16 }; @@ -1739,7 +1739,7 @@ static int nand_set_features_op(struct nand_chip *chip, u8 feature, const u8 *params = data; int i, ret; - if (chip->exec_op) { + if (nand_has_exec_op(chip)) { const struct nand_sdr_timings *sdr = nand_get_sdr_timings(&chip->data_interface); struct nand_op_instr instrs[] = { @@ -1786,7 +1786,7 @@ static int nand_get_features_op(struct nand_chip *chip, u8 feature, u8 *params = data; int i; - if (chip->exec_op) { + if (nand_has_exec_op(chip)) { const struct nand_sdr_timings *sdr = nand_get_sdr_timings(&chip->data_interface); struct nand_op_instr instrs[] = { @@ -1812,7 +1812,7 @@ static int nand_get_features_op(struct nand_chip *chip, u8 feature, static int nand_wait_rdy_op(struct nand_chip *chip, unsigned int timeout_ms, unsigned int delay_ns) { - if (chip->exec_op) { + if (nand_has_exec_op(chip)) { struct nand_op_instr instrs[] = { NAND_OP_WAIT_RDY(PSEC_TO_MSEC(timeout_ms), PSEC_TO_NSEC(delay_ns)), @@ -1843,7 +1843,7 @@ static int nand_wait_rdy_op(struct nand_chip *chip, unsigned int timeout_ms, */ int nand_reset_op(struct nand_chip *chip) { - if (chip->exec_op) { + if (nand_has_exec_op(chip)) { const struct nand_sdr_timings *sdr = nand_get_sdr_timings(&chip->data_interface); struct nand_op_instr instrs[] = { @@ -1880,7 +1880,7 @@ int nand_read_data_op(struct nand_chip *chip, void *buf, unsigned int len, if (!len || !buf) return -EINVAL; - if (chip->exec_op) { + if (nand_has_exec_op(chip)) { struct nand_op_instr instrs[] = { NAND_OP_DATA_IN(len, buf, 0), }; @@ -1924,7 +1924,7 @@ int nand_write_data_op(struct nand_chip *chip, const void *buf, if (!len || !buf) return -EINVAL; - if (chip->exec_op) { + if (nand_has_exec_op(chip)) { struct nand_op_instr instrs[] = { NAND_OP_DATA_OUT(len, buf, 0), }; @@ -4417,13 +4417,14 @@ static void nand_shutdown(struct mtd_info *mtd) /* Set default functions */ static void nand_set_defaults(struct nand_chip *chip) { - nand_legacy_set_defaults(chip); - + /* If no controller is provided, use the dummy one. */ if (!chip->controller) { chip->controller = &chip->dummy_controller; nand_controller_init(chip->controller); } + nand_legacy_set_defaults(chip); + if (!chip->buf_align) chip->buf_align = 1; } @@ -5025,10 +5026,6 @@ static int nand_scan_ident(struct nand_chip *chip, unsigned int maxchips, if (!mtd->name && mtd->dev.parent) mtd->name = dev_name(mtd->dev.parent); - ret = nand_legacy_check_hooks(chip); - if (ret) - return ret; - /* * Start with chips->numchips = maxchips to let nand_select_target() do * its job. chip->numchips will be adjusted after. @@ -5038,6 +5035,10 @@ static int nand_scan_ident(struct nand_chip *chip, unsigned int maxchips, /* Set the default functions */ nand_set_defaults(chip); + ret = nand_legacy_check_hooks(chip); + if (ret) + return ret; + /* Read the flash type */ ret = nand_detect(chip, table); if (ret) { diff --git a/drivers/mtd/nand/raw/nand_hynix.c b/drivers/mtd/nand/raw/nand_hynix.c index 1e4499d01e14..343f477362d1 100644 --- a/drivers/mtd/nand/raw/nand_hynix.c +++ b/drivers/mtd/nand/raw/nand_hynix.c @@ -80,7 +80,7 @@ static bool hynix_nand_has_valid_jedecid(struct nand_chip *chip) static int hynix_nand_cmd_op(struct nand_chip *chip, u8 cmd) { - if (chip->exec_op) { + if (nand_has_exec_op(chip)) { struct nand_op_instr instrs[] = { NAND_OP_CMD(cmd, 0), }; @@ -98,7 +98,7 @@ static int hynix_nand_reg_write_op(struct nand_chip *chip, u8 addr, u8 val) { u16 column = ((u16)addr << 8) | addr; - if (chip->exec_op) { + if (nand_has_exec_op(chip)) { struct nand_op_instr instrs[] = { NAND_OP_ADDR(1, &addr, 0), NAND_OP_8BIT_DATA_OUT(1, &val, 0), diff --git a/drivers/mtd/nand/raw/nand_legacy.c b/drivers/mtd/nand/raw/nand_legacy.c index 4596a538b967..47364237861e 100644 --- a/drivers/mtd/nand/raw/nand_legacy.c +++ b/drivers/mtd/nand/raw/nand_legacy.c @@ -577,7 +577,7 @@ void nand_legacy_set_defaults(struct nand_chip *chip) { unsigned int busw = chip->options & NAND_BUSWIDTH_16; - if (chip->exec_op) + if (nand_has_exec_op(chip)) return; /* check for proper chip_delay setup, set 20us if not */ @@ -621,7 +621,7 @@ int nand_legacy_check_hooks(struct nand_chip *chip) * ->legacy.cmdfunc() is legacy and will only be used if ->exec_op() is * not populated. */ - if (chip->exec_op) + if (nand_has_exec_op(chip)) return 0; /* diff --git a/drivers/mtd/nand/raw/tegra_nand.c b/drivers/mtd/nand/raw/tegra_nand.c index 590393d93ffc..2fe6de09f4ff 100644 --- a/drivers/mtd/nand/raw/tegra_nand.c +++ b/drivers/mtd/nand/raw/tegra_nand.c @@ -1050,6 +1050,7 @@ static int tegra_nand_attach_chip(struct nand_chip *chip) static const struct nand_controller_ops tegra_nand_controller_ops = { .attach_chip = &tegra_nand_attach_chip, + .exec_op = tegra_nand_exec_op, }; static int tegra_nand_chips_init(struct device *dev, @@ -1112,7 +1113,6 @@ static int tegra_nand_chips_init(struct device *dev, mtd->name = "tegra_nand"; chip->options = NAND_NO_SUBPAGE_WRITE | NAND_USE_BOUNCE_BUFFER; - chip->exec_op = tegra_nand_exec_op; chip->setup_data_interface = tegra_nand_setup_data_interface; ret = nand_scan(chip, 1); diff --git a/drivers/mtd/nand/raw/vf610_nfc.c b/drivers/mtd/nand/raw/vf610_nfc.c index 49a174e30211..0fa7cac4ce14 100644 --- a/drivers/mtd/nand/raw/vf610_nfc.c +++ b/drivers/mtd/nand/raw/vf610_nfc.c @@ -812,6 +812,8 @@ static int vf610_nfc_attach_chip(struct nand_chip *chip) static const struct nand_controller_ops vf610_nfc_controller_ops = { .attach_chip = vf610_nfc_attach_chip, + .exec_op = vf610_nfc_exec_op, + }; static int vf610_nfc_probe(struct platform_device *pdev) @@ -879,8 +881,6 @@ static int vf610_nfc_probe(struct platform_device *pdev) goto err_disable_clk; } - chip->exec_op = vf610_nfc_exec_op; - chip->options |= NAND_NO_SUBPAGE_WRITE; init_completion(&nfc->cmd_done); diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h index 40b74fb1792d..297b40c56403 100644 --- a/include/linux/mtd/rawnand.h +++ b/include/linux/mtd/rawnand.h @@ -240,49 +240,6 @@ struct nand_id { int len; }; -/** - * struct nand_controller_ops - Controller operations - * - * @attach_chip: this method is called after the NAND detection phase after - * flash ID and MTD fields such as erase size, page size and OOB - * size have been set up. ECC requirements are available if - * provided by the NAND chip or device tree. Typically used to - * choose the appropriate ECC configuration and allocate - * associated resources. - * This hook is optional. - * @detach_chip: free all resources allocated/claimed in - * nand_controller_ops->attach_chip(). - * This hook is optional. - */ -struct nand_controller_ops { - int (*attach_chip)(struct nand_chip *chip); - void (*detach_chip)(struct nand_chip *chip); -}; - -/** - * struct nand_controller - Structure used to describe a NAND controller - * - * @lock: protection lock - * @active: the mtd device which holds the controller currently - * @wq: wait queue to sleep on if a NAND operation is in - * progress used instead of the per chip wait queue - * when a hw controller is available. - * @ops: NAND controller operations. - */ -struct nand_controller { - spinlock_t lock; - struct nand_chip *active; - wait_queue_head_t wq; - const struct nand_controller_ops *ops; -}; - -static inline void nand_controller_init(struct nand_controller *nfc) -{ - nfc->active = NULL; - spin_lock_init(&nfc->lock); - init_waitqueue_head(&nfc->wq); -} - /** * struct nand_ecc_step_info - ECC step information of ECC engine * @stepsize: data bytes per ECC step @@ -897,6 +854,55 @@ struct nand_operation { int nand_op_parser_exec_op(struct nand_chip *chip, const struct nand_op_parser *parser, const struct nand_operation *op, bool check_only); +/** + * struct nand_controller_ops - Controller operations + * + * @attach_chip: this method is called after the NAND detection phase after + * flash ID and MTD fields such as erase size, page size and OOB + * size have been set up. ECC requirements are available if + * provided by the NAND chip or device tree. Typically used to + * choose the appropriate ECC configuration and allocate + * associated resources. + * This hook is optional. + * @detach_chip: free all resources allocated/claimed in + * nand_controller_ops->attach_chip(). + * This hook is optional. + * @exec_op: controller specific method to execute NAND operations. + * This method replaces chip->legacy.cmdfunc(), + * chip->legacy.{read,write}_{buf,byte,word}(), + * chip->legacy.dev_ready() and chip->legacy.waifunc(). + */ +struct nand_controller_ops { + int (*attach_chip)(struct nand_chip *chip); + void (*detach_chip)(struct nand_chip *chip); + int (*exec_op)(struct nand_chip *chip, + const struct nand_operation *op, + bool check_only); +}; + +/** + * struct nand_controller - Structure used to describe a NAND controller + * + * @lock: protection lock + * @active: the mtd device which holds the controller currently + * @wq: wait queue to sleep on if a NAND operation is in + * progress used instead of the per chip wait queue + * when a hw controller is available. + * @ops: NAND controller operations. + */ +struct nand_controller { + spinlock_t lock; + struct nand_chip *active; + wait_queue_head_t wq; + const struct nand_controller_ops *ops; +}; + +static inline void nand_controller_init(struct nand_controller *nfc) +{ + nfc->active = NULL; + spin_lock_init(&nfc->lock); + init_waitqueue_head(&nfc->wq); +} /** * struct nand_legacy - NAND chip legacy fields/hooks @@ -956,10 +962,6 @@ struct nand_legacy { * you're modifying an existing driver that is using those * fields/hooks, you should consider reworking the driver * avoid using them. - * @exec_op: controller specific method to execute NAND operations. - * This method replaces ->cmdfunc(), - * ->legacy.{read,write}_{buf,byte,word}(), - * ->legacy.dev_ready() and ->waifunc(). * @setup_read_retry: [FLASHSPECIFIC] flash (vendor) specific function for * setting the read-retry mode. Mostly needed for MLC NAND. * @ecc: [BOARDSPECIFIC] ECC control structure @@ -1041,9 +1043,6 @@ struct nand_chip { struct nand_legacy legacy; - int (*exec_op)(struct nand_chip *chip, - const struct nand_operation *op, - bool check_only); int (*setup_read_retry)(struct nand_chip *chip, int retry_mode); int (*setup_data_interface)(struct nand_chip *chip, int chipnr, const struct nand_data_interface *conf); -- cgit v1.2.3 From 4440f781969dcc28d8af0e66a6d6d741845bb67b Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Tue, 20 Nov 2018 10:02:36 +0100 Subject: mtd: rawnand: vf610: Stop passing mtd_info to internal functions Mimic what has been done in the core and avoid passing mtd_info object internally. Signed-off-by: Boris Brezillon Reviewed-by: Stefan Agner Signed-off-by: Miquel Raynal --- drivers/mtd/nand/raw/vf610_nfc.c | 48 ++++++++++++++++------------------------ 1 file changed, 19 insertions(+), 29 deletions(-) (limited to 'drivers/mtd/nand/raw/vf610_nfc.c') diff --git a/drivers/mtd/nand/raw/vf610_nfc.c b/drivers/mtd/nand/raw/vf610_nfc.c index 0fa7cac4ce14..845a639b0595 100644 --- a/drivers/mtd/nand/raw/vf610_nfc.c +++ b/drivers/mtd/nand/raw/vf610_nfc.c @@ -168,11 +168,6 @@ struct vf610_nfc { u32 ecc_mode; }; -static inline struct vf610_nfc *mtd_to_nfc(struct mtd_info *mtd) -{ - return container_of(mtd_to_nand(mtd), struct vf610_nfc, chip); -} - static inline struct vf610_nfc *chip_to_nfc(struct nand_chip *chip) { return container_of(chip, struct vf610_nfc, chip); @@ -316,8 +311,7 @@ static void vf610_nfc_done(struct vf610_nfc *nfc) static irqreturn_t vf610_nfc_irq(int irq, void *data) { - struct mtd_info *mtd = data; - struct vf610_nfc *nfc = mtd_to_nfc(mtd); + struct vf610_nfc *nfc = data; vf610_nfc_clear(nfc, NFC_IRQ_STATUS, IDLE_EN_BIT); complete(&nfc->cmd_done); @@ -492,7 +486,7 @@ static const struct nand_op_parser vf610_nfc_op_parser = NAND_OP_PARSER( */ static void vf610_nfc_select_target(struct nand_chip *chip, unsigned int cs) { - struct vf610_nfc *nfc = mtd_to_nfc(nand_to_mtd(chip)); + struct vf610_nfc *nfc = chip_to_nfc(chip); u32 tmp; /* Vybrid only (MPC5125 would have full RB and four CS) */ @@ -516,10 +510,11 @@ static int vf610_nfc_exec_op(struct nand_chip *chip, check_only); } -static inline int vf610_nfc_correct_data(struct mtd_info *mtd, uint8_t *dat, +static inline int vf610_nfc_correct_data(struct nand_chip *chip, uint8_t *dat, uint8_t *oob, int page) { - struct vf610_nfc *nfc = mtd_to_nfc(mtd); + struct vf610_nfc *nfc = chip_to_nfc(chip); + struct mtd_info *mtd = nand_to_mtd(chip); u32 ecc_status_off = NFC_MAIN_AREA(0) + ECC_SRAM_ADDR + ECC_STATUS; u8 ecc_status; u8 ecc_count; @@ -559,8 +554,8 @@ static void vf610_nfc_fill_row(struct nand_chip *chip, int page, u32 *code, static int vf610_nfc_read_page(struct nand_chip *chip, uint8_t *buf, int oob_required, int page) { + struct vf610_nfc *nfc = chip_to_nfc(chip); struct mtd_info *mtd = nand_to_mtd(chip); - struct vf610_nfc *nfc = mtd_to_nfc(mtd); int trfr_sz = mtd->writesize + mtd->oobsize; u32 row = 0, cmd1 = 0, cmd2 = 0, code = 0; int stat; @@ -593,7 +588,7 @@ static int vf610_nfc_read_page(struct nand_chip *chip, uint8_t *buf, mtd->writesize, mtd->oobsize, false); - stat = vf610_nfc_correct_data(mtd, buf, chip->oob_poi, page); + stat = vf610_nfc_correct_data(chip, buf, chip->oob_poi, page); if (stat < 0) { mtd->ecc_stats.failed++; @@ -607,8 +602,8 @@ static int vf610_nfc_read_page(struct nand_chip *chip, uint8_t *buf, static int vf610_nfc_write_page(struct nand_chip *chip, const uint8_t *buf, int oob_required, int page) { + struct vf610_nfc *nfc = chip_to_nfc(chip); struct mtd_info *mtd = nand_to_mtd(chip); - struct vf610_nfc *nfc = mtd_to_nfc(mtd); int trfr_sz = mtd->writesize + mtd->oobsize; u32 row = 0, cmd1 = 0, cmd2 = 0, code = 0; u8 status; @@ -651,8 +646,7 @@ static int vf610_nfc_write_page(struct nand_chip *chip, const uint8_t *buf, static int vf610_nfc_read_page_raw(struct nand_chip *chip, u8 *buf, int oob_required, int page) { - struct mtd_info *mtd = nand_to_mtd(chip); - struct vf610_nfc *nfc = mtd_to_nfc(mtd); + struct vf610_nfc *nfc = chip_to_nfc(chip); int ret; nfc->data_access = true; @@ -665,8 +659,8 @@ static int vf610_nfc_read_page_raw(struct nand_chip *chip, u8 *buf, static int vf610_nfc_write_page_raw(struct nand_chip *chip, const u8 *buf, int oob_required, int page) { + struct vf610_nfc *nfc = chip_to_nfc(chip); struct mtd_info *mtd = nand_to_mtd(chip); - struct vf610_nfc *nfc = mtd_to_nfc(mtd); int ret; nfc->data_access = true; @@ -684,7 +678,7 @@ static int vf610_nfc_write_page_raw(struct nand_chip *chip, const u8 *buf, static int vf610_nfc_read_oob(struct nand_chip *chip, int page) { - struct vf610_nfc *nfc = mtd_to_nfc(nand_to_mtd(chip)); + struct vf610_nfc *nfc = chip_to_nfc(chip); int ret; nfc->data_access = true; @@ -697,7 +691,7 @@ static int vf610_nfc_read_oob(struct nand_chip *chip, int page) static int vf610_nfc_write_oob(struct nand_chip *chip, int page) { struct mtd_info *mtd = nand_to_mtd(chip); - struct vf610_nfc *nfc = mtd_to_nfc(mtd); + struct vf610_nfc *nfc = chip_to_nfc(chip); int ret; nfc->data_access = true; @@ -754,7 +748,7 @@ static void vf610_nfc_init_controller(struct vf610_nfc *nfc) static int vf610_nfc_attach_chip(struct nand_chip *chip) { struct mtd_info *mtd = nand_to_mtd(chip); - struct vf610_nfc *nfc = mtd_to_nfc(mtd); + struct vf610_nfc *nfc = chip_to_nfc(chip); vf610_nfc_init_controller(nfc); @@ -885,7 +879,7 @@ static int vf610_nfc_probe(struct platform_device *pdev) init_completion(&nfc->cmd_done); - err = devm_request_irq(nfc->dev, irq, vf610_nfc_irq, 0, DRV_NAME, mtd); + 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; @@ -899,7 +893,7 @@ static int vf610_nfc_probe(struct platform_device *pdev) if (err) goto err_disable_clk; - platform_set_drvdata(pdev, mtd); + platform_set_drvdata(pdev, nfc); /* Register device in MTD */ err = mtd_device_register(mtd, NULL, 0); @@ -916,10 +910,9 @@ err_disable_clk: static int vf610_nfc_remove(struct platform_device *pdev) { - struct mtd_info *mtd = platform_get_drvdata(pdev); - struct vf610_nfc *nfc = mtd_to_nfc(mtd); + struct vf610_nfc *nfc = platform_get_drvdata(pdev); - nand_release(mtd_to_nand(mtd)); + nand_release(&nfc->chip); clk_disable_unprepare(nfc->clk); return 0; } @@ -927,8 +920,7 @@ static int vf610_nfc_remove(struct platform_device *pdev) #ifdef CONFIG_PM_SLEEP static int vf610_nfc_suspend(struct device *dev) { - struct mtd_info *mtd = dev_get_drvdata(dev); - struct vf610_nfc *nfc = mtd_to_nfc(mtd); + struct vf610_nfc *nfc = dev_get_drvdata(dev); clk_disable_unprepare(nfc->clk); return 0; @@ -936,11 +928,9 @@ static int vf610_nfc_suspend(struct device *dev) static int vf610_nfc_resume(struct device *dev) { + struct vf610_nfc *nfc = dev_get_drvdata(dev); int err; - struct mtd_info *mtd = dev_get_drvdata(dev); - struct vf610_nfc *nfc = mtd_to_nfc(mtd); - err = clk_prepare_enable(nfc->clk); if (err) return err; -- cgit v1.2.3 From da59b4538c4cddfcd77e1c3e45e087d6b757729b Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Tue, 20 Nov 2018 10:02:37 +0100 Subject: mtd: rawnand: vf610: Stop using the dummy controller obj The dummy controller is kept around to support old drivers. Let's patch this one and declare our own nand_controller instance. Signed-off-by: Boris Brezillon Reviewed-by: Stefan Agner Signed-off-by: Miquel Raynal --- drivers/mtd/nand/raw/vf610_nfc.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers/mtd/nand/raw/vf610_nfc.c') diff --git a/drivers/mtd/nand/raw/vf610_nfc.c b/drivers/mtd/nand/raw/vf610_nfc.c index 845a639b0595..2e8b7e9314a3 100644 --- a/drivers/mtd/nand/raw/vf610_nfc.c +++ b/drivers/mtd/nand/raw/vf610_nfc.c @@ -152,6 +152,7 @@ enum vf610_nfc_variant { }; struct vf610_nfc { + struct nand_controller base; struct nand_chip chip; struct device *dev; void __iomem *regs; @@ -887,8 +888,11 @@ static int vf610_nfc_probe(struct platform_device *pdev) vf610_nfc_preinit_controller(nfc); + nand_controller_init(&nfc->base); + nfc->base.ops = &vf610_nfc_controller_ops; + chip->controller = &nfc->base; + /* Scan the NAND chip */ - chip->dummy_controller.ops = &vf610_nfc_controller_ops; err = nand_scan(chip, 1); if (err) goto err_disable_clk; -- cgit v1.2.3 From 419e5b84a4be6c796e421b82e9673e2fa1ec1b07 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Tue, 20 Nov 2018 10:02:38 +0100 Subject: mtd: rawnand: vf610: Add an SPDX tag to replace the license text Replace the license text by an SPDX tag. Signed-off-by: Boris Brezillon Reviewed-by: Stefan Agner Signed-off-by: Miquel Raynal --- drivers/mtd/nand/raw/vf610_nfc.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'drivers/mtd/nand/raw/vf610_nfc.c') diff --git a/drivers/mtd/nand/raw/vf610_nfc.c b/drivers/mtd/nand/raw/vf610_nfc.c index 2e8b7e9314a3..a662ca1970e5 100644 --- a/drivers/mtd/nand/raw/vf610_nfc.c +++ b/drivers/mtd/nand/raw/vf610_nfc.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright 2009-2015 Freescale Semiconductor, Inc. and others * @@ -10,11 +11,6 @@ * * Based on original driver mpc5121_nfc.c. * - * This is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * * Limitations: * - Untested on MPC5125 and M54418. * - DMA and pipelining not used. -- cgit v1.2.3