msdc_irq.c 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356
  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. #include <mt_gic.h>
  36. static event_t msdc_int_event;
  37. static u32 g_int_status = 0;
  38. void lk_msdc_irq_handler(unsigned int irq)
  39. {
  40. u32 intrs,sts;
  41. struct mmc_host *host = mmc_get_host(irq-MT_MSDC0_IRQ_ID);
  42. u32 base = host->base;
  43. mt_irq_ack(irq);
  44. intrs = MSDC_READ32(MSDC_INTEN);
  45. msdc_intr_mask(host,intrs);
  46. MSG(INT, "[lk_msdc_irq_handler]irq %x enable:%x %x\n",irq,intrs,MSDC_READ32(MSDC_INT));
  47. if ((sts = MSDC_READ32(MSDC_INT))& intrs) {
  48. g_int_status = sts;
  49. MSG(INT, "[lk_msdc_irq_handler]send event,%x\n",g_int_status);
  50. MSDC_WRITE32(MSDC_INT, sts);
  51. event_signal(&msdc_int_event,0);
  52. }
  53. return;
  54. }
  55. #endif
  56. #if defined(MSDC_USE_IRQ)
  57. #include "isrentry.h"
  58. //#include "inc/Jade/x_define_irq.h"
  59. //For CTP only
  60. typedef void (*irq_handler_t)(void);
  61. static const u32 msdc_irq_line[MSDC_MAX_NUM] = {MSDC0_IRQ_B_ID+8, MSDC1_IRQ_B_ID+8};
  62. static void *msdc_irq_data[MSDC_MAX_NUM];
  63. volatile u32 msdc_irq_sts[MSDC_MAX_NUM];
  64. static hw_irq_handler_t sdio_irq_handler[MSDC_MAX_NUM];
  65. #define DECLARE_MSDC_IRQ_HANDLER(x) \
  66. static void msdc_irq_handler_##x(void) \
  67. { \
  68. msdc_irq_handler(msdc_irq_data[(x)]); \
  69. }
  70. #define REGISTER_MSDC_IRQ_HANDLER(id, hndl, data) \
  71. do { \
  72. msdc_irq_data[(id)] = (void*)(data); \
  73. IRQSensitivity(msdc_irq_line[(id)], LEVEL_SENSITIVE); \
  74. IRQPolarity(msdc_irq_line[(id)], LOW_LEVEL_TRIGGER); \
  75. IRQ_Register_LISR(msdc_irq_line[(id)], hndl, NULL); \
  76. IRQUnmask(msdc_irq_line[(id)]); \
  77. } while(0)
  78. #define UNREGISTER_MSDC_IRQ_HANDLER(id) \
  79. do { \
  80. IRQMask(msdc_irq_line[(id)]); \
  81. msdc_irq_data[(id)] = NULL; \
  82. IRQ_Register_LISR(msdc_irq_line[(id)], IRQ_Default_LISR, NULL); \
  83. } while(0)
  84. #if defined(FEATURE_MMC_SDIO)
  85. static hw_irq_handler_t sdio_irq_handler[MSDC_MAX_NUM];
  86. void msdc_register_hwirq(struct mmc_host *host, hw_irq_handler_t handler)
  87. {
  88. sdio_irq_handler[host->id] = handler;
  89. }
  90. #endif
  91. #if defined(MMC_MSDC_DRV_CTP) && defined(FEATURE_MTH)
  92. extern void mth_get_gic_pending_reg(void);
  93. #endif
  94. int in_irq = 0;
  95. static void msdc_irq_handler(void *data)
  96. {
  97. struct mmc_host *host = (struct mmc_host*)data;
  98. u32 id = host->id;
  99. u32 base = host->base;
  100. u32 intsts;
  101. msdc_int_reg *int_reg = (msdc_int_reg*)&intsts;
  102. BUG_ON(base == 0);
  103. //IRQMask(msdc_irq_line[id]);
  104. DisableIRQ();
  105. #if defined(MMC_MSDC_DRV_CTP) && defined(FEATURE_MTH)
  106. mth_get_gic_pending_reg();
  107. #endif
  108. intsts = MSDC_READ32(MSDC_INT);
  109. msdc_irq_sts[id] |= intsts;
  110. if (intsts & MSDC_INT_CDSC) {
  111. /* card detection */
  112. in_irq++;
  113. MSG(INF, "in_irq(%d) intsts(0x%x)\n",in_irq, intsts);
  114. MSG(INF, "[SD%d] Card %s\n", id, msdc_card_avail(host) ? "Inserted" : "Removed");
  115. }
  116. if (intsts & MSDC_INT_SDIOIRQ) {
  117. /* sdio bus interrupt */
  118. MSG(INT, "[SD%d] SDIO interrupt <===\n", id);
  119. /* Note. msdc detects logical-low of dat1 to trigger sdio interrupt.
  120. * It will be triggered and should be _IGNORED_ since DAT1 of
  121. * SDIO/MMC/SD/SDXC card is pulled low when it's inserted into the slot.
  122. */
  123. #if defined(FEATURE_MMC_SDIO)
  124. if (sdio_irq_handler[id]) {
  125. sdio_irq_handler[id]();
  126. /* clear it since it's already handled */
  127. msdc_irq_sts[id] &= ~MSDC_INT_SDIOIRQ;
  128. }
  129. #endif
  130. }
  131. if (intsts & (MSDC_INT_CMDRDY|MSDC_INT_CMDTMO|MSDC_INT_RSPCRCERR)) {
  132. /* command done */
  133. }
  134. if (intsts & (MSDC_INT_ACMDRDY|MSDC_INT_ACMDTMO|MSDC_INT_ACMDCRCERR)) {
  135. /* auto command done */
  136. }
  137. if (intsts & MSDC_INT_ACMD19_DONE) {
  138. /* auto command 10 done */
  139. }
  140. if (intsts & MSDC_INT_XFER_COMPL) {
  141. /* data transfer done */
  142. }
  143. if (intsts & (MSDC_INT_DATCRCERR|MSDC_INT_DATTMO)) {
  144. /* data error */
  145. }
  146. if (intsts & MSDC_INT_DXFER_DONE) {
  147. /* dma transfer done */
  148. }
  149. if (intsts & MSDC_INT_DMAQ_EMPTY) {
  150. /* DMA queue empty */
  151. }
  152. if (intsts & MSDC_INT_CSTA) {
  153. /* CSTA available */
  154. }
  155. if (intsts & MSDC_INT_MMCIRQ) {
  156. /* MMCIRQ available */
  157. }
  158. MSG(INT, "[SD%d] IRQ_EVT(0x%x): MMCIRQ(%d) CDSC(%d), ACRDY(%d), ACTMO(%d), ACCRE(%d) AC19DN(%d)\n",
  159. id,
  160. intsts,
  161. int_reg->mmcirq,
  162. int_reg->cdsc,
  163. int_reg->atocmdrdy,
  164. int_reg->atocmdtmo,
  165. int_reg->atocmdcrc,
  166. int_reg->atocmd19done);
  167. MSG(INT, "[SD%d] IRQ_EVT(0x%x): SDIO(%d) CMDRDY(%d), CMDTMO(%d), RSPCRC(%d), CSTA(%d)\n",
  168. id,
  169. intsts,
  170. int_reg->sdioirq,
  171. int_reg->cmdrdy,
  172. int_reg->cmdtmo,
  173. int_reg->rspcrc,
  174. int_reg->csta);
  175. MSG(INT, "[SD%d] IRQ_EVT(0x%x): XFCMP(%d) DXDONE(%d), DATTMO(%d), DATCRC(%d), DMAEMP(%d)\n",
  176. id,
  177. intsts,
  178. int_reg->xfercomp,
  179. int_reg->dxferdone,
  180. int_reg->dattmo,
  181. int_reg->datcrc,
  182. int_reg->dmaqempty);
  183. MSDC_WRITE32(MSDC_INT, intsts); /* clear interrupts */
  184. //IRQUnmask(msdc_irq_line[id]);
  185. EnableIRQ();
  186. }
  187. DECLARE_MSDC_IRQ_HANDLER(0);
  188. DECLARE_MSDC_IRQ_HANDLER(1);
  189. DECLARE_MSDC_IRQ_HANDLER(2);
  190. DECLARE_MSDC_IRQ_HANDLER(3);
  191. static irq_handler_t isr[] = {
  192. msdc_irq_handler_0,
  193. msdc_irq_handler_1,
  194. msdc_irq_handler_2,
  195. msdc_irq_handler_3
  196. };
  197. #endif
  198. void msdc_irq_init(struct mmc_host *host)
  199. {
  200. #if defined(MMC_MSDC_DRV_LK)
  201. msdc_intr_mask(host,0xffffffff);
  202. mt_irq_set_sens(MT_MSDC0_IRQ_ID, MT65xx_LEVEL_SENSITIVE);
  203. mt_irq_set_polarity(MT_MSDC0_IRQ_ID, MT65xx_POLARITY_LOW);
  204. event_init(&msdc_int_event,false,EVENT_FLAG_AUTOUNSIGNAL);
  205. mt_irq_unmask(MT_MSDC0_IRQ_ID);
  206. #endif
  207. #if defined(MSDC_USE_IRQ)
  208. //For CTP only
  209. msdc_irq_sts[host->id] = 0;
  210. #if defined(FEATURE_MMC_SDIO)
  211. sdio_irq_handler[id] = NULL;
  212. #endif
  213. REGISTER_MSDC_IRQ_HANDLER(host->id, isr[host->id], host);
  214. #endif
  215. }
  216. void msdc_irq_deinit(struct mmc_host *host)
  217. {
  218. #if defined(MSDC_USE_IRQ)
  219. //UNREGISTER_MSDC_IRQ_HANDLER(host->id); //Light: Comment it out to solve build error in CTP
  220. #endif
  221. }
  222. extern u32 mth_get_gic_pending_reg(u32 user); //Light temp
  223. #if defined(MMC_MSDC_DRV_LK)
  224. u32 msdc_lk_intr_wait(struct mmc_host *host, u32 intrs)
  225. {
  226. u32 base = host->base;
  227. u32 sts;
  228. #if defined(FPGA_PLATFORM)
  229. u32 tmo = 0xFFFFFFFF;
  230. //SW timeout may occur on FPGA if request size is large, e.g., LK read kernel
  231. #else
  232. u32 tmo = 0xFFFF;
  233. #endif
  234. int ret = 0;
  235. MSG(INT, "[msdc_lk_intr_wait]\n");
  236. /* warning that interrupts are not enabled */
  237. WARN_ON((MSDC_READ32(MSDC_INTEN) & intrs) != intrs);
  238. ret = event_wait_timeout(&msdc_int_event, tmo);
  239. if (ret != 0) {
  240. msdc_pr_err("[%s]: failed to get event\n", __func__);
  241. } else {
  242. MSG(INT, "[%s]: get event\n", __func__);
  243. }
  244. sts = g_int_status;
  245. g_int_status = 0;
  246. MSG(INT, "[SD%d] INT(0x%x)\n", host->id, sts);
  247. if (~intrs & sts) {
  248. MSG(WRN, "[SD%d]<CHECKME> Unexpected INT(0x%x)\n",
  249. host->id, ~intrs & sts);
  250. }
  251. return sts;
  252. }
  253. #endif
  254. u32 msdc_intr_wait(struct mmc_host *host, u32 intrs)
  255. {
  256. u32 base = host->base;
  257. u32 sts;
  258. /* warning that interrupts are not enabled */
  259. WARN_ON((MSDC_READ32(MSDC_INTEN) & intrs) != intrs);
  260. #if defined(MSDC_USE_IRQ)
  261. //For CTP only
  262. while (1) {
  263. DisableIRQ();
  264. if (msdc_irq_sts[host->id] & intrs) {
  265. sts = msdc_irq_sts[host->id];
  266. msdc_irq_sts[host->id] &= ~intrs;
  267. EnableIRQ();
  268. break;
  269. }
  270. EnableIRQ();
  271. }
  272. #else
  273. {
  274. u32 tmo; //set tmo=0 to choose infinite wait
  275. if (host->cur_bus_clk > 1000000)
  276. tmo = 1000;
  277. else
  278. tmo = 5000;
  279. WAIT_COND( ((sts = MSDC_READ32(MSDC_INT)) & intrs), tmo, tmo);
  280. if (tmo == 0) {
  281. msdc_pr_err("[SD%d] Wait INT timeout\n", host->id);
  282. MSDC_RESET();
  283. }
  284. }
  285. MSDC_WRITE32(MSDC_INT, (sts & intrs));
  286. #endif
  287. MSG(INT, "[SD%d] INT(0x%x)\n", host->id, sts);
  288. if (~intrs & sts) {
  289. MSG(WRN, "[SD%d]<CHECKME> Unexpected INT(0x%x)\n",
  290. host->id, ~intrs & sts);
  291. }
  292. #if defined(FEATURE_MMC_SDIO)
  293. if (sts & MSDC_INT_SDIOIRQ) {
  294. #if (0 == MSDC_SLT_MASK_LOG)
  295. msdc_pr_info("(%s)INT status:0x%x\n", __func__, sts);
  296. #endif
  297. //if ( (host->id == 2) || (host->id == 3) ) {
  298. //mmc_sdio_proc_pending_irqs(host->card);
  299. //isPendingIRQ++;
  300. //}
  301. }
  302. #endif
  303. return sts;
  304. }