860-qcom-mtd-nand-Add-bam_dma-support-in-qcom_nand-drive.patch 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370
  1. From 074036f9de6b8c5fc642e8e2540950f6a35aa804 Mon Sep 17 00:00:00 2001
  2. From: Ram Chandra Jangir <[email protected]>
  3. Date: Thu, 20 Apr 2017 10:31:10 +0530
  4. Subject: [PATCH] qcom: mtd: nand: Add bam_dma support in qcom_nand driver
  5. The current driver only support ADM DMA so this patch adds the
  6. BAM DMA support in current NAND driver with compatible string
  7. qcom,ebi2-nandc-bam.
  8. Added bam channels and data buffers, NAND BAM uses 3 channels:
  9. command, data tx and data rx, while ADM uses only single channel.
  10. So this patch adds the BAM channel in device tree and using the
  11. same in NAND driver allocation function.
  12. Signed-off-by: Ram Chandra Jangir <[email protected]>
  13. ---
  14. .../devicetree/bindings/mtd/qcom_nandc.txt | 69 +++++++--
  15. drivers/mtd/nand/qcom_nandc.c | 160 +++++++++++++++++----
  16. 2 files changed, 190 insertions(+), 39 deletions(-)
  17. --- a/Documentation/devicetree/bindings/mtd/qcom_nandc.txt
  18. +++ b/Documentation/devicetree/bindings/mtd/qcom_nandc.txt
  19. @@ -1,21 +1,26 @@
  20. * Qualcomm NAND controller
  21. Required properties:
  22. -- compatible: should be "qcom,ipq806x-nand"
  23. +- compatible: "qcom,ipq806x-nand" for IPQ8064 which uses
  24. + ADM DMA.
  25. + "qcom,ebi2-nand-bam" - nand drivers using BAM DMA
  26. + like IPQ4019.
  27. - reg: MMIO address range
  28. - clocks: must contain core clock and always on clock
  29. - clock-names: must contain "core" for the core clock and "aon" for the
  30. always on clock
  31. - dmas: DMA specifier, consisting of a phandle to the ADM DMA
  32. - controller node and the channel number to be used for
  33. - NAND. Refer to dma.txt and qcom_adm.txt for more details
  34. -- dma-names: must be "rxtx"
  35. -- qcom,cmd-crci: must contain the ADM command type CRCI block instance
  36. - number specified for the NAND controller on the given
  37. - platform
  38. -- qcom,data-crci: must contain the ADM data type CRCI block instance
  39. - number specified for the NAND controller on the given
  40. - platform
  41. + or BAM DMA controller node and the channel number to
  42. + be used for NAND. Refer to dma.txt, qcom_adm.txt(ADM)
  43. + and qcom_bam_dma.txt(BAM) for more details
  44. +- dma-names: "rxtx" - ADM
  45. + "tx", "rx", "cmd" - BAM
  46. +- qcom,cmd-crci: Only required for ADM DMA. must contain the ADM command
  47. + type CRCI block instance number specified for the NAND
  48. + controller on the given platform.
  49. +- qcom,data-crci: Only required for ADM DMA. must contain the ADM data
  50. + type CRCI block instance number specified for the NAND
  51. + controller on the given platform.
  52. - #address-cells: <1> - subnodes give the chip-select number
  53. - #size-cells: <0>
  54. @@ -44,7 +49,7 @@ partition.txt for more detail.
  55. Example:
  56. nand@1ac00000 {
  57. - compatible = "qcom,ebi2-nandc";
  58. + compatible = "qcom,ipq806x-nand","qcom.qcom_nand";
  59. reg = <0x1ac00000 0x800>;
  60. clocks = <&gcc EBI2_CLK>,
  61. @@ -58,6 +63,48 @@ nand@1ac00000 {
  62. #address-cells = <1>;
  63. #size-cells = <0>;
  64. +
  65. + nandcs@0 {
  66. + compatible = "qcom,nandcs";
  67. + reg = <0>;
  68. +
  69. + nand-ecc-strength = <4>;
  70. + nand-ecc-step-size = <512>;
  71. + nand-bus-width = <8>;
  72. +
  73. + partitions {
  74. + compatible = "fixed-partitions";
  75. + #address-cells = <1>;
  76. + #size-cells = <1>;
  77. +
  78. + partition@0 {
  79. + label = "boot-nand";
  80. + reg = <0 0x58a0000>;
  81. + };
  82. +
  83. + partition@58a0000 {
  84. + label = "fs-nand";
  85. + reg = <0x58a0000 0x4000000>;
  86. + };
  87. + };
  88. + };
  89. +};
  90. +
  91. +nand@79B0000 {
  92. + compatible = "qcom,ebi2-nandc-bam";
  93. + reg = <0x79B0000 0x1000>;
  94. +
  95. + clocks = <&gcc EBI2_CLK>,
  96. + <&gcc EBI2_AON_CLK>;
  97. + clock-names = "core", "aon";
  98. +
  99. + dmas = <&qpicbam 0>,
  100. + <&qpicbam 1>,
  101. + <&qpicbam 2>;
  102. + dma-names = "tx", "rx", "cmd";
  103. +
  104. + #address-cells = <1>;
  105. + #size-cells = <0>;
  106. nandcs@0 {
  107. compatible = "qcom,nandcs";
  108. --- a/drivers/mtd/nand/qcom_nandc.c
  109. +++ b/drivers/mtd/nand/qcom_nandc.c
  110. @@ -234,6 +234,7 @@ struct nandc_regs {
  111. * by upper layers directly
  112. * @buf_size/count/start: markers for chip->read_buf/write_buf functions
  113. * @reg_read_buf: local buffer for reading back registers via DMA
  114. + * @reg_read_buf_phys: contains dma address for register read buffer
  115. * @reg_read_pos: marker for data read in reg_read_buf
  116. *
  117. * @regs: a contiguous chunk of memory for DMA register
  118. @@ -242,7 +243,10 @@ struct nandc_regs {
  119. * @cmd1/vld: some fixed controller register values
  120. * @ecc_modes: supported ECC modes by the current controller,
  121. * initialized via DT match data
  122. - */
  123. + * @bch_enabled: flag to tell whether BCH or RS ECC mode is used
  124. + * @dma_bam_enabled: flag to tell whether nand controller is using
  125. + * bam dma
  126. +*/
  127. struct qcom_nand_controller {
  128. struct nand_hw_control controller;
  129. struct list_head host_list;
  130. @@ -255,17 +259,28 @@ struct qcom_nand_controller {
  131. struct clk *core_clk;
  132. struct clk *aon_clk;
  133. - struct dma_chan *chan;
  134. - unsigned int cmd_crci;
  135. - unsigned int data_crci;
  136. struct list_head desc_list;
  137. + union {
  138. + struct {
  139. + struct dma_chan *tx_chan;
  140. + struct dma_chan *rx_chan;
  141. + struct dma_chan *cmd_chan;
  142. + };
  143. + struct {
  144. + struct dma_chan *chan;
  145. + unsigned int cmd_crci;
  146. + unsigned int data_crci;
  147. + };
  148. + };
  149. u8 *data_buffer;
  150. + bool dma_bam_enabled;
  151. int buf_size;
  152. int buf_count;
  153. int buf_start;
  154. __le32 *reg_read_buf;
  155. + dma_addr_t reg_read_buf_phys;
  156. int reg_read_pos;
  157. struct nandc_regs *regs;
  158. @@ -324,6 +339,17 @@ struct qcom_nand_host {
  159. u32 clrreadstatus;
  160. };
  161. +/*
  162. + * This data type corresponds to the nand driver data which will be used at
  163. + * driver probe time
  164. + * @ecc_modes - ecc mode for nand
  165. + * @dma_bam_enabled - whether this driver is using bam
  166. + */
  167. +struct qcom_nand_driver_data {
  168. + u32 ecc_modes;
  169. + bool dma_bam_enabled;
  170. +};
  171. +
  172. static inline struct qcom_nand_host *to_qcom_nand_host(struct nand_chip *chip)
  173. {
  174. return container_of(chip, struct qcom_nand_host, chip);
  175. @@ -1949,16 +1975,46 @@ static int qcom_nandc_alloc(struct qcom_
  176. if (!nandc->regs)
  177. return -ENOMEM;
  178. - nandc->reg_read_buf = devm_kzalloc(nandc->dev,
  179. - MAX_REG_RD * sizeof(*nandc->reg_read_buf),
  180. - GFP_KERNEL);
  181. - if (!nandc->reg_read_buf)
  182. - return -ENOMEM;
  183. + if (!nandc->dma_bam_enabled) {
  184. + nandc->reg_read_buf = devm_kzalloc(nandc->dev,
  185. + MAX_REG_RD *
  186. + sizeof(*nandc->reg_read_buf),
  187. + GFP_KERNEL);
  188. - nandc->chan = dma_request_slave_channel(nandc->dev, "rxtx");
  189. - if (!nandc->chan) {
  190. - dev_err(nandc->dev, "failed to request slave channel\n");
  191. - return -ENODEV;
  192. + if (!nandc->reg_read_buf)
  193. + return -ENOMEM;
  194. +
  195. + nandc->chan = dma_request_slave_channel(nandc->dev, "rxtx");
  196. + if (!nandc->chan) {
  197. + dev_err(nandc->dev, "failed to request slave channel\n");
  198. + return -ENODEV;
  199. + }
  200. + } else {
  201. + nandc->reg_read_buf = dmam_alloc_coherent(nandc->dev,
  202. + MAX_REG_RD *
  203. + sizeof(*nandc->reg_read_buf),
  204. + &nandc->reg_read_buf_phys, GFP_KERNEL);
  205. +
  206. + if (!nandc->reg_read_buf)
  207. + return -ENOMEM;
  208. +
  209. + nandc->tx_chan = dma_request_slave_channel(nandc->dev, "tx");
  210. + if (!nandc->tx_chan) {
  211. + dev_err(nandc->dev, "failed to request tx channel\n");
  212. + return -ENODEV;
  213. + }
  214. +
  215. + nandc->rx_chan = dma_request_slave_channel(nandc->dev, "rx");
  216. + if (!nandc->rx_chan) {
  217. + dev_err(nandc->dev, "failed to request rx channel\n");
  218. + return -ENODEV;
  219. + }
  220. +
  221. + nandc->cmd_chan = dma_request_slave_channel(nandc->dev, "cmd");
  222. + if (!nandc->cmd_chan) {
  223. + dev_err(nandc->dev, "failed to request cmd channel\n");
  224. + return -ENODEV;
  225. + }
  226. }
  227. INIT_LIST_HEAD(&nandc->desc_list);
  228. @@ -1971,8 +2027,35 @@ static int qcom_nandc_alloc(struct qcom_
  229. static void qcom_nandc_unalloc(struct qcom_nand_controller *nandc)
  230. {
  231. - dma_release_channel(nandc->chan);
  232. -}
  233. + if (nandc->dma_bam_enabled) {
  234. + if (nandc->tx_chan)
  235. + dma_release_channel(nandc->tx_chan);
  236. +
  237. + if (nandc->rx_chan)
  238. + dma_release_channel(nandc->rx_chan);
  239. +
  240. + if (nandc->cmd_chan)
  241. + dma_release_channel(nandc->tx_chan);
  242. +
  243. + if (nandc->reg_read_buf)
  244. + dmam_free_coherent(nandc->dev, MAX_REG_RD *
  245. + sizeof(*nandc->reg_read_buf),
  246. + nandc->reg_read_buf,
  247. + nandc->reg_read_buf_phys);
  248. + } else {
  249. + if (nandc->chan)
  250. + dma_release_channel(nandc->chan);
  251. +
  252. + if (nandc->reg_read_buf)
  253. + devm_kfree(nandc->dev, nandc->reg_read_buf);
  254. + }
  255. +
  256. + if (nandc->regs)
  257. + devm_kfree(nandc->dev, nandc->regs);
  258. +
  259. + if (nandc->data_buffer)
  260. + devm_kfree(nandc->dev, nandc->data_buffer);
  261. + }
  262. /* one time setup of a few nand controller registers */
  263. static int qcom_nandc_setup(struct qcom_nand_controller *nandc)
  264. @@ -2010,6 +2093,8 @@ static int qcom_nand_host_init(struct qc
  265. mtd->name = devm_kasprintf(dev, GFP_KERNEL, "qcom_nand.%d", host->cs);
  266. mtd->owner = THIS_MODULE;
  267. mtd->dev.parent = dev;
  268. + mtd->priv = chip;
  269. + chip->priv = nandc;
  270. chip->cmdfunc = qcom_nandc_command;
  271. chip->select_chip = qcom_nandc_select_chip;
  272. @@ -2057,16 +2142,20 @@ static int qcom_nandc_parse_dt(struct pl
  273. struct device_node *np = nandc->dev->of_node;
  274. int ret;
  275. - ret = of_property_read_u32(np, "qcom,cmd-crci", &nandc->cmd_crci);
  276. - if (ret) {
  277. - dev_err(nandc->dev, "command CRCI unspecified\n");
  278. - return ret;
  279. - }
  280. + if (!nandc->dma_bam_enabled) {
  281. + ret = of_property_read_u32(np, "qcom,cmd-crci",
  282. + &nandc->cmd_crci);
  283. + if (ret) {
  284. + dev_err(nandc->dev, "command CRCI unspecified\n");
  285. + return ret;
  286. + }
  287. - ret = of_property_read_u32(np, "qcom,data-crci", &nandc->data_crci);
  288. - if (ret) {
  289. - dev_err(nandc->dev, "data CRCI unspecified\n");
  290. - return ret;
  291. + ret = of_property_read_u32(np, "qcom,data-crci",
  292. + &nandc->data_crci);
  293. + if (ret) {
  294. + dev_err(nandc->dev, "data CRCI unspecified\n");
  295. + return ret;
  296. + }
  297. }
  298. return 0;
  299. @@ -2081,6 +2170,7 @@ static int qcom_nandc_probe(struct platf
  300. struct device_node *dn = dev->of_node, *child;
  301. struct resource *res;
  302. int ret;
  303. + struct qcom_nand_driver_data *driver_data;
  304. nandc = devm_kzalloc(&pdev->dev, sizeof(*nandc), GFP_KERNEL);
  305. if (!nandc)
  306. @@ -2095,7 +2185,10 @@ static int qcom_nandc_probe(struct platf
  307. return -ENODEV;
  308. }
  309. - nandc->ecc_modes = (unsigned long)dev_data;
  310. + driver_data = (struct qcom_nand_driver_data *)dev_data;
  311. +
  312. + nandc->ecc_modes = driver_data->ecc_modes;
  313. + nandc->dma_bam_enabled = driver_data->dma_bam_enabled;
  314. res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  315. nandc->base = devm_ioremap_resource(dev, res);
  316. @@ -2187,7 +2280,15 @@ static int qcom_nandc_remove(struct plat
  317. return 0;
  318. }
  319. -#define EBI2_NANDC_ECC_MODES (ECC_RS_4BIT | ECC_BCH_8BIT)
  320. +struct qcom_nand_driver_data ebi2_nandc_bam_data = {
  321. + .ecc_modes = (ECC_BCH_4BIT | ECC_BCH_8BIT),
  322. + .dma_bam_enabled = true,
  323. +};
  324. +
  325. +struct qcom_nand_driver_data ebi2_nandc_data = {
  326. + .ecc_modes = (ECC_RS_4BIT | ECC_BCH_8BIT),
  327. + .dma_bam_enabled = false,
  328. +};
  329. /*
  330. * data will hold a struct pointer containing more differences once we support
  331. @@ -2195,7 +2296,10 @@ static int qcom_nandc_remove(struct plat
  332. */
  333. static const struct of_device_id qcom_nandc_of_match[] = {
  334. { .compatible = "qcom,ipq806x-nand",
  335. - .data = (void *)EBI2_NANDC_ECC_MODES,
  336. + .data = (void *) &ebi2_nandc_data,
  337. + },
  338. + { .compatible = "qcom,ebi2-nandc-bam",
  339. + .data = (void *) &ebi2_nandc_bam_data,
  340. },
  341. {}
  342. };