--- zzzz-none-000/linux-4.1.52/drivers/irqchip/irq-gic.c 2018-05-28 02:26:45.000000000 +0000 +++ bcm63-7530ax-731/linux-4.1.52/drivers/irqchip/irq-gic.c 2022-03-02 11:37:13.000000000 +0000 @@ -20,6 +20,12 @@ * As such, the enable set/clear, pending set/clear and active bit * registers are banked per-cpu for these sources. */ + +#ifdef CONFIG_AVM_FASTIRQ +#include +#define CLIENT_FIQ_PRIO FIQ_PRIO_WATCHDOG +#endif + #include #include #include @@ -44,12 +50,37 @@ #include #include + +#if defined(CONFIG_BCM963138) +#include +#include +#endif + #include #include +#include +#include + + #include "irq-gic-common.h" #include "irqchip.h" +#if defined(CONFIG_AVM_FASTIRQ) + +#include +#include +#include + +#include +#define __BUILD_AVM_CONTEXT_FUNC(func) firq_##func + +#else + +#define __BUILD_AVM_CONTEXT_FUNC(func) func + +#endif + union gic_base { void __iomem *common_base; void __percpu * __iomem *percpu_base; @@ -60,9 +91,11 @@ union gic_base cpu_base; #ifdef CONFIG_CPU_PM u32 saved_spi_enable[DIV_ROUND_UP(1020, 32)]; + u32 saved_spi_security[DIV_ROUND_UP(1020, 32)]; u32 saved_spi_conf[DIV_ROUND_UP(1020, 16)]; u32 saved_spi_target[DIV_ROUND_UP(1020, 4)]; u32 __percpu *saved_ppi_enable; + u32 __percpu *saved_ppi_security; u32 __percpu *saved_ppi_conf; #endif struct irq_domain *domain; @@ -72,7 +105,7 @@ #endif }; -static DEFINE_RAW_SPINLOCK(irq_controller_lock); +DEFINE_RAW_SPINLOCK(irq_controller_lock); /* * The GIC mapping of CPU interfaces does not necessarily match @@ -120,6 +153,40 @@ #define gic_set_base_accessor(d, f) #endif +void __iomem * get_dist_base( unsigned int gic_nr ) +{ + struct gic_chip_data *gic; + + BUG_ON(gic_nr >= MAX_GIC_NR); + + gic = &gic_data[gic_nr]; + + return(gic_data_dist_base(gic)); +} + +void __iomem * get_cpu_base( unsigned int gic_nr ) +{ + struct gic_chip_data *gic; + + BUG_ON(gic_nr >= MAX_GIC_NR); + + gic = &gic_data[gic_nr]; + + return(gic_data_cpu_base(gic)); +} + +#ifndef CONFIG_AVM_FASTIRQ_TZ +#define SCU_PHYS_BASE 0x8001e000 +#define DIST_BASE_PHY (SCU_PHYS_BASE + CA9MP_GIC_DIST_OFF) +#define CPU_BASE_PHY (SCU_PHYS_BASE + CA9MP_GIC_CPUIF_OFF) +#endif + +struct irq_domain *get_irq_domain( void ) +{ + struct gic_chip_data *gic = &gic_data[0]; + return( gic->domain ); +} + static inline void __iomem *gic_dist_base(struct irq_data *d) { struct gic_chip_data *gic_data = irq_data_get_irq_chip_data(d); @@ -154,6 +221,9 @@ static void gic_mask_irq(struct irq_data *d) { +#if defined(CONFIG_AVM_FASTIRQ) + BUG_ON(avm_gic_fiq_is(gic_irq(d))); +#endif/*--- #if defined(CONFIG_AVM_FASTIRQ) ---*/ gic_poke_irq(d, GIC_DIST_ENABLE_CLEAR); } @@ -162,9 +232,16 @@ gic_poke_irq(d, GIC_DIST_ENABLE_SET); } +#if defined(CONFIG_AVM_FASTIRQ) && !defined(CONFIG_AVM_FASTIRQ_TZ) +unsigned int avm_secmon_gate(unsigned int wr, unsigned int addr, unsigned int val); +#endif static void gic_eoi_irq(struct irq_data *d) { +#if defined(CONFIG_AVM_FASTIRQ) && !defined(CONFIG_AVM_FASTIRQ_TZ) + (void)avm_secmon_gate(1, (CPU_BASE_PHY + GIC_CPU_EOI), gic_irq(d)); +#else writel_relaxed(gic_irq(d), gic_cpu_base(d) + GIC_CPU_EOI); +#endif } static int gic_irq_set_irqchip_state(struct irq_data *d, @@ -250,33 +327,129 @@ if (cpu >= NR_GIC_CPU_IF || cpu >= nr_cpu_ids) return -EINVAL; - raw_spin_lock_irqsave(&irq_controller_lock, flags); + __BUILD_AVM_CONTEXT_FUNC(raw_spin_lock_irqsave(&irq_controller_lock, flags)); mask = 0xff << shift; bit = gic_cpu_map[cpu] << shift; val = readl_relaxed(reg) & ~mask; writel_relaxed(val | bit, reg); - raw_spin_unlock_irqrestore(&irq_controller_lock, flags); + __BUILD_AVM_CONTEXT_FUNC(raw_spin_unlock_irqrestore(&irq_controller_lock, flags)); return IRQ_SET_MASK_OK; } #endif +#if defined(CONFIG_AVM_FASTIRQ) && !defined(CONFIG_AVM_FASTIRQ_TZ) +/*--------------------------------------------------------------------------------*\ + * Code, um aus dem IRQ in den FIQ zu wechseln und den FIQ-Handler anzuspringen * +\*--------------------------------------------------------------------------------*/ + +static void noinline handle_FIQ(unsigned long flags) +{ + unsigned long addr; + unsigned long flags_save; + + asm volatile( \ + "mrs %1, cpsr \n" \ + "bic %1, %1, #0x1f \n" \ + "orr %1, %1, #0x11 \n" \ + "msr cpsr_fsxc, %1 \n" \ + "isb \n" \ + "msr spsr_fsxc, %2 \n" \ + "movw lr, #:lower16:2f \n" \ + "movt lr, #:upper16:2f \n" \ + "ldr %0, =avm_fiq_handler_begin \n" \ + "bx %0 \n" \ + "1: mov pc, lr \n" \ + "2: \n" \ + : "=r" (addr), "=&r" (flags_save) \ + : "r" (flags) \ + : "cc" \ + ); +} +#endif + static void __exception_irq_entry gic_handle_irq(struct pt_regs *regs) { - u32 irqstat, irqnr; + u32 irq_handled, irqstat, irqnr; struct gic_chip_data *gic = &gic_data[0]; void __iomem *cpu_base = gic_data_cpu_base(gic); +#ifndef CONFIG_AVM_FASTIRQ_TZ + unsigned long flags; +#endif + + avm_cpu_wait_end(); /*auch wenn es wait_irqoff gibt: trotzdem aufrufen, um system-load-Ausgabe zu triggern */ +#if !defined(CONFIG_AVM_FASTIRQ) + /* trace code only if no fastirq-profiler exist */ + avm_simple_profiling_enter_irq_context(regs->ARM_pc, regs->ARM_lr); +#endif + irq_handled = 0; do { + dsb(); + +#if defined(CONFIG_AVM_FASTIRQ) + + /* NON-SECURE - Zugriff zum Auslesen des Interrupts ... */ +#ifndef CONFIG_AVM_FASTIRQ_TZ + flags = avm_raw_local_fiq_and_iq_disable(); + + irqstat = avm_secmon_gate(0, (CPU_BASE_PHY + GIC_CPU_INTACK), 0); +#else irqstat = readl_relaxed(cpu_base + GIC_CPU_INTACK); +#endif irqnr = irqstat & GICC_IAR_INT_ID_MASK; - if (likely(irqnr > 15 && irqnr < 1021)) { +#ifndef CONFIG_AVM_FASTIRQ_TZ + if (unlikely(irqnr >= 1020))//(unlikely(avm_gic_fiq_is(irqnr))) + { + irqstat = readl_relaxed(cpu_base + OFFSET_ICCHPIR); + irqnr = irqstat & GICC_IAR_INT_ID_MASK; + + if (likely(avm_gic_fiq_is(irqnr))) + { + /* SECURE interrupt, passiert ungluecklicherweise ab und zu ... */ + handle_FIQ(flags); // avm_raw_local_fiq_and_iq_enable(flags) implizit bei Ruecksprung + // mit Modewechsel fuer flags + break; + } + else + { + avm_raw_local_fiq_and_iq_enable(flags); + + /* Interrupt Nr 1020, 1021, 1022 und Nr > 1023 fuer NON-SECURE nicht definiert, einfach Beenden ... */ + /* Spurious Interrupts zählen */ + if(!irq_handled) { + __this_cpu_write(spurious_count, (__this_cpu_read(spurious_count) + 1)); + } + + break; + } + } + + avm_raw_local_fiq_and_iq_enable(flags); +#endif + +#else + irqstat = readl_relaxed(cpu_base + GIC_CPU_INTACK); + irqnr = irqstat & GICC_IAR_INT_ID_MASK; +#endif + + if (likely(irqnr > 15 && irqnr < 1020)) { + /* NON-SECURE interrupt */ + avm_simple_profiling_log(avm_profile_data_type_hw_irq_begin, (unsigned long)(irq_to_desc(irqnr)), irqnr); handle_domain_irq(gic->domain, irqnr, regs); + avm_simple_profiling_log(avm_profile_data_type_hw_irq_end, (unsigned long)(irq_to_desc(irqnr)), irqnr); + irq_handled = 1; continue; } - if (irqnr < 16) { + if (likely(irqnr < 16)) { + /* NON-SECURE IPI */ +#if defined(CONFIG_AVM_FASTIRQ) && !defined(CONFIG_AVM_FASTIRQ_TZ) + (void)avm_secmon_gate(1, (CPU_BASE_PHY + GIC_CPU_EOI), irqstat); +#else writel_relaxed(irqstat, cpu_base + GIC_CPU_EOI); +#endif + #ifdef CONFIG_SMP /* * Ensure any shared data written by the CPU sending @@ -286,11 +459,22 @@ * Pairs with the write barrier in gic_raise_softirq */ smp_rmb(); + avm_simple_profiling_log(avm_profile_data_type_hw_irq_begin, (unsigned long)(irq_to_desc(irqnr)), irqnr); handle_IPI(irqnr, regs); + avm_simple_profiling_log(avm_profile_data_type_hw_irq_end, (unsigned long)(irq_to_desc(irqnr)), irqnr); #endif + irq_handled = 1; continue; } +#if defined(CONFIG_AVM_FASTIRQ) + /* Interrupt Nr 1020, 1021, 1022 und Nr > 1023 fuer NON-SECURE nicht definiert, einfach Beenden ... */ + /* Spurious Interrupts zählen */ + if(!irq_handled) { + __this_cpu_write(spurious_count, (__this_cpu_read(spurious_count) + 1)); + } +#endif break; + } while (1); } @@ -303,9 +487,13 @@ chained_irq_enter(chip, desc); - raw_spin_lock(&irq_controller_lock); + __BUILD_AVM_CONTEXT_FUNC(raw_spin_lock(&irq_controller_lock)); +#if defined(CONFIG_AVM_FASTIRQ) && !defined(CONFIG_AVM_FASTIRQ_TZ) + status = avm_secmon_gate(0, (CPU_BASE_PHY + GIC_CPU_INTACK), 0); +#else status = readl_relaxed(gic_data_cpu_base(chip_data) + GIC_CPU_INTACK); - raw_spin_unlock(&irq_controller_lock); +#endif + __BUILD_AVM_CONTEXT_FUNC(raw_spin_unlock(&irq_controller_lock)); gic_irq = (status & GICC_IAR_INT_ID_MASK); if (gic_irq == GICC_INT_SPURIOUS) @@ -407,20 +595,20 @@ unsigned int cpu_mask, cpu = smp_processor_id(); int i; - /* - * Get what the GIC says our CPU mask is. - */ - BUG_ON(cpu >= NR_GIC_CPU_IF); - cpu_mask = gic_get_cpumask(gic); - gic_cpu_map[cpu] = cpu_mask; + /* + * Get what the GIC says our CPU mask is. + */ + BUG_ON(cpu >= NR_GIC_CPU_IF); + cpu_mask = gic_get_cpumask(gic); + gic_cpu_map[cpu] = cpu_mask; - /* - * Clear our mask from the other map entries in case they're - * still undefined. - */ - for (i = 0; i < NR_GIC_CPU_IF; i++) - if (i != cpu) - gic_cpu_map[i] &= ~cpu_mask; + /* + * Clear our mask from the other map entries in case they're + * still undefined. + */ + for (i = 0; i < NR_GIC_CPU_IF; i++) + if (i != cpu) + gic_cpu_map[i] &= ~cpu_mask; gic_cpu_config(dist_base, NULL); @@ -469,6 +657,10 @@ readl_relaxed(dist_base + GIC_DIST_TARGET + i * 4); for (i = 0; i < DIV_ROUND_UP(gic_irqs, 32); i++) + gic_data[gic_nr].saved_spi_security[i] = + readl_relaxed(dist_base + GIC_DIST_IGROUP + i * 4); + + for (i = 0; i < DIV_ROUND_UP(gic_irqs, 32); i++) gic_data[gic_nr].saved_spi_enable[i] = readl_relaxed(dist_base + GIC_DIST_ENABLE_SET + i * 4); } @@ -510,6 +702,10 @@ dist_base + GIC_DIST_TARGET + i * 4); for (i = 0; i < DIV_ROUND_UP(gic_irqs, 32); i++) + writel_relaxed(gic_data[gic_nr].saved_spi_security[i], + dist_base + GIC_DIST_IGROUP + i * 4); + + for (i = 0; i < DIV_ROUND_UP(gic_irqs, 32); i++) writel_relaxed(gic_data[gic_nr].saved_spi_enable[i], dist_base + GIC_DIST_ENABLE_SET + i * 4); @@ -536,6 +732,10 @@ for (i = 0; i < DIV_ROUND_UP(32, 32); i++) ptr[i] = readl_relaxed(dist_base + GIC_DIST_ENABLE_SET + i * 4); + ptr = raw_cpu_ptr(gic_data[gic_nr].saved_ppi_security); + for (i = 0; i < DIV_ROUND_UP(32, 32); i++) + ptr[i] = readl_relaxed(dist_base + GIC_DIST_IGROUP + i * 4); + ptr = raw_cpu_ptr(gic_data[gic_nr].saved_ppi_conf); for (i = 0; i < DIV_ROUND_UP(32, 16); i++) ptr[i] = readl_relaxed(dist_base + GIC_DIST_CONFIG + i * 4); @@ -562,6 +762,10 @@ for (i = 0; i < DIV_ROUND_UP(32, 32); i++) writel_relaxed(ptr[i], dist_base + GIC_DIST_ENABLE_SET + i * 4); + ptr = raw_cpu_ptr(gic_data[gic_nr].saved_ppi_security); + for (i = 0; i < DIV_ROUND_UP(32, 32); i++) + writel_relaxed(ptr[i], dist_base + GIC_DIST_IGROUP + i * 4); + ptr = raw_cpu_ptr(gic_data[gic_nr].saved_ppi_conf); for (i = 0; i < DIV_ROUND_UP(32, 16); i++) writel_relaxed(ptr[i], dist_base + GIC_DIST_CONFIG + i * 4); @@ -615,6 +819,10 @@ sizeof(u32)); BUG_ON(!gic->saved_ppi_enable); + gic->saved_ppi_security = __alloc_percpu(DIV_ROUND_UP(32, 32) * 4, + sizeof(u32)); + BUG_ON(!gic->saved_ppi_security); + gic->saved_ppi_conf = __alloc_percpu(DIV_ROUND_UP(32, 16) * 4, sizeof(u32)); BUG_ON(!gic->saved_ppi_conf); @@ -634,7 +842,7 @@ int cpu; unsigned long flags, map = 0; - raw_spin_lock_irqsave(&irq_controller_lock, flags); + __BUILD_AVM_CONTEXT_FUNC(raw_spin_lock_irqsave(&irq_controller_lock, flags)); /* Convert our logical CPU mask into a physical one. */ for_each_cpu(cpu, mask) @@ -647,9 +855,13 @@ dmb(ishst); /* this always happens on GIC0 */ +#ifdef CONFIG_AVM_FASTIRQ_TZ writel_relaxed(map << 16 | irq, gic_data_dist_base(&gic_data[0]) + GIC_DIST_SOFTINT); +#else + writel_relaxed(map << 16 | (1 << 15) | irq, gic_data_dist_base(&gic_data[0]) + GIC_DIST_SOFTINT); +#endif - raw_spin_unlock_irqrestore(&irq_controller_lock, flags); + __BUILD_AVM_CONTEXT_FUNC(raw_spin_unlock_irqrestore(&irq_controller_lock, flags)); } #endif @@ -718,7 +930,7 @@ cur_target_mask = 0x01010101 << cur_cpu_id; ror_val = (cur_cpu_id - new_cpu_id) & 31; - raw_spin_lock(&irq_controller_lock); + __BUILD_AVM_CONTEXT_FUNC(raw_spin_lock(&irq_controller_lock)); /* Update the target interface for this logical CPU */ gic_cpu_map[cpu] = 1 << new_cpu_id; @@ -738,7 +950,7 @@ } } - raw_spin_unlock(&irq_controller_lock); + __BUILD_AVM_CONTEXT_FUNC(raw_spin_unlock(&irq_controller_lock)); /* * Now let's migrate and clear any potential SGIs that might be @@ -823,9 +1035,9 @@ if (d->of_node != controller) return -EINVAL; if (intsize < 3) - return -EINVAL; + return -EINVAL; - /* Get the interrupt number and add 16 to skip over SGIs */ + /* Get the interrupt number and add 16 to skip over SGIs */ *out_hwirq = intspec[1] + 16; /* For SPIs, we need to add 16 more to get the GIC irq ID number */ @@ -835,7 +1047,7 @@ *out_type = intspec[2] & IRQ_TYPE_SENSE_MASK; return ret; -} + } #ifdef CONFIG_SMP static int gic_secondary_init(struct notifier_block *nfb, unsigned long action, @@ -953,10 +1165,17 @@ gic_irqs = 1020; gic->gic_irqs = gic_irqs; +#if defined(CONFIG_BCM_KF_ARM_BCM963XX) && (defined(CONFIG_BCM963138) || defined(CONFIG_BCM963148)) + /* To support GIC in device tree for 63138/63148 legacy device, always use legacy way to add + irq domain and allocate irqs first. A lot of devices has not using device tree yet so need to + pre-allocate irq heres otherwise request_irq function return error */ + if (false) { +#else if (node) { /* DT case */ +#endif gic->domain = irq_domain_add_linear(node, gic_irqs, - &gic_irq_domain_hierarchy_ops, - gic); + &gic_irq_domain_hierarchy_ops, + gic); } else { /* Non-DT case */ /* * For primary GICs, skip over SGIs. @@ -1080,7 +1299,7 @@ static int __init gic_acpi_parse_madt_distributor(struct acpi_subtable_header *header, - const unsigned long end) + const unsigned long end) { struct acpi_madt_generic_distributor *dist;