| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322 |
- /*
- * Copyright (c) 2008, Google Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google, Inc. nor the names of its contributors
- * may be used to endorse or promote products derived from this
- * software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
- #include <arch/arm.h>
- #include <reg.h>
- #include <mt_gic.h>
- #include <kernel/thread.h>
- #include <platform/interrupts.h>
- #include <platform/mt_typedefs.h>
- #include <platform/mt_reg_base.h>
- #include <platform/mt_gpt.h>
- #include <platform/mt_irq.h>
- #include <debug.h>
- #define GIC_ICDISER0 (GIC_DIST_BASE + 0x100)
- #define GIC_ICDISER1 (GIC_DIST_BASE + 0x104)
- #define GIC_ICDISER2 (GIC_DIST_BASE + 0x108)
- #define GIC_ICDISER3 (GIC_DIST_BASE + 0x10C)
- #define GIC_ICDISER4 (GIC_DIST_BASE + 0x110)
- #define GIC_ICDISER5 (GIC_DIST_BASE + 0x114)
- #define GIC_ICDISER6 (GIC_DIST_BASE + 0x118)
- #define GIC_ICDISER7 (GIC_DIST_BASE + 0x11C)
- #define GIC_ICDICER0 (GIC_DIST_BASE + 0x180)
- #define GIC_ICDICER1 (GIC_DIST_BASE + 0x184)
- #define GIC_ICDICER2 (GIC_DIST_BASE + 0x188)
- #define GIC_ICDICER3 (GIC_DIST_BASE + 0x18C)
- #define GIC_ICDICER4 (GIC_DIST_BASE + 0x190)
- #define GIC_ICDICER5 (GIC_DIST_BASE + 0x194)
- #define GIC_ICDICER6 (GIC_DIST_BASE + 0x198)
- #define GIC_ICDICER7 (GIC_DIST_BASE + 0x19C)
- #define INT_POL_CTL0 (MCUCFG_BASE + 0x620)
- static void mt_gic_cpu_init(void)
- {
- DRV_WriteReg32(GIC_CPU_BASE + GIC_CPU_PRIMASK, 0xF0);
- DRV_WriteReg32(GIC_CPU_BASE + GIC_CPU_CTRL, 0x1);
- dsb();
- }
- static void mt_gic_dist_init(void)
- {
- unsigned int i;
- #ifndef MTK_FORCE_CLUSTER1
- unsigned int cpumask = 1 << 0;
- #else
- unsigned int cpumask = 1 << 4;
- #endif
- cpumask |= cpumask << 8;
- cpumask |= cpumask << 16;
- DRV_WriteReg32(GIC_DIST_BASE + GIC_DIST_CTRL, 0);
- /*
- * Set all global interrupts to be level triggered, active low.
- */
- for (i = 32; i < (MT_NR_SPI + 32); i += 16) {
- DRV_WriteReg32(GIC_DIST_BASE + GIC_DIST_CONFIG + i * 4 / 16, 0);
- }
- /*
- * Set all global interrupts to this CPU only.
- */
- for (i = 32; i < (MT_NR_SPI + 32); i += 4) {
- DRV_WriteReg32(GIC_DIST_BASE + GIC_DIST_TARGET + i * 4 / 4, cpumask);
- }
- /*
- * Set priority on all interrupts.
- */
- for (i = 0; i < NR_IRQ_LINE; i += 4) {
- DRV_WriteReg32(GIC_DIST_BASE + GIC_DIST_PRI + i * 4 / 4, 0xA0A0A0A0);
- }
- /*
- * Disable all interrupts.
- */
- for (i = 0; i < NR_IRQ_LINE; i += 32) {
- DRV_WriteReg32(GIC_DIST_BASE + GIC_DIST_ENABLE_CLEAR + i * 4 / 32, 0xFFFFFFFF);
- }
- dsb();
- DRV_WriteReg32(GIC_DIST_BASE + GIC_DIST_CTRL, 1);
- }
- void platform_init_interrupts(void)
- {
- mt_gic_dist_init();
- mt_gic_cpu_init();
- }
- void platform_deinit_interrupts(void)
- {
- unsigned int irq;
- DRV_WriteReg32(GIC_ICDICER0, 0xFFFFFFFF);
- DRV_WriteReg32(GIC_ICDICER1, 0xFFFFFFFF);
- DRV_WriteReg32(GIC_ICDICER2, 0xFFFFFFFF);
- DRV_WriteReg32(GIC_ICDICER3, 0xFFFFFFFF);
- DRV_WriteReg32(GIC_ICDICER4, 0xFFFFFFFF);
- DRV_WriteReg32(GIC_ICDICER5, 0xFFFFFFFF);
- DRV_WriteReg32(GIC_ICDICER6, 0xFFFFFFFF);
- DRV_WriteReg32(GIC_ICDICER7, 0xFFFFFFFF);
- dsb();
- while((irq = DRV_Reg32(GIC_CPU_BASE + GIC_CPU_INTACK)) != 1023 ) {
- DRV_WriteReg32(GIC_CPU_BASE + GIC_CPU_EOI, irq);
- }
- }
- extern void lk_scheduler(void);
- extern void lk_usb_scheduler(void);
- extern void lk_nand_irq_handler(unsigned int irq);
- extern void lk_msdc_irq_handler(unsigned int irq);
- extern void dummy_ap_irq_handler(unsigned int irq)__attribute__((weak)); /* this function is empty for normal load */
- enum handler_return platform_irq(struct arm_iframe *frame)
- {
- unsigned int irq = DRV_Reg32(GIC_CPU_BASE + GIC_CPU_INTACK);
- if(irq == MT_GPT_IRQ_ID)
- lk_scheduler();
- else if(irq == MT_USB0_IRQ_ID)
- lk_usb_scheduler();
- #ifndef MTK_EMMC_SUPPORT
- else if(irq == MT_NFI_IRQ_ID)
- lk_nand_irq_handler(irq);
- #endif
- else if(irq == MT_MSDC0_IRQ_ID || irq == MT_MSDC1_IRQ_ID)
- lk_msdc_irq_handler(irq);
- if (dummy_ap_irq_handler)
- dummy_ap_irq_handler(irq);
- //return INT_NO_RESCHEDULE;
- return INT_RESCHEDULE;
- }
- void platform_fiq(struct arm_iframe *frame)
- {
- }
- void mt_irq_set_polarity(unsigned int irq, unsigned int polarity)
- {
- unsigned int offset;
- unsigned int reg_index;
- unsigned int value;
- // peripheral device's IRQ line is using GIC's SPI, and line ID >= GIC_PRIVATE_SIGNALS
- if (irq < GIC_PRIVATE_SIGNALS) {
- return;
- }
- offset = (irq - GIC_PRIVATE_SIGNALS) & 0x1F;
- reg_index = (irq - GIC_PRIVATE_SIGNALS) >> 5;
- if (polarity == 0) {
- value = DRV_Reg32(INT_POL_CTL0 + (reg_index * 4));
- value |= (1 << offset); // always invert the incoming IRQ's polarity
- DRV_WriteReg32((INT_POL_CTL0 + (reg_index * 4)), value);
- }else {
- value = DRV_Reg32(INT_POL_CTL0 + (reg_index * 4));
- value &= ~(0x1 << offset);
- DRV_WriteReg32(INT_POL_CTL0 + (reg_index * 4), value);
- }
- }
- void mt_irq_set_sens(unsigned int irq, unsigned int sens)
- {
- unsigned int config;
- if (sens == MT65xx_EDGE_SENSITIVE) {
- config = DRV_Reg32(GIC_DIST_BASE + GIC_DIST_CONFIG + (irq / 16) * 4);
- config |= (0x2 << (irq % 16) * 2);
- DRV_WriteReg32(GIC_DIST_BASE + GIC_DIST_CONFIG + (irq / 16) * 4, config);
- }else {
- config = DRV_Reg32(GIC_DIST_BASE + GIC_DIST_CONFIG + (irq / 16) * 4);
- config &= ~(0x2 << (irq % 16) * 2);
- DRV_WriteReg32( GIC_DIST_BASE + GIC_DIST_CONFIG + (irq / 16) * 4, config);
- }
- dsb();
- }
- /*
- * mt_irq_mask: mask one IRQ
- * @irq: IRQ line of the IRQ to mask
- */
- void mt_irq_mask(unsigned int irq)
- {
- unsigned int mask = 1 << (irq % 32);
- DRV_WriteReg32(GIC_DIST_BASE + GIC_DIST_ENABLE_CLEAR + irq / 32 * 4, mask);
- dsb();
- }
- /*
- * mt_irq_unmask: unmask one IRQ
- * @irq: IRQ line of the IRQ to unmask
- */
- void mt_irq_unmask(unsigned int irq)
- {
- unsigned int mask = 1 << (irq % 32);
- DRV_WriteReg32(GIC_DIST_BASE + GIC_DIST_ENABLE_SET + irq / 32 * 4, mask);
- dsb();
- }
- /*
- * mt_irq_mask: mask one IRQ
- * @irq: IRQ line of the IRQ to mask
- */
- void mt_irq_ack(unsigned int irq)
- {
- DRV_WriteReg32(GIC_CPU_BASE + GIC_CPU_EOI, irq);
- dsb();
- }
- /*
- * mt_irq_mask_all: mask all IRQ lines. (This is ONLY used for the sleep driver)
- * @mask: pointer to struct mtk_irq_mask for storing the original mask value.
- * Return 0 for success; return negative values for failure.
- */
- int mt_irq_mask_all(struct mtk_irq_mask *mask)
- {
- if (mask) {
- mask->mask[0] = DRV_Reg32(GIC_ICDISER0);
- mask->mask[1] = DRV_Reg32(GIC_ICDISER1);
- mask->mask[2] = DRV_Reg32(GIC_ICDISER2);
- mask->mask[3] = DRV_Reg32(GIC_ICDISER3);
- mask->mask[4] = DRV_Reg32(GIC_ICDISER4);
- mask->mask[5] = DRV_Reg32(GIC_ICDISER5);
- mask->mask[6] = DRV_Reg32(GIC_ICDISER6);
- mask->mask[7] = DRV_Reg32(GIC_ICDISER7);
- DRV_WriteReg32(GIC_ICDICER0, 0xFFFFFFFF);
- DRV_WriteReg32(GIC_ICDICER1, 0xFFFFFFFF);
- DRV_WriteReg32(GIC_ICDICER2, 0xFFFFFFFF);
- DRV_WriteReg32(GIC_ICDICER3, 0xFFFFFFFF);
- DRV_WriteReg32(GIC_ICDICER4, 0xFFFFFFFF);
- DRV_WriteReg32(GIC_ICDICER5, 0xFFFFFFFF);
- DRV_WriteReg32(GIC_ICDICER6, 0xFFFFFFFF);
- DRV_WriteReg32(GIC_ICDICER7, 0xFFFFFFFF);
- dsb();
- mask->header = IRQ_MASK_HEADER;
- mask->footer = IRQ_MASK_FOOTER;
- return 0;
- } else {
- return -1;
- }
- }
- /*
- * mt_irq_mask_restore: restore all IRQ lines' masks. (This is ONLY used for the sleep driver)
- * @mask: pointer to struct mtk_irq_mask for storing the original mask value.
- * Return 0 for success; return negative values for failure.
- */
- int mt_irq_mask_restore(struct mtk_irq_mask *mask)
- {
- if (!mask) {
- return -1;
- }
- if (mask->header != IRQ_MASK_HEADER) {
- return -1;
- }
- if (mask->footer != IRQ_MASK_FOOTER) {
- return -1;
- }
- DRV_WriteReg32(GIC_ICDISER0,mask->mask[0]);
- DRV_WriteReg32(GIC_ICDISER1,mask->mask[1]);
- DRV_WriteReg32(GIC_ICDISER2,mask->mask[2]);
- DRV_WriteReg32(GIC_ICDISER3,mask->mask[3]);
- DRV_WriteReg32(GIC_ICDISER4,mask->mask[4]);
- DRV_WriteReg32(GIC_ICDISER5,mask->mask[5]);
- DRV_WriteReg32(GIC_ICDISER6,mask->mask[6]);
- DRV_WriteReg32(GIC_ICDISER7,mask->mask[7]);
- dsb();
- return 0;
- }
|