msm_sdcc_dml.c 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. /*
  2. * linux/drivers/mmc/host/msm_sdcc_dml.c - Qualcomm MSM SDCC DML Driver
  3. *
  4. * Copyright (c) 2011, The Linux Foundation. All rights reserved.
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License version 2 and
  8. * only version 2 as published by the Free Software Foundation.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. */
  16. #include <linux/io.h>
  17. #include <asm/sizes.h>
  18. #include <mach/msm_iomap.h>
  19. #include "msm_sdcc_dml.h"
  20. /*
  21. * DML registers definations
  22. */
  23. /* DML config register defination */
  24. #define DML_CONFIG 0x0000
  25. #define PRODUCER_CRCI_DIS 0x00
  26. #define PRODUCER_CRCI_X_SEL 0x01
  27. #define PRODUCER_CRCI_Y_SEL 0x02
  28. #define PRODUCER_CRCI_MSK 0x3
  29. #define CONSUMER_CRCI_DIS (0x00 << 2)
  30. #define CONSUMER_CRCI_X_SEL (0x01 << 2)
  31. #define CONSUMER_CRCI_Y_SEL (0x02 << 2)
  32. #define CONSUMER_CRCI_MSK (0x3 << 2)
  33. #define PRODUCER_TRANS_END_EN (1 << 4)
  34. #define BYPASS (1 << 16)
  35. #define DIRECT_MODE (1 << 17)
  36. #define INFINITE_CONS_TRANS (1 << 18)
  37. /* DML status register defination */
  38. #define DML_STATUS 0x0004
  39. #define PRODUCER_IDLE (1 << 0)
  40. #define CONSUMER_IDLE (1 << 16)
  41. /*
  42. * DML SW RESET register defination
  43. * NOTE: write to this register resets the DML core.
  44. * All internal state information will be lost and all
  45. * register values will be reset as well
  46. */
  47. #define DML_SW_RESET 0x0008
  48. /*
  49. * DML PRODUCER START register defination
  50. * NOTE: A write to this register triggers the DML
  51. * Producer state machine. No SW register values will be
  52. * altered.
  53. */
  54. #define DML_PRODUCER_START 0x000C
  55. /*
  56. * DML CONSUMER START register defination
  57. * NOTE: A write to this register triggers the DML
  58. * Consumer state machine. No SW register values will be
  59. * altered.
  60. */
  61. #define DML_CONSUMER_START 0x0010
  62. /*
  63. * DML producer pipe logical size register defination
  64. * NOTE: This register holds the size of the producer pipe
  65. * (in units of bytes) _to_ which the peripheral can
  66. * keep writing data to when its the PRODUCER.
  67. */
  68. #define DML_PRODUCER_PIPE_LOGICAL_SIZE 0x0014
  69. /*
  70. * DML producer pipe logical size register defination
  71. * NOTE: This register holds the size of the consumer pipe
  72. * (in units of bytes) _from_ which the peripheral
  73. * can keep _reading_ data from when its the CONSUMER.
  74. */
  75. #define DML_CONSUMER_PIPE_LOGICAL_SIZE 0x00018
  76. /*
  77. * DML PIPE ID register
  78. * This register holds pipe IDs that services
  79. * the producer and consumer side of the peripheral
  80. */
  81. #define DML_PIPE_ID 0x0001C
  82. #define PRODUCER_PIPE_ID_SHFT 0
  83. #define PRODUCER_PIPE_ID_MSK 0x1f
  84. #define CONSUMER_PIPE_ID_SHFT 16
  85. #define CONSUMER_PIPE_ID_MSK (0x1f << 16)
  86. /*
  87. * DML Producer trackers register defination.
  88. * This register is for debug purposes only. They reflect
  89. * the value of the producer block and transaction counters
  90. * when read. The values may be dynamically changing when
  91. * a transaction is in progress.
  92. */
  93. #define DML_PRODUCER_TRACKERS 0x00020
  94. #define PROD_BLOCK_CNT_SHFT 0
  95. #define PROD_BLOCK_CNT_MSK 0xffff
  96. #define PROD_TRANS_CNT_SHFT 16
  97. #define PROD_TRANS_CNT_MSK (0xffff << 16)
  98. /*
  99. * DML Producer BAM block size register defination.
  100. * This regsiter holds the block size, in units of bytes,
  101. * associated with the Producer BAM. The DML asserts the
  102. * block_end side band signal to the BAM whenever the producer
  103. * side of the peripheral has generated the said amount of data.
  104. * This register value should be an integral multiple of the
  105. * Producer CRCI Block Size.
  106. */
  107. #define DML_PRODUCER_BAM_BLOCK_SIZE 0x00024
  108. /*
  109. * DML Producer BAM Transaction size defination.
  110. * This regsiter holds the transaction size, in units of bytes,
  111. * associated with the Producer BAM. The DML asserts the transaction_end
  112. * side band signal to the BAM whenever the producer side of the peripheral
  113. * has generated the said amount of data.
  114. */
  115. #define DML_PRODUCER_BAM_TRANS_SIZE 0x00028
  116. /*
  117. * DML Direct mode base address defination
  118. * This register is used whenever the DIRECT_MODE bit
  119. * in config register is set.
  120. */
  121. #define DML_DIRECT_MODE_BASE_ADDR 0x002C
  122. #define PRODUCER_BASE_ADDR_BSHFT 0
  123. #define PRODUCER_BASE_ADDR_BMSK 0xffff
  124. #define CONSUMER_BASE_ADDR_BSHFT 16
  125. #define CONSUMER_BASE_ADDR_BMSK (0xffff << 16)
  126. /*
  127. * DMA Debug and status register defination.
  128. * These are the read-only registers useful debugging.
  129. */
  130. #define DML_DEBUG 0x0030
  131. #define DML_BAM_SIDE_STATUS_1 0x0034
  132. #define DML_BAM_SIDE_STATUS_2 0x0038
  133. /* other definations */
  134. #define PRODUCER_PIPE_LOGICAL_SIZE 4096
  135. #define CONSUMER_PIPE_LOGICAL_SIZE 4096
  136. #ifdef CONFIG_MMC_MSM_SPS_SUPPORT
  137. /**
  138. * Initialize DML HW connected with SDCC core
  139. *
  140. */
  141. int msmsdcc_dml_init(struct msmsdcc_host *host)
  142. {
  143. int rc = 0;
  144. u32 config = 0;
  145. void __iomem *dml_base;
  146. if (!host->dml_base) {
  147. host->dml_base = ioremap(host->dml_memres->start,
  148. resource_size(host->dml_memres));
  149. if (!host->dml_base) {
  150. pr_err("%s: DML ioremap() failed!!! %pr\n",
  151. mmc_hostname(host->mmc), host->dml_memres);
  152. rc = -ENOMEM;
  153. goto out;
  154. }
  155. pr_info("%s: Qualcomm MSM SDCC-DML %pr\n",
  156. mmc_hostname(host->mmc), host->dml_memres);
  157. }
  158. dml_base = host->dml_base;
  159. /* Reset the DML block */
  160. writel_relaxed(1, (dml_base + DML_SW_RESET));
  161. /* Disable the producer and consumer CRCI */
  162. config = (PRODUCER_CRCI_DIS | CONSUMER_CRCI_DIS);
  163. /*
  164. * Disable the bypass mode. Bypass mode will only be used
  165. * if data transfer is to happen in PIO mode and don't
  166. * want the BAM interface to connect with SDCC-DML.
  167. */
  168. config &= ~BYPASS;
  169. /*
  170. * Disable direct mode as we don't DML to MASTER the AHB bus.
  171. * BAM connected with DML should MASTER the AHB bus.
  172. */
  173. config &= ~DIRECT_MODE;
  174. /*
  175. * Disable infinite mode transfer as we won't be doing any
  176. * infinite size data transfers. All data transfer will be
  177. * of finite data size.
  178. */
  179. config &= ~INFINITE_CONS_TRANS;
  180. writel_relaxed(config, (dml_base + DML_CONFIG));
  181. /*
  182. * Initialize the logical BAM pipe size for producer
  183. * and consumer.
  184. */
  185. writel_relaxed(PRODUCER_PIPE_LOGICAL_SIZE,
  186. (dml_base + DML_PRODUCER_PIPE_LOGICAL_SIZE));
  187. writel_relaxed(CONSUMER_PIPE_LOGICAL_SIZE,
  188. (dml_base + DML_CONSUMER_PIPE_LOGICAL_SIZE));
  189. /* Initialize Producer/consumer pipe id */
  190. writel_relaxed(host->sps.src_pipe_index |
  191. (host->sps.dest_pipe_index << CONSUMER_PIPE_ID_SHFT),
  192. (dml_base + DML_PIPE_ID));
  193. mb();
  194. out:
  195. return rc;
  196. }
  197. /**
  198. * Soft reset DML HW
  199. *
  200. */
  201. void msmsdcc_dml_reset(struct msmsdcc_host *host)
  202. {
  203. /* Reset the DML block */
  204. writel_relaxed(1, (host->dml_base + DML_SW_RESET));
  205. mb();
  206. }
  207. /**
  208. * Checks if DML HW is busy or not?
  209. *
  210. */
  211. bool msmsdcc_is_dml_busy(struct msmsdcc_host *host)
  212. {
  213. return !(readl_relaxed(host->dml_base + DML_STATUS) & PRODUCER_IDLE) ||
  214. !(readl_relaxed(host->dml_base + DML_STATUS) & CONSUMER_IDLE);
  215. }
  216. /**
  217. * Start data transfer.
  218. *
  219. */
  220. void msmsdcc_dml_start_xfer(struct msmsdcc_host *host, struct mmc_data *data)
  221. {
  222. u32 config;
  223. void __iomem *dml_base = host->dml_base;
  224. if (data->flags & MMC_DATA_READ) {
  225. /* Read operation: configure DML for producer operation */
  226. /* Set producer CRCI-x and disable consumer CRCI */
  227. config = readl_relaxed(dml_base + DML_CONFIG);
  228. config = (config & ~PRODUCER_CRCI_MSK) | PRODUCER_CRCI_X_SEL;
  229. config = (config & ~CONSUMER_CRCI_MSK) | CONSUMER_CRCI_DIS;
  230. writel_relaxed(config, (dml_base + DML_CONFIG));
  231. /* Set the Producer BAM block size */
  232. writel_relaxed(data->blksz, (dml_base +
  233. DML_PRODUCER_BAM_BLOCK_SIZE));
  234. /* Set Producer BAM Transaction size */
  235. writel_relaxed(host->curr.xfer_size,
  236. (dml_base + DML_PRODUCER_BAM_TRANS_SIZE));
  237. /* Set Producer Transaction End bit */
  238. writel_relaxed((readl_relaxed(dml_base + DML_CONFIG)
  239. | PRODUCER_TRANS_END_EN),
  240. (dml_base + DML_CONFIG));
  241. /* Trigger producer */
  242. writel_relaxed(1, (dml_base + DML_PRODUCER_START));
  243. } else {
  244. /* Write operation: configure DML for consumer operation */
  245. /* Set consumer CRCI-x and disable producer CRCI*/
  246. config = readl_relaxed(dml_base + DML_CONFIG);
  247. config = (config & ~CONSUMER_CRCI_MSK) | CONSUMER_CRCI_X_SEL;
  248. config = (config & ~PRODUCER_CRCI_MSK) | PRODUCER_CRCI_DIS;
  249. writel_relaxed(config, (dml_base + DML_CONFIG));
  250. /* Clear Producer Transaction End bit */
  251. writel_relaxed((readl_relaxed(dml_base + DML_CONFIG)
  252. & ~PRODUCER_TRANS_END_EN),
  253. (dml_base + DML_CONFIG));
  254. /* Trigger consumer */
  255. writel_relaxed(1, (dml_base + DML_CONSUMER_START));
  256. }
  257. mb();
  258. }
  259. /**
  260. * Deinitialize DML HW connected with SDCC core
  261. *
  262. */
  263. void msmsdcc_dml_exit(struct msmsdcc_host *host)
  264. {
  265. /* Put DML block in reset state before exiting */
  266. msmsdcc_dml_reset(host);
  267. iounmap(host->dml_base);
  268. }
  269. #endif /* CONFIG_MMC_MSM_SPS_SUPPORT */