1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Overview: 4 * Platform independent driver for NDFC (NanD Flash Controller) 5 * integrated into EP440 cores 6 * 7 * Ported to an OF platform driver by Sean MacLennan 8 * 9 * The NDFC supports multiple chips, but this driver only supports a 10 * single chip since I do not have access to any boards with 11 * multiple chips. 12 * 13 * Author: Thomas Gleixner 14 * 15 * Copyright 2006 IBM 16 * Copyright 2008 PIKA Technologies 17 * Sean MacLennan <smaclennan@pikatech.com> 18 */ 19 #include <linux/module.h> 20 #include <linux/mtd/rawnand.h> 21 #include <linux/mtd/partitions.h> 22 #include <linux/mtd/ndfc.h> 23 #include <linux/slab.h> 24 #include <linux/mtd/mtd.h> 25 #include <linux/mtd/nand-ecc-sw-hamming.h> 26 #include <linux/of_address.h> 27 #include <linux/of_platform.h> 28 #include <asm/io.h> 29 30 #define NDFC_MAX_CS 4 31 32 struct ndfc_controller { 33 struct platform_device *ofdev; 34 void __iomem *ndfcbase; 35 struct nand_chip chip; 36 int chip_select; 37 struct nand_controller ndfc_control; 38 }; 39 40 static struct ndfc_controller ndfc_ctrl[NDFC_MAX_CS]; 41 42 static void ndfc_select_chip(struct nand_chip *nchip, int chip) 43 { 44 uint32_t ccr; 45 struct ndfc_controller *ndfc = nand_get_controller_data(nchip); 46 47 ccr = in_be32(ndfc->ndfcbase + NDFC_CCR); 48 if (chip >= 0) { 49 ccr &= ~NDFC_CCR_BS_MASK; 50 ccr |= NDFC_CCR_BS(chip + ndfc->chip_select); 51 } else 52 ccr |= NDFC_CCR_RESET_CE; 53 out_be32(ndfc->ndfcbase + NDFC_CCR, ccr); 54 } 55 56 static void ndfc_hwcontrol(struct nand_chip *chip, int cmd, unsigned int ctrl) 57 { 58 struct ndfc_controller *ndfc = nand_get_controller_data(chip); 59 60 if (cmd == NAND_CMD_NONE) 61 return; 62 63 if (ctrl & NAND_CLE) 64 writel(cmd & 0xFF, ndfc->ndfcbase + NDFC_CMD); 65 else 66 writel(cmd & 0xFF, ndfc->ndfcbase + NDFC_ALE); 67 } 68 69 static int ndfc_ready(struct nand_chip *chip) 70 { 71 struct ndfc_controller *ndfc = nand_get_controller_data(chip); 72 73 return in_be32(ndfc->ndfcbase + NDFC_STAT) & NDFC_STAT_IS_READY; 74 } 75 76 static void ndfc_enable_hwecc(struct nand_chip *chip, int mode) 77 { 78 uint32_t ccr; 79 struct ndfc_controller *ndfc = nand_get_controller_data(chip); 80 81 ccr = in_be32(ndfc->ndfcbase + NDFC_CCR); 82 ccr |= NDFC_CCR_RESET_ECC; 83 out_be32(ndfc->ndfcbase + NDFC_CCR, ccr); 84 wmb(); 85 } 86 87 static int ndfc_calculate_ecc(struct nand_chip *chip, 88 const u_char *dat, u_char *ecc_code) 89 { 90 struct ndfc_controller *ndfc = nand_get_controller_data(chip); 91 uint32_t ecc; 92 uint8_t *p = (uint8_t *)&ecc; 93 94 wmb(); 95 ecc = in_be32(ndfc->ndfcbase + NDFC_ECC); 96 /* The NDFC uses Smart Media (SMC) bytes order */ 97 ecc_code[0] = p[1]; 98 ecc_code[1] = p[2]; 99 ecc_code[2] = p[3]; 100 101 return 0; 102 } 103 104 static int ndfc_correct_ecc(struct nand_chip *chip, 105 unsigned char *buf, 106 unsigned char *read_ecc, 107 unsigned char *calc_ecc) 108 { 109 return ecc_sw_hamming_correct(buf, read_ecc, calc_ecc, 110 chip->ecc.size, false); 111 } 112 113 /* 114 * Speedups for buffer read/write/verify 115 * 116 * NDFC allows 32bit read/write of data. So we can speed up the buffer 117 * functions. No further checking, as nand_base will always read/write 118 * page aligned. 119 */ 120 static void ndfc_read_buf(struct nand_chip *chip, uint8_t *buf, int len) 121 { 122 struct ndfc_controller *ndfc = nand_get_controller_data(chip); 123 uint32_t *p = (uint32_t *) buf; 124 125 for(;len > 0; len -= 4) 126 *p++ = in_be32(ndfc->ndfcbase + NDFC_DATA); 127 } 128 129 static void ndfc_write_buf(struct nand_chip *chip, const uint8_t *buf, int len) 130 { 131 struct ndfc_controller *ndfc = nand_get_controller_data(chip); 132 uint32_t *p = (uint32_t *) buf; 133 134 for(;len > 0; len -= 4) 135 out_be32(ndfc->ndfcbase + NDFC_DATA, *p++); 136 } 137 138 /* 139 * Initialize chip structure 140 */ 141 static int ndfc_chip_init(struct ndfc_controller *ndfc, 142 struct device_node *node) 143 { 144 struct device_node *flash_np; 145 struct nand_chip *chip = &ndfc->chip; 146 struct mtd_info *mtd = nand_to_mtd(chip); 147 int ret; 148 149 chip->legacy.IO_ADDR_R = ndfc->ndfcbase + NDFC_DATA; 150 chip->legacy.IO_ADDR_W = ndfc->ndfcbase + NDFC_DATA; 151 chip->legacy.cmd_ctrl = ndfc_hwcontrol; 152 chip->legacy.dev_ready = ndfc_ready; 153 chip->legacy.select_chip = ndfc_select_chip; 154 chip->legacy.chip_delay = 50; 155 chip->controller = &ndfc->ndfc_control; 156 chip->legacy.read_buf = ndfc_read_buf; 157 chip->legacy.write_buf = ndfc_write_buf; 158 chip->ecc.correct = ndfc_correct_ecc; 159 chip->ecc.hwctl = ndfc_enable_hwecc; 160 chip->ecc.calculate = ndfc_calculate_ecc; 161 chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_ON_HOST; 162 chip->ecc.size = 256; 163 chip->ecc.bytes = 3; 164 chip->ecc.strength = 1; 165 nand_set_controller_data(chip, ndfc); 166 167 mtd->dev.parent = &ndfc->ofdev->dev; 168 169 flash_np = of_get_next_child(node, NULL); 170 if (!flash_np) 171 return -ENODEV; 172 nand_set_flash_node(chip, flash_np); 173 174 mtd->name = kasprintf(GFP_KERNEL, "%s.%pOFn", dev_name(&ndfc->ofdev->dev), 175 flash_np); 176 if (!mtd->name) { 177 ret = -ENOMEM; 178 goto err; 179 } 180 181 ret = nand_scan(chip, 1); 182 if (ret) 183 goto err; 184 185 ret = mtd_device_register(mtd, NULL, 0); 186 187 err: 188 of_node_put(flash_np); 189 if (ret) 190 kfree(mtd->name); 191 return ret; 192 } 193 194 static int ndfc_probe(struct platform_device *ofdev) 195 { 196 struct ndfc_controller *ndfc; 197 const __be32 *reg; 198 u32 ccr; 199 u32 cs; 200 int err, len; 201 202 /* Read the reg property to get the chip select */ 203 reg = of_get_property(ofdev->dev.of_node, "reg", &len); 204 if (reg == NULL || len != 12) { 205 dev_err(&ofdev->dev, "unable read reg property (%d)\n", len); 206 return -ENOENT; 207 } 208 209 cs = be32_to_cpu(reg[0]); 210 if (cs >= NDFC_MAX_CS) { 211 dev_err(&ofdev->dev, "invalid CS number (%d)\n", cs); 212 return -EINVAL; 213 } 214 215 ndfc = &ndfc_ctrl[cs]; 216 ndfc->chip_select = cs; 217 218 nand_controller_init(&ndfc->ndfc_control); 219 ndfc->ofdev = ofdev; 220 dev_set_drvdata(&ofdev->dev, ndfc); 221 222 ndfc->ndfcbase = of_iomap(ofdev->dev.of_node, 0); 223 if (!ndfc->ndfcbase) { 224 dev_err(&ofdev->dev, "failed to get memory\n"); 225 return -EIO; 226 } 227 228 ccr = NDFC_CCR_BS(ndfc->chip_select); 229 230 /* It is ok if ccr does not exist - just default to 0 */ 231 reg = of_get_property(ofdev->dev.of_node, "ccr", NULL); 232 if (reg) 233 ccr |= be32_to_cpup(reg); 234 235 out_be32(ndfc->ndfcbase + NDFC_CCR, ccr); 236 237 /* Set the bank settings if given */ 238 reg = of_get_property(ofdev->dev.of_node, "bank-settings", NULL); 239 if (reg) { 240 int offset = NDFC_BCFG0 + (ndfc->chip_select << 2); 241 out_be32(ndfc->ndfcbase + offset, be32_to_cpup(reg)); 242 } 243 244 err = ndfc_chip_init(ndfc, ofdev->dev.of_node); 245 if (err) { 246 iounmap(ndfc->ndfcbase); 247 return err; 248 } 249 250 return 0; 251 } 252 253 static int ndfc_remove(struct platform_device *ofdev) 254 { 255 struct ndfc_controller *ndfc = dev_get_drvdata(&ofdev->dev); 256 struct nand_chip *chip = &ndfc->chip; 257 struct mtd_info *mtd = nand_to_mtd(chip); 258 int ret; 259 260 ret = mtd_device_unregister(mtd); 261 WARN_ON(ret); 262 nand_cleanup(chip); 263 kfree(mtd->name); 264 265 return 0; 266 } 267 268 static const struct of_device_id ndfc_match[] = { 269 { .compatible = "ibm,ndfc", }, 270 {} 271 }; 272 MODULE_DEVICE_TABLE(of, ndfc_match); 273 274 static struct platform_driver ndfc_driver = { 275 .driver = { 276 .name = "ndfc", 277 .of_match_table = ndfc_match, 278 }, 279 .probe = ndfc_probe, 280 .remove = ndfc_remove, 281 }; 282 283 module_platform_driver(ndfc_driver); 284 285 MODULE_LICENSE("GPL"); 286 MODULE_AUTHOR("Thomas Gleixner <tglx@linutronix.de>"); 287 MODULE_DESCRIPTION("OF Platform driver for NDFC"); 288