Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mtd: nand: jz4780: driver for NAND devices on JZ4780 SoCs

Add a driver for NAND devices connected to the NEMC on JZ4780 SoCs, as
well as the hardware BCH controller. DMA is not currently implemented.

While older 47xx SoCs also have a BCH controller, they are incompatible
with the one in the 4780 due to differing register/bit positions, which
would make implementing a common driver for them quite messy.

Signed-off-by: Alex Smith <alex.smith@imgtec.com>
Cc: Zubair Lutfullah Kakakhel <Zubair.Kakakhel@imgtec.com>
Cc: David Woodhouse <dwmw2@infradead.org>
Cc: linux-mtd@lists.infradead.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Harvey Hunt <harvey.hunt@imgtec.com>
Reviewed-by: Boris Brezillon <boris.brezillon@free-electrons.com>
[Brian: fixed a few small mistakes]
Signed-off-by: Brian Norris <computersforpeace@gmail.com>

authored by

Alex Smith and committed by
Brian Norris
ae02ab00 48bf35de

+857
+7
drivers/mtd/nand/Kconfig
··· 519 519 help 520 520 Enables support for NAND Flash on JZ4740 SoC based boards. 521 521 522 + config MTD_NAND_JZ4780 523 + tristate "Support for NAND on JZ4780 SoC" 524 + depends on MACH_JZ4780 && JZ4780_NEMC 525 + help 526 + Enables support for NAND Flash connected to the NEMC on JZ4780 SoC 527 + based boards, using the BCH controller for hardware error correction. 528 + 522 529 config MTD_NAND_FSMC 523 530 tristate "Support for NAND on ST Micros FSMC" 524 531 depends on PLAT_SPEAR || ARCH_NOMADIK || ARCH_U8500 || MACH_U300
+1
drivers/mtd/nand/Makefile
··· 49 49 obj-$(CONFIG_MTD_NAND_VF610_NFC) += vf610_nfc.o 50 50 obj-$(CONFIG_MTD_NAND_RICOH) += r852.o 51 51 obj-$(CONFIG_MTD_NAND_JZ4740) += jz4740_nand.o 52 + obj-$(CONFIG_MTD_NAND_JZ4780) += jz4780_nand.o jz4780_bch.o 52 53 obj-$(CONFIG_MTD_NAND_GPMI_NAND) += gpmi-nand/ 53 54 obj-$(CONFIG_MTD_NAND_XWAY) += xway_nand.o 54 55 obj-$(CONFIG_MTD_NAND_BCM47XXNFLASH) += bcm47xxnflash/
+381
drivers/mtd/nand/jz4780_bch.c
··· 1 + /* 2 + * JZ4780 BCH controller 3 + * 4 + * Copyright (c) 2015 Imagination Technologies 5 + * Author: Alex Smith <alex.smith@imgtec.com> 6 + * 7 + * This program is free software; you can redistribute it and/or modify it 8 + * under the terms of the GNU General Public License version 2 as published 9 + * by the Free Software Foundation. 10 + */ 11 + 12 + #include <linux/bitops.h> 13 + #include <linux/clk.h> 14 + #include <linux/delay.h> 15 + #include <linux/init.h> 16 + #include <linux/iopoll.h> 17 + #include <linux/module.h> 18 + #include <linux/mutex.h> 19 + #include <linux/of.h> 20 + #include <linux/of_platform.h> 21 + #include <linux/platform_device.h> 22 + #include <linux/sched.h> 23 + #include <linux/slab.h> 24 + 25 + #include "jz4780_bch.h" 26 + 27 + #define BCH_BHCR 0x0 28 + #define BCH_BHCCR 0x8 29 + #define BCH_BHCNT 0xc 30 + #define BCH_BHDR 0x10 31 + #define BCH_BHPAR0 0x14 32 + #define BCH_BHERR0 0x84 33 + #define BCH_BHINT 0x184 34 + #define BCH_BHINTES 0x188 35 + #define BCH_BHINTEC 0x18c 36 + #define BCH_BHINTE 0x190 37 + 38 + #define BCH_BHCR_BSEL_SHIFT 4 39 + #define BCH_BHCR_BSEL_MASK (0x7f << BCH_BHCR_BSEL_SHIFT) 40 + #define BCH_BHCR_ENCE BIT(2) 41 + #define BCH_BHCR_INIT BIT(1) 42 + #define BCH_BHCR_BCHE BIT(0) 43 + 44 + #define BCH_BHCNT_PARITYSIZE_SHIFT 16 45 + #define BCH_BHCNT_PARITYSIZE_MASK (0x7f << BCH_BHCNT_PARITYSIZE_SHIFT) 46 + #define BCH_BHCNT_BLOCKSIZE_SHIFT 0 47 + #define BCH_BHCNT_BLOCKSIZE_MASK (0x7ff << BCH_BHCNT_BLOCKSIZE_SHIFT) 48 + 49 + #define BCH_BHERR_MASK_SHIFT 16 50 + #define BCH_BHERR_MASK_MASK (0xffff << BCH_BHERR_MASK_SHIFT) 51 + #define BCH_BHERR_INDEX_SHIFT 0 52 + #define BCH_BHERR_INDEX_MASK (0x7ff << BCH_BHERR_INDEX_SHIFT) 53 + 54 + #define BCH_BHINT_ERRC_SHIFT 24 55 + #define BCH_BHINT_ERRC_MASK (0x7f << BCH_BHINT_ERRC_SHIFT) 56 + #define BCH_BHINT_TERRC_SHIFT 16 57 + #define BCH_BHINT_TERRC_MASK (0x7f << BCH_BHINT_TERRC_SHIFT) 58 + #define BCH_BHINT_DECF BIT(3) 59 + #define BCH_BHINT_ENCF BIT(2) 60 + #define BCH_BHINT_UNCOR BIT(1) 61 + #define BCH_BHINT_ERR BIT(0) 62 + 63 + #define BCH_CLK_RATE (200 * 1000 * 1000) 64 + 65 + /* Timeout for BCH calculation/correction. */ 66 + #define BCH_TIMEOUT_US 100000 67 + 68 + struct jz4780_bch { 69 + struct device *dev; 70 + void __iomem *base; 71 + struct clk *clk; 72 + struct mutex lock; 73 + }; 74 + 75 + static void jz4780_bch_init(struct jz4780_bch *bch, 76 + struct jz4780_bch_params *params, bool encode) 77 + { 78 + u32 reg; 79 + 80 + /* Clear interrupt status. */ 81 + writel(readl(bch->base + BCH_BHINT), bch->base + BCH_BHINT); 82 + 83 + /* Set up BCH count register. */ 84 + reg = params->size << BCH_BHCNT_BLOCKSIZE_SHIFT; 85 + reg |= params->bytes << BCH_BHCNT_PARITYSIZE_SHIFT; 86 + writel(reg, bch->base + BCH_BHCNT); 87 + 88 + /* Initialise and enable BCH. */ 89 + reg = BCH_BHCR_BCHE | BCH_BHCR_INIT; 90 + reg |= params->strength << BCH_BHCR_BSEL_SHIFT; 91 + if (encode) 92 + reg |= BCH_BHCR_ENCE; 93 + writel(reg, bch->base + BCH_BHCR); 94 + } 95 + 96 + static void jz4780_bch_disable(struct jz4780_bch *bch) 97 + { 98 + writel(readl(bch->base + BCH_BHINT), bch->base + BCH_BHINT); 99 + writel(BCH_BHCR_BCHE, bch->base + BCH_BHCCR); 100 + } 101 + 102 + static void jz4780_bch_write_data(struct jz4780_bch *bch, const void *buf, 103 + size_t size) 104 + { 105 + size_t size32 = size / sizeof(u32); 106 + size_t size8 = size % sizeof(u32); 107 + const u32 *src32; 108 + const u8 *src8; 109 + 110 + src32 = (const u32 *)buf; 111 + while (size32--) 112 + writel(*src32++, bch->base + BCH_BHDR); 113 + 114 + src8 = (const u8 *)src32; 115 + while (size8--) 116 + writeb(*src8++, bch->base + BCH_BHDR); 117 + } 118 + 119 + static void jz4780_bch_read_parity(struct jz4780_bch *bch, void *buf, 120 + size_t size) 121 + { 122 + size_t size32 = size / sizeof(u32); 123 + size_t size8 = size % sizeof(u32); 124 + u32 *dest32; 125 + u8 *dest8; 126 + u32 val, offset = 0; 127 + 128 + dest32 = (u32 *)buf; 129 + while (size32--) { 130 + *dest32++ = readl(bch->base + BCH_BHPAR0 + offset); 131 + offset += sizeof(u32); 132 + } 133 + 134 + dest8 = (u8 *)dest32; 135 + val = readl(bch->base + BCH_BHPAR0 + offset); 136 + switch (size8) { 137 + case 3: 138 + dest8[2] = (val >> 16) & 0xff; 139 + case 2: 140 + dest8[1] = (val >> 8) & 0xff; 141 + case 1: 142 + dest8[0] = val & 0xff; 143 + break; 144 + } 145 + } 146 + 147 + static bool jz4780_bch_wait_complete(struct jz4780_bch *bch, unsigned int irq, 148 + u32 *status) 149 + { 150 + u32 reg; 151 + int ret; 152 + 153 + /* 154 + * While we could use interrupts here and sleep until the operation 155 + * completes, the controller works fairly quickly (usually a few 156 + * microseconds) and so the overhead of sleeping until we get an 157 + * interrupt quite noticeably decreases performance. 158 + */ 159 + ret = readl_poll_timeout(bch->base + BCH_BHINT, reg, 160 + (reg & irq) == irq, 0, BCH_TIMEOUT_US); 161 + if (ret) 162 + return false; 163 + 164 + if (status) 165 + *status = reg; 166 + 167 + writel(reg, bch->base + BCH_BHINT); 168 + return true; 169 + } 170 + 171 + /** 172 + * jz4780_bch_calculate() - calculate ECC for a data buffer 173 + * @bch: BCH device. 174 + * @params: BCH parameters. 175 + * @buf: input buffer with raw data. 176 + * @ecc_code: output buffer with ECC. 177 + * 178 + * Return: 0 on success, -ETIMEDOUT if timed out while waiting for BCH 179 + * controller. 180 + */ 181 + int jz4780_bch_calculate(struct jz4780_bch *bch, struct jz4780_bch_params *params, 182 + const u8 *buf, u8 *ecc_code) 183 + { 184 + int ret = 0; 185 + 186 + mutex_lock(&bch->lock); 187 + jz4780_bch_init(bch, params, true); 188 + jz4780_bch_write_data(bch, buf, params->size); 189 + 190 + if (jz4780_bch_wait_complete(bch, BCH_BHINT_ENCF, NULL)) { 191 + jz4780_bch_read_parity(bch, ecc_code, params->bytes); 192 + } else { 193 + dev_err(bch->dev, "timed out while calculating ECC\n"); 194 + ret = -ETIMEDOUT; 195 + } 196 + 197 + jz4780_bch_disable(bch); 198 + mutex_unlock(&bch->lock); 199 + return ret; 200 + } 201 + EXPORT_SYMBOL(jz4780_bch_calculate); 202 + 203 + /** 204 + * jz4780_bch_correct() - detect and correct bit errors 205 + * @bch: BCH device. 206 + * @params: BCH parameters. 207 + * @buf: raw data read from the chip. 208 + * @ecc_code: ECC read from the chip. 209 + * 210 + * Given the raw data and the ECC read from the NAND device, detects and 211 + * corrects errors in the data. 212 + * 213 + * Return: the number of bit errors corrected, or -1 if there are too many 214 + * errors to correct or we timed out waiting for the controller. 215 + */ 216 + int jz4780_bch_correct(struct jz4780_bch *bch, struct jz4780_bch_params *params, 217 + u8 *buf, u8 *ecc_code) 218 + { 219 + u32 reg, mask, index; 220 + int i, ret, count; 221 + 222 + mutex_lock(&bch->lock); 223 + 224 + jz4780_bch_init(bch, params, false); 225 + jz4780_bch_write_data(bch, buf, params->size); 226 + jz4780_bch_write_data(bch, ecc_code, params->bytes); 227 + 228 + if (!jz4780_bch_wait_complete(bch, BCH_BHINT_DECF, &reg)) { 229 + dev_err(bch->dev, "timed out while correcting data\n"); 230 + ret = -1; 231 + goto out; 232 + } 233 + 234 + if (reg & BCH_BHINT_UNCOR) { 235 + dev_warn(bch->dev, "uncorrectable ECC error\n"); 236 + ret = -1; 237 + goto out; 238 + } 239 + 240 + /* Correct any detected errors. */ 241 + if (reg & BCH_BHINT_ERR) { 242 + count = (reg & BCH_BHINT_ERRC_MASK) >> BCH_BHINT_ERRC_SHIFT; 243 + ret = (reg & BCH_BHINT_TERRC_MASK) >> BCH_BHINT_TERRC_SHIFT; 244 + 245 + for (i = 0; i < count; i++) { 246 + reg = readl(bch->base + BCH_BHERR0 + (i * 4)); 247 + mask = (reg & BCH_BHERR_MASK_MASK) >> 248 + BCH_BHERR_MASK_SHIFT; 249 + index = (reg & BCH_BHERR_INDEX_MASK) >> 250 + BCH_BHERR_INDEX_SHIFT; 251 + buf[(index * 2) + 0] ^= mask; 252 + buf[(index * 2) + 1] ^= mask >> 8; 253 + } 254 + } else { 255 + ret = 0; 256 + } 257 + 258 + out: 259 + jz4780_bch_disable(bch); 260 + mutex_unlock(&bch->lock); 261 + return ret; 262 + } 263 + EXPORT_SYMBOL(jz4780_bch_correct); 264 + 265 + /** 266 + * jz4780_bch_get() - get the BCH controller device 267 + * @np: BCH device tree node. 268 + * 269 + * Gets the BCH controller device from the specified device tree node. The 270 + * device must be released with jz4780_bch_release() when it is no longer being 271 + * used. 272 + * 273 + * Return: a pointer to jz4780_bch, errors are encoded into the pointer. 274 + * PTR_ERR(-EPROBE_DEFER) if the device hasn't been initialised yet. 275 + */ 276 + static struct jz4780_bch *jz4780_bch_get(struct device_node *np) 277 + { 278 + struct platform_device *pdev; 279 + struct jz4780_bch *bch; 280 + 281 + pdev = of_find_device_by_node(np); 282 + if (!pdev || !platform_get_drvdata(pdev)) 283 + return ERR_PTR(-EPROBE_DEFER); 284 + 285 + get_device(&pdev->dev); 286 + 287 + bch = platform_get_drvdata(pdev); 288 + clk_prepare_enable(bch->clk); 289 + 290 + bch->dev = &pdev->dev; 291 + return bch; 292 + } 293 + 294 + /** 295 + * of_jz4780_bch_get() - get the BCH controller from a DT node 296 + * @of_node: the node that contains a bch-controller property. 297 + * 298 + * Get the bch-controller property from the given device tree 299 + * node and pass it to jz4780_bch_get to do the work. 300 + * 301 + * Return: a pointer to jz4780_bch, errors are encoded into the pointer. 302 + * PTR_ERR(-EPROBE_DEFER) if the device hasn't been initialised yet. 303 + */ 304 + struct jz4780_bch *of_jz4780_bch_get(struct device_node *of_node) 305 + { 306 + struct jz4780_bch *bch = NULL; 307 + struct device_node *np; 308 + 309 + np = of_parse_phandle(of_node, "ingenic,bch-controller", 0); 310 + 311 + if (np) { 312 + bch = jz4780_bch_get(np); 313 + of_node_put(np); 314 + } 315 + return bch; 316 + } 317 + EXPORT_SYMBOL(of_jz4780_bch_get); 318 + 319 + /** 320 + * jz4780_bch_release() - release the BCH controller device 321 + * @bch: BCH device. 322 + */ 323 + void jz4780_bch_release(struct jz4780_bch *bch) 324 + { 325 + clk_disable_unprepare(bch->clk); 326 + put_device(bch->dev); 327 + } 328 + EXPORT_SYMBOL(jz4780_bch_release); 329 + 330 + static int jz4780_bch_probe(struct platform_device *pdev) 331 + { 332 + struct device *dev = &pdev->dev; 333 + struct jz4780_bch *bch; 334 + struct resource *res; 335 + 336 + bch = devm_kzalloc(dev, sizeof(*bch), GFP_KERNEL); 337 + if (!bch) 338 + return -ENOMEM; 339 + 340 + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 341 + bch->base = devm_ioremap_resource(dev, res); 342 + if (IS_ERR(bch->base)) 343 + return PTR_ERR(bch->base); 344 + 345 + jz4780_bch_disable(bch); 346 + 347 + bch->clk = devm_clk_get(dev, NULL); 348 + if (IS_ERR(bch->clk)) { 349 + dev_err(dev, "failed to get clock: %ld\n", PTR_ERR(bch->clk)); 350 + return PTR_ERR(bch->clk); 351 + } 352 + 353 + clk_set_rate(bch->clk, BCH_CLK_RATE); 354 + 355 + mutex_init(&bch->lock); 356 + 357 + bch->dev = dev; 358 + platform_set_drvdata(pdev, bch); 359 + 360 + return 0; 361 + } 362 + 363 + static const struct of_device_id jz4780_bch_dt_match[] = { 364 + { .compatible = "ingenic,jz4780-bch" }, 365 + {}, 366 + }; 367 + MODULE_DEVICE_TABLE(of, jz4780_bch_dt_match); 368 + 369 + static struct platform_driver jz4780_bch_driver = { 370 + .probe = jz4780_bch_probe, 371 + .driver = { 372 + .name = "jz4780-bch", 373 + .of_match_table = of_match_ptr(jz4780_bch_dt_match), 374 + }, 375 + }; 376 + module_platform_driver(jz4780_bch_driver); 377 + 378 + MODULE_AUTHOR("Alex Smith <alex@alex-smith.me.uk>"); 379 + MODULE_AUTHOR("Harvey Hunt <harvey.hunt@imgtec.com>"); 380 + MODULE_DESCRIPTION("Ingenic JZ4780 BCH error correction driver"); 381 + MODULE_LICENSE("GPL v2");
+43
drivers/mtd/nand/jz4780_bch.h
··· 1 + /* 2 + * JZ4780 BCH controller 3 + * 4 + * Copyright (c) 2015 Imagination Technologies 5 + * Author: Alex Smith <alex.smith@imgtec.com> 6 + * 7 + * This program is free software; you can redistribute it and/or modify it 8 + * under the terms of the GNU General Public License version 2 as published 9 + * by the Free Software Foundation. 10 + */ 11 + 12 + #ifndef __DRIVERS_MTD_NAND_JZ4780_BCH_H__ 13 + #define __DRIVERS_MTD_NAND_JZ4780_BCH_H__ 14 + 15 + #include <linux/types.h> 16 + 17 + struct device; 18 + struct device_node; 19 + struct jz4780_bch; 20 + 21 + /** 22 + * struct jz4780_bch_params - BCH parameters 23 + * @size: data bytes per ECC step. 24 + * @bytes: ECC bytes per step. 25 + * @strength: number of correctable bits per ECC step. 26 + */ 27 + struct jz4780_bch_params { 28 + int size; 29 + int bytes; 30 + int strength; 31 + }; 32 + 33 + int jz4780_bch_calculate(struct jz4780_bch *bch, 34 + struct jz4780_bch_params *params, 35 + const u8 *buf, u8 *ecc_code); 36 + int jz4780_bch_correct(struct jz4780_bch *bch, 37 + struct jz4780_bch_params *params, u8 *buf, 38 + u8 *ecc_code); 39 + 40 + void jz4780_bch_release(struct jz4780_bch *bch); 41 + struct jz4780_bch *of_jz4780_bch_get(struct device_node *np); 42 + 43 + #endif /* __DRIVERS_MTD_NAND_JZ4780_BCH_H__ */
+425
drivers/mtd/nand/jz4780_nand.c
··· 1 + /* 2 + * JZ4780 NAND driver 3 + * 4 + * Copyright (c) 2015 Imagination Technologies 5 + * Author: Alex Smith <alex.smith@imgtec.com> 6 + * 7 + * This program is free software; you can redistribute it and/or modify it 8 + * under the terms of the GNU General Public License version 2 as published 9 + * by the Free Software Foundation. 10 + */ 11 + 12 + #include <linux/delay.h> 13 + #include <linux/init.h> 14 + #include <linux/io.h> 15 + #include <linux/list.h> 16 + #include <linux/module.h> 17 + #include <linux/of.h> 18 + #include <linux/of_address.h> 19 + #include <linux/gpio/consumer.h> 20 + #include <linux/of_mtd.h> 21 + #include <linux/platform_device.h> 22 + #include <linux/slab.h> 23 + #include <linux/mtd/mtd.h> 24 + #include <linux/mtd/nand.h> 25 + #include <linux/mtd/partitions.h> 26 + 27 + #include <linux/jz4780-nemc.h> 28 + 29 + #include "jz4780_bch.h" 30 + 31 + #define DRV_NAME "jz4780-nand" 32 + 33 + #define OFFSET_DATA 0x00000000 34 + #define OFFSET_CMD 0x00400000 35 + #define OFFSET_ADDR 0x00800000 36 + 37 + /* Command delay when there is no R/B pin. */ 38 + #define RB_DELAY_US 100 39 + 40 + struct jz4780_nand_cs { 41 + unsigned int bank; 42 + void __iomem *base; 43 + }; 44 + 45 + struct jz4780_nand_controller { 46 + struct device *dev; 47 + struct jz4780_bch *bch; 48 + struct nand_hw_control controller; 49 + unsigned int num_banks; 50 + struct list_head chips; 51 + int selected; 52 + struct jz4780_nand_cs cs[]; 53 + }; 54 + 55 + struct jz4780_nand_chip { 56 + struct nand_chip chip; 57 + struct list_head chip_list; 58 + 59 + struct nand_ecclayout ecclayout; 60 + 61 + struct gpio_desc *busy_gpio; 62 + struct gpio_desc *wp_gpio; 63 + unsigned int reading: 1; 64 + }; 65 + 66 + static inline struct jz4780_nand_chip *to_jz4780_nand_chip(struct mtd_info *mtd) 67 + { 68 + return container_of(mtd_to_nand(mtd), struct jz4780_nand_chip, chip); 69 + } 70 + 71 + static inline struct jz4780_nand_controller *to_jz4780_nand_controller(struct nand_hw_control *ctrl) 72 + { 73 + return container_of(ctrl, struct jz4780_nand_controller, controller); 74 + } 75 + 76 + static void jz4780_nand_select_chip(struct mtd_info *mtd, int chipnr) 77 + { 78 + struct jz4780_nand_chip *nand = to_jz4780_nand_chip(mtd); 79 + struct jz4780_nand_controller *nfc = to_jz4780_nand_controller(nand->chip.controller); 80 + struct jz4780_nand_cs *cs; 81 + 82 + /* Ensure the currently selected chip is deasserted. */ 83 + if (chipnr == -1 && nfc->selected >= 0) { 84 + cs = &nfc->cs[nfc->selected]; 85 + jz4780_nemc_assert(nfc->dev, cs->bank, false); 86 + } 87 + 88 + nfc->selected = chipnr; 89 + } 90 + 91 + static void jz4780_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, 92 + unsigned int ctrl) 93 + { 94 + struct jz4780_nand_chip *nand = to_jz4780_nand_chip(mtd); 95 + struct jz4780_nand_controller *nfc = to_jz4780_nand_controller(nand->chip.controller); 96 + struct jz4780_nand_cs *cs; 97 + 98 + if (WARN_ON(nfc->selected < 0)) 99 + return; 100 + 101 + cs = &nfc->cs[nfc->selected]; 102 + 103 + jz4780_nemc_assert(nfc->dev, cs->bank, ctrl & NAND_NCE); 104 + 105 + if (cmd == NAND_CMD_NONE) 106 + return; 107 + 108 + if (ctrl & NAND_ALE) 109 + writeb(cmd, cs->base + OFFSET_ADDR); 110 + else if (ctrl & NAND_CLE) 111 + writeb(cmd, cs->base + OFFSET_CMD); 112 + } 113 + 114 + static int jz4780_nand_dev_ready(struct mtd_info *mtd) 115 + { 116 + struct jz4780_nand_chip *nand = to_jz4780_nand_chip(mtd); 117 + 118 + return !gpiod_get_value_cansleep(nand->busy_gpio); 119 + } 120 + 121 + static void jz4780_nand_ecc_hwctl(struct mtd_info *mtd, int mode) 122 + { 123 + struct jz4780_nand_chip *nand = to_jz4780_nand_chip(mtd); 124 + 125 + nand->reading = (mode == NAND_ECC_READ); 126 + } 127 + 128 + static int jz4780_nand_ecc_calculate(struct mtd_info *mtd, const u8 *dat, 129 + u8 *ecc_code) 130 + { 131 + struct jz4780_nand_chip *nand = to_jz4780_nand_chip(mtd); 132 + struct jz4780_nand_controller *nfc = to_jz4780_nand_controller(nand->chip.controller); 133 + struct jz4780_bch_params params; 134 + 135 + /* 136 + * Don't need to generate the ECC when reading, BCH does it for us as 137 + * part of decoding/correction. 138 + */ 139 + if (nand->reading) 140 + return 0; 141 + 142 + params.size = nand->chip.ecc.size; 143 + params.bytes = nand->chip.ecc.bytes; 144 + params.strength = nand->chip.ecc.strength; 145 + 146 + return jz4780_bch_calculate(nfc->bch, &params, dat, ecc_code); 147 + } 148 + 149 + static int jz4780_nand_ecc_correct(struct mtd_info *mtd, u8 *dat, 150 + u8 *read_ecc, u8 *calc_ecc) 151 + { 152 + struct jz4780_nand_chip *nand = to_jz4780_nand_chip(mtd); 153 + struct jz4780_nand_controller *nfc = to_jz4780_nand_controller(nand->chip.controller); 154 + struct jz4780_bch_params params; 155 + 156 + params.size = nand->chip.ecc.size; 157 + params.bytes = nand->chip.ecc.bytes; 158 + params.strength = nand->chip.ecc.strength; 159 + 160 + return jz4780_bch_correct(nfc->bch, &params, dat, read_ecc); 161 + } 162 + 163 + static int jz4780_nand_init_ecc(struct jz4780_nand_chip *nand, struct device *dev) 164 + { 165 + struct nand_chip *chip = &nand->chip; 166 + struct mtd_info *mtd = nand_to_mtd(chip); 167 + struct jz4780_nand_controller *nfc = to_jz4780_nand_controller(chip->controller); 168 + struct nand_ecclayout *layout = &nand->ecclayout; 169 + u32 start, i; 170 + 171 + chip->ecc.bytes = fls((1 + 8) * chip->ecc.size) * 172 + (chip->ecc.strength / 8); 173 + 174 + if (nfc->bch && chip->ecc.mode == NAND_ECC_HW) { 175 + chip->ecc.hwctl = jz4780_nand_ecc_hwctl; 176 + chip->ecc.calculate = jz4780_nand_ecc_calculate; 177 + chip->ecc.correct = jz4780_nand_ecc_correct; 178 + } else if (!nfc->bch && chip->ecc.mode == NAND_ECC_HW) { 179 + dev_err(dev, "HW BCH selected, but BCH controller not found\n"); 180 + return -ENODEV; 181 + } 182 + 183 + if (chip->ecc.mode == NAND_ECC_HW_SYNDROME) { 184 + dev_err(dev, "ECC HW syndrome not supported\n"); 185 + return -EINVAL; 186 + } 187 + 188 + if (chip->ecc.mode != NAND_ECC_NONE) 189 + dev_info(dev, "using %s (strength %d, size %d, bytes %d)\n", 190 + (nfc->bch) ? "hardware BCH" : "software ECC", 191 + chip->ecc.strength, chip->ecc.size, chip->ecc.bytes); 192 + else 193 + dev_info(dev, "not using ECC\n"); 194 + 195 + /* The NAND core will generate the ECC layout. */ 196 + if (chip->ecc.mode == NAND_ECC_SOFT || chip->ecc.mode == NAND_ECC_SOFT_BCH) 197 + return 0; 198 + 199 + /* Generate ECC layout. ECC codes are right aligned in the OOB area. */ 200 + layout->eccbytes = mtd->writesize / chip->ecc.size * chip->ecc.bytes; 201 + 202 + if (layout->eccbytes > mtd->oobsize - 2) { 203 + dev_err(dev, 204 + "invalid ECC config: required %d ECC bytes, but only %d are available", 205 + layout->eccbytes, mtd->oobsize - 2); 206 + return -EINVAL; 207 + } 208 + 209 + start = mtd->oobsize - layout->eccbytes; 210 + for (i = 0; i < layout->eccbytes; i++) 211 + layout->eccpos[i] = start + i; 212 + 213 + layout->oobfree[0].offset = 2; 214 + layout->oobfree[0].length = mtd->oobsize - layout->eccbytes - 2; 215 + 216 + chip->ecc.layout = layout; 217 + return 0; 218 + } 219 + 220 + static int jz4780_nand_init_chip(struct platform_device *pdev, 221 + struct jz4780_nand_controller *nfc, 222 + struct device_node *np, 223 + unsigned int chipnr) 224 + { 225 + struct device *dev = &pdev->dev; 226 + struct jz4780_nand_chip *nand; 227 + struct jz4780_nand_cs *cs; 228 + struct resource *res; 229 + struct nand_chip *chip; 230 + struct mtd_info *mtd; 231 + const __be32 *reg; 232 + int ret = 0; 233 + 234 + cs = &nfc->cs[chipnr]; 235 + 236 + reg = of_get_property(np, "reg", NULL); 237 + if (!reg) 238 + return -EINVAL; 239 + 240 + cs->bank = be32_to_cpu(*reg); 241 + 242 + jz4780_nemc_set_type(nfc->dev, cs->bank, JZ4780_NEMC_BANK_NAND); 243 + 244 + res = platform_get_resource(pdev, IORESOURCE_MEM, chipnr); 245 + cs->base = devm_ioremap_resource(dev, res); 246 + if (IS_ERR(cs->base)) 247 + return PTR_ERR(cs->base); 248 + 249 + nand = devm_kzalloc(dev, sizeof(*nand), GFP_KERNEL); 250 + if (!nand) 251 + return -ENOMEM; 252 + 253 + nand->busy_gpio = devm_gpiod_get_optional(dev, "rb", GPIOD_IN); 254 + 255 + if (IS_ERR(nand->busy_gpio)) { 256 + ret = PTR_ERR(nand->busy_gpio); 257 + dev_err(dev, "failed to request busy GPIO: %d\n", ret); 258 + return ret; 259 + } else if (nand->busy_gpio) { 260 + nand->chip.dev_ready = jz4780_nand_dev_ready; 261 + } 262 + 263 + nand->wp_gpio = devm_gpiod_get_optional(dev, "wp", GPIOD_OUT_LOW); 264 + 265 + if (IS_ERR(nand->wp_gpio)) { 266 + ret = PTR_ERR(nand->wp_gpio); 267 + dev_err(dev, "failed to request WP GPIO: %d\n", ret); 268 + return ret; 269 + } 270 + 271 + chip = &nand->chip; 272 + mtd = nand_to_mtd(chip); 273 + mtd->priv = chip; 274 + mtd->name = devm_kasprintf(dev, GFP_KERNEL, "%s.%d", dev_name(dev), 275 + cs->bank); 276 + if (!mtd->name) 277 + return -ENOMEM; 278 + mtd->dev.parent = dev; 279 + 280 + chip->IO_ADDR_R = cs->base + OFFSET_DATA; 281 + chip->IO_ADDR_W = cs->base + OFFSET_DATA; 282 + chip->chip_delay = RB_DELAY_US; 283 + chip->options = NAND_NO_SUBPAGE_WRITE; 284 + chip->select_chip = jz4780_nand_select_chip; 285 + chip->cmd_ctrl = jz4780_nand_cmd_ctrl; 286 + chip->ecc.mode = NAND_ECC_HW; 287 + chip->controller = &nfc->controller; 288 + nand_set_flash_node(chip, np); 289 + 290 + ret = nand_scan_ident(mtd, 1, NULL); 291 + if (ret) 292 + return ret; 293 + 294 + ret = jz4780_nand_init_ecc(nand, dev); 295 + if (ret) 296 + return ret; 297 + 298 + ret = nand_scan_tail(mtd); 299 + if (ret) 300 + return ret; 301 + 302 + ret = mtd_device_register(mtd, NULL, 0); 303 + if (ret) { 304 + nand_release(mtd); 305 + return ret; 306 + } 307 + 308 + list_add_tail(&nand->chip_list, &nfc->chips); 309 + 310 + return 0; 311 + } 312 + 313 + static void jz4780_nand_cleanup_chips(struct jz4780_nand_controller *nfc) 314 + { 315 + struct jz4780_nand_chip *chip; 316 + 317 + while (!list_empty(&nfc->chips)) { 318 + chip = list_first_entry(&nfc->chips, struct jz4780_nand_chip, chip_list); 319 + nand_release(nand_to_mtd(&chip->chip)); 320 + list_del(&chip->chip_list); 321 + } 322 + } 323 + 324 + static int jz4780_nand_init_chips(struct jz4780_nand_controller *nfc, 325 + struct platform_device *pdev) 326 + { 327 + struct device *dev = &pdev->dev; 328 + struct device_node *np; 329 + int i = 0; 330 + int ret; 331 + int num_chips = of_get_child_count(dev->of_node); 332 + 333 + if (num_chips > nfc->num_banks) { 334 + dev_err(dev, "found %d chips but only %d banks\n", num_chips, nfc->num_banks); 335 + return -EINVAL; 336 + } 337 + 338 + for_each_child_of_node(dev->of_node, np) { 339 + ret = jz4780_nand_init_chip(pdev, nfc, np, i); 340 + if (ret) { 341 + jz4780_nand_cleanup_chips(nfc); 342 + return ret; 343 + } 344 + 345 + i++; 346 + } 347 + 348 + return 0; 349 + } 350 + 351 + static int jz4780_nand_probe(struct platform_device *pdev) 352 + { 353 + struct device *dev = &pdev->dev; 354 + unsigned int num_banks; 355 + struct jz4780_nand_controller *nfc; 356 + int ret; 357 + 358 + num_banks = jz4780_nemc_num_banks(dev); 359 + if (num_banks == 0) { 360 + dev_err(dev, "no banks found\n"); 361 + return -ENODEV; 362 + } 363 + 364 + nfc = devm_kzalloc(dev, sizeof(*nfc) + (sizeof(nfc->cs[0]) * num_banks), GFP_KERNEL); 365 + if (!nfc) 366 + return -ENOMEM; 367 + 368 + /* 369 + * Check for BCH HW before we call nand_scan_ident, to prevent us from 370 + * having to call it again if the BCH driver returns -EPROBE_DEFER. 371 + */ 372 + nfc->bch = of_jz4780_bch_get(dev->of_node); 373 + if (IS_ERR(nfc->bch)) 374 + return PTR_ERR(nfc->bch); 375 + 376 + nfc->dev = dev; 377 + nfc->num_banks = num_banks; 378 + 379 + spin_lock_init(&nfc->controller.lock); 380 + INIT_LIST_HEAD(&nfc->chips); 381 + init_waitqueue_head(&nfc->controller.wq); 382 + 383 + ret = jz4780_nand_init_chips(nfc, pdev); 384 + if (ret) { 385 + if (nfc->bch) 386 + jz4780_bch_release(nfc->bch); 387 + return ret; 388 + } 389 + 390 + platform_set_drvdata(pdev, nfc); 391 + return 0; 392 + } 393 + 394 + static int jz4780_nand_remove(struct platform_device *pdev) 395 + { 396 + struct jz4780_nand_controller *nfc = platform_get_drvdata(pdev); 397 + 398 + if (nfc->bch) 399 + jz4780_bch_release(nfc->bch); 400 + 401 + jz4780_nand_cleanup_chips(nfc); 402 + 403 + return 0; 404 + } 405 + 406 + static const struct of_device_id jz4780_nand_dt_match[] = { 407 + { .compatible = "ingenic,jz4780-nand" }, 408 + {}, 409 + }; 410 + MODULE_DEVICE_TABLE(of, jz4780_nand_dt_match); 411 + 412 + static struct platform_driver jz4780_nand_driver = { 413 + .probe = jz4780_nand_probe, 414 + .remove = jz4780_nand_remove, 415 + .driver = { 416 + .name = DRV_NAME, 417 + .of_match_table = of_match_ptr(jz4780_nand_dt_match), 418 + }, 419 + }; 420 + module_platform_driver(jz4780_nand_driver); 421 + 422 + MODULE_AUTHOR("Alex Smith <alex@alex-smith.me.uk>"); 423 + MODULE_AUTHOR("Harvey Hunt <harvey.hunt@imgtec.com>"); 424 + MODULE_DESCRIPTION("Ingenic JZ4780 NAND driver"); 425 + MODULE_LICENSE("GPL v2");