1
0

0001-mtd-add-rb4xx-nand-driver.patch 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351
  1. From 1e692cc0c53202b932eedabd0315107910c5b093 Mon Sep 17 00:00:00 2001
  2. From: Phil Sutter <phil@nwl.cc>
  3. Date: Tue, 13 May 2014 00:08:54 +0200
  4. Subject: [PATCH] mtd: add rb4xx nand driver
  5. ---
  6. drivers/mtd/nand/Kconfig | 4 +
  7. drivers/mtd/nand/Makefile | 1 +
  8. drivers/mtd/nand/rb4xx_nand.c | 305 ++++++++++++++++++++++++++++++++++++++++++
  9. 3 files changed, 310 insertions(+)
  10. create mode 100644 drivers/mtd/nand/rb4xx_nand.c
  11. diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
  12. index 90ff447..bb01309 100644
  13. --- a/drivers/mtd/nand/Kconfig
  14. +++ b/drivers/mtd/nand/Kconfig
  15. @@ -510,4 +510,8 @@ config MTD_NAND_XWAY
  16. Enables support for NAND Flash chips on Lantiq XWAY SoCs. NAND is attached
  17. to the External Bus Unit (EBU).
  18. +config MTD_NAND_RB4XX
  19. + tristate "NAND flash driver for RouterBoard 4xx series"
  20. + depends on MTD_NAND && ATH79_MACH_RB4XX
  21. +
  22. endif # MTD_NAND
  23. diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
  24. index 542b568..e2b5e1c 100644
  25. --- a/drivers/mtd/nand/Makefile
  26. +++ b/drivers/mtd/nand/Makefile
  27. @@ -31,6 +31,7 @@ obj-$(CONFIG_MTD_NAND_CM_X270) += cmx270_nand.o
  28. obj-$(CONFIG_MTD_NAND_PXA3xx) += pxa3xx_nand.o
  29. obj-$(CONFIG_MTD_NAND_TMIO) += tmio_nand.o
  30. obj-$(CONFIG_MTD_NAND_PLATFORM) += plat_nand.o
  31. +obj-$(CONFIG_MTD_NAND_RB4XX) += rb4xx_nand.o
  32. obj-$(CONFIG_MTD_NAND_PASEMI) += pasemi_nand.o
  33. obj-$(CONFIG_MTD_NAND_ORION) += orion_nand.o
  34. obj-$(CONFIG_MTD_NAND_FSL_ELBC) += fsl_elbc_nand.o
  35. diff --git a/drivers/mtd/nand/rb4xx_nand.c b/drivers/mtd/nand/rb4xx_nand.c
  36. new file mode 100644
  37. index 0000000..5b9841b
  38. --- /dev/null
  39. +++ b/drivers/mtd/nand/rb4xx_nand.c
  40. @@ -0,0 +1,305 @@
  41. +/*
  42. + * NAND flash driver for the MikroTik RouterBoard 4xx series
  43. + *
  44. + * Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
  45. + * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
  46. + *
  47. + * This file was based on the driver for Linux 2.6.22 published by
  48. + * MikroTik for their RouterBoard 4xx series devices.
  49. + *
  50. + * This program is free software; you can redistribute it and/or modify it
  51. + * under the terms of the GNU General Public License version 2 as published
  52. + * by the Free Software Foundation.
  53. + */
  54. +
  55. +#include <linux/kernel.h>
  56. +#include <linux/module.h>
  57. +#include <linux/init.h>
  58. +#include <linux/mtd/nand.h>
  59. +#include <linux/mtd/mtd.h>
  60. +#include <linux/mtd/partitions.h>
  61. +#include <linux/platform_device.h>
  62. +#include <linux/delay.h>
  63. +#include <linux/io.h>
  64. +#include <linux/gpio.h>
  65. +#include <linux/slab.h>
  66. +
  67. +#include <asm/mach-ath79/ath79.h>
  68. +#include <asm/mach-ath79/rb4xx_cpld.h>
  69. +
  70. +#define DRV_NAME "rb4xx-nand"
  71. +#define DRV_VERSION "0.2.0"
  72. +#define DRV_DESC "NAND flash driver for RouterBoard 4xx series"
  73. +
  74. +#define RB4XX_NAND_GPIO_READY 5
  75. +#define RB4XX_NAND_GPIO_ALE 37
  76. +#define RB4XX_NAND_GPIO_CLE 38
  77. +#define RB4XX_NAND_GPIO_NCE 39
  78. +
  79. +struct rb4xx_nand_info {
  80. + struct nand_chip chip;
  81. + struct mtd_info mtd;
  82. +};
  83. +
  84. +/*
  85. + * We need to use the OLD Yaffs-1 OOB layout, otherwise the RB bootloader
  86. + * will not be able to find the kernel that we load.
  87. + */
  88. +static struct nand_ecclayout rb4xx_nand_ecclayout = {
  89. + .eccbytes = 6,
  90. + .eccpos = { 8, 9, 10, 13, 14, 15 },
  91. + .oobavail = 9,
  92. + .oobfree = { { 0, 4 }, { 6, 2 }, { 11, 2 }, { 4, 1 } }
  93. +};
  94. +
  95. +static struct mtd_partition rb4xx_nand_partitions[] = {
  96. + {
  97. + .name = "booter",
  98. + .offset = 0,
  99. + .size = (256 * 1024),
  100. + .mask_flags = MTD_WRITEABLE,
  101. + },
  102. + {
  103. + .name = "kernel",
  104. + .offset = (256 * 1024),
  105. + .size = (4 * 1024 * 1024) - (256 * 1024),
  106. + },
  107. + {
  108. + .name = "rootfs",
  109. + .offset = MTDPART_OFS_NXTBLK,
  110. + .size = MTDPART_SIZ_FULL,
  111. + },
  112. +};
  113. +
  114. +static int rb4xx_nand_dev_ready(struct mtd_info *mtd)
  115. +{
  116. + return gpio_get_value_cansleep(RB4XX_NAND_GPIO_READY);
  117. +}
  118. +
  119. +static void rb4xx_nand_write_cmd(unsigned char cmd)
  120. +{
  121. + unsigned char data = cmd;
  122. + int err;
  123. +
  124. + err = rb4xx_cpld_write(&data, 1);
  125. + if (err)
  126. + pr_err("rb4xx_nand: write cmd failed, err=%d\n", err);
  127. +}
  128. +
  129. +static void rb4xx_nand_cmd_ctrl(struct mtd_info *mtd, int cmd,
  130. + unsigned int ctrl)
  131. +{
  132. + if (ctrl & NAND_CTRL_CHANGE) {
  133. + gpio_set_value_cansleep(RB4XX_NAND_GPIO_CLE,
  134. + (ctrl & NAND_CLE) ? 1 : 0);
  135. + gpio_set_value_cansleep(RB4XX_NAND_GPIO_ALE,
  136. + (ctrl & NAND_ALE) ? 1 : 0);
  137. + gpio_set_value_cansleep(RB4XX_NAND_GPIO_NCE,
  138. + (ctrl & NAND_NCE) ? 0 : 1);
  139. + }
  140. +
  141. + if (cmd != NAND_CMD_NONE)
  142. + rb4xx_nand_write_cmd(cmd);
  143. +}
  144. +
  145. +static unsigned char rb4xx_nand_read_byte(struct mtd_info *mtd)
  146. +{
  147. + unsigned char data = 0;
  148. + int err;
  149. +
  150. + err = rb4xx_cpld_read(&data, NULL, 1);
  151. + if (err) {
  152. + pr_err("rb4xx_nand: read data failed, err=%d\n", err);
  153. + data = 0xff;
  154. + }
  155. +
  156. + return data;
  157. +}
  158. +
  159. +static void rb4xx_nand_write_buf(struct mtd_info *mtd, const unsigned char *buf,
  160. + int len)
  161. +{
  162. + int err;
  163. +
  164. + err = rb4xx_cpld_write(buf, len);
  165. + if (err)
  166. + pr_err("rb4xx_nand: write buf failed, err=%d\n", err);
  167. +}
  168. +
  169. +static void rb4xx_nand_read_buf(struct mtd_info *mtd, unsigned char *buf,
  170. + int len)
  171. +{
  172. + int err;
  173. +
  174. + err = rb4xx_cpld_read(buf, NULL, len);
  175. + if (err)
  176. + pr_err("rb4xx_nand: read buf failed, err=%d\n", err);
  177. +}
  178. +
  179. +static int rb4xx_nand_probe(struct platform_device *pdev)
  180. +{
  181. + struct rb4xx_nand_info *info;
  182. + int ret;
  183. +
  184. + printk(KERN_INFO DRV_DESC " version " DRV_VERSION "\n");
  185. +
  186. + ret = gpio_request(RB4XX_NAND_GPIO_READY, "NAND RDY");
  187. + if (ret) {
  188. + dev_err(&pdev->dev, "unable to request gpio %d\n",
  189. + RB4XX_NAND_GPIO_READY);
  190. + goto err;
  191. + }
  192. +
  193. + ret = gpio_direction_input(RB4XX_NAND_GPIO_READY);
  194. + if (ret) {
  195. + dev_err(&pdev->dev, "unable to set input mode on gpio %d\n",
  196. + RB4XX_NAND_GPIO_READY);
  197. + goto err_free_gpio_ready;
  198. + }
  199. +
  200. + ret = gpio_request(RB4XX_NAND_GPIO_ALE, "NAND ALE");
  201. + if (ret) {
  202. + dev_err(&pdev->dev, "unable to request gpio %d\n",
  203. + RB4XX_NAND_GPIO_ALE);
  204. + goto err_free_gpio_ready;
  205. + }
  206. +
  207. + ret = gpio_direction_output(RB4XX_NAND_GPIO_ALE, 0);
  208. + if (ret) {
  209. + dev_err(&pdev->dev, "unable to set output mode on gpio %d\n",
  210. + RB4XX_NAND_GPIO_ALE);
  211. + goto err_free_gpio_ale;
  212. + }
  213. +
  214. + ret = gpio_request(RB4XX_NAND_GPIO_CLE, "NAND CLE");
  215. + if (ret) {
  216. + dev_err(&pdev->dev, "unable to request gpio %d\n",
  217. + RB4XX_NAND_GPIO_CLE);
  218. + goto err_free_gpio_ale;
  219. + }
  220. +
  221. + ret = gpio_direction_output(RB4XX_NAND_GPIO_CLE, 0);
  222. + if (ret) {
  223. + dev_err(&pdev->dev, "unable to set output mode on gpio %d\n",
  224. + RB4XX_NAND_GPIO_CLE);
  225. + goto err_free_gpio_cle;
  226. + }
  227. +
  228. + ret = gpio_request(RB4XX_NAND_GPIO_NCE, "NAND NCE");
  229. + if (ret) {
  230. + dev_err(&pdev->dev, "unable to request gpio %d\n",
  231. + RB4XX_NAND_GPIO_NCE);
  232. + goto err_free_gpio_cle;
  233. + }
  234. +
  235. + ret = gpio_direction_output(RB4XX_NAND_GPIO_NCE, 1);
  236. + if (ret) {
  237. + dev_err(&pdev->dev, "unable to set output mode on gpio %d\n",
  238. + RB4XX_NAND_GPIO_ALE);
  239. + goto err_free_gpio_nce;
  240. + }
  241. +
  242. + info = kzalloc(sizeof(*info), GFP_KERNEL);
  243. + if (!info) {
  244. + dev_err(&pdev->dev, "rb4xx-nand: no memory for private data\n");
  245. + ret = -ENOMEM;
  246. + goto err_free_gpio_nce;
  247. + }
  248. +
  249. + info->chip.priv = &info;
  250. + info->mtd.priv = &info->chip;
  251. + info->mtd.owner = THIS_MODULE;
  252. +
  253. + info->chip.cmd_ctrl = rb4xx_nand_cmd_ctrl;
  254. + info->chip.dev_ready = rb4xx_nand_dev_ready;
  255. + info->chip.read_byte = rb4xx_nand_read_byte;
  256. + info->chip.write_buf = rb4xx_nand_write_buf;
  257. + info->chip.read_buf = rb4xx_nand_read_buf;
  258. +
  259. + info->chip.chip_delay = 25;
  260. + info->chip.ecc.mode = NAND_ECC_SOFT;
  261. +
  262. + platform_set_drvdata(pdev, info);
  263. +
  264. + ret = nand_scan_ident(&info->mtd, 1, NULL);
  265. + if (ret) {
  266. + ret = -ENXIO;
  267. + goto err_free_info;
  268. + }
  269. +
  270. + if (info->mtd.writesize == 512)
  271. + info->chip.ecc.layout = &rb4xx_nand_ecclayout;
  272. +
  273. + ret = nand_scan_tail(&info->mtd);
  274. + if (ret) {
  275. + return -ENXIO;
  276. + goto err_set_drvdata;
  277. + }
  278. +
  279. + mtd_device_register(&info->mtd, rb4xx_nand_partitions,
  280. + ARRAY_SIZE(rb4xx_nand_partitions));
  281. + if (ret)
  282. + goto err_release_nand;
  283. +
  284. + return 0;
  285. +
  286. +err_release_nand:
  287. + nand_release(&info->mtd);
  288. +err_set_drvdata:
  289. + platform_set_drvdata(pdev, NULL);
  290. +err_free_info:
  291. + kfree(info);
  292. +err_free_gpio_nce:
  293. + gpio_free(RB4XX_NAND_GPIO_NCE);
  294. +err_free_gpio_cle:
  295. + gpio_free(RB4XX_NAND_GPIO_CLE);
  296. +err_free_gpio_ale:
  297. + gpio_free(RB4XX_NAND_GPIO_ALE);
  298. +err_free_gpio_ready:
  299. + gpio_free(RB4XX_NAND_GPIO_READY);
  300. +err:
  301. + return ret;
  302. +}
  303. +
  304. +static int rb4xx_nand_remove(struct platform_device *pdev)
  305. +{
  306. + struct rb4xx_nand_info *info = platform_get_drvdata(pdev);
  307. +
  308. + nand_release(&info->mtd);
  309. + platform_set_drvdata(pdev, NULL);
  310. + kfree(info);
  311. + gpio_free(RB4XX_NAND_GPIO_NCE);
  312. + gpio_free(RB4XX_NAND_GPIO_CLE);
  313. + gpio_free(RB4XX_NAND_GPIO_ALE);
  314. + gpio_free(RB4XX_NAND_GPIO_READY);
  315. +
  316. + return 0;
  317. +}
  318. +
  319. +static struct platform_driver rb4xx_nand_driver = {
  320. + .probe = rb4xx_nand_probe,
  321. + .remove = rb4xx_nand_remove,
  322. + .driver = {
  323. + .name = DRV_NAME,
  324. + .owner = THIS_MODULE,
  325. + },
  326. +};
  327. +
  328. +static int __init rb4xx_nand_init(void)
  329. +{
  330. + return platform_driver_register(&rb4xx_nand_driver);
  331. +}
  332. +
  333. +static void __exit rb4xx_nand_exit(void)
  334. +{
  335. + platform_driver_unregister(&rb4xx_nand_driver);
  336. +}
  337. +
  338. +module_init(rb4xx_nand_init);
  339. +module_exit(rb4xx_nand_exit);
  340. +
  341. +MODULE_DESCRIPTION(DRV_DESC);
  342. +MODULE_VERSION(DRV_VERSION);
  343. +MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org>");
  344. +MODULE_AUTHOR("Imre Kaloz <kaloz@openwrt.org>");
  345. +MODULE_LICENSE("GPL v2");
  346. --
  347. 1.8.5.3