Lines Matching +full:charge +full:- +full:integration

1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (C) 2013-2017 ARM Limited, All Rights Reserved.
26 #include <linux/irqchip/arm-gic-common.h>
27 #include <linux/irqchip/arm-gic-v3.h>
28 #include <linux/irqchip/arm-gic-v3-prio.h>
29 #include <linux/irqchip/irq-partition-percpu.h>
32 #include <linux/arm-smccc.h>
39 #include "irq-gic-common.h"
95 * SCR_EL3.FIQ, and the behaviour of non-secure priority registers of the
99 * When security is enabled, non-secure priority values from the (re)distributor
103 * If SCR_EL3.FIQ == 1, the values written to/read from PMR and RPR at non-secure
109 * - section 4.8.1 Non-secure accesses to register fields for Secure interrupt
111 * - Figure 4-7 Secure read of the priority field for a Non-secure Group 1
137 * setting the highest possible, non-zero priority in PMR. in gic_has_group0()
141 * actual priority in the non-secure range. In the process, it in gic_has_group0()
146 gic_write_pmr(BIT(8 - gic_get_pribits())); in gic_has_group0()
176 pr_warn("Broken GIC integration, security disabled"); in gic_prio_init()
185 * and if Group 0 interrupts can be delivered to Linux in the non-secure in gic_prio_init()
190 * ------------------------------------------------------- in gic_prio_init()
191 * 1 | - | unchanged | unchanged in gic_prio_init()
192 * ------------------------------------------------------- in gic_prio_init()
193 * 0 | 1 | non-secure | non-secure in gic_prio_init()
194 * ------------------------------------------------------- in gic_prio_init()
195 * 0 | 0 | unchanged | non-secure in gic_prio_init()
197 * In the non-secure view reads and writes are modified: in gic_prio_init()
199 * - A value written is right-shifted by one and the MSB is set, in gic_prio_init()
200 * forcing the priority into the non-secure range. in gic_prio_init()
202 * - A value read is left-shifted by one. in gic_prio_init()
209 * be in the non-secure range, we program the non-secure values into in gic_prio_init()
230 #define gic_data_rdist_rd_base() (gic_data_rdist()->rd_base)
268 return __get_intid_range(d->hwirq); in get_intid_range()
290 * For the erratum T241-FABRIC-4, read accesses to GICD_In{E} in gic_dist_base_alias()
295 * Chip0 = 32-351 in gic_dist_base_alias()
296 * Chip1 = 352-671 in gic_dist_base_alias()
297 * Chip2 = 672-991 in gic_dist_base_alias()
298 * Chip3 = 4096-4415 in gic_dist_base_alias()
302 chip = (hwirq - 32) / 320; in gic_dist_base_alias()
322 /* SGI+PPI -> SGI_base for this CPU */ in gic_dist_base()
327 /* SPI -> dist_base */ in gic_dist_base()
342 if (ret == -ETIMEDOUT) in gic_do_wait_for_rwp()
386 if (ret == -ETIMEDOUT) { in gic_enable_redist()
401 *index = d->hwirq; in convert_offset_index()
409 *index = d->hwirq - EPPI_BASE_INTID + 32; in convert_offset_index()
412 *index = d->hwirq - ESPI_BASE_INTID; in convert_offset_index()
441 *index = d->hwirq; in convert_offset_index()
517 if (d->hwirq >= 8192) /* SGI/PPI/SPI only */ in gic_irq_set_irqchip_state()
518 return -EINVAL; in gic_irq_set_irqchip_state()
538 return -EINVAL; in gic_irq_set_irqchip_state()
544 * Force read-back to guarantee that the active state has taken in gic_irq_set_irqchip_state()
545 * effect, and won't race with a guest-driven deactivation. in gic_irq_set_irqchip_state()
555 if (d->hwirq >= 8192) /* PPI/SPI only */ in gic_irq_get_irqchip_state()
556 return -EINVAL; in gic_irq_get_irqchip_state()
572 return -EINVAL; in gic_irq_get_irqchip_state()
592 return hwirq - 16; in __gic_get_ppi_index()
594 return hwirq - EPPI_BASE_INTID + 16; in __gic_get_ppi_index()
607 return hwirq - EPPI_BASE_INTID + 32; in __gic_get_rdist_index()
615 return __gic_get_rdist_index(d->hwirq); in gic_get_rdist_index()
620 struct irq_desc *desc = irq_to_desc(d->irq); in gic_irq_nmi_setup()
623 return -EINVAL; in gic_irq_nmi_setup()
626 pr_err("Cannot set NMI property of enabled IRQ %u\n", d->irq); in gic_irq_nmi_setup()
627 return -EINVAL; in gic_irq_nmi_setup()
631 * A secondary irq_chip should be in charge of LPI request, in gic_irq_nmi_setup()
635 return -EINVAL; in gic_irq_nmi_setup()
647 desc->handle_irq = handle_percpu_devid_fasteoi_nmi; in gic_irq_nmi_setup()
650 desc->handle_irq = handle_fasteoi_nmi; in gic_irq_nmi_setup()
660 struct irq_desc *desc = irq_to_desc(d->irq); in gic_irq_nmi_teardown()
666 pr_err("Cannot set NMI property of enabled IRQ %u\n", d->irq); in gic_irq_nmi_teardown()
671 * A secondary irq_chip should be in charge of LPI request, in gic_irq_nmi_teardown()
683 desc->handle_irq = handle_percpu_devid_irq; in gic_irq_nmi_teardown()
685 desc->handle_irq = handle_fasteoi_irq; in gic_irq_nmi_teardown()
753 return type != IRQ_TYPE_EDGE_RISING ? -EINVAL : 0; in gic_set_type()
758 return -EINVAL; in gic_set_type()
780 return -EINVAL; in gic_irq_set_vcpu_affinity()
879 WARN_ONCE(true, "Unexpected pseudo-NMI (irqnr %u)\n", irqnr); in __gic_handle_nmi()
975 * Configure SPIs as non-secure Group-1. This will only matter in gic_dist_init()
1026 int ret = -ENODEV; in gic_iterate_rdists()
1060 return ret ? -ENODEV : 0; in gic_iterate_rdists()
1082 u64 offset = ptr - region->redist_base; in __gic_populate_rdist()
1083 raw_spin_lock_init(&gic_data_rdist()->rd_lock); in __gic_populate_rdist()
1085 gic_data_rdist()->phys_base = region->phys_base + offset; in __gic_populate_rdist()
1089 (int)(region - gic_data.redist_regions), in __gic_populate_rdist()
1090 &gic_data_rdist()->phys_base); in __gic_populate_rdist()
1104 WARN(true, "CPU%d: mpidr %lx has no re-distributor!\n", in gic_populate_rdist()
1107 return -ENODEV; in gic_populate_rdist()
1116 /* Boot-time cleanup */ in __gic_update_rdist_properties()
1136 * doc says... :-/ And CTLR.IR implies another subset of DirectLPI in __gic_update_rdist_properties()
1149 /* Detect non-sensical configurations */ in __gic_update_rdist_properties()
1223 * any pre-emptive interrupts from working at all). Writing a zero in gic_cpu_sys_reg_init()
1292 * - The write is ignored. in gic_cpu_sys_reg_init()
1293 * - The RS field is treated as 0. in gic_cpu_sys_reg_init()
1332 /* Configure SGIs/PPIs as non-secure Group-1 */ in gic_cpu_init()
1355 return -EINVAL; in gic_check_rdist()
1391 cpu--; in gic_compute_target_list()
1423 if (WARN_ON(d->hwirq >= 16)) in gic_ipi_send_mask()
1437 gic_send_sgi(cluster_id, tlist, d->hwirq); in gic_ipi_send_mask()
1460 /* Register all 8 non-secure SGIs */ in gic_smp_init()
1483 return -EINVAL; in gic_set_affinity()
1486 return -EINVAL; in gic_set_affinity()
1601 irq_domain_set_info(d, irq, hw, chip, d->host_data, in gic_irq_domain_map()
1607 irq_domain_set_info(d, irq, hw, chip, d->host_data, in gic_irq_domain_map()
1615 return -EPERM; in gic_irq_domain_map()
1616 irq_domain_set_info(d, irq, hw, chip, d->host_data, in gic_irq_domain_map()
1621 return -EPERM; in gic_irq_domain_map()
1634 if (fwspec->param_count == 1 && fwspec->param[0] < 16) { in gic_irq_domain_translate()
1635 *hwirq = fwspec->param[0]; in gic_irq_domain_translate()
1640 if (is_of_node(fwspec->fwnode)) { in gic_irq_domain_translate()
1641 if (fwspec->param_count < 3) in gic_irq_domain_translate()
1642 return -EINVAL; in gic_irq_domain_translate()
1644 switch (fwspec->param[0]) { in gic_irq_domain_translate()
1646 *hwirq = fwspec->param[1] + 32; in gic_irq_domain_translate()
1649 *hwirq = fwspec->param[1] + 16; in gic_irq_domain_translate()
1652 *hwirq = fwspec->param[1] + ESPI_BASE_INTID; in gic_irq_domain_translate()
1655 *hwirq = fwspec->param[1] + EPPI_BASE_INTID; in gic_irq_domain_translate()
1658 *hwirq = fwspec->param[1]; in gic_irq_domain_translate()
1661 *hwirq = fwspec->param[1]; in gic_irq_domain_translate()
1662 if (fwspec->param[1] >= 16) in gic_irq_domain_translate()
1663 *hwirq += EPPI_BASE_INTID - 16; in gic_irq_domain_translate()
1668 return -EINVAL; in gic_irq_domain_translate()
1671 *type = fwspec->param[2] & IRQ_TYPE_SENSE_MASK; in gic_irq_domain_translate()
1678 fwspec->param[0] != GIC_IRQ_TYPE_PARTITION); in gic_irq_domain_translate()
1682 if (is_fwnode_irqchip(fwspec->fwnode)) { in gic_irq_domain_translate()
1683 if(fwspec->param_count != 2) in gic_irq_domain_translate()
1684 return -EINVAL; in gic_irq_domain_translate()
1686 if (fwspec->param[0] < 16) { in gic_irq_domain_translate()
1688 fwspec->param[0]); in gic_irq_domain_translate()
1689 return -EINVAL; in gic_irq_domain_translate()
1692 *hwirq = fwspec->param[0]; in gic_irq_domain_translate()
1693 *type = fwspec->param[1]; in gic_irq_domain_translate()
1699 return -EINVAL; in gic_irq_domain_translate()
1743 if (!is_of_node(fwspec->fwnode)) in fwspec_is_partitioned_ppi()
1746 if (fwspec->param_count < 4 || !fwspec->param[3]) in fwspec_is_partitioned_ppi()
1764 if (fwspec->fwnode != d->fwnode) in gic_irq_domain_select()
1768 if (!fwspec->param_count) in gic_irq_domain_select()
1769 return d->bus_token == bus_token; in gic_irq_domain_select()
1772 if (!is_of_node(fwspec->fwnode)) in gic_irq_domain_select()
1783 * If this is a PPI and we have a 4th (non-null) parameter, in gic_irq_domain_select()
1808 return -ENOMEM; in partition_domain_translate()
1810 np = of_find_node_by_phandle(fwspec->param[3]); in partition_domain_translate()
1812 return -EINVAL; in partition_domain_translate()
1825 *type = fwspec->param[2] & IRQ_TYPE_SENSE_MASK; in partition_domain_translate()
1839 d->flags |= FLAGS_WORKAROUND_GICR_WAKER_MSM8996; in gic_enable_quirk_msm8996()
1848 d->flags |= FLAGS_WORKAROUND_CAVIUM_ERRATUM_38539; in gic_enable_quirk_cavium_38539()
1858 * HIP06 GICD_IIDR clashes with GIC-600 product number (despite in gic_enable_quirk_hip06_07()
1860 * that GIC-600 doesn't have ESPI, so nothing to do in that case. in gic_enable_quirk_hip06_07()
1864 if (d->rdists.gicd_typer & GICD_TYPER_ESPI) { in gic_enable_quirk_hip06_07()
1866 d->rdists.gicd_typer &= ~GENMASK(9, 8); in gic_enable_quirk_hip06_07()
1914 d->flags |= FLAGS_WORKAROUND_ASR_ERRATUM_8601001; in gic_enable_quirk_asr8601()
1929 d->rdists.flags |= RDIST_FLAGS_FORCE_NON_SHAREABLE; in rd_set_non_coherent()
1936 .compatible = "qcom,msm8996-gic-v3",
1941 .compatible = "asr,asr8601-gic-v3",
1960 * - ThunderX: CN88xx
1961 * - OCTEON TX: CN83xx, CN81xx
1962 * - OCTEON TX2: CN93xx, CN96xx, CN98xx, CNF95xx*
1970 .desc = "GICv3: NVIDIA erratum T241-FABRIC-4",
1977 * GIC-700: 2941627 workaround - IP variant [0,1]
1987 * GIC-700: 2941627 workaround - IP variant [2]
1995 .desc = "GICv3: non-coherent attribute",
1996 .property = "dma-noncoherent",
2018 pr_info("Pseudo-NMIs enabled using %s ICC_PMR_EL1 synchronisation\n", in gic_enable_nmi_support()
2061 pr_info("%d SPIs implemented\n", GIC_LINE_NR - 32); in gic_init_bases()
2075 /* Disable GICv4.x features for the erratum T241-FABRIC-4 */ in gic_init_bases()
2083 err = -ENOMEM; in gic_init_bases()
2132 return -ENODEV; in gic_validate_dist_version()
2145 parts_node = of_get_child_by_name(gic_node, "ppi-partitions"); in gic_populate_ppi_partitions()
2168 part->partition_id = of_node_to_fwnode(child_part); in gic_populate_ppi_partitions()
2199 cpumask_set_cpu(cpu, &part->mask); in gic_populate_ppi_partitions()
2274 gic_request_region(res->start, resource_size(res), name); in gic_of_iomap()
2277 return base ?: IOMEM_ERR_PTR(-ENOMEM); in gic_of_iomap()
2304 if (of_property_read_u32(node, "#redistributor-regions", &nr_redist_regions)) in gic_of_init()
2310 err = -ENOMEM; in gic_of_init()
2318 err = -ENODEV; in gic_of_init()
2324 if (of_property_read_u64(node, "redistributor-stride", &redist_stride)) in gic_of_init()
2330 nr_redist_regions, redist_stride, &node->fwnode); in gic_of_init()
2350 IRQCHIP_DECLARE(gic_v3, "arm,gic-v3", gic_of_init);
2384 redist_base = ioremap(redist->base_address, redist->length); in gic_acpi_parse_madt_redist()
2386 pr_err("Couldn't map GICR region @%llx\n", redist->base_address); in gic_acpi_parse_madt_redist()
2387 return -ENOMEM; in gic_acpi_parse_madt_redist()
2391 (redist->flags & ACPI_MADT_GICR_NON_COHERENT)) in gic_acpi_parse_madt_redist()
2394 gic_request_region(redist->base_address, redist->length, "GICR"); in gic_acpi_parse_madt_redist()
2396 gic_acpi_register_redist(redist->base_address, redist_base); in gic_acpi_parse_madt_redist()
2411 if (!(gicc->flags & (ACPI_MADT_ENABLED | ACPI_MADT_GICC_ONLINE_CAPABLE))) in gic_acpi_parse_madt_gicc()
2417 * Virtual hotplug systems can use the MADT's "always-on" GICR entries. in gic_acpi_parse_madt_gicc()
2420 if (!(gicc->flags & ACPI_MADT_ENABLED)) { in gic_acpi_parse_madt_gicc()
2421 int cpu = get_cpu_for_acpi_id(gicc->uid); in gic_acpi_parse_madt_gicc()
2429 redist_base = ioremap(gicc->gicr_base_address, size); in gic_acpi_parse_madt_gicc()
2431 return -ENOMEM; in gic_acpi_parse_madt_gicc()
2432 gic_request_region(gicc->gicr_base_address, size, "GICR"); in gic_acpi_parse_madt_gicc()
2435 (gicc->flags & ACPI_MADT_GICC_NON_COHERENT)) in gic_acpi_parse_madt_gicc()
2438 gic_acpi_register_redist(gicc->gicr_base_address, redist_base); in gic_acpi_parse_madt_gicc()
2460 return -ENODEV; in gic_acpi_collect_gicr_base()
2483 if (gicc->flags & ACPI_MADT_ENABLED && gicc->gicr_base_address) in gic_acpi_match_gicc()
2522 if (dist->version != ape->driver_data) in acpi_validate_gic_table()
2542 if (!(gicc->flags & in gic_acpi_parse_virt_madt_gicc()
2546 maint_irq_mode = (gicc->flags & ACPI_MADT_VGIC_IRQ_MODE) ? in gic_acpi_parse_virt_madt_gicc()
2552 acpi_data.maint_irq = gicc->vgic_interrupt; in gic_acpi_parse_virt_madt_gicc()
2554 acpi_data.vcpu_base = gicc->gicv_base_address; in gic_acpi_parse_virt_madt_gicc()
2562 if ((acpi_data.maint_irq != gicc->vgic_interrupt) || in gic_acpi_parse_virt_madt_gicc()
2564 (acpi_data.vcpu_base != gicc->gicv_base_address)) in gic_acpi_parse_virt_madt_gicc()
2565 return -EINVAL; in gic_acpi_parse_virt_madt_gicc()
2606 vcpu->flags = IORESOURCE_MEM; in gic_acpi_setup_kvm_info()
2607 vcpu->start = acpi_data.vcpu_base; in gic_acpi_setup_kvm_info()
2608 vcpu->end = vcpu->start + ACPI_GICV2_VCPU_MEM_SIZE - 1; in gic_acpi_setup_kvm_info()
2632 acpi_data.dist_base = ioremap(dist->base_address, in gic_acpi_init()
2636 return -ENOMEM; in gic_acpi_init()
2638 gic_request_region(dist->base_address, ACPI_GICV3_DIST_MEM_SIZE, "GICD"); in gic_acpi_init()
2650 err = -ENOMEM; in gic_acpi_init()
2658 gsi_domain_handle = irq_domain_alloc_fwnode(&dist->base_address); in gic_acpi_init()
2660 err = -ENOMEM; in gic_acpi_init()
2664 err = gic_init_bases(dist->base_address, acpi_data.dist_base, in gic_acpi_init()