msdc_irq.c 9.0 KB

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