msdc_irq.c 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  1. /* Copyright Statement:
  2. *
  3. * This software/firmware and related documentation ("MediaTek Software") are
  4. * protected under relevant copyright laws. The information contained herein
  5. * is confidential and proprietary to MediaTek Inc. and/or its licensors.
  6. * Without the prior written permission of MediaTek inc. and/or its licensors,
  7. * any reproduction, modification, use or disclosure of MediaTek Software,
  8. * and information contained herein, in whole or in part, shall be strictly prohibited.
  9. */
  10. /* MediaTek Inc. (C) 2015. All rights reserved.
  11. *
  12. * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
  13. * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
  14. * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON
  15. * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
  16. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
  17. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
  18. * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
  19. * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
  20. * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH
  21. * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES
  22. * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES
  23. * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK
  24. * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
  25. * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND
  26. * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
  27. * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
  28. * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO
  29. * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
  30. */
  31. #include "msdc.h"
  32. #if defined(MMC_MSDC_DRV_LK)
  33. #include <kernel/event.h>
  34. #include <platform/mt_irq.h>
  35. static event_t msdc_int_event;
  36. static u32 g_int_status = 0;
  37. void lk_msdc_irq_handler(unsigned int irq)
  38. {
  39. u32 intrs,sts;
  40. struct mmc_host *host = mmc_get_host(irq-MT_MSDC0_IRQ_ID);
  41. u32 base = host->base;
  42. mt_irq_ack(irq);
  43. intrs = MSDC_READ32(MSDC_INTEN);
  44. msdc_intr_mask(host,intrs);
  45. MSG(INT, "[lk_msdc_irq_handler]irq %x enable:%x %x\n",irq,intrs,MSDC_READ32(MSDC_INT));
  46. if ((sts = MSDC_READ32(MSDC_INT))& intrs) {
  47. g_int_status = sts;
  48. MSG(INT, "[lk_msdc_irq_handler]send event,%x\n",g_int_status);
  49. MSDC_WRITE32(MSDC_INT, sts);
  50. event_signal(&msdc_int_event,0);
  51. }
  52. return;
  53. }
  54. #endif
  55. #if defined(MSDC_USE_IRQ)
  56. #include "isrentry.h"
  57. //#include "inc/Jade/x_define_irq.h"
  58. //For CTP only
  59. typedef void (*irq_handler_t)(void);
  60. static const u32 msdc_irq_line[MSDC_MAX_NUM] = {MSDC0_IRQ_B_ID+8, MSDC1_IRQ_B_ID+8};
  61. static void *msdc_irq_data[MSDC_MAX_NUM];
  62. volatile u32 msdc_irq_sts[MSDC_MAX_NUM];
  63. static hw_irq_handler_t sdio_irq_handler[MSDC_MAX_NUM];
  64. #define DECLARE_MSDC_IRQ_HANDLER(x) \
  65. static void msdc_irq_handler_##x(void) \
  66. { \
  67. msdc_irq_handler(msdc_irq_data[(x)]); \
  68. }
  69. #define REGISTER_MSDC_IRQ_HANDLER(id, hndl, data) \
  70. do { \
  71. msdc_irq_data[(id)] = (void*)(data); \
  72. IRQSensitivity(msdc_irq_line[(id)], LEVEL_SENSITIVE); \
  73. IRQPolarity(msdc_irq_line[(id)], LOW_LEVEL_TRIGGER); \
  74. IRQ_Register_LISR(msdc_irq_line[(id)], hndl, NULL); \
  75. IRQUnmask(msdc_irq_line[(id)]); \
  76. } while(0)
  77. #define UNREGISTER_MSDC_IRQ_HANDLER(id) \
  78. do { \
  79. IRQMask(msdc_irq_line[(id)]); \
  80. msdc_irq_data[(id)] = NULL; \
  81. IRQ_Register_LISR(msdc_irq_line[(id)], IRQ_Default_LISR, NULL); \
  82. } while(0)
  83. #if defined(FEATURE_MMC_SDIO)
  84. static hw_irq_handler_t sdio_irq_handler[MSDC_MAX_NUM];
  85. void msdc_register_hwirq(struct mmc_host *host, hw_irq_handler_t handler)
  86. {
  87. sdio_irq_handler[host->id] = handler;
  88. }
  89. #endif
  90. int in_iqr = 0;
  91. static void msdc_irq_handler(void *data)
  92. {
  93. struct mmc_host *host = (struct mmc_host*)data;
  94. u32 id = host->id;
  95. u32 base = host->base;
  96. u32 intsts;
  97. msdc_int_reg *int_reg = (msdc_int_reg*)&intsts;
  98. BUG_ON(base == 0);
  99. //IRQMask(msdc_irq_line[id]);
  100. DisableIRQ();
  101. intsts = MSDC_READ32(MSDC_INT);
  102. msdc_irq_sts[id] |= intsts;
  103. if (intsts & MSDC_INT_CDSC) {
  104. /* card detection */
  105. in_iqr++;
  106. MSG(INT, "in_irq(%d) intsts(0x%x)",in_iqr,intsts);
  107. MSG(INT, "\n[SD%d] Card %s\n", id, msdc_card_avail(host) ? "Inserted" : "Removed");
  108. }
  109. if (intsts & MSDC_INT_SDIOIRQ) {
  110. /* sdio bus interrupt */
  111. MSG(INT, "[SD%d] SDIO interrupt <===\n", id);
  112. /* Note. msdc detects logical-low of dat1 to trigger sdio interrupt.
  113. * It will be triggered and should be _IGNORED_ since DAT1 of
  114. * SDIO/MMC/SD/SDXC card is pulled low when it's inserted into the slot.
  115. */
  116. #if defined(FEATURE_MMC_SDIO)
  117. if (sdio_irq_handler[id]) {
  118. sdio_irq_handler[id]();
  119. /* clear it since it's already handled */
  120. msdc_irq_sts[id] &= ~MSDC_INT_SDIOIRQ;
  121. }
  122. #endif
  123. }
  124. if (intsts & (MSDC_INT_CMDRDY|MSDC_INT_CMDTMO|MSDC_INT_RSPCRCERR)) {
  125. /* command done */
  126. }
  127. if (intsts & (MSDC_INT_ACMDRDY|MSDC_INT_ACMDTMO|MSDC_INT_ACMDCRCERR)) {
  128. /* auto command done */
  129. }
  130. if (intsts & MSDC_INT_ACMD19_DONE) {
  131. /* auto command 10 done */
  132. }
  133. if (intsts & MSDC_INT_XFER_COMPL) {
  134. /* data transfer done */
  135. }
  136. if (intsts & (MSDC_INT_DATCRCERR|MSDC_INT_DATTMO)) {
  137. /* data error */
  138. }
  139. if (intsts & MSDC_INT_DXFER_DONE) {
  140. /* dma transfer done */
  141. }
  142. if (intsts & MSDC_INT_DMAQ_EMPTY) {
  143. /* DMA queue empty */
  144. }
  145. if (intsts & MSDC_INT_CSTA) {
  146. /* CSTA available */
  147. }
  148. if (intsts & MSDC_INT_MMCIRQ) {
  149. /* MMCIRQ available */
  150. }
  151. MSG(INT, "[SD%d] IRQ_EVT(0x%x): MMCIRQ(%d) CDSC(%d), ACRDY(%d), ACTMO(%d), ACCRE(%d) AC19DN(%d)\n",
  152. id,
  153. intsts,
  154. int_reg->mmcirq,
  155. int_reg->cdsc,
  156. int_reg->atocmdrdy,
  157. int_reg->atocmdtmo,
  158. int_reg->atocmdcrc,
  159. int_reg->atocmd19done);
  160. MSG(INT, "[SD%d] IRQ_EVT(0x%x): SDIO(%d) CMDRDY(%d), CMDTMO(%d), RSPCRC(%d), CSTA(%d)\n",
  161. id,
  162. intsts,
  163. int_reg->sdioirq,
  164. int_reg->cmdrdy,
  165. int_reg->cmdtmo,
  166. int_reg->rspcrc,
  167. int_reg->csta);
  168. MSG(INT, "[SD%d] IRQ_EVT(0x%x): XFCMP(%d) DXDONE(%d), DATTMO(%d), DATCRC(%d), DMAEMP(%d)\n",
  169. id,
  170. intsts,
  171. int_reg->xfercomp,
  172. int_reg->dxferdone,
  173. int_reg->dattmo,
  174. int_reg->datcrc,
  175. int_reg->dmaqempty);
  176. MSDC_WRITE32(MSDC_INT, intsts); /* clear interrupts */
  177. //IRQUnmask(msdc_irq_line[id]);
  178. EnableIRQ();
  179. }
  180. DECLARE_MSDC_IRQ_HANDLER(0);
  181. DECLARE_MSDC_IRQ_HANDLER(1);
  182. DECLARE_MSDC_IRQ_HANDLER(2);
  183. DECLARE_MSDC_IRQ_HANDLER(3);
  184. static irq_handler_t isr[] = {
  185. msdc_irq_handler_0,
  186. msdc_irq_handler_1,
  187. msdc_irq_handler_2,
  188. msdc_irq_handler_3
  189. };
  190. #endif
  191. void msdc_irq_init(struct mmc_host *host)
  192. {
  193. #if defined(MMC_MSDC_DRV_LK)
  194. msdc_intr_mask(host,0xffffffff);
  195. mt_irq_set_sens(MT_MSDC0_IRQ_ID, MT65xx_LEVEL_SENSITIVE);
  196. mt_irq_set_polarity(MT_MSDC0_IRQ_ID, MT65xx_POLARITY_LOW);
  197. event_init(&msdc_int_event,false,EVENT_FLAG_AUTOUNSIGNAL);
  198. mt_irq_unmask(MT_MSDC0_IRQ_ID);
  199. #endif
  200. #if defined(MSDC_USE_IRQ)
  201. //For CTP only
  202. msdc_irq_sts[host->id] = 0;
  203. #if defined(FEATURE_MMC_SDIO)
  204. sdio_irq_handler[id] = NULL;
  205. #endif
  206. REGISTER_MSDC_IRQ_HANDLER(host->id, isr[host->id], host);
  207. #endif
  208. }
  209. void msdc_irq_deinit(struct mmc_host *host)
  210. {
  211. #if defined(MSDC_USE_IRQ)
  212. //UNREGISTER_MSDC_IRQ_HANDLER(host->id); //Light: Comment it out to solve build error in CTP
  213. #endif
  214. }
  215. #if defined(MMC_MSDC_DRV_LK)
  216. u32 msdc_lk_intr_wait(struct mmc_host *host, u32 intrs)
  217. {
  218. u32 base = host->base;
  219. u32 sts;
  220. #ifdef FPGA_PLATFORM
  221. u32 tmo = 0xFFFFFF;
  222. //SW timeout may occur on FPGA if request size is large, e.g., LK read kernel
  223. #else
  224. u32 tmo = 0xFFFF;
  225. #endif
  226. int ret = 0;
  227. MSG(INT, "[msdc_lk_intr_wait]\n");
  228. /* warning that interrupts are not enabled */
  229. WARN_ON((MSDC_READ32(MSDC_INTEN) & intrs) != intrs);
  230. ret = event_wait_timeout(&msdc_int_event, tmo);
  231. if (ret != 0) {
  232. msdc_pr_err("[%s]: failed to get event\n", __func__);
  233. } else {
  234. MSG(INT, "[%s]: get event\n", __func__);
  235. }
  236. sts = g_int_status;
  237. g_int_status = 0;
  238. MSG(INT, "[SD%d] INT(0x%x)\n", host->id, sts);
  239. if (~intrs & sts) {
  240. MSG(WRN, "[SD%d]<CHECKME> Unexpected INT(0x%x)\n",
  241. host->id, ~intrs & sts);
  242. }
  243. return sts;
  244. }
  245. #endif
  246. u32 msdc_intr_wait(struct mmc_host *host, u32 intrs)
  247. {
  248. u32 base = host->base;
  249. u32 sts;
  250. /* warning that interrupts are not enabled */
  251. WARN_ON((MSDC_READ32(MSDC_INTEN) & intrs) != intrs);
  252. #if defined(MSDC_USE_IRQ)
  253. //For CTP only
  254. while (1) {
  255. DisableIRQ();
  256. if (msdc_irq_sts[host->id] & intrs) {
  257. sts = msdc_irq_sts[host->id];
  258. msdc_irq_sts[host->id] &= ~intrs;
  259. EnableIRQ();
  260. break;
  261. }
  262. EnableIRQ();
  263. }
  264. #else
  265. {
  266. //Light: WAIT_COND is added after E1 ECO workaround.
  267. // I combine WAIT_COND with infinite wait
  268. u32 tmo = 500000; //set tmo=0 to choose infinite wait
  269. WAIT_COND( ((sts = MSDC_READ32(MSDC_INT)) & intrs), tmo, tmo);
  270. if (tmo == 0) {
  271. msdc_pr_err("[SD%d] ECO WARNNING ==> Wait INT timeout\n", host->id);
  272. MSDC_RESET();
  273. }
  274. }
  275. MSDC_WRITE32(MSDC_INT, (sts & intrs));
  276. #endif
  277. MSG(INT, "[SD%d] INT(0x%x)\n", host->id, sts);
  278. if (~intrs & sts) {
  279. MSG(WRN, "[SD%d]<CHECKME> Unexpected INT(0x%x)\n",
  280. host->id, ~intrs & sts);
  281. }
  282. #if defined(FEATURE_MMC_SDIO)
  283. if (sts & MSDC_INT_SDIOIRQ) {
  284. #if (0 == MSDC_SLT_MASK_LOG)
  285. msdc_pr_info("(%s)INT status:0x%x\n", __func__, sts);
  286. #endif
  287. //if ( (host->id == 2) || (host->id == 3) ) {
  288. //mmc_sdio_proc_pending_irqs(host->card);
  289. //isPendingIRQ++;
  290. //}
  291. }
  292. #endif
  293. return sts;
  294. }