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