607 lines
17 KiB
C
Executable File
607 lines
17 KiB
C
Executable File
/*
|
|
* irqchip.c- Sigmastar
|
|
*
|
|
* Copyright (c) [2019~2020] SigmaStar Technology.
|
|
*
|
|
*
|
|
* This software is licensed under the terms of the GNU General Public
|
|
* License version 2, as published by the Free Software Foundation, and
|
|
* may be copied, distributed, and modified under those terms.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License version 2 for more details.
|
|
*
|
|
*/
|
|
#include <linux/init.h>
|
|
#include <linux/io.h>
|
|
#include <linux/irqchip/chained_irq.h>
|
|
#include <linux/irqdomain.h>
|
|
#include <linux/of.h>
|
|
#include <linux/syscore_ops.h>
|
|
#include <asm/mach/irq.h>
|
|
#include <linux/irqchip/arm-gic.h>
|
|
#include <linux/irqchip.h>
|
|
#include <linux/irqdesc.h>
|
|
|
|
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
|
|
|
#include "irqs.h"
|
|
#include "registers.h"
|
|
|
|
#include "_ms_private.h"
|
|
#include "ms_platform.h"
|
|
#include "ms_types.h"
|
|
|
|
/* _ _ _ _ _ _ _ _ _ _ */
|
|
/* | | */
|
|
/* | PM_SLEEP_IRQ(32) | */
|
|
/* |_ _ _ _ _ _ _ _ _ _| */
|
|
/* | | */
|
|
/* | MS_FIQ (32) | */
|
|
/* |_ _ _ _ _ _ _ _ _ _| ms_fiq */
|
|
/* | | */
|
|
/* | MS_IRQ (64) | */
|
|
/* |_ _ _ _ _ _ _ _ _ _| ms_irq */
|
|
/* | | */
|
|
/* | ARM_INTERNAL(32) | */
|
|
/* |_ _ _ _ _ _ _ _ _ _| gic_spi */
|
|
/* | | */
|
|
/* | PPI (16) | */
|
|
/* |_ _ _ _ _ _ _ _ _ _| */
|
|
/* | | */
|
|
/* | SGI (16) | */
|
|
/* |_ _ _ _ _ _ _ _ _ _| */
|
|
/* */
|
|
|
|
|
|
static void ms_pm_irq_eoi(struct irq_data *d)
|
|
{
|
|
U16 pmsleep_fiq;
|
|
|
|
pmsleep_fiq = d->hwirq;
|
|
|
|
if(pmsleep_fiq == INT_PMSLEEP_IR)
|
|
{
|
|
SETREG16(BASE_REG_PMSLEEP_PA + REG_ID_02, BIT0);
|
|
}
|
|
else if(pmsleep_fiq == INT_PMSLEEP_DVI_CK_DET)
|
|
{
|
|
SETREG16(BASE_REG_PMSLEEP_PA + REG_ID_02, BIT1);
|
|
}
|
|
else if(pmsleep_fiq < PMSLEEP_FIQ_END)
|
|
{
|
|
pmsleep_fiq -= 2/*first 2 pm_sleep_irqs are not gpio*/;
|
|
SETREG16(BASE_REG_PMGPIO_PA + (pmsleep_fiq << 2), BIT6);
|
|
}
|
|
else
|
|
{
|
|
pr_err("[%s] Unknown hwirq %lu\n", __func__, d->hwirq);
|
|
return;
|
|
}
|
|
|
|
irq_chip_eoi_parent(d);
|
|
}
|
|
|
|
static void ms_pm_irq_mask(struct irq_data *d)
|
|
{
|
|
U16 pmsleep_fiq;
|
|
|
|
pmsleep_fiq = d->hwirq;
|
|
|
|
if(pmsleep_fiq == INT_PMSLEEP_IR)
|
|
{
|
|
SETREG16(BASE_REG_PMSLEEP_PA + REG_ID_00, BIT0);
|
|
}
|
|
else if(pmsleep_fiq == INT_PMSLEEP_DVI_CK_DET)
|
|
{
|
|
SETREG16(BASE_REG_PMSLEEP_PA + REG_ID_00, BIT1);
|
|
}
|
|
else if(pmsleep_fiq < PMSLEEP_FIQ_END)
|
|
{
|
|
pmsleep_fiq -= 2/*first 2 pm_sleep_irqs are not gpio*/;
|
|
SETREG16(BASE_REG_PMGPIO_PA + (pmsleep_fiq << 2), BIT4);
|
|
}
|
|
else if(pmsleep_fiq < PMSLEEP_IRQ_END)
|
|
{
|
|
SETREG8(BASE_REG_PMSLEEP_PA + REG_ID_08, 1<<(pmsleep_fiq-PMSLEEP_IRQ_START) );
|
|
}
|
|
else
|
|
{
|
|
pr_err("[%s] Unknown hwirq %lu\n", __func__, d->hwirq);
|
|
return;
|
|
}
|
|
|
|
irq_chip_mask_parent(d);
|
|
}
|
|
|
|
static void ms_pm_irq_unmask(struct irq_data *d)
|
|
{
|
|
U16 pmsleep_fiq;
|
|
|
|
pmsleep_fiq = d->hwirq;
|
|
|
|
if(pmsleep_fiq == INT_PMSLEEP_IR)
|
|
{
|
|
CLRREG16(BASE_REG_PMSLEEP_PA + REG_ID_00, BIT0);
|
|
}
|
|
else if(pmsleep_fiq == INT_PMSLEEP_DVI_CK_DET)
|
|
{
|
|
CLRREG16(BASE_REG_PMSLEEP_PA + REG_ID_00, BIT1);
|
|
}
|
|
else if(pmsleep_fiq < PMSLEEP_FIQ_END)
|
|
{
|
|
pmsleep_fiq -= 2/*first 2 pm_sleep_irqs are not gpio*/;
|
|
CLRREG16(BASE_REG_PMGPIO_PA + (pmsleep_fiq << 2), BIT4);
|
|
}
|
|
else if(pmsleep_fiq < PMSLEEP_IRQ_END)
|
|
{
|
|
CLRREG8(BASE_REG_PMSLEEP_PA + REG_ID_08, 1<<(pmsleep_fiq-PMSLEEP_IRQ_START) );
|
|
}
|
|
else
|
|
{
|
|
pr_err("[%s] Unknown hwirq %lu\n", __func__, d->hwirq);
|
|
return;
|
|
}
|
|
|
|
CLRREG16(BASE_REG_INTRCTL_PA + REG_ID_54, BIT2);
|
|
irq_chip_unmask_parent(d);
|
|
}
|
|
|
|
static int ms_pm_irq_set_type(struct irq_data *d, unsigned int type)
|
|
{
|
|
U16 pmsleep_fiq;
|
|
|
|
pmsleep_fiq = d->hwirq;
|
|
|
|
if(pmsleep_fiq == INT_PMSLEEP_IR)
|
|
{
|
|
if(type&IRQ_TYPE_EDGE_FALLING)
|
|
SETREG16(BASE_REG_PMSLEEP_PA + REG_ID_03, BIT0);
|
|
else
|
|
CLRREG16(BASE_REG_PMSLEEP_PA + REG_ID_03, BIT0);
|
|
}
|
|
else if(pmsleep_fiq == INT_PMSLEEP_DVI_CK_DET)
|
|
{
|
|
if(type&IRQ_TYPE_EDGE_FALLING)
|
|
SETREG16(BASE_REG_PMSLEEP_PA + REG_ID_03, BIT1);
|
|
else
|
|
CLRREG16(BASE_REG_PMSLEEP_PA + REG_ID_03, BIT1);
|
|
}
|
|
else if(pmsleep_fiq < PMSLEEP_FIQ_END)
|
|
{
|
|
pmsleep_fiq -= 2/*first 2 pm_sleep_irqs are not gpio*/;
|
|
if(type&IRQ_TYPE_EDGE_FALLING)
|
|
SETREG16(BASE_REG_PMGPIO_PA + (pmsleep_fiq << 2), BIT7);
|
|
else
|
|
CLRREG16(BASE_REG_PMGPIO_PA + (pmsleep_fiq << 2), BIT7);
|
|
}
|
|
else if(pmsleep_fiq < PMSLEEP_IRQ_END)
|
|
{
|
|
if(type&IRQ_TYPE_LEVEL_LOW)
|
|
SETREG8(BASE_REG_PMSLEEP_PA + REG_ID_09, 1<<(pmsleep_fiq-PMSLEEP_IRQ_START) );
|
|
else
|
|
CLRREG8(BASE_REG_PMSLEEP_PA + REG_ID_09, 1<<(pmsleep_fiq-PMSLEEP_IRQ_START) );
|
|
}
|
|
else
|
|
{
|
|
pr_err("[%s] Unknown hwirq %lu\n", __func__, d->hwirq);
|
|
return -EINVAL;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
struct irq_chip ms_pm_intc_irqchip = {
|
|
.name = "MS_PM_INTC",
|
|
.irq_eoi = ms_pm_irq_eoi,
|
|
.irq_mask = ms_pm_irq_mask,
|
|
.irq_unmask = ms_pm_irq_unmask,
|
|
.irq_set_type = ms_pm_irq_set_type,
|
|
};
|
|
|
|
static void ms_main_irq_ack(struct irq_data *d)
|
|
{
|
|
s16 ms_fiq;
|
|
|
|
ms_fiq = d->hwirq - GIC_SPI_ARM_INTERNAL_NR - GIC_SPI_MS_IRQ_NR;
|
|
|
|
if( ms_fiq >= 0 && ms_fiq < GIC_SPI_MS_FIQ_NR )
|
|
{
|
|
SETREG16( (BASE_REG_INTRCTL_PA + REG_ID_4C + (ms_fiq/16)*4 ) , (1 << (ms_fiq%16)) );
|
|
}
|
|
else if( ms_fiq >= GIC_SPI_MS_FIQ_NR )
|
|
{
|
|
pr_err("[%s] Unknown hwirq %lu, ms_fiq %d\n", __func__, d->hwirq, ms_fiq);
|
|
return;
|
|
}
|
|
|
|
if(d && d->chip && d->parent_data && d->parent_data->chip->irq_ack)
|
|
{
|
|
irq_chip_ack_parent(d);
|
|
}
|
|
}
|
|
|
|
static void ms_main_irq_eoi(struct irq_data *d)
|
|
{
|
|
s16 ms_fiq;
|
|
|
|
ms_fiq = d->hwirq - GIC_SPI_ARM_INTERNAL_NR - GIC_SPI_MS_IRQ_NR;
|
|
|
|
if( ms_fiq >= 0 && ms_fiq < GIC_SPI_MS_FIQ_NR )
|
|
{
|
|
SETREG16( (BASE_REG_INTRCTL_PA + REG_ID_4C + (ms_fiq/16)*4 ) , (1 << (ms_fiq%16)) );
|
|
}
|
|
else if( ms_fiq >= GIC_SPI_MS_FIQ_NR )
|
|
{
|
|
pr_err("[%s] Unknown hwirq %lu, ms_fiq %lu\n", __func__, d->hwirq, ms_fiq);
|
|
return;
|
|
}
|
|
|
|
irq_chip_eoi_parent(d);
|
|
}
|
|
|
|
static void ms_main_irq_mask(struct irq_data *d)
|
|
{
|
|
s16 ms_irq;
|
|
s16 ms_fiq;
|
|
|
|
ms_irq = d->hwirq - GIC_SPI_ARM_INTERNAL_NR;
|
|
ms_fiq = d->hwirq - GIC_SPI_ARM_INTERNAL_NR - GIC_SPI_MS_IRQ_NR;
|
|
|
|
if( ms_fiq >= 0 && ms_fiq < GIC_SPI_MS_FIQ_NR )
|
|
{
|
|
SETREG16( (BASE_REG_INTRCTL_PA + REG_ID_44 + (ms_fiq/16)*4 ) , (1 << (ms_fiq%16)) );
|
|
}
|
|
else if( ms_irq >=0 && ms_irq < GIC_SPI_MS_IRQ_NR )
|
|
{
|
|
SETREG16( (BASE_REG_INTRCTL_PA + REG_ID_54 + (ms_irq/16)*4 ) , (1 << (ms_irq%16)) );
|
|
}
|
|
else
|
|
{
|
|
pr_err("[%s] Unknown hwirq %lu\n", __func__, d->hwirq);
|
|
return;
|
|
}
|
|
|
|
irq_chip_mask_parent(d);
|
|
}
|
|
|
|
static void ms_main_irq_unmask(struct irq_data *d)
|
|
{
|
|
s16 ms_irq;
|
|
s16 ms_fiq;
|
|
|
|
ms_irq = d->hwirq - GIC_SPI_ARM_INTERNAL_NR;
|
|
ms_fiq = d->hwirq - GIC_SPI_ARM_INTERNAL_NR - GIC_SPI_MS_IRQ_NR;
|
|
|
|
if( ms_fiq >= 0 && ms_fiq < GIC_SPI_MS_FIQ_NR )
|
|
{
|
|
CLRREG16( (BASE_REG_INTRCTL_PA + REG_ID_44 + (ms_fiq/16)*4 ) , (1 << (ms_fiq%16)) );
|
|
}
|
|
else if( ms_irq >=0 && ms_irq < GIC_SPI_MS_IRQ_NR )
|
|
{
|
|
CLRREG16( (BASE_REG_INTRCTL_PA + REG_ID_54 + (ms_irq/16)*4 ) , (1 << (ms_irq%16)) );
|
|
}
|
|
else
|
|
{
|
|
pr_err("[%s] Unknown hwirq %lu\n", __func__, d->hwirq);
|
|
return;
|
|
}
|
|
|
|
irq_chip_unmask_parent(d);
|
|
}
|
|
|
|
static int ms_main_irq_set_type(struct irq_data *data, unsigned int flow_type)
|
|
{
|
|
s16 ms_irq;
|
|
s16 ms_fiq;
|
|
|
|
if( (flow_type&IRQ_TYPE_EDGE_BOTH)==IRQ_TYPE_EDGE_BOTH)
|
|
{
|
|
pr_err("Not support IRQ_TYPE_EDGE_BOTH mode 0x%x\n",flow_type);
|
|
return 0;
|
|
}
|
|
|
|
|
|
ms_irq = data->hwirq - GIC_SPI_ARM_INTERNAL_NR;
|
|
ms_fiq = data->hwirq - GIC_SPI_ARM_INTERNAL_NR - GIC_SPI_MS_IRQ_NR;
|
|
|
|
if( ms_fiq >= 0 && ms_fiq < GIC_SPI_MS_FIQ_NR )
|
|
{
|
|
if (flow_type&IRQ_TYPE_EDGE_FALLING)
|
|
SETREG16( (BASE_REG_INTRCTL_PA + REG_ID_48 + (ms_fiq/16)*4 ) , (1 << (ms_fiq%16)) );
|
|
else
|
|
CLRREG16( (BASE_REG_INTRCTL_PA + REG_ID_48 + (ms_fiq/16)*4 ) , (1 << (ms_fiq%16)) );
|
|
}
|
|
else if( ms_irq >=0 && ms_irq < GIC_SPI_MS_IRQ_NR )
|
|
{
|
|
if (flow_type&IRQ_TYPE_LEVEL_LOW)
|
|
SETREG16( (BASE_REG_INTRCTL_PA + REG_ID_58 + (ms_irq/16)*4 ) , (1 << (ms_irq%16)) );
|
|
else
|
|
CLRREG16( (BASE_REG_INTRCTL_PA + REG_ID_58 + (ms_irq/16)*4 ) , (1 << (ms_irq%16)) );
|
|
}
|
|
else
|
|
{
|
|
pr_err("[%s] Unknown hwirq %lu\n", __func__, data->hwirq);
|
|
return -EINVAL;
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
struct irq_chip ms_main_intc_irqchip = {
|
|
.name = "MS_MAIN_INTC",
|
|
.irq_ack = ms_main_irq_ack,
|
|
.irq_eoi = ms_main_irq_eoi,
|
|
.irq_mask = ms_main_irq_mask,
|
|
.irq_unmask = ms_main_irq_unmask,
|
|
.irq_set_type = ms_main_irq_set_type,
|
|
};
|
|
EXPORT_SYMBOL(ms_main_intc_irqchip);
|
|
|
|
static DEFINE_SPINLOCK(ss_irq_controller_lock);
|
|
|
|
static void ms_handle_cascade_pm_irq(struct irq_desc *desc)
|
|
{
|
|
unsigned int cascade_irq = 0xFFFFFFFF, i;
|
|
struct irq_chip *chip = irq_desc_get_chip(desc);
|
|
unsigned int final_status = INREG16(BASE_REG_PMSLEEP_PA + REG_ID_04) | (INREG16(BASE_REG_PMSLEEP_PA + REG_ID_05)<<16);
|
|
|
|
chained_irq_enter(chip, desc);
|
|
|
|
spin_lock(&ss_irq_controller_lock);
|
|
{
|
|
for(i=0;i<32;i++)
|
|
{
|
|
if(0 !=(final_status & (1<<i)))
|
|
{
|
|
cascade_irq = i + (GIC_HWIRQ_MS_START+GIC_SPI_MS_IRQ_NR+GIC_SPI_MS_FIQ_NR);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
spin_unlock(&ss_irq_controller_lock);
|
|
|
|
if(0xFFFFFFFF==cascade_irq)
|
|
BUG();
|
|
|
|
generic_handle_irq(cascade_irq);
|
|
|
|
chained_irq_exit(chip, desc);
|
|
}
|
|
|
|
/*
|
|
static int pm_irq_domain_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw)
|
|
{
|
|
irq_set_chip_and_handler(irq, &ms_pm_intc_irqchip, handle_level_irq);
|
|
return 0;
|
|
}
|
|
*/
|
|
static int ms_pm_intc_domain_translate(struct irq_domain *domain, struct irq_fwspec *fwspec,
|
|
unsigned long *hwirq, unsigned int *type)
|
|
{
|
|
if (is_of_node(fwspec->fwnode)) {
|
|
if (fwspec->param_count != 1)
|
|
return -EINVAL;
|
|
*hwirq = fwspec->param[0];
|
|
return 0;
|
|
}
|
|
|
|
return -EINVAL;
|
|
}
|
|
|
|
static int ms_pm_intc_domain_alloc(struct irq_domain *domain, unsigned int virq,
|
|
unsigned int nr_irqs, void *data)
|
|
{
|
|
struct irq_fwspec *fwspec = data;
|
|
struct irq_fwspec parent_fwspec;
|
|
irq_hw_number_t hwirq;
|
|
unsigned int i;
|
|
|
|
if (fwspec->param_count != 1)
|
|
return -EINVAL;
|
|
|
|
hwirq = fwspec->param[0];
|
|
|
|
for (i = 0; i < nr_irqs; i++)
|
|
{
|
|
irq_domain_set_info(domain, virq + i, hwirq + i , &ms_pm_intc_irqchip, NULL,
|
|
ms_handle_cascade_pm_irq, NULL, NULL);
|
|
pr_debug("[MS_PM_INTC] hw:%d -> v:%d\n", (unsigned int)hwirq+i, virq+i);
|
|
}
|
|
|
|
parent_fwspec = *fwspec;
|
|
parent_fwspec.fwnode = domain->parent->fwnode;
|
|
//extend to GIC format, pass to parents
|
|
parent_fwspec.param_count=3;
|
|
parent_fwspec.param[0]=GIC_SPI;
|
|
parent_fwspec.param[1]=INT_IRQ_PM_SLEEP;
|
|
return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs,
|
|
&parent_fwspec);
|
|
}
|
|
|
|
static void ms_pm_intc_domain_free(struct irq_domain *domain, unsigned int virq, unsigned int nr_irqs)
|
|
{
|
|
unsigned int i;
|
|
|
|
for (i = 0; i < nr_irqs; i++) {
|
|
struct irq_data *d = irq_domain_get_irq_data(domain, virq + i);
|
|
irq_domain_reset_irq_data(d);
|
|
}
|
|
}
|
|
|
|
|
|
struct irq_domain_ops ms_pm_intc_domain_ops = {
|
|
.translate = ms_pm_intc_domain_translate,
|
|
.alloc = ms_pm_intc_domain_alloc,
|
|
.free = ms_pm_intc_domain_free,
|
|
};
|
|
|
|
static int ms_main_intc_domain_translate(struct irq_domain *domain, struct irq_fwspec *fwspec,
|
|
unsigned long *hwirq, unsigned int *type)
|
|
{
|
|
if (is_of_node(fwspec->fwnode)) {
|
|
if (fwspec->param_count != 3)
|
|
return -EINVAL;
|
|
|
|
/* No PPI should point to this domain */
|
|
if (fwspec->param[0] != 0)
|
|
return -EINVAL;
|
|
|
|
*hwirq = fwspec->param[1];
|
|
*type = fwspec->param[2];
|
|
return 0;
|
|
}
|
|
|
|
return -EINVAL;
|
|
}
|
|
|
|
static int ms_main_intc_domain_alloc(struct irq_domain *domain, unsigned int virq,
|
|
unsigned int nr_irqs, void *data)
|
|
{
|
|
struct irq_fwspec *fwspec = data;
|
|
struct irq_fwspec parent_fwspec;
|
|
irq_hw_number_t hwirq;
|
|
unsigned int i;
|
|
|
|
if (fwspec->param_count != 3)
|
|
return -EINVAL; /* Not GIC compliant */
|
|
|
|
if (fwspec->param[0] != GIC_SPI)
|
|
return -EINVAL; /* No PPI should point to this domain */
|
|
|
|
hwirq = fwspec->param[1];
|
|
|
|
for (i = 0; i < nr_irqs; i++)
|
|
{
|
|
irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq + i, &ms_main_intc_irqchip, NULL);
|
|
pr_debug("[MS_MAIN_INTC] hw:%d -> v:%d\n", (unsigned int)hwirq+i, virq+i);
|
|
}
|
|
|
|
parent_fwspec = *fwspec;
|
|
parent_fwspec.fwnode = domain->parent->fwnode;
|
|
return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs,
|
|
&parent_fwspec);
|
|
}
|
|
|
|
static void ms_main_intc_domain_free(struct irq_domain *domain, unsigned int virq, unsigned int nr_irqs)
|
|
{
|
|
unsigned int i;
|
|
|
|
for (i = 0; i < nr_irqs; i++) {
|
|
struct irq_data *d = irq_domain_get_irq_data(domain, virq + i);
|
|
irq_domain_reset_irq_data(d);
|
|
}
|
|
}
|
|
|
|
|
|
struct irq_domain_ops ms_main_intc_domain_ops = {
|
|
.translate = ms_main_intc_domain_translate,
|
|
.alloc = ms_main_intc_domain_alloc,
|
|
.free = ms_main_intc_domain_free,
|
|
};
|
|
|
|
|
|
static int ms_irqchip_suspend(void)
|
|
{
|
|
pr_debug("\nms_irqchip_suspend\n\n");
|
|
return 0;
|
|
}
|
|
|
|
static void ms_irqchip_resume(void)
|
|
{
|
|
pr_debug("\nms_irqchip_resume\n\n");
|
|
|
|
//Patch for disable bypass IRQ/FIQ
|
|
{
|
|
u32 bypass = 0;
|
|
bypass = INREG32(GIC_PHYS + 0x2000 + GIC_CPU_CTRL);
|
|
bypass |= GICC_DIS_BYPASS_MASK;
|
|
OUTREG32(GIC_PHYS + 0x2000 + GIC_CPU_CTRL, bypass | GICC_ENABLE);
|
|
}
|
|
}
|
|
|
|
struct syscore_ops ms_irq_syscore_ops = {
|
|
.suspend = ms_irqchip_suspend,
|
|
.resume = ms_irqchip_resume,
|
|
};
|
|
|
|
static int __init ms_init_main_intc(struct device_node *np, struct device_node *interrupt_parent)
|
|
{
|
|
struct irq_domain *parent_domain, *domain;
|
|
|
|
if (!interrupt_parent)
|
|
{
|
|
pr_err("%s: %s no parent\n", __func__, np->name);
|
|
return -ENODEV;
|
|
}
|
|
|
|
pr_err("%s: np->name=%s, parent=%s\n", __func__, np->name, interrupt_parent->name);
|
|
|
|
parent_domain = irq_find_host(interrupt_parent);
|
|
if (!parent_domain)
|
|
{
|
|
pr_err("%s: %s unable to obtain parent domain\n", __func__, np->name);
|
|
return -ENXIO;
|
|
}
|
|
|
|
//Patch for disable bypass IRQ/FIQ
|
|
{
|
|
u32 bypass = 0;
|
|
bypass = INREG32(GIC_PHYS + 0x2000 + GIC_CPU_CTRL);
|
|
bypass |= GICC_DIS_BYPASS_MASK;
|
|
OUTREG32(GIC_PHYS + 0x2000 + GIC_CPU_CTRL, bypass | GICC_ENABLE);
|
|
}
|
|
|
|
domain = irq_domain_add_hierarchy(parent_domain, 0,
|
|
GIC_SPI_ARM_INTERNAL_NR+GIC_SPI_MS_IRQ_NR+GIC_SPI_MS_FIQ_NR,
|
|
np, &ms_main_intc_domain_ops, NULL);
|
|
|
|
if (!domain)
|
|
{
|
|
pr_err("%s: %s allocat domain fail\n", __func__, np->name);
|
|
return -ENOMEM;
|
|
}
|
|
|
|
register_syscore_ops(&ms_irq_syscore_ops);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int __init ms_init_pm_intc(struct device_node *np, struct device_node *interrupt_parent)
|
|
{
|
|
// int virq_base;
|
|
struct irq_domain *parent_domain, *ms_pm_irq_domain;
|
|
|
|
if (!interrupt_parent)
|
|
{
|
|
pr_err("%s: %s no parent\n", __func__, np->name);
|
|
return -ENODEV;
|
|
}
|
|
|
|
pr_err("%s: np->name=%s, parent=%s\n", __func__, np->name, interrupt_parent->name);
|
|
|
|
parent_domain = irq_find_host(interrupt_parent);
|
|
if (!parent_domain)
|
|
{
|
|
pr_err("%s: %s unable to obtain parent domain\n", __func__, np->name);
|
|
return -ENXIO;
|
|
}
|
|
|
|
ms_pm_irq_domain = irq_domain_add_hierarchy(parent_domain, 0,
|
|
PMSLEEP_FIQ_NR,
|
|
np, &ms_pm_intc_domain_ops, NULL);
|
|
|
|
if (!ms_pm_irq_domain)
|
|
{
|
|
pr_err("%s: %s allocat domain fail\n", __func__, np->name);
|
|
return -ENOMEM;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
IRQCHIP_DECLARE(ms_main_intc, "sstar,main-intc", ms_init_main_intc);
|
|
IRQCHIP_DECLARE(ms_pm_intc, "sstar,pm-intc", ms_init_pm_intc);
|