ndfc.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  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 <[email protected]>
  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/of_address.h>
  26. #include <linux/of_platform.h>
  27. #include <asm/io.h>
  28. #define NDFC_MAX_CS 4
  29. struct ndfc_controller {
  30. struct platform_device *ofdev;
  31. void __iomem *ndfcbase;
  32. struct nand_chip chip;
  33. int chip_select;
  34. struct nand_controller ndfc_control;
  35. };
  36. static struct ndfc_controller ndfc_ctrl[NDFC_MAX_CS];
  37. static void ndfc_select_chip(struct nand_chip *nchip, int chip)
  38. {
  39. uint32_t ccr;
  40. struct ndfc_controller *ndfc = nand_get_controller_data(nchip);
  41. ccr = in_be32(ndfc->ndfcbase + NDFC_CCR);
  42. if (chip >= 0) {
  43. ccr &= ~NDFC_CCR_BS_MASK;
  44. ccr |= NDFC_CCR_BS(chip + ndfc->chip_select);
  45. } else
  46. ccr |= NDFC_CCR_RESET_CE;
  47. out_be32(ndfc->ndfcbase + NDFC_CCR, ccr);
  48. }
  49. static void ndfc_hwcontrol(struct nand_chip *chip, int cmd, unsigned int ctrl)
  50. {
  51. struct ndfc_controller *ndfc = nand_get_controller_data(chip);
  52. if (cmd == NAND_CMD_NONE)
  53. return;
  54. if (ctrl & NAND_CLE)
  55. writel(cmd & 0xFF, ndfc->ndfcbase + NDFC_CMD);
  56. else
  57. writel(cmd & 0xFF, ndfc->ndfcbase + NDFC_ALE);
  58. }
  59. static int ndfc_ready(struct nand_chip *chip)
  60. {
  61. struct ndfc_controller *ndfc = nand_get_controller_data(chip);
  62. return in_be32(ndfc->ndfcbase + NDFC_STAT) & NDFC_STAT_IS_READY;
  63. }
  64. static void ndfc_enable_hwecc(struct nand_chip *chip, int mode)
  65. {
  66. uint32_t ccr;
  67. struct ndfc_controller *ndfc = nand_get_controller_data(chip);
  68. ccr = in_be32(ndfc->ndfcbase + NDFC_CCR);
  69. ccr |= NDFC_CCR_RESET_ECC;
  70. out_be32(ndfc->ndfcbase + NDFC_CCR, ccr);
  71. wmb();
  72. }
  73. static int ndfc_calculate_ecc(struct nand_chip *chip,
  74. const u_char *dat, u_char *ecc_code)
  75. {
  76. struct ndfc_controller *ndfc = nand_get_controller_data(chip);
  77. uint32_t ecc;
  78. uint8_t *p = (uint8_t *)&ecc;
  79. wmb();
  80. ecc = in_be32(ndfc->ndfcbase + NDFC_ECC);
  81. /* The NDFC uses Smart Media (SMC) bytes order */
  82. ecc_code[0] = p[1];
  83. ecc_code[1] = p[2];
  84. ecc_code[2] = p[3];
  85. return 0;
  86. }
  87. /*
  88. * Speedups for buffer read/write/verify
  89. *
  90. * NDFC allows 32bit read/write of data. So we can speed up the buffer
  91. * functions. No further checking, as nand_base will always read/write
  92. * page aligned.
  93. */
  94. static void ndfc_read_buf(struct nand_chip *chip, uint8_t *buf, int len)
  95. {
  96. struct ndfc_controller *ndfc = nand_get_controller_data(chip);
  97. uint32_t *p = (uint32_t *) buf;
  98. for(;len > 0; len -= 4)
  99. *p++ = in_be32(ndfc->ndfcbase + NDFC_DATA);
  100. }
  101. static void ndfc_write_buf(struct nand_chip *chip, const uint8_t *buf, int len)
  102. {
  103. struct ndfc_controller *ndfc = nand_get_controller_data(chip);
  104. uint32_t *p = (uint32_t *) buf;
  105. for(;len > 0; len -= 4)
  106. out_be32(ndfc->ndfcbase + NDFC_DATA, *p++);
  107. }
  108. /*
  109. * Initialize chip structure
  110. */
  111. static int ndfc_chip_init(struct ndfc_controller *ndfc,
  112. struct device_node *node)
  113. {
  114. struct device_node *flash_np;
  115. struct nand_chip *chip = &ndfc->chip;
  116. struct mtd_info *mtd = nand_to_mtd(chip);
  117. int ret;
  118. chip->legacy.IO_ADDR_R = ndfc->ndfcbase + NDFC_DATA;
  119. chip->legacy.IO_ADDR_W = ndfc->ndfcbase + NDFC_DATA;
  120. chip->legacy.cmd_ctrl = ndfc_hwcontrol;
  121. chip->legacy.dev_ready = ndfc_ready;
  122. chip->legacy.select_chip = ndfc_select_chip;
  123. chip->legacy.chip_delay = 50;
  124. chip->controller = &ndfc->ndfc_control;
  125. chip->legacy.read_buf = ndfc_read_buf;
  126. chip->legacy.write_buf = ndfc_write_buf;
  127. chip->ecc.correct = rawnand_sw_hamming_correct;
  128. chip->ecc.hwctl = ndfc_enable_hwecc;
  129. chip->ecc.calculate = ndfc_calculate_ecc;
  130. chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_ON_HOST;
  131. chip->ecc.size = 256;
  132. chip->ecc.bytes = 3;
  133. chip->ecc.strength = 1;
  134. nand_set_controller_data(chip, ndfc);
  135. mtd->dev.parent = &ndfc->ofdev->dev;
  136. flash_np = of_get_next_child(node, NULL);
  137. if (!flash_np)
  138. return -ENODEV;
  139. nand_set_flash_node(chip, flash_np);
  140. mtd->name = kasprintf(GFP_KERNEL, "%s.%pOFn", dev_name(&ndfc->ofdev->dev),
  141. flash_np);
  142. if (!mtd->name) {
  143. ret = -ENOMEM;
  144. goto err;
  145. }
  146. ret = nand_scan(chip, 1);
  147. if (ret)
  148. goto err;
  149. ret = mtd_device_register(mtd, NULL, 0);
  150. err:
  151. of_node_put(flash_np);
  152. if (ret)
  153. kfree(mtd->name);
  154. return ret;
  155. }
  156. static int ndfc_probe(struct platform_device *ofdev)
  157. {
  158. struct ndfc_controller *ndfc;
  159. const __be32 *reg;
  160. u32 ccr;
  161. u32 cs;
  162. int err, len;
  163. /* Read the reg property to get the chip select */
  164. reg = of_get_property(ofdev->dev.of_node, "reg", &len);
  165. if (reg == NULL || len != 12) {
  166. dev_err(&ofdev->dev, "unable read reg property (%d)\n", len);
  167. return -ENOENT;
  168. }
  169. cs = be32_to_cpu(reg[0]);
  170. if (cs >= NDFC_MAX_CS) {
  171. dev_err(&ofdev->dev, "invalid CS number (%d)\n", cs);
  172. return -EINVAL;
  173. }
  174. ndfc = &ndfc_ctrl[cs];
  175. ndfc->chip_select = cs;
  176. nand_controller_init(&ndfc->ndfc_control);
  177. ndfc->ofdev = ofdev;
  178. dev_set_drvdata(&ofdev->dev, ndfc);
  179. ndfc->ndfcbase = of_iomap(ofdev->dev.of_node, 0);
  180. if (!ndfc->ndfcbase) {
  181. dev_err(&ofdev->dev, "failed to get memory\n");
  182. return -EIO;
  183. }
  184. ccr = NDFC_CCR_BS(ndfc->chip_select);
  185. /* It is ok if ccr does not exist - just default to 0 */
  186. reg = of_get_property(ofdev->dev.of_node, "ccr", NULL);
  187. if (reg)
  188. ccr |= be32_to_cpup(reg);
  189. out_be32(ndfc->ndfcbase + NDFC_CCR, ccr);
  190. /* Set the bank settings if given */
  191. reg = of_get_property(ofdev->dev.of_node, "bank-settings", NULL);
  192. if (reg) {
  193. int offset = NDFC_BCFG0 + (ndfc->chip_select << 2);
  194. out_be32(ndfc->ndfcbase + offset, be32_to_cpup(reg));
  195. }
  196. err = ndfc_chip_init(ndfc, ofdev->dev.of_node);
  197. if (err) {
  198. iounmap(ndfc->ndfcbase);
  199. return err;
  200. }
  201. return 0;
  202. }
  203. static int ndfc_remove(struct platform_device *ofdev)
  204. {
  205. struct ndfc_controller *ndfc = dev_get_drvdata(&ofdev->dev);
  206. struct nand_chip *chip = &ndfc->chip;
  207. struct mtd_info *mtd = nand_to_mtd(chip);
  208. int ret;
  209. ret = mtd_device_unregister(mtd);
  210. WARN_ON(ret);
  211. nand_cleanup(chip);
  212. kfree(mtd->name);
  213. return 0;
  214. }
  215. static const struct of_device_id ndfc_match[] = {
  216. { .compatible = "ibm,ndfc", },
  217. {}
  218. };
  219. MODULE_DEVICE_TABLE(of, ndfc_match);
  220. static struct platform_driver ndfc_driver = {
  221. .driver = {
  222. .name = "ndfc",
  223. .of_match_table = ndfc_match,
  224. },
  225. .probe = ndfc_probe,
  226. .remove = ndfc_remove,
  227. };
  228. module_platform_driver(ndfc_driver);
  229. MODULE_LICENSE("GPL");
  230. MODULE_AUTHOR("Thomas Gleixner <[email protected]>");
  231. MODULE_DESCRIPTION("OF Platform driver for NDFC");