interrupts.c 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. /*
  2. * Copyright (c) 2008, Google Inc.
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions
  7. * are met:
  8. * * Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * * Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in
  12. * the documentation and/or other materials provided with the
  13. * distribution.
  14. * * Neither the name of Google, Inc. nor the names of its contributors
  15. * may be used to endorse or promote products derived from this
  16. * software without specific prior written permission.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  19. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  20. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  21. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  22. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  23. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  24. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  25. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  26. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  27. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  28. * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  29. * SUCH DAMAGE.
  30. */
  31. #include <arch/arm.h>
  32. #include <reg.h>
  33. #include <mt_gic.h>
  34. #include <kernel/thread.h>
  35. #include <platform/interrupts.h>
  36. #include <platform/mt_typedefs.h>
  37. #include <platform/mt_reg_base.h>
  38. #include <platform/mt_gpt.h>
  39. #include <platform/mt_irq.h>
  40. #include <debug.h>
  41. #define GIC_ICDISER0 (GIC_DIST_BASE + 0x100)
  42. #define GIC_ICDISER1 (GIC_DIST_BASE + 0x104)
  43. #define GIC_ICDISER2 (GIC_DIST_BASE + 0x108)
  44. #define GIC_ICDISER3 (GIC_DIST_BASE + 0x10C)
  45. #define GIC_ICDISER4 (GIC_DIST_BASE + 0x110)
  46. #define GIC_ICDISER5 (GIC_DIST_BASE + 0x114)
  47. #define GIC_ICDISER6 (GIC_DIST_BASE + 0x118)
  48. #define GIC_ICDISER7 (GIC_DIST_BASE + 0x11C)
  49. #define GIC_ICDICER0 (GIC_DIST_BASE + 0x180)
  50. #define GIC_ICDICER1 (GIC_DIST_BASE + 0x184)
  51. #define GIC_ICDICER2 (GIC_DIST_BASE + 0x188)
  52. #define GIC_ICDICER3 (GIC_DIST_BASE + 0x18C)
  53. #define GIC_ICDICER4 (GIC_DIST_BASE + 0x190)
  54. #define GIC_ICDICER5 (GIC_DIST_BASE + 0x194)
  55. #define GIC_ICDICER6 (GIC_DIST_BASE + 0x198)
  56. #define GIC_ICDICER7 (GIC_DIST_BASE + 0x19C)
  57. #define INT_POL_CTL0 (MCUCFG_BASE + 0x620)
  58. static void mt_gic_cpu_init(void)
  59. {
  60. DRV_WriteReg32(GIC_CPU_BASE + GIC_CPU_PRIMASK, 0xF0);
  61. DRV_WriteReg32(GIC_CPU_BASE + GIC_CPU_CTRL, 0x1);
  62. dsb();
  63. }
  64. static void mt_gic_dist_init(void)
  65. {
  66. unsigned int i;
  67. #ifndef MTK_FORCE_CLUSTER1
  68. unsigned int cpumask = 1 << 0;
  69. #else
  70. unsigned int cpumask = 1 << 4;
  71. #endif
  72. cpumask |= cpumask << 8;
  73. cpumask |= cpumask << 16;
  74. DRV_WriteReg32(GIC_DIST_BASE + GIC_DIST_CTRL, 0);
  75. /*
  76. * Set all global interrupts to be level triggered, active low.
  77. */
  78. for (i = 32; i < (MT_NR_SPI + 32); i += 16) {
  79. DRV_WriteReg32(GIC_DIST_BASE + GIC_DIST_CONFIG + i * 4 / 16, 0);
  80. }
  81. /*
  82. * Set all global interrupts to this CPU only.
  83. */
  84. for (i = 32; i < (MT_NR_SPI + 32); i += 4) {
  85. DRV_WriteReg32(GIC_DIST_BASE + GIC_DIST_TARGET + i * 4 / 4, cpumask);
  86. }
  87. /*
  88. * Set priority on all interrupts.
  89. */
  90. for (i = 0; i < NR_IRQ_LINE; i += 4) {
  91. DRV_WriteReg32(GIC_DIST_BASE + GIC_DIST_PRI + i * 4 / 4, 0xA0A0A0A0);
  92. }
  93. /*
  94. * Disable all interrupts.
  95. */
  96. for (i = 0; i < NR_IRQ_LINE; i += 32) {
  97. DRV_WriteReg32(GIC_DIST_BASE + GIC_DIST_ENABLE_CLEAR + i * 4 / 32, 0xFFFFFFFF);
  98. }
  99. dsb();
  100. DRV_WriteReg32(GIC_DIST_BASE + GIC_DIST_CTRL, 1);
  101. }
  102. void platform_init_interrupts(void)
  103. {
  104. mt_gic_dist_init();
  105. mt_gic_cpu_init();
  106. }
  107. void platform_deinit_interrupts(void)
  108. {
  109. unsigned int irq;
  110. DRV_WriteReg32(GIC_ICDICER0, 0xFFFFFFFF);
  111. DRV_WriteReg32(GIC_ICDICER1, 0xFFFFFFFF);
  112. DRV_WriteReg32(GIC_ICDICER2, 0xFFFFFFFF);
  113. DRV_WriteReg32(GIC_ICDICER3, 0xFFFFFFFF);
  114. DRV_WriteReg32(GIC_ICDICER4, 0xFFFFFFFF);
  115. DRV_WriteReg32(GIC_ICDICER5, 0xFFFFFFFF);
  116. DRV_WriteReg32(GIC_ICDICER6, 0xFFFFFFFF);
  117. DRV_WriteReg32(GIC_ICDICER7, 0xFFFFFFFF);
  118. dsb();
  119. while((irq = DRV_Reg32(GIC_CPU_BASE + GIC_CPU_INTACK)) != 1023 ) {
  120. DRV_WriteReg32(GIC_CPU_BASE + GIC_CPU_EOI, irq);
  121. }
  122. }
  123. extern void lk_scheduler(void);
  124. extern void lk_usb_scheduler(void);
  125. extern void lk_nand_irq_handler(unsigned int irq);
  126. extern void lk_msdc_irq_handler(unsigned int irq);
  127. extern void dummy_ap_irq_handler(unsigned int irq)__attribute__((weak)); /* this function is empty for normal load */
  128. enum handler_return platform_irq(struct arm_iframe *frame)
  129. {
  130. unsigned int irq = DRV_Reg32(GIC_CPU_BASE + GIC_CPU_INTACK);
  131. if(irq == MT_GPT_IRQ_ID)
  132. lk_scheduler();
  133. else if(irq == MT_USB0_IRQ_ID)
  134. lk_usb_scheduler();
  135. #ifndef MTK_EMMC_SUPPORT
  136. else if(irq == MT_NFI_IRQ_ID)
  137. lk_nand_irq_handler(irq);
  138. #endif
  139. else if(irq == MT_MSDC0_IRQ_ID || irq == MT_MSDC1_IRQ_ID)
  140. lk_msdc_irq_handler(irq);
  141. if (dummy_ap_irq_handler)
  142. dummy_ap_irq_handler(irq);
  143. //return INT_NO_RESCHEDULE;
  144. return INT_RESCHEDULE;
  145. }
  146. void platform_fiq(struct arm_iframe *frame)
  147. {
  148. }
  149. void mt_irq_set_polarity(unsigned int irq, unsigned int polarity)
  150. {
  151. unsigned int offset;
  152. unsigned int reg_index;
  153. unsigned int value;
  154. // peripheral device's IRQ line is using GIC's SPI, and line ID >= GIC_PRIVATE_SIGNALS
  155. if (irq < GIC_PRIVATE_SIGNALS) {
  156. return;
  157. }
  158. offset = (irq - GIC_PRIVATE_SIGNALS) & 0x1F;
  159. reg_index = (irq - GIC_PRIVATE_SIGNALS) >> 5;
  160. if (polarity == 0) {
  161. value = DRV_Reg32(INT_POL_CTL0 + (reg_index * 4));
  162. value |= (1 << offset); // always invert the incoming IRQ's polarity
  163. DRV_WriteReg32((INT_POL_CTL0 + (reg_index * 4)), value);
  164. }else {
  165. value = DRV_Reg32(INT_POL_CTL0 + (reg_index * 4));
  166. value &= ~(0x1 << offset);
  167. DRV_WriteReg32(INT_POL_CTL0 + (reg_index * 4), value);
  168. }
  169. }
  170. void mt_irq_set_sens(unsigned int irq, unsigned int sens)
  171. {
  172. unsigned int config;
  173. if (sens == MT65xx_EDGE_SENSITIVE) {
  174. config = DRV_Reg32(GIC_DIST_BASE + GIC_DIST_CONFIG + (irq / 16) * 4);
  175. config |= (0x2 << (irq % 16) * 2);
  176. DRV_WriteReg32(GIC_DIST_BASE + GIC_DIST_CONFIG + (irq / 16) * 4, config);
  177. }else {
  178. config = DRV_Reg32(GIC_DIST_BASE + GIC_DIST_CONFIG + (irq / 16) * 4);
  179. config &= ~(0x2 << (irq % 16) * 2);
  180. DRV_WriteReg32( GIC_DIST_BASE + GIC_DIST_CONFIG + (irq / 16) * 4, config);
  181. }
  182. dsb();
  183. }
  184. /*
  185. * mt_irq_mask: mask one IRQ
  186. * @irq: IRQ line of the IRQ to mask
  187. */
  188. void mt_irq_mask(unsigned int irq)
  189. {
  190. unsigned int mask = 1 << (irq % 32);
  191. DRV_WriteReg32(GIC_DIST_BASE + GIC_DIST_ENABLE_CLEAR + irq / 32 * 4, mask);
  192. dsb();
  193. }
  194. /*
  195. * mt_irq_unmask: unmask one IRQ
  196. * @irq: IRQ line of the IRQ to unmask
  197. */
  198. void mt_irq_unmask(unsigned int irq)
  199. {
  200. unsigned int mask = 1 << (irq % 32);
  201. DRV_WriteReg32(GIC_DIST_BASE + GIC_DIST_ENABLE_SET + irq / 32 * 4, mask);
  202. dsb();
  203. }
  204. /*
  205. * mt_irq_mask: mask one IRQ
  206. * @irq: IRQ line of the IRQ to mask
  207. */
  208. void mt_irq_ack(unsigned int irq)
  209. {
  210. DRV_WriteReg32(GIC_CPU_BASE + GIC_CPU_EOI, irq);
  211. dsb();
  212. }
  213. /*
  214. * mt_irq_mask_all: mask all IRQ lines. (This is ONLY used for the sleep driver)
  215. * @mask: pointer to struct mtk_irq_mask for storing the original mask value.
  216. * Return 0 for success; return negative values for failure.
  217. */
  218. int mt_irq_mask_all(struct mtk_irq_mask *mask)
  219. {
  220. if (mask) {
  221. mask->mask[0] = DRV_Reg32(GIC_ICDISER0);
  222. mask->mask[1] = DRV_Reg32(GIC_ICDISER1);
  223. mask->mask[2] = DRV_Reg32(GIC_ICDISER2);
  224. mask->mask[3] = DRV_Reg32(GIC_ICDISER3);
  225. mask->mask[4] = DRV_Reg32(GIC_ICDISER4);
  226. mask->mask[5] = DRV_Reg32(GIC_ICDISER5);
  227. mask->mask[6] = DRV_Reg32(GIC_ICDISER6);
  228. mask->mask[7] = DRV_Reg32(GIC_ICDISER7);
  229. DRV_WriteReg32(GIC_ICDICER0, 0xFFFFFFFF);
  230. DRV_WriteReg32(GIC_ICDICER1, 0xFFFFFFFF);
  231. DRV_WriteReg32(GIC_ICDICER2, 0xFFFFFFFF);
  232. DRV_WriteReg32(GIC_ICDICER3, 0xFFFFFFFF);
  233. DRV_WriteReg32(GIC_ICDICER4, 0xFFFFFFFF);
  234. DRV_WriteReg32(GIC_ICDICER5, 0xFFFFFFFF);
  235. DRV_WriteReg32(GIC_ICDICER6, 0xFFFFFFFF);
  236. DRV_WriteReg32(GIC_ICDICER7, 0xFFFFFFFF);
  237. dsb();
  238. mask->header = IRQ_MASK_HEADER;
  239. mask->footer = IRQ_MASK_FOOTER;
  240. return 0;
  241. } else {
  242. return -1;
  243. }
  244. }
  245. /*
  246. * mt_irq_mask_restore: restore all IRQ lines' masks. (This is ONLY used for the sleep driver)
  247. * @mask: pointer to struct mtk_irq_mask for storing the original mask value.
  248. * Return 0 for success; return negative values for failure.
  249. */
  250. int mt_irq_mask_restore(struct mtk_irq_mask *mask)
  251. {
  252. if (!mask) {
  253. return -1;
  254. }
  255. if (mask->header != IRQ_MASK_HEADER) {
  256. return -1;
  257. }
  258. if (mask->footer != IRQ_MASK_FOOTER) {
  259. return -1;
  260. }
  261. DRV_WriteReg32(GIC_ICDISER0,mask->mask[0]);
  262. DRV_WriteReg32(GIC_ICDISER1,mask->mask[1]);
  263. DRV_WriteReg32(GIC_ICDISER2,mask->mask[2]);
  264. DRV_WriteReg32(GIC_ICDISER3,mask->mask[3]);
  265. DRV_WriteReg32(GIC_ICDISER4,mask->mask[4]);
  266. DRV_WriteReg32(GIC_ICDISER5,mask->mask[5]);
  267. DRV_WriteReg32(GIC_ICDISER6,mask->mask[6]);
  268. DRV_WriteReg32(GIC_ICDISER7,mask->mask[7]);
  269. dsb();
  270. return 0;
  271. }