mt_gic_v2.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  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 <reg.h>
  32. #include <platform/mt_typedefs.h>
  33. #include <platform/mt_reg_base.h>
  34. #include <platform/mt_irq.h>
  35. #include <mt_gic.h>
  36. #include <debug.h>
  37. extern uint32_t mt_irq_get_target(void);
  38. static void mt_gic_cpu_init(void)
  39. {
  40. DRV_WriteReg32(GIC_CPU_BASE + GIC_CPU_PRIMASK, 0xF0);
  41. DRV_WriteReg32(GIC_CPU_BASE + GIC_CPU_CTRL, 0x1);
  42. dsb();
  43. }
  44. static void mt_gic_dist_init(void)
  45. {
  46. unsigned int i;
  47. unsigned int cpumask = mt_irq_get_target();
  48. DRV_WriteReg32(GIC_DIST_BASE + GIC_DIST_CTRL, 0);
  49. /*
  50. * Set all global interrupts to be level triggered, active low.
  51. */
  52. for (i = 32; i < (MT_NR_SPI + 32); i += 16) {
  53. DRV_WriteReg32(GIC_DIST_BASE + GIC_DIST_CONFIG + i * 4 / 16, 0);
  54. }
  55. /*
  56. * Set all global interrupts to this CPU only.
  57. */
  58. for (i = 32; i < (MT_NR_SPI + 32); i += 4) {
  59. DRV_WriteReg32(GIC_DIST_BASE + GIC_DIST_TARGET + i * 4 / 4, cpumask);
  60. }
  61. /*
  62. * Set priority on all interrupts.
  63. */
  64. for (i = 0; i < NR_IRQ_LINE; i += 4) {
  65. DRV_WriteReg32(GIC_DIST_BASE + GIC_DIST_PRI + i * 4 / 4, 0xA0A0A0A0);
  66. }
  67. /*
  68. * Disable all interrupts.
  69. */
  70. for (i = 0; i < NR_IRQ_LINE; i += 32) {
  71. DRV_WriteReg32(GIC_DIST_BASE + GIC_DIST_ENABLE_CLEAR + i * 4 / 32, 0xFFFFFFFF);
  72. }
  73. dsb();
  74. DRV_WriteReg32(GIC_DIST_BASE + GIC_DIST_CTRL, 1);
  75. }
  76. void platform_init_interrupts(void)
  77. {
  78. mt_gic_dist_init();
  79. mt_gic_cpu_init();
  80. }
  81. void platform_deinit_interrupts(void)
  82. {
  83. unsigned int irq;
  84. for (irq = 0; irq < NR_IRQ_LINE; irq += 32) {
  85. DRV_WriteReg32(GIC_DIST_BASE + GIC_DIST_ENABLE_CLEAR + irq * 4 / 32, 0xFFFFFFFF);
  86. }
  87. dsb();
  88. while ((irq = DRV_Reg32(GIC_CPU_BASE + GIC_CPU_INTACK)) != 1023 ) {
  89. DRV_WriteReg32(GIC_CPU_BASE + GIC_CPU_EOI, irq);
  90. }
  91. }
  92. uint32_t mt_irq_get(void)
  93. {
  94. return DRV_Reg32(GIC_CPU_BASE + GIC_CPU_INTACK);
  95. }
  96. void mt_irq_set_polarity(unsigned int irq, unsigned int polarity)
  97. {
  98. unsigned int offset;
  99. unsigned int reg_index;
  100. unsigned int value;
  101. // peripheral device's IRQ line is using GIC's SPI, and line ID >= GIC_PRIVATE_SIGNALS
  102. if (irq < GIC_PRIVATE_SIGNALS) {
  103. return;
  104. }
  105. offset = (irq - GIC_PRIVATE_SIGNALS) & 0x1F;
  106. reg_index = (irq - GIC_PRIVATE_SIGNALS) >> 5;
  107. if (polarity == 0) {
  108. value = DRV_Reg32(INT_POL_CTL0 + (reg_index * 4));
  109. value |= (1 << offset); // always invert the incoming IRQ's polarity
  110. DRV_WriteReg32((INT_POL_CTL0 + (reg_index * 4)), value);
  111. } else {
  112. value = DRV_Reg32(INT_POL_CTL0 + (reg_index * 4));
  113. value &= ~(0x1 << offset);
  114. DRV_WriteReg32(INT_POL_CTL0 + (reg_index * 4), value);
  115. }
  116. }
  117. void mt_irq_set_sens(unsigned int irq, unsigned int sens)
  118. {
  119. unsigned int config;
  120. if (sens == MT65xx_EDGE_SENSITIVE) {
  121. config = DRV_Reg32(GIC_DIST_BASE + GIC_DIST_CONFIG + (irq / 16) * 4);
  122. config |= (0x2 << (irq % 16) * 2);
  123. DRV_WriteReg32(GIC_DIST_BASE + GIC_DIST_CONFIG + (irq / 16) * 4, config);
  124. } else {
  125. config = DRV_Reg32(GIC_DIST_BASE + GIC_DIST_CONFIG + (irq / 16) * 4);
  126. config &= ~(0x2 << (irq % 16) * 2);
  127. DRV_WriteReg32( GIC_DIST_BASE + GIC_DIST_CONFIG + (irq / 16) * 4, config);
  128. }
  129. dsb();
  130. }
  131. /*
  132. * mt_irq_mask: mask one IRQ
  133. * @irq: IRQ line of the IRQ to mask
  134. */
  135. void mt_irq_mask(unsigned int irq)
  136. {
  137. unsigned int mask = 1 << (irq % 32);
  138. DRV_WriteReg32(GIC_DIST_BASE + GIC_DIST_ENABLE_CLEAR + irq / 32 * 4, mask);
  139. dsb();
  140. }
  141. /*
  142. * mt_irq_unmask: unmask one IRQ
  143. * @irq: IRQ line of the IRQ to unmask
  144. */
  145. void mt_irq_unmask(unsigned int irq)
  146. {
  147. unsigned int mask = 1 << (irq % 32);
  148. DRV_WriteReg32(GIC_DIST_BASE + GIC_DIST_ENABLE_SET + irq / 32 * 4, mask);
  149. dsb();
  150. }
  151. /*
  152. * mt_irq_ack: ack IRQ
  153. * @irq: IRQ line of the IRQ to mask
  154. */
  155. void mt_irq_ack(unsigned int irq)
  156. {
  157. DRV_WriteReg32(GIC_CPU_BASE + GIC_CPU_EOI, irq);
  158. dsb();
  159. }
  160. /*
  161. * mt_irq_mask_all: mask all IRQ lines. (This is ONLY used for the sleep driver)
  162. * @mask: pointer to struct mtk_irq_mask for storing the original mask value.
  163. * Return 0 for success; return negative values for failure.
  164. */
  165. int mt_irq_mask_all(struct mtk_irq_mask *mask)
  166. {
  167. unsigned int i;
  168. if (mask) {
  169. for (i = 0; i < IRQ_REGS; i++) {
  170. mask->mask[i] = DRV_Reg32(GIC_DIST_BASE + GIC_DIST_ENABLE_SET + i * 4);
  171. DRV_WriteReg32(GIC_DIST_BASE + GIC_DIST_ENABLE_CLEAR + i * 4, 0xFFFFFFFF);
  172. }
  173. dsb();
  174. mask->header = IRQ_MASK_HEADER;
  175. mask->footer = IRQ_MASK_FOOTER;
  176. return 0;
  177. } else {
  178. return -1;
  179. }
  180. }
  181. /*
  182. * mt_irq_mask_restore: restore all IRQ lines' masks. (This is ONLY used for the sleep driver)
  183. * @mask: pointer to struct mtk_irq_mask for storing the original mask value.
  184. * Return 0 for success; return negative values for failure.
  185. */
  186. int mt_irq_mask_restore(struct mtk_irq_mask *mask)
  187. {
  188. unsigned int i;
  189. if (!mask) {
  190. return -1;
  191. }
  192. if (mask->header != IRQ_MASK_HEADER) {
  193. return -1;
  194. }
  195. if (mask->footer != IRQ_MASK_FOOTER) {
  196. return -1;
  197. }
  198. for (i = 0; i < IRQ_REGS; i++) {
  199. DRV_WriteReg32(GIC_DIST_BASE + GIC_DIST_ENABLE_SET + i * 4, mask->mask[i]);
  200. }
  201. dsb();
  202. return 0;
  203. }