interrupts.c 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  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 <kernel/thread.h>
  34. #include <platform/interrupts.h>
  35. #include <platform/mt_typedefs.h>
  36. #include <platform/mt_reg_base.h>
  37. #include <platform/mt_gpt.h>
  38. #include <platform/mt_irq.h>
  39. #include <debug.h>
  40. #define GIC_ICDISER0 (GIC_DIST_BASE + 0x100)
  41. #define GIC_ICDISER1 (GIC_DIST_BASE + 0x104)
  42. #define GIC_ICDISER2 (GIC_DIST_BASE + 0x108)
  43. #define GIC_ICDISER3 (GIC_DIST_BASE + 0x10C)
  44. #define GIC_ICDISER4 (GIC_DIST_BASE + 0x110)
  45. #define GIC_ICDISER5 (GIC_DIST_BASE + 0x114)
  46. #define GIC_ICDISER6 (GIC_DIST_BASE + 0x118)
  47. #define GIC_ICDISER7 (GIC_DIST_BASE + 0x11C)
  48. #define GIC_ICDICER0 (GIC_DIST_BASE + 0x180)
  49. #define GIC_ICDICER1 (GIC_DIST_BASE + 0x184)
  50. #define GIC_ICDICER2 (GIC_DIST_BASE + 0x188)
  51. #define GIC_ICDICER3 (GIC_DIST_BASE + 0x18C)
  52. #define GIC_ICDICER4 (GIC_DIST_BASE + 0x190)
  53. #define GIC_ICDICER5 (GIC_DIST_BASE + 0x194)
  54. #define GIC_ICDICER6 (GIC_DIST_BASE + 0x198)
  55. #define GIC_ICDICER7 (GIC_DIST_BASE + 0x19C)
  56. #define INT_POL_CTL0 (MCUCFG_BASE + 0x100)
  57. static void mt_gic_cpu_init(void)
  58. {
  59. DRV_WriteReg32(GIC_CPU_BASE + GIC_CPU_PRIMASK, 0xF0);
  60. DRV_WriteReg32(GIC_CPU_BASE + GIC_CPU_CTRL, 0x1);
  61. dsb();
  62. }
  63. static void mt_gic_dist_init(void)
  64. {
  65. unsigned int i;
  66. #ifndef MTK_FORCE_CLUSTER1
  67. unsigned int cpumask = 1 << 0;
  68. #else
  69. unsigned int cpumask = 1 << 4;
  70. #endif
  71. cpumask |= cpumask << 8;
  72. cpumask |= cpumask << 16;
  73. DRV_WriteReg32(GIC_DIST_BASE + GIC_DIST_CTRL, 0);
  74. /*
  75. * Set all global interrupts to be level triggered, active low.
  76. */
  77. for (i = 32; i < (MT_NR_SPI + 32); i += 16) {
  78. DRV_WriteReg32(GIC_DIST_BASE + GIC_DIST_CONFIG + i * 4 / 16, 0);
  79. }
  80. /*
  81. * Set all global interrupts to this CPU only.
  82. */
  83. for (i = 32; i < (MT_NR_SPI + 32); i += 4) {
  84. DRV_WriteReg32(GIC_DIST_BASE + GIC_DIST_TARGET + i * 4 / 4, cpumask);
  85. }
  86. /*
  87. * Set priority on all interrupts.
  88. */
  89. for (i = 0; i < NR_IRQ_LINE; i += 4) {
  90. DRV_WriteReg32(GIC_DIST_BASE + GIC_DIST_PRI + i * 4 / 4, 0xA0A0A0A0);
  91. }
  92. /*
  93. * Disable all interrupts.
  94. */
  95. for (i = 0; i < NR_IRQ_LINE; i += 32) {
  96. DRV_WriteReg32(GIC_DIST_BASE + GIC_DIST_ENABLE_CLEAR + i * 4 / 32, 0xFFFFFFFF);
  97. }
  98. dsb();
  99. DRV_WriteReg32(GIC_DIST_BASE + GIC_DIST_CTRL, 1);
  100. }
  101. void platform_init_interrupts(void)
  102. {
  103. mt_gic_dist_init();
  104. mt_gic_cpu_init();
  105. }
  106. void platform_deinit_interrupts(void)
  107. {
  108. unsigned int irq;
  109. DRV_WriteReg32(GIC_ICDICER0, 0xFFFFFFFF);
  110. DRV_WriteReg32(GIC_ICDICER1, 0xFFFFFFFF);
  111. DRV_WriteReg32(GIC_ICDICER2, 0xFFFFFFFF);
  112. DRV_WriteReg32(GIC_ICDICER3, 0xFFFFFFFF);
  113. DRV_WriteReg32(GIC_ICDICER4, 0xFFFFFFFF);
  114. DRV_WriteReg32(GIC_ICDICER5, 0xFFFFFFFF);
  115. DRV_WriteReg32(GIC_ICDICER6, 0xFFFFFFFF);
  116. DRV_WriteReg32(GIC_ICDICER7, 0xFFFFFFFF);
  117. dsb();
  118. while((irq = DRV_Reg32(GIC_CPU_BASE + GIC_CPU_INTACK)) != 1023 ) {
  119. DRV_WriteReg32(GIC_CPU_BASE + GIC_CPU_EOI, irq);
  120. }
  121. }
  122. extern void lk_scheduler(void);
  123. extern void lk_usb_scheduler(void);
  124. extern void lk_nand_irq_handler(unsigned int irq);
  125. extern void lk_msdc_irq_handler(unsigned int irq);
  126. #ifdef DUMMY_AP
  127. extern void dummy_ap_irq_handler(unsigned int irq);
  128. #endif
  129. enum handler_return platform_irq(struct arm_iframe *frame)
  130. {
  131. unsigned int irq = DRV_Reg32(GIC_CPU_BASE + GIC_CPU_INTACK);
  132. if(irq == MT_GPT_IRQ_ID)
  133. lk_scheduler();
  134. else if(irq == MT_USB0_IRQ_ID)
  135. lk_usb_scheduler();
  136. #ifndef MTK_EMMC_SUPPORT
  137. else if(irq == MT_NFI_IRQ_ID)
  138. lk_nand_irq_handler(irq);
  139. #endif
  140. else if(irq == MT_MSDC0_IRQ_ID || irq == MT_MSDC1_IRQ_ID)
  141. lk_msdc_irq_handler(irq);
  142. #ifdef DUMMY_AP
  143. dummy_ap_irq_handler(irq);
  144. #endif
  145. //return INT_NO_RESCHEDULE;
  146. return INT_RESCHEDULE;
  147. }
  148. void platform_fiq(struct arm_iframe *frame)
  149. {
  150. }
  151. void mt_irq_set_polarity(unsigned int irq, unsigned int polarity)
  152. {
  153. unsigned int offset;
  154. unsigned int reg_index;
  155. unsigned int value;
  156. // peripheral device's IRQ line is using GIC's SPI, and line ID >= GIC_PRIVATE_SIGNALS
  157. if (irq < GIC_PRIVATE_SIGNALS) {
  158. return;
  159. }
  160. offset = (irq - GIC_PRIVATE_SIGNALS) & 0x1F;
  161. reg_index = (irq - GIC_PRIVATE_SIGNALS) >> 5;
  162. if (polarity == 0) {
  163. value = DRV_Reg32(INT_POL_CTL0 + (reg_index * 4));
  164. value |= (1 << offset); // always invert the incoming IRQ's polarity
  165. DRV_WriteReg32((INT_POL_CTL0 + (reg_index * 4)), value);
  166. }else {
  167. value = DRV_Reg32(INT_POL_CTL0 + (reg_index * 4));
  168. value &= ~(0x1 << offset);
  169. DRV_WriteReg32(INT_POL_CTL0 + (reg_index * 4), value);
  170. }
  171. }
  172. void mt_irq_set_sens(unsigned int irq, unsigned int sens)
  173. {
  174. unsigned int config;
  175. if (sens == MT65xx_EDGE_SENSITIVE) {
  176. config = DRV_Reg32(GIC_DIST_BASE + GIC_DIST_CONFIG + (irq / 16) * 4);
  177. config |= (0x2 << (irq % 16) * 2);
  178. DRV_WriteReg32(GIC_DIST_BASE + GIC_DIST_CONFIG + (irq / 16) * 4, config);
  179. }else {
  180. config = DRV_Reg32(GIC_DIST_BASE + GIC_DIST_CONFIG + (irq / 16) * 4);
  181. config &= ~(0x2 << (irq % 16) * 2);
  182. DRV_WriteReg32( GIC_DIST_BASE + GIC_DIST_CONFIG + (irq / 16) * 4, config);
  183. }
  184. dsb();
  185. }
  186. /*
  187. * mt_irq_mask: mask one IRQ
  188. * @irq: IRQ line of the IRQ to mask
  189. */
  190. void mt_irq_mask(unsigned int irq)
  191. {
  192. unsigned int mask = 1 << (irq % 32);
  193. DRV_WriteReg32(GIC_DIST_BASE + GIC_DIST_ENABLE_CLEAR + irq / 32 * 4, mask);
  194. dsb();
  195. }
  196. /*
  197. * mt_irq_unmask: unmask one IRQ
  198. * @irq: IRQ line of the IRQ to unmask
  199. */
  200. void mt_irq_unmask(unsigned int irq)
  201. {
  202. unsigned int mask = 1 << (irq % 32);
  203. DRV_WriteReg32(GIC_DIST_BASE + GIC_DIST_ENABLE_SET + irq / 32 * 4, mask);
  204. dsb();
  205. }
  206. /*
  207. * mt_irq_mask: mask one IRQ
  208. * @irq: IRQ line of the IRQ to mask
  209. */
  210. void mt_irq_ack(unsigned int irq)
  211. {
  212. DRV_WriteReg32(GIC_CPU_BASE + GIC_CPU_EOI, irq);
  213. dsb();
  214. }
  215. /*
  216. * mt_irq_mask_all: mask all IRQ lines. (This is ONLY used for the sleep driver)
  217. * @mask: pointer to struct mtk_irq_mask for storing the original mask value.
  218. * Return 0 for success; return negative values for failure.
  219. */
  220. int mt_irq_mask_all(struct mtk_irq_mask *mask)
  221. {
  222. if (mask) {
  223. mask->mask0 = DRV_Reg32(GIC_ICDISER0);
  224. mask->mask1 = DRV_Reg32(GIC_ICDISER1);
  225. mask->mask2 = DRV_Reg32(GIC_ICDISER2);
  226. mask->mask3 = DRV_Reg32(GIC_ICDISER3);
  227. mask->mask4 = DRV_Reg32(GIC_ICDISER4);
  228. mask->mask5 = DRV_Reg32(GIC_ICDISER5);
  229. mask->mask6 = DRV_Reg32(GIC_ICDISER6);
  230. mask->mask7 = DRV_Reg32(GIC_ICDISER7);
  231. DRV_WriteReg32(GIC_ICDICER0, 0xFFFFFFFF);
  232. DRV_WriteReg32(GIC_ICDICER1, 0xFFFFFFFF);
  233. DRV_WriteReg32(GIC_ICDICER2, 0xFFFFFFFF);
  234. DRV_WriteReg32(GIC_ICDICER3, 0xFFFFFFFF);
  235. DRV_WriteReg32(GIC_ICDICER4, 0xFFFFFFFF);
  236. DRV_WriteReg32(GIC_ICDICER5, 0xFFFFFFFF);
  237. DRV_WriteReg32(GIC_ICDICER6, 0xFFFFFFFF);
  238. DRV_WriteReg32(GIC_ICDICER7, 0xFFFFFFFF);
  239. dsb();
  240. mask->header = IRQ_MASK_HEADER;
  241. mask->footer = IRQ_MASK_FOOTER;
  242. return 0;
  243. } else {
  244. return -1;
  245. }
  246. }
  247. /*
  248. * mt_irq_mask_restore: restore all IRQ lines' masks. (This is ONLY used for the sleep driver)
  249. * @mask: pointer to struct mtk_irq_mask for storing the original mask value.
  250. * Return 0 for success; return negative values for failure.
  251. */
  252. int mt_irq_mask_restore(struct mtk_irq_mask *mask)
  253. {
  254. if (!mask) {
  255. return -1;
  256. }
  257. if (mask->header != IRQ_MASK_HEADER) {
  258. return -1;
  259. }
  260. if (mask->footer != IRQ_MASK_FOOTER) {
  261. return -1;
  262. }
  263. DRV_WriteReg32(GIC_ICDISER0,mask->mask0);
  264. DRV_WriteReg32(GIC_ICDISER1,mask->mask1);
  265. DRV_WriteReg32(GIC_ICDISER2,mask->mask2);
  266. DRV_WriteReg32(GIC_ICDISER3,mask->mask3);
  267. DRV_WriteReg32(GIC_ICDISER4,mask->mask4);
  268. DRV_WriteReg32(GIC_ICDISER5,mask->mask5);
  269. DRV_WriteReg32(GIC_ICDISER6,mask->mask6);
  270. DRV_WriteReg32(GIC_ICDISER7,mask->mask7);
  271. dsb();
  272. return 0;
  273. }