goldfish_nand.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442
  1. /*
  2. * drivers/mtd/devices/goldfish_nand.c
  3. *
  4. * Copyright (C) 2007 Google, Inc.
  5. * Copyright (C) 2012 Intel, Inc.
  6. * Copyright (C) 2013 Intel, Inc.
  7. *
  8. * This software is licensed under the terms of the GNU General Public
  9. * License version 2, as published by the Free Software Foundation, and
  10. * may be copied, distributed, and modified under those terms.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. */
  18. #include <linux/io.h>
  19. #include <linux/device.h>
  20. #include <linux/module.h>
  21. #include <linux/slab.h>
  22. #include <linux/ioport.h>
  23. #include <linux/vmalloc.h>
  24. #include <linux/mtd/mtd.h>
  25. #include <linux/platform_device.h>
  26. #include <linux/mutex.h>
  27. #include <linux/goldfish.h>
  28. #include <asm/div64.h>
  29. #include "goldfish_nand_reg.h"
  30. struct goldfish_nand {
  31. /* lock protects access to the device registers */
  32. struct mutex lock;
  33. unsigned char __iomem *base;
  34. struct cmd_params *cmd_params;
  35. size_t mtd_count;
  36. struct mtd_info mtd[0];
  37. };
  38. static u32 goldfish_nand_cmd_with_params(struct mtd_info *mtd,
  39. enum nand_cmd cmd, u64 addr, u32 len,
  40. void *ptr, u32 *rv)
  41. {
  42. u32 cmdp;
  43. struct goldfish_nand *nand = mtd->priv;
  44. struct cmd_params *cps = nand->cmd_params;
  45. unsigned char __iomem *base = nand->base;
  46. if (!cps)
  47. return -1;
  48. switch (cmd) {
  49. case NAND_CMD_ERASE:
  50. cmdp = NAND_CMD_ERASE_WITH_PARAMS;
  51. break;
  52. case NAND_CMD_READ:
  53. cmdp = NAND_CMD_READ_WITH_PARAMS;
  54. break;
  55. case NAND_CMD_WRITE:
  56. cmdp = NAND_CMD_WRITE_WITH_PARAMS;
  57. break;
  58. default:
  59. return -1;
  60. }
  61. cps->dev = mtd - nand->mtd;
  62. cps->addr_high = (u32)(addr >> 32);
  63. cps->addr_low = (u32)addr;
  64. cps->transfer_size = len;
  65. cps->data = (unsigned long)ptr;
  66. writel(cmdp, base + NAND_COMMAND);
  67. *rv = cps->result;
  68. return 0;
  69. }
  70. static u32 goldfish_nand_cmd(struct mtd_info *mtd, enum nand_cmd cmd,
  71. u64 addr, u32 len, void *ptr)
  72. {
  73. struct goldfish_nand *nand = mtd->priv;
  74. u32 rv;
  75. unsigned char __iomem *base = nand->base;
  76. mutex_lock(&nand->lock);
  77. if (goldfish_nand_cmd_with_params(mtd, cmd, addr, len, ptr, &rv)) {
  78. writel(mtd - nand->mtd, base + NAND_DEV);
  79. writel((u32)(addr >> 32), base + NAND_ADDR_HIGH);
  80. writel((u32)addr, base + NAND_ADDR_LOW);
  81. writel(len, base + NAND_TRANSFER_SIZE);
  82. gf_write_ptr(ptr, base + NAND_DATA, base + NAND_DATA_HIGH);
  83. writel(cmd, base + NAND_COMMAND);
  84. rv = readl(base + NAND_RESULT);
  85. }
  86. mutex_unlock(&nand->lock);
  87. return rv;
  88. }
  89. static int goldfish_nand_erase(struct mtd_info *mtd, struct erase_info *instr)
  90. {
  91. loff_t ofs = instr->addr;
  92. u32 len = instr->len;
  93. u32 rem;
  94. if (ofs + len > mtd->size)
  95. goto invalid_arg;
  96. rem = do_div(ofs, mtd->writesize);
  97. if (rem)
  98. goto invalid_arg;
  99. ofs *= (mtd->writesize + mtd->oobsize);
  100. if (len % mtd->writesize)
  101. goto invalid_arg;
  102. len = len / mtd->writesize * (mtd->writesize + mtd->oobsize);
  103. if (goldfish_nand_cmd(mtd, NAND_CMD_ERASE, ofs, len, NULL) != len) {
  104. pr_err("goldfish_nand_erase: erase failed, start %llx, len %x, dev_size %llx, erase_size %x\n",
  105. ofs, len, mtd->size, mtd->erasesize);
  106. return -EIO;
  107. }
  108. instr->state = MTD_ERASE_DONE;
  109. mtd_erase_callback(instr);
  110. return 0;
  111. invalid_arg:
  112. pr_err("goldfish_nand_erase: invalid erase, start %llx, len %x, dev_size %llx, erase_size %x\n",
  113. ofs, len, mtd->size, mtd->erasesize);
  114. return -EINVAL;
  115. }
  116. static int goldfish_nand_read_oob(struct mtd_info *mtd, loff_t ofs,
  117. struct mtd_oob_ops *ops)
  118. {
  119. u32 rem;
  120. if (ofs + ops->len > mtd->size)
  121. goto invalid_arg;
  122. if (ops->datbuf && ops->len && ops->len != mtd->writesize)
  123. goto invalid_arg;
  124. if (ops->ooblen + ops->ooboffs > mtd->oobsize)
  125. goto invalid_arg;
  126. rem = do_div(ofs, mtd->writesize);
  127. if (rem)
  128. goto invalid_arg;
  129. ofs *= (mtd->writesize + mtd->oobsize);
  130. if (ops->datbuf)
  131. ops->retlen = goldfish_nand_cmd(mtd, NAND_CMD_READ, ofs,
  132. ops->len, ops->datbuf);
  133. ofs += mtd->writesize + ops->ooboffs;
  134. if (ops->oobbuf)
  135. ops->oobretlen = goldfish_nand_cmd(mtd, NAND_CMD_READ, ofs,
  136. ops->ooblen, ops->oobbuf);
  137. return 0;
  138. invalid_arg:
  139. pr_err("goldfish_nand_read_oob: invalid read, start %llx, len %zx, ooblen %zx, dev_size %llx, write_size %x\n",
  140. ofs, ops->len, ops->ooblen, mtd->size, mtd->writesize);
  141. return -EINVAL;
  142. }
  143. static int goldfish_nand_write_oob(struct mtd_info *mtd, loff_t ofs,
  144. struct mtd_oob_ops *ops)
  145. {
  146. u32 rem;
  147. if (ofs + ops->len > mtd->size)
  148. goto invalid_arg;
  149. if (ops->len && ops->len != mtd->writesize)
  150. goto invalid_arg;
  151. if (ops->ooblen + ops->ooboffs > mtd->oobsize)
  152. goto invalid_arg;
  153. rem = do_div(ofs, mtd->writesize);
  154. if (rem)
  155. goto invalid_arg;
  156. ofs *= (mtd->writesize + mtd->oobsize);
  157. if (ops->datbuf)
  158. ops->retlen = goldfish_nand_cmd(mtd, NAND_CMD_WRITE, ofs,
  159. ops->len, ops->datbuf);
  160. ofs += mtd->writesize + ops->ooboffs;
  161. if (ops->oobbuf)
  162. ops->oobretlen = goldfish_nand_cmd(mtd, NAND_CMD_WRITE, ofs,
  163. ops->ooblen, ops->oobbuf);
  164. return 0;
  165. invalid_arg:
  166. pr_err("goldfish_nand_write_oob: invalid write, start %llx, len %zx, ooblen %zx, dev_size %llx, write_size %x\n",
  167. ofs, ops->len, ops->ooblen, mtd->size, mtd->writesize);
  168. return -EINVAL;
  169. }
  170. static int goldfish_nand_read(struct mtd_info *mtd, loff_t from, size_t len,
  171. size_t *retlen, u_char *buf)
  172. {
  173. u32 rem;
  174. if (from + len > mtd->size)
  175. goto invalid_arg;
  176. rem = do_div(from, mtd->writesize);
  177. if (rem)
  178. goto invalid_arg;
  179. from *= (mtd->writesize + mtd->oobsize);
  180. *retlen = goldfish_nand_cmd(mtd, NAND_CMD_READ, from, len, buf);
  181. return 0;
  182. invalid_arg:
  183. pr_err("goldfish_nand_read: invalid read, start %llx, len %zx, dev_size %llx, write_size %x\n",
  184. from, len, mtd->size, mtd->writesize);
  185. return -EINVAL;
  186. }
  187. static int goldfish_nand_write(struct mtd_info *mtd, loff_t to, size_t len,
  188. size_t *retlen, const u_char *buf)
  189. {
  190. u32 rem;
  191. if (to + len > mtd->size)
  192. goto invalid_arg;
  193. rem = do_div(to, mtd->writesize);
  194. if (rem)
  195. goto invalid_arg;
  196. to *= (mtd->writesize + mtd->oobsize);
  197. *retlen = goldfish_nand_cmd(mtd, NAND_CMD_WRITE, to, len, (void *)buf);
  198. return 0;
  199. invalid_arg:
  200. pr_err("goldfish_nand_write: invalid write, start %llx, len %zx, dev_size %llx, write_size %x\n",
  201. to, len, mtd->size, mtd->writesize);
  202. return -EINVAL;
  203. }
  204. static int goldfish_nand_block_isbad(struct mtd_info *mtd, loff_t ofs)
  205. {
  206. u32 rem;
  207. if (ofs >= mtd->size)
  208. goto invalid_arg;
  209. rem = do_div(ofs, mtd->erasesize);
  210. if (rem)
  211. goto invalid_arg;
  212. ofs *= mtd->erasesize / mtd->writesize;
  213. ofs *= (mtd->writesize + mtd->oobsize);
  214. return goldfish_nand_cmd(mtd, NAND_CMD_BLOCK_BAD_GET, ofs, 0, NULL);
  215. invalid_arg:
  216. pr_err("goldfish_nand_block_isbad: invalid arg, ofs %llx, dev_size %llx, write_size %x\n",
  217. ofs, mtd->size, mtd->writesize);
  218. return -EINVAL;
  219. }
  220. static int goldfish_nand_block_markbad(struct mtd_info *mtd, loff_t ofs)
  221. {
  222. u32 rem;
  223. if (ofs >= mtd->size)
  224. goto invalid_arg;
  225. rem = do_div(ofs, mtd->erasesize);
  226. if (rem)
  227. goto invalid_arg;
  228. ofs *= mtd->erasesize / mtd->writesize;
  229. ofs *= (mtd->writesize + mtd->oobsize);
  230. if (goldfish_nand_cmd(mtd, NAND_CMD_BLOCK_BAD_SET, ofs, 0, NULL) != 1)
  231. return -EIO;
  232. return 0;
  233. invalid_arg:
  234. pr_err("goldfish_nand_block_markbad: invalid arg, ofs %llx, dev_size %llx, write_size %x\n",
  235. ofs, mtd->size, mtd->writesize);
  236. return -EINVAL;
  237. }
  238. static int nand_setup_cmd_params(struct platform_device *pdev,
  239. struct goldfish_nand *nand)
  240. {
  241. u64 paddr;
  242. unsigned char __iomem *base = nand->base;
  243. nand->cmd_params = devm_kzalloc(&pdev->dev,
  244. sizeof(struct cmd_params), GFP_KERNEL);
  245. if (!nand->cmd_params)
  246. return -1;
  247. paddr = __pa(nand->cmd_params);
  248. writel((u32)(paddr >> 32), base + NAND_CMD_PARAMS_ADDR_HIGH);
  249. writel((u32)paddr, base + NAND_CMD_PARAMS_ADDR_LOW);
  250. return 0;
  251. }
  252. static int goldfish_nand_init_device(struct platform_device *pdev,
  253. struct goldfish_nand *nand, int id)
  254. {
  255. u32 name_len;
  256. u32 result;
  257. u32 flags;
  258. unsigned char __iomem *base = nand->base;
  259. struct mtd_info *mtd = &nand->mtd[id];
  260. char *name;
  261. mutex_lock(&nand->lock);
  262. writel(id, base + NAND_DEV);
  263. flags = readl(base + NAND_DEV_FLAGS);
  264. name_len = readl(base + NAND_DEV_NAME_LEN);
  265. mtd->writesize = readl(base + NAND_DEV_PAGE_SIZE);
  266. mtd->size = readl(base + NAND_DEV_SIZE_LOW);
  267. mtd->size |= (u64)readl(base + NAND_DEV_SIZE_HIGH) << 32;
  268. mtd->oobsize = readl(base + NAND_DEV_EXTRA_SIZE);
  269. mtd->oobavail = mtd->oobsize;
  270. mtd->erasesize = readl(base + NAND_DEV_ERASE_SIZE) /
  271. (mtd->writesize + mtd->oobsize) * mtd->writesize;
  272. do_div(mtd->size, mtd->writesize + mtd->oobsize);
  273. mtd->size *= mtd->writesize;
  274. dev_dbg(&pdev->dev,
  275. "goldfish nand dev%d: size %llx, page %d, extra %d, erase %d\n",
  276. id, mtd->size, mtd->writesize,
  277. mtd->oobsize, mtd->erasesize);
  278. mutex_unlock(&nand->lock);
  279. mtd->priv = nand;
  280. name = devm_kzalloc(&pdev->dev, name_len + 1, GFP_KERNEL);
  281. if (!name)
  282. return -ENOMEM;
  283. mtd->name = name;
  284. result = goldfish_nand_cmd(mtd, NAND_CMD_GET_DEV_NAME, 0, name_len,
  285. name);
  286. if (result != name_len) {
  287. dev_err(&pdev->dev,
  288. "goldfish_nand_init_device failed to get dev name %d != %d\n",
  289. result, name_len);
  290. return -ENODEV;
  291. }
  292. ((char *)mtd->name)[name_len] = '\0';
  293. /* Setup the MTD structure */
  294. mtd->type = MTD_NANDFLASH;
  295. mtd->flags = MTD_CAP_NANDFLASH;
  296. if (flags & NAND_DEV_FLAG_READ_ONLY)
  297. mtd->flags &= ~MTD_WRITEABLE;
  298. if (flags & NAND_DEV_FLAG_CMD_PARAMS_CAP)
  299. nand_setup_cmd_params(pdev, nand);
  300. mtd->owner = THIS_MODULE;
  301. mtd->_erase = goldfish_nand_erase;
  302. mtd->_read = goldfish_nand_read;
  303. mtd->_write = goldfish_nand_write;
  304. mtd->_read_oob = goldfish_nand_read_oob;
  305. mtd->_write_oob = goldfish_nand_write_oob;
  306. mtd->_block_isbad = goldfish_nand_block_isbad;
  307. mtd->_block_markbad = goldfish_nand_block_markbad;
  308. if (mtd_device_register(mtd, NULL, 0))
  309. return -EIO;
  310. return 0;
  311. }
  312. static int goldfish_nand_probe(struct platform_device *pdev)
  313. {
  314. u32 num_dev;
  315. int i;
  316. int err;
  317. u32 num_dev_working;
  318. u32 version;
  319. struct resource *r;
  320. struct goldfish_nand *nand;
  321. unsigned char __iomem *base;
  322. r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  323. if (!r)
  324. return -ENODEV;
  325. base = devm_ioremap(&pdev->dev, r->start, PAGE_SIZE);
  326. if (!base)
  327. return -ENOMEM;
  328. version = readl(base + NAND_VERSION);
  329. if (version != NAND_VERSION_CURRENT) {
  330. dev_err(&pdev->dev,
  331. "goldfish_nand_init: version mismatch, got %d, expected %d\n",
  332. version, NAND_VERSION_CURRENT);
  333. return -ENODEV;
  334. }
  335. num_dev = readl(base + NAND_NUM_DEV);
  336. if (num_dev == 0)
  337. return -ENODEV;
  338. nand = devm_kzalloc(&pdev->dev, sizeof(*nand) +
  339. sizeof(struct mtd_info) * num_dev, GFP_KERNEL);
  340. if (!nand)
  341. return -ENOMEM;
  342. mutex_init(&nand->lock);
  343. nand->base = base;
  344. nand->mtd_count = num_dev;
  345. platform_set_drvdata(pdev, nand);
  346. num_dev_working = 0;
  347. for (i = 0; i < num_dev; i++) {
  348. err = goldfish_nand_init_device(pdev, nand, i);
  349. if (err == 0)
  350. num_dev_working++;
  351. }
  352. if (num_dev_working == 0)
  353. return -ENODEV;
  354. return 0;
  355. }
  356. static int goldfish_nand_remove(struct platform_device *pdev)
  357. {
  358. struct goldfish_nand *nand = platform_get_drvdata(pdev);
  359. int i;
  360. for (i = 0; i < nand->mtd_count; i++) {
  361. if (nand->mtd[i].name)
  362. mtd_device_unregister(&nand->mtd[i]);
  363. }
  364. return 0;
  365. }
  366. static struct platform_driver goldfish_nand_driver = {
  367. .probe = goldfish_nand_probe,
  368. .remove = goldfish_nand_remove,
  369. .driver = {
  370. .name = "goldfish_nand"
  371. }
  372. };
  373. module_platform_driver(goldfish_nand_driver);
  374. MODULE_LICENSE("GPL");