msdc_irq.c 10 KB

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