Lines Matching +full:nand +full:- +full:int +full:- +full:base

1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Freescale UPM NAND driver.
5 * Copyright © 2007-2008 MontaVista Software, Inc.
23 struct nand_controller base; member
42 static int fun_chip_init(struct fsl_upm_nand *fun, in fun_chip_init()
46 struct mtd_info *mtd = nand_to_mtd(&fun->chip); in fun_chip_init()
47 int ret; in fun_chip_init()
50 fun->chip.ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT; in fun_chip_init()
51 fun->chip.ecc.algo = NAND_ECC_ALGO_HAMMING; in fun_chip_init()
52 fun->chip.controller = &fun->base; in fun_chip_init()
53 mtd->dev.parent = fun->dev; in fun_chip_init()
57 return -ENODEV; in fun_chip_init()
59 nand_set_flash_node(&fun->chip, flash_np); in fun_chip_init()
60 mtd->name = devm_kasprintf(fun->dev, GFP_KERNEL, "0x%llx.%pOFn", in fun_chip_init()
61 (u64)io_res->start, in fun_chip_init()
63 if (!mtd->name) { in fun_chip_init()
64 ret = -ENOMEM; in fun_chip_init()
68 ret = nand_scan(&fun->chip, fun->mchip_count); in fun_chip_init()
78 static int func_exec_instr(struct nand_chip *chip, in func_exec_instr()
82 u32 mar, reg_offs = fun->mchip_offsets[fun->mchip_number]; in func_exec_instr()
83 unsigned int i; in func_exec_instr()
87 switch (instr->type) { in func_exec_instr()
89 fsl_upm_start_pattern(&fun->upm, fun->upm_cmd_offset); in func_exec_instr()
90 mar = (instr->ctx.cmd.opcode << (32 - fun->upm.width)) | in func_exec_instr()
92 fsl_upm_run_pattern(&fun->upm, fun->io_base + reg_offs, mar); in func_exec_instr()
93 fsl_upm_end_pattern(&fun->upm); in func_exec_instr()
97 fsl_upm_start_pattern(&fun->upm, fun->upm_addr_offset); in func_exec_instr()
98 for (i = 0; i < instr->ctx.addr.naddrs; i++) { in func_exec_instr()
99 mar = (instr->ctx.addr.addrs[i] << (32 - fun->upm.width)) | in func_exec_instr()
101 fsl_upm_run_pattern(&fun->upm, fun->io_base + reg_offs, mar); in func_exec_instr()
103 fsl_upm_end_pattern(&fun->upm); in func_exec_instr()
107 in = instr->ctx.data.buf.in; in func_exec_instr()
108 for (i = 0; i < instr->ctx.data.len; i++) in func_exec_instr()
109 in[i] = in_8(fun->io_base + reg_offs); in func_exec_instr()
113 out = instr->ctx.data.buf.out; in func_exec_instr()
114 for (i = 0; i < instr->ctx.data.len; i++) in func_exec_instr()
115 out_8(fun->io_base + reg_offs, out[i]); in func_exec_instr()
119 if (!fun->rnb_gpio[fun->mchip_number]) in func_exec_instr()
120 return nand_soft_waitrdy(chip, instr->ctx.waitrdy.timeout_ms); in func_exec_instr()
122 return nand_gpio_waitrdy(chip, fun->rnb_gpio[fun->mchip_number], in func_exec_instr()
123 instr->ctx.waitrdy.timeout_ms); in func_exec_instr()
126 return -EINVAL; in func_exec_instr()
132 static int fun_exec_op(struct nand_chip *chip, const struct nand_operation *op, in fun_exec_op()
136 unsigned int i; in fun_exec_op()
137 int ret; in fun_exec_op()
139 if (op->cs >= NAND_MAX_CHIPS) in fun_exec_op()
140 return -EINVAL; in fun_exec_op()
145 fun->mchip_number = op->cs; in fun_exec_op()
147 for (i = 0; i < op->ninstrs; i++) { in fun_exec_op()
148 ret = func_exec_instr(chip, &op->instrs[i]); in fun_exec_op()
152 if (op->instrs[i].delay_ns) in fun_exec_op()
153 ndelay(op->instrs[i].delay_ns); in fun_exec_op()
163 static int fun_probe(struct platform_device *ofdev) in fun_probe()
168 int ret; in fun_probe()
169 int size; in fun_probe()
170 int i; in fun_probe()
172 fun = devm_kzalloc(&ofdev->dev, sizeof(*fun), GFP_KERNEL); in fun_probe()
174 return -ENOMEM; in fun_probe()
176 fun->io_base = devm_platform_get_and_ioremap_resource(ofdev, 0, &io_res); in fun_probe()
177 if (IS_ERR(fun->io_base)) in fun_probe()
178 return PTR_ERR(fun->io_base); in fun_probe()
180 ret = fsl_upm_find(io_res->start, &fun->upm); in fun_probe()
182 dev_err(&ofdev->dev, "can't find UPM\n"); in fun_probe()
186 prop = of_get_property(ofdev->dev.of_node, "fsl,upm-addr-offset", in fun_probe()
189 dev_err(&ofdev->dev, "can't get UPM address offset\n"); in fun_probe()
190 return -EINVAL; in fun_probe()
192 fun->upm_addr_offset = *prop; in fun_probe()
194 prop = of_get_property(ofdev->dev.of_node, "fsl,upm-cmd-offset", &size); in fun_probe()
196 dev_err(&ofdev->dev, "can't get UPM command offset\n"); in fun_probe()
197 return -EINVAL; in fun_probe()
199 fun->upm_cmd_offset = *prop; in fun_probe()
201 prop = of_get_property(ofdev->dev.of_node, in fun_probe()
202 "fsl,upm-addr-line-cs-offsets", &size); in fun_probe()
204 fun->mchip_count = size / sizeof(uint32_t); in fun_probe()
205 if (fun->mchip_count >= NAND_MAX_CHIPS) { in fun_probe()
206 dev_err(&ofdev->dev, "too much multiple chips\n"); in fun_probe()
207 return -EINVAL; in fun_probe()
209 for (i = 0; i < fun->mchip_count; i++) in fun_probe()
210 fun->mchip_offsets[i] = be32_to_cpu(prop[i]); in fun_probe()
212 fun->mchip_count = 1; in fun_probe()
215 for (i = 0; i < fun->mchip_count; i++) { in fun_probe()
216 fun->rnb_gpio[i] = devm_gpiod_get_index_optional(&ofdev->dev, in fun_probe()
219 if (IS_ERR(fun->rnb_gpio[i])) { in fun_probe()
220 dev_err(&ofdev->dev, "RNB gpio #%d is invalid\n", i); in fun_probe()
221 return PTR_ERR(fun->rnb_gpio[i]); in fun_probe()
225 nand_controller_init(&fun->base); in fun_probe()
226 fun->base.ops = &fun_ops; in fun_probe()
227 fun->dev = &ofdev->dev; in fun_probe()
229 ret = fun_chip_init(fun, ofdev->dev.of_node, io_res); in fun_probe()
233 dev_set_drvdata(&ofdev->dev, fun); in fun_probe()
240 struct fsl_upm_nand *fun = dev_get_drvdata(&ofdev->dev); in fun_remove()
241 struct nand_chip *chip = &fun->chip; in fun_remove()
243 int ret; in fun_remove()
251 { .compatible = "fsl,upm-nand" },
258 .name = "fsl,upm-nand",
269 MODULE_DESCRIPTION("Driver for NAND chips working through Freescale "
270 "LocalBus User-Programmable Machine");