From ccc49eff77bee2885447a032948959a134029fe3 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Wed, 3 Jun 2020 15:49:13 +0200 Subject: mtd: rawnand: fsl_upm: Remove unused mtd var The mtd var in fun_wait_rnb() is now unused, let's get rid of it and fix the warning resulting from this unused var. Fixes: 50a487e7719c ("mtd: rawnand: Pass a nand_chip object to chip->dev_ready()") Signed-off-by: Boris Brezillon Reviewed-by: Miquel Raynal Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20200603134922.1352340-2-boris.brezillon@collabora.com --- drivers/mtd/nand/raw/fsl_upm.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/mtd/nand/raw/fsl_upm.c') diff --git a/drivers/mtd/nand/raw/fsl_upm.c b/drivers/mtd/nand/raw/fsl_upm.c index 627deb26db51..76d1032cd35e 100644 --- a/drivers/mtd/nand/raw/fsl_upm.c +++ b/drivers/mtd/nand/raw/fsl_upm.c @@ -62,7 +62,6 @@ static int fun_chip_ready(struct nand_chip *chip) static void fun_wait_rnb(struct fsl_upm_nand *fun) { if (fun->rnb_gpio[fun->mchip_number] >= 0) { - struct mtd_info *mtd = nand_to_mtd(&fun->chip); int cnt = 1000000; while (--cnt && !fun_chip_ready(&fun->chip)) -- cgit v1.2.3 From 5290833c10b9f997de16f5bd158efcde3f96db54 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Wed, 3 Jun 2020 15:49:14 +0200 Subject: mtd: rawnand: fsl_upm: Get rid of the unused fsl_upm_nand.parts field fsl_upm_nand.parts is unused, let's get rid of it. Signed-off-by: Boris Brezillon Reviewed-by: Miquel Raynal Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20200603134922.1352340-3-boris.brezillon@collabora.com --- drivers/mtd/nand/raw/fsl_upm.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/mtd/nand/raw/fsl_upm.c') diff --git a/drivers/mtd/nand/raw/fsl_upm.c b/drivers/mtd/nand/raw/fsl_upm.c index 76d1032cd35e..6eba2f4a2f5a 100644 --- a/drivers/mtd/nand/raw/fsl_upm.c +++ b/drivers/mtd/nand/raw/fsl_upm.c @@ -29,7 +29,6 @@ struct fsl_upm_nand { struct device *dev; struct nand_chip chip; int last_ctrl; - struct mtd_partition *parts; struct fsl_upm upm; uint8_t upm_addr_offset; uint8_t upm_cmd_offset; -- cgit v1.2.3 From f760bf29f8676b67fda766d3cf1dbc2fe79829e6 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Wed, 3 Jun 2020 15:49:15 +0200 Subject: mtd: rawnand: fsl_upm: Allocate the fsl_upm_nand object using devm_kzalloc() This simplifies the init error path and remove function. Signed-off-by: Boris Brezillon Reviewed-by: Miquel Raynal Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20200603134922.1352340-4-boris.brezillon@collabora.com --- drivers/mtd/nand/raw/fsl_upm.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) (limited to 'drivers/mtd/nand/raw/fsl_upm.c') diff --git a/drivers/mtd/nand/raw/fsl_upm.c b/drivers/mtd/nand/raw/fsl_upm.c index 6eba2f4a2f5a..9cf79c62ef22 100644 --- a/drivers/mtd/nand/raw/fsl_upm.c +++ b/drivers/mtd/nand/raw/fsl_upm.c @@ -205,36 +205,34 @@ static int fun_probe(struct platform_device *ofdev) int size; int i; - fun = kzalloc(sizeof(*fun), GFP_KERNEL); + fun = devm_kzalloc(&ofdev->dev, sizeof(*fun), GFP_KERNEL); if (!fun) return -ENOMEM; ret = of_address_to_resource(ofdev->dev.of_node, 0, &io_res); if (ret) { dev_err(&ofdev->dev, "can't get IO base\n"); - goto err1; + return ret; } ret = fsl_upm_find(io_res.start, &fun->upm); if (ret) { dev_err(&ofdev->dev, "can't find UPM\n"); - goto err1; + return ret; } prop = of_get_property(ofdev->dev.of_node, "fsl,upm-addr-offset", &size); if (!prop || size != sizeof(uint32_t)) { dev_err(&ofdev->dev, "can't get UPM address offset\n"); - ret = -EINVAL; - goto err1; + return -EINVAL; } fun->upm_addr_offset = *prop; prop = of_get_property(ofdev->dev.of_node, "fsl,upm-cmd-offset", &size); if (!prop || size != sizeof(uint32_t)) { dev_err(&ofdev->dev, "can't get UPM command offset\n"); - ret = -EINVAL; - goto err1; + return -EINVAL; } fun->upm_cmd_offset = *prop; @@ -244,7 +242,7 @@ static int fun_probe(struct platform_device *ofdev) fun->mchip_count = size / sizeof(uint32_t); if (fun->mchip_count >= NAND_MAX_CHIPS) { dev_err(&ofdev->dev, "too much multiple chips\n"); - goto err1; + return -EINVAL; } for (i = 0; i < fun->mchip_count; i++) fun->mchip_offsets[i] = be32_to_cpu(prop[i]); @@ -306,8 +304,6 @@ err2: break; gpio_free(fun->rnb_gpio[i]); } -err1: - kfree(fun); return ret; } @@ -330,8 +326,6 @@ static int fun_remove(struct platform_device *ofdev) gpio_free(fun->rnb_gpio[i]); } - kfree(fun); - return 0; } -- cgit v1.2.3 From 0016648cdc45eea00bd585ccb4b2596784f60615 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Wed, 3 Jun 2020 15:49:16 +0200 Subject: mtd: rawnand: fsl_upm: Use devm_kasprintf() to allocate the MTD name This simplifies the init() error path and the remove() handler. Signed-off-by: Boris Brezillon Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20200603134922.1352340-5-boris.brezillon@collabora.com --- drivers/mtd/nand/raw/fsl_upm.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'drivers/mtd/nand/raw/fsl_upm.c') diff --git a/drivers/mtd/nand/raw/fsl_upm.c b/drivers/mtd/nand/raw/fsl_upm.c index 9cf79c62ef22..a3e3a968891d 100644 --- a/drivers/mtd/nand/raw/fsl_upm.c +++ b/drivers/mtd/nand/raw/fsl_upm.c @@ -176,8 +176,9 @@ static int fun_chip_init(struct fsl_upm_nand *fun, return -ENODEV; nand_set_flash_node(&fun->chip, flash_np); - mtd->name = kasprintf(GFP_KERNEL, "0x%llx.%pOFn", (u64)io_res->start, - flash_np); + mtd->name = devm_kasprintf(fun->dev, GFP_KERNEL, "0x%llx.%pOFn", + (u64)io_res->start, + flash_np); if (!mtd->name) { ret = -ENOMEM; goto err; @@ -190,8 +191,6 @@ static int fun_chip_init(struct fsl_upm_nand *fun, ret = mtd_device_register(mtd, NULL, 0); err: of_node_put(flash_np); - if (ret) - kfree(mtd->name); return ret; } @@ -318,7 +317,6 @@ static int fun_remove(struct platform_device *ofdev) ret = mtd_device_unregister(mtd); WARN_ON(ret); nand_cleanup(chip); - kfree(mtd->name); for (i = 0; i < fun->mchip_count; i++) { if (fun->rnb_gpio[i] < 0) -- cgit v1.2.3 From 58c5a0e04dfceb1c64c84553bc909d1aa39a3bd5 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Wed, 3 Jun 2020 15:49:17 +0200 Subject: mtd: rawnand: fsl_upm: Use platform_get_resource() + devm_ioremap_resource() Replace the of_address_to_resource() + devm_ioremap() calls by platform_get_resource() + devm_ioremap_resource() ones which allows us to get rid of one error message since devm_ioremap_resource() already takes care of that. Signed-off-by: Boris Brezillon Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20200603134922.1352340-6-boris.brezillon@collabora.com --- drivers/mtd/nand/raw/fsl_upm.c | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) (limited to 'drivers/mtd/nand/raw/fsl_upm.c') diff --git a/drivers/mtd/nand/raw/fsl_upm.c b/drivers/mtd/nand/raw/fsl_upm.c index a3e3a968891d..54851e9ea784 100644 --- a/drivers/mtd/nand/raw/fsl_upm.c +++ b/drivers/mtd/nand/raw/fsl_upm.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include @@ -197,7 +196,7 @@ err: static int fun_probe(struct platform_device *ofdev) { struct fsl_upm_nand *fun; - struct resource io_res; + struct resource *io_res; const __be32 *prop; int rnb_gpio; int ret; @@ -208,13 +207,12 @@ static int fun_probe(struct platform_device *ofdev) if (!fun) return -ENOMEM; - ret = of_address_to_resource(ofdev->dev.of_node, 0, &io_res); - if (ret) { - dev_err(&ofdev->dev, "can't get IO base\n"); - return ret; - } + io_res = platform_get_resource(ofdev, IORESOURCE_MEM, 0); + fun->io_base = devm_ioremap_resource(&ofdev->dev, io_res); + if (IS_ERR(fun->io_base)) + return PTR_ERR(fun->io_base); - ret = fsl_upm_find(io_res.start, &fun->upm); + ret = fsl_upm_find(io_res->start, &fun->upm); if (ret) { dev_err(&ofdev->dev, "can't find UPM\n"); return ret; @@ -280,17 +278,10 @@ static int fun_probe(struct platform_device *ofdev) fun->wait_flags = FSL_UPM_WAIT_RUN_PATTERN | FSL_UPM_WAIT_WRITE_BYTE; - fun->io_base = devm_ioremap(&ofdev->dev, io_res.start, - resource_size(&io_res)); - if (!fun->io_base) { - ret = -ENOMEM; - goto err2; - } - fun->dev = &ofdev->dev; fun->last_ctrl = NAND_CLE; - ret = fun_chip_init(fun, ofdev->dev.of_node, &io_res); + ret = fun_chip_init(fun, ofdev->dev.of_node, io_res); if (ret) goto err2; -- cgit v1.2.3 From a50895bbdbd433173c698c4a2321b0f02ff19ba1 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Wed, 3 Jun 2020 15:49:18 +0200 Subject: mtd: rawnand: fsl_upm: Use gpio descriptors The integer-based GPIO ids are now deprecated in favor of the GPIO desc API. The PPC platforms have already been converted to GPIOLIB, so let's use gpio descs in the NAND driver too. While at it, we use devm_gpiod_get_index_optional() so we can get rid of the manual gpio desc release done in the init error path and in the remove function. Signed-off-by: Boris Brezillon Reviewed-by: Miquel Raynal Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20200603134922.1352340-7-boris.brezillon@collabora.com --- drivers/mtd/nand/raw/fsl_upm.c | 44 ++++++++++-------------------------------- 1 file changed, 10 insertions(+), 34 deletions(-) (limited to 'drivers/mtd/nand/raw/fsl_upm.c') diff --git a/drivers/mtd/nand/raw/fsl_upm.c b/drivers/mtd/nand/raw/fsl_upm.c index 54851e9ea784..977b7aad419b 100644 --- a/drivers/mtd/nand/raw/fsl_upm.c +++ b/drivers/mtd/nand/raw/fsl_upm.c @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include @@ -32,7 +31,7 @@ struct fsl_upm_nand { uint8_t upm_addr_offset; uint8_t upm_cmd_offset; void __iomem *io_base; - int rnb_gpio[NAND_MAX_CHIPS]; + struct gpio_desc *rnb_gpio[NAND_MAX_CHIPS]; uint32_t mchip_offsets[NAND_MAX_CHIPS]; uint32_t mchip_count; uint32_t mchip_number; @@ -50,7 +49,7 @@ static int fun_chip_ready(struct nand_chip *chip) { struct fsl_upm_nand *fun = to_fsl_upm_nand(nand_to_mtd(chip)); - if (gpio_get_value(fun->rnb_gpio[fun->mchip_number])) + if (gpiod_get_value(fun->rnb_gpio[fun->mchip_number])) return 1; dev_vdbg(fun->dev, "busy\n"); @@ -165,7 +164,7 @@ static int fun_chip_init(struct fsl_upm_nand *fun, if (fun->mchip_count > 1) fun->chip.legacy.select_chip = fun_select_chip; - if (fun->rnb_gpio[0] >= 0) + if (!fun->rnb_gpio[0]) fun->chip.legacy.dev_ready = fun_chip_ready; mtd->dev.parent = fun->dev; @@ -198,7 +197,6 @@ static int fun_probe(struct platform_device *ofdev) struct fsl_upm_nand *fun; struct resource *io_res; const __be32 *prop; - int rnb_gpio; int ret; int size; int i; @@ -248,20 +246,12 @@ static int fun_probe(struct platform_device *ofdev) } for (i = 0; i < fun->mchip_count; i++) { - fun->rnb_gpio[i] = -1; - rnb_gpio = of_get_gpio(ofdev->dev.of_node, i); - if (rnb_gpio >= 0) { - ret = gpio_request(rnb_gpio, dev_name(&ofdev->dev)); - if (ret) { - dev_err(&ofdev->dev, - "can't request RNB gpio #%d\n", i); - goto err2; - } - gpio_direction_input(rnb_gpio); - fun->rnb_gpio[i] = rnb_gpio; - } else if (rnb_gpio == -EINVAL) { + fun->rnb_gpio[i] = devm_gpiod_get_index_optional(&ofdev->dev, + NULL, i, + GPIOD_IN); + if (IS_ERR(fun->rnb_gpio[i])) { dev_err(&ofdev->dev, "RNB gpio #%d is invalid\n", i); - goto err2; + return PTR_ERR(fun->rnb_gpio[i]); } } @@ -283,19 +273,11 @@ static int fun_probe(struct platform_device *ofdev) ret = fun_chip_init(fun, ofdev->dev.of_node, io_res); if (ret) - goto err2; + return ret; dev_set_drvdata(&ofdev->dev, fun); return 0; -err2: - for (i = 0; i < fun->mchip_count; i++) { - if (fun->rnb_gpio[i] < 0) - break; - gpio_free(fun->rnb_gpio[i]); - } - - return ret; } static int fun_remove(struct platform_device *ofdev) @@ -303,18 +285,12 @@ static int fun_remove(struct platform_device *ofdev) struct fsl_upm_nand *fun = dev_get_drvdata(&ofdev->dev); struct nand_chip *chip = &fun->chip; struct mtd_info *mtd = nand_to_mtd(chip); - int ret, i; + int ret; ret = mtd_device_unregister(mtd); WARN_ON(ret); nand_cleanup(chip); - for (i = 0; i < fun->mchip_count; i++) { - if (fun->rnb_gpio[i] < 0) - break; - gpio_free(fun->rnb_gpio[i]); - } - return 0; } -- cgit v1.2.3 From abc846afda664b7f229f32b40bbef738c3511801 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Wed, 3 Jun 2020 15:49:19 +0200 Subject: mtd: rawnand: fsl_upm: Inherit from nand_controller Explicitly inherit from nand_controller instead of relying on the nand_chip.legacy.dummy_controller field. Signed-off-by: Boris Brezillon Reviewed-by: Miquel Raynal Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20200603134922.1352340-8-boris.brezillon@collabora.com --- drivers/mtd/nand/raw/fsl_upm.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/mtd/nand/raw/fsl_upm.c') diff --git a/drivers/mtd/nand/raw/fsl_upm.c b/drivers/mtd/nand/raw/fsl_upm.c index 977b7aad419b..9a63e36825d8 100644 --- a/drivers/mtd/nand/raw/fsl_upm.c +++ b/drivers/mtd/nand/raw/fsl_upm.c @@ -24,6 +24,7 @@ #define FSL_UPM_WAIT_WRITE_BUFFER 0x4 struct fsl_upm_nand { + struct nand_controller base; struct device *dev; struct nand_chip chip; int last_ctrl; @@ -167,6 +168,7 @@ static int fun_chip_init(struct fsl_upm_nand *fun, if (!fun->rnb_gpio[0]) fun->chip.legacy.dev_ready = fun_chip_ready; + fun->chip.controller = &fun->base; mtd->dev.parent = fun->dev; flash_np = of_get_next_child(upm_np, NULL); @@ -268,6 +270,7 @@ static int fun_probe(struct platform_device *ofdev) fun->wait_flags = FSL_UPM_WAIT_RUN_PATTERN | FSL_UPM_WAIT_WRITE_BYTE; + nand_controller_init(&fun->base); fun->dev = &ofdev->dev; fun->last_ctrl = NAND_CLE; -- cgit v1.2.3 From 54309d65776755bcdb9dcf3744cd764fc1e254ea Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Wed, 3 Jun 2020 15:49:20 +0200 Subject: mtd: rawnand: fsl_upm: Implement exec_op() Implement exec_op() so we can get rid of the legacy interface implementation. Signed-off-by: Boris Brezillon Reviewed-by: Miquel Raynal Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20200603134922.1352340-9-boris.brezillon@collabora.com --- drivers/mtd/nand/raw/fsl_upm.c | 86 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) (limited to 'drivers/mtd/nand/raw/fsl_upm.c') diff --git a/drivers/mtd/nand/raw/fsl_upm.c b/drivers/mtd/nand/raw/fsl_upm.c index 9a63e36825d8..03ca20930274 100644 --- a/drivers/mtd/nand/raw/fsl_upm.c +++ b/drivers/mtd/nand/raw/fsl_upm.c @@ -194,6 +194,91 @@ err: return ret; } +static int func_exec_instr(struct nand_chip *chip, + const struct nand_op_instr *instr) +{ + struct fsl_upm_nand *fun = to_fsl_upm_nand(nand_to_mtd(chip)); + u32 mar, reg_offs = fun->mchip_offsets[fun->mchip_number]; + unsigned int i; + const u8 *out; + u8 *in; + + switch (instr->type) { + case NAND_OP_CMD_INSTR: + fsl_upm_start_pattern(&fun->upm, fun->upm_cmd_offset); + mar = (instr->ctx.cmd.opcode << (32 - fun->upm.width)) | + reg_offs; + fsl_upm_run_pattern(&fun->upm, fun->io_base + reg_offs, mar); + fsl_upm_end_pattern(&fun->upm); + return 0; + + case NAND_OP_ADDR_INSTR: + fsl_upm_start_pattern(&fun->upm, fun->upm_addr_offset); + for (i = 0; i < instr->ctx.addr.naddrs; i++) { + mar = (instr->ctx.addr.addrs[i] << (32 - fun->upm.width)) | + reg_offs; + fsl_upm_run_pattern(&fun->upm, fun->io_base + reg_offs, mar); + } + fsl_upm_end_pattern(&fun->upm); + return 0; + + case NAND_OP_DATA_IN_INSTR: + in = instr->ctx.data.buf.in; + for (i = 0; i < instr->ctx.data.len; i++) + in[i] = in_8(fun->io_base + reg_offs); + return 0; + + case NAND_OP_DATA_OUT_INSTR: + out = instr->ctx.data.buf.out; + for (i = 0; i < instr->ctx.data.len; i++) + out_8(fun->io_base + reg_offs, out[i]); + return 0; + + case NAND_OP_WAITRDY_INSTR: + if (!fun->rnb_gpio[fun->mchip_number]) + return nand_soft_waitrdy(chip, instr->ctx.waitrdy.timeout_ms); + + return nand_gpio_waitrdy(chip, fun->rnb_gpio[fun->mchip_number], + instr->ctx.waitrdy.timeout_ms); + + default: + return -EINVAL; + } + + return 0; +} + +static int fun_exec_op(struct nand_chip *chip, const struct nand_operation *op, + bool check_only) +{ + struct fsl_upm_nand *fun = to_fsl_upm_nand(nand_to_mtd(chip)); + unsigned int i; + int ret; + + if (op->cs > NAND_MAX_CHIPS) + return -EINVAL; + + if (check_only) + return 0; + + fun->mchip_number = op->cs; + + for (i = 0; i < op->ninstrs; i++) { + ret = func_exec_instr(chip, &op->instrs[i]); + if (ret) + return ret; + + if (op->instrs[i].delay_ns) + ndelay(op->instrs[i].delay_ns); + } + + return 0; +} + +static const struct nand_controller_ops fun_ops = { + .exec_op = fun_exec_op, +}; + static int fun_probe(struct platform_device *ofdev) { struct fsl_upm_nand *fun; @@ -271,6 +356,7 @@ static int fun_probe(struct platform_device *ofdev) FSL_UPM_WAIT_WRITE_BYTE; nand_controller_init(&fun->base); + fun->base.ops = &fun_ops; fun->dev = &ofdev->dev; fun->last_ctrl = NAND_CLE; -- cgit v1.2.3 From 8fac41ebe2895fccf4bc40347f1638fe845d4936 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Wed, 3 Jun 2020 15:49:21 +0200 Subject: mtd: rawnand: fsl_upm: Get rid of the legacy interface implementation Now that the driver implements exec_op(), we can get rid of the legacy interface implementation. Signed-off-by: Boris Brezillon Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20200603134922.1352340-10-boris.brezillon@collabora.com --- drivers/mtd/nand/raw/fsl_upm.c | 133 ----------------------------------------- 1 file changed, 133 deletions(-) (limited to 'drivers/mtd/nand/raw/fsl_upm.c') diff --git a/drivers/mtd/nand/raw/fsl_upm.c b/drivers/mtd/nand/raw/fsl_upm.c index 03ca20930274..197850aeb261 100644 --- a/drivers/mtd/nand/raw/fsl_upm.c +++ b/drivers/mtd/nand/raw/fsl_upm.c @@ -19,15 +19,10 @@ #include #include -#define FSL_UPM_WAIT_RUN_PATTERN 0x1 -#define FSL_UPM_WAIT_WRITE_BYTE 0x2 -#define FSL_UPM_WAIT_WRITE_BUFFER 0x4 - struct fsl_upm_nand { struct nand_controller base; struct device *dev; struct nand_chip chip; - int last_ctrl; struct fsl_upm upm; uint8_t upm_addr_offset; uint8_t upm_cmd_offset; @@ -36,8 +31,6 @@ struct fsl_upm_nand { uint32_t mchip_offsets[NAND_MAX_CHIPS]; uint32_t mchip_count; uint32_t mchip_number; - int chip_delay; - uint32_t wait_flags; }; static inline struct fsl_upm_nand *to_fsl_upm_nand(struct mtd_info *mtdinfo) @@ -46,105 +39,6 @@ static inline struct fsl_upm_nand *to_fsl_upm_nand(struct mtd_info *mtdinfo) chip); } -static int fun_chip_ready(struct nand_chip *chip) -{ - struct fsl_upm_nand *fun = to_fsl_upm_nand(nand_to_mtd(chip)); - - if (gpiod_get_value(fun->rnb_gpio[fun->mchip_number])) - return 1; - - dev_vdbg(fun->dev, "busy\n"); - return 0; -} - -static void fun_wait_rnb(struct fsl_upm_nand *fun) -{ - if (fun->rnb_gpio[fun->mchip_number] >= 0) { - int cnt = 1000000; - - while (--cnt && !fun_chip_ready(&fun->chip)) - cpu_relax(); - if (!cnt) - dev_err(fun->dev, "tired waiting for RNB\n"); - } else { - ndelay(100); - } -} - -static void fun_cmd_ctrl(struct nand_chip *chip, int cmd, unsigned int ctrl) -{ - struct fsl_upm_nand *fun = to_fsl_upm_nand(nand_to_mtd(chip)); - u32 mar; - - if (!(ctrl & fun->last_ctrl)) { - fsl_upm_end_pattern(&fun->upm); - - if (cmd == NAND_CMD_NONE) - return; - - fun->last_ctrl = ctrl & (NAND_ALE | NAND_CLE); - } - - if (ctrl & NAND_CTRL_CHANGE) { - if (ctrl & NAND_ALE) - fsl_upm_start_pattern(&fun->upm, fun->upm_addr_offset); - else if (ctrl & NAND_CLE) - fsl_upm_start_pattern(&fun->upm, fun->upm_cmd_offset); - } - - mar = (cmd << (32 - fun->upm.width)) | - fun->mchip_offsets[fun->mchip_number]; - fsl_upm_run_pattern(&fun->upm, chip->legacy.IO_ADDR_R, mar); - - if (fun->wait_flags & FSL_UPM_WAIT_RUN_PATTERN) - fun_wait_rnb(fun); -} - -static void fun_select_chip(struct nand_chip *chip, int mchip_nr) -{ - struct fsl_upm_nand *fun = to_fsl_upm_nand(nand_to_mtd(chip)); - - if (mchip_nr == -1) { - chip->legacy.cmd_ctrl(chip, NAND_CMD_NONE, 0 | NAND_CTRL_CHANGE); - } else if (mchip_nr >= 0 && mchip_nr < NAND_MAX_CHIPS) { - fun->mchip_number = mchip_nr; - chip->legacy.IO_ADDR_R = fun->io_base + fun->mchip_offsets[mchip_nr]; - chip->legacy.IO_ADDR_W = chip->legacy.IO_ADDR_R; - } else { - BUG(); - } -} - -static uint8_t fun_read_byte(struct nand_chip *chip) -{ - struct fsl_upm_nand *fun = to_fsl_upm_nand(nand_to_mtd(chip)); - - return in_8(fun->chip.legacy.IO_ADDR_R); -} - -static void fun_read_buf(struct nand_chip *chip, uint8_t *buf, int len) -{ - struct fsl_upm_nand *fun = to_fsl_upm_nand(nand_to_mtd(chip)); - int i; - - for (i = 0; i < len; i++) - buf[i] = in_8(fun->chip.legacy.IO_ADDR_R); -} - -static void fun_write_buf(struct nand_chip *chip, const uint8_t *buf, int len) -{ - struct fsl_upm_nand *fun = to_fsl_upm_nand(nand_to_mtd(chip)); - int i; - - for (i = 0; i < len; i++) { - out_8(fun->chip.legacy.IO_ADDR_W, buf[i]); - if (fun->wait_flags & FSL_UPM_WAIT_WRITE_BYTE) - fun_wait_rnb(fun); - } - if (fun->wait_flags & FSL_UPM_WAIT_WRITE_BUFFER) - fun_wait_rnb(fun); -} - static int fun_chip_init(struct fsl_upm_nand *fun, const struct device_node *upm_np, const struct resource *io_res) @@ -153,21 +47,8 @@ static int fun_chip_init(struct fsl_upm_nand *fun, int ret; struct device_node *flash_np; - fun->chip.legacy.IO_ADDR_R = fun->io_base; - fun->chip.legacy.IO_ADDR_W = fun->io_base; - fun->chip.legacy.cmd_ctrl = fun_cmd_ctrl; - fun->chip.legacy.chip_delay = fun->chip_delay; - fun->chip.legacy.read_byte = fun_read_byte; - fun->chip.legacy.read_buf = fun_read_buf; - fun->chip.legacy.write_buf = fun_write_buf; fun->chip.ecc.mode = NAND_ECC_SOFT; fun->chip.ecc.algo = NAND_ECC_HAMMING; - if (fun->mchip_count > 1) - fun->chip.legacy.select_chip = fun_select_chip; - - if (!fun->rnb_gpio[0]) - fun->chip.legacy.dev_ready = fun_chip_ready; - fun->chip.controller = &fun->base; mtd->dev.parent = fun->dev; @@ -342,23 +223,9 @@ static int fun_probe(struct platform_device *ofdev) } } - prop = of_get_property(ofdev->dev.of_node, "chip-delay", NULL); - if (prop) - fun->chip_delay = be32_to_cpup(prop); - else - fun->chip_delay = 50; - - prop = of_get_property(ofdev->dev.of_node, "fsl,upm-wait-flags", &size); - if (prop && size == sizeof(uint32_t)) - fun->wait_flags = be32_to_cpup(prop); - else - fun->wait_flags = FSL_UPM_WAIT_RUN_PATTERN | - FSL_UPM_WAIT_WRITE_BYTE; - nand_controller_init(&fun->base); fun->base.ops = &fun_ops; fun->dev = &ofdev->dev; - fun->last_ctrl = NAND_CLE; ret = fun_chip_init(fun, ofdev->dev.of_node, io_res); if (ret) -- cgit v1.2.3