Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 /*
0003  * Root interrupt controller for the BCM2836 (Raspberry Pi 2).
0004  *
0005  * Copyright 2015 Broadcom
0006  */
0007 
0008 #include <linux/cpu.h>
0009 #include <linux/of_address.h>
0010 #include <linux/of_irq.h>
0011 #include <linux/irqchip.h>
0012 #include <linux/irqdomain.h>
0013 #include <linux/irqchip/chained_irq.h>
0014 #include <linux/irqchip/irq-bcm2836.h>
0015 
0016 #include <asm/exception.h>
0017 
0018 struct bcm2836_arm_irqchip_intc {
0019     struct irq_domain *domain;
0020     void __iomem *base;
0021 };
0022 
0023 static struct bcm2836_arm_irqchip_intc intc  __read_mostly;
0024 
0025 static void bcm2836_arm_irqchip_mask_per_cpu_irq(unsigned int reg_offset,
0026                          unsigned int bit,
0027                          int cpu)
0028 {
0029     void __iomem *reg = intc.base + reg_offset + 4 * cpu;
0030 
0031     writel(readl(reg) & ~BIT(bit), reg);
0032 }
0033 
0034 static void bcm2836_arm_irqchip_unmask_per_cpu_irq(unsigned int reg_offset,
0035                            unsigned int bit,
0036                          int cpu)
0037 {
0038     void __iomem *reg = intc.base + reg_offset + 4 * cpu;
0039 
0040     writel(readl(reg) | BIT(bit), reg);
0041 }
0042 
0043 static void bcm2836_arm_irqchip_mask_timer_irq(struct irq_data *d)
0044 {
0045     bcm2836_arm_irqchip_mask_per_cpu_irq(LOCAL_TIMER_INT_CONTROL0,
0046                          d->hwirq - LOCAL_IRQ_CNTPSIRQ,
0047                          smp_processor_id());
0048 }
0049 
0050 static void bcm2836_arm_irqchip_unmask_timer_irq(struct irq_data *d)
0051 {
0052     bcm2836_arm_irqchip_unmask_per_cpu_irq(LOCAL_TIMER_INT_CONTROL0,
0053                            d->hwirq - LOCAL_IRQ_CNTPSIRQ,
0054                            smp_processor_id());
0055 }
0056 
0057 static struct irq_chip bcm2836_arm_irqchip_timer = {
0058     .name       = "bcm2836-timer",
0059     .irq_mask   = bcm2836_arm_irqchip_mask_timer_irq,
0060     .irq_unmask = bcm2836_arm_irqchip_unmask_timer_irq,
0061 };
0062 
0063 static void bcm2836_arm_irqchip_mask_pmu_irq(struct irq_data *d)
0064 {
0065     writel(1 << smp_processor_id(), intc.base + LOCAL_PM_ROUTING_CLR);
0066 }
0067 
0068 static void bcm2836_arm_irqchip_unmask_pmu_irq(struct irq_data *d)
0069 {
0070     writel(1 << smp_processor_id(), intc.base + LOCAL_PM_ROUTING_SET);
0071 }
0072 
0073 static struct irq_chip bcm2836_arm_irqchip_pmu = {
0074     .name       = "bcm2836-pmu",
0075     .irq_mask   = bcm2836_arm_irqchip_mask_pmu_irq,
0076     .irq_unmask = bcm2836_arm_irqchip_unmask_pmu_irq,
0077 };
0078 
0079 static void bcm2836_arm_irqchip_mask_gpu_irq(struct irq_data *d)
0080 {
0081 }
0082 
0083 static void bcm2836_arm_irqchip_unmask_gpu_irq(struct irq_data *d)
0084 {
0085 }
0086 
0087 static struct irq_chip bcm2836_arm_irqchip_gpu = {
0088     .name       = "bcm2836-gpu",
0089     .irq_mask   = bcm2836_arm_irqchip_mask_gpu_irq,
0090     .irq_unmask = bcm2836_arm_irqchip_unmask_gpu_irq,
0091 };
0092 
0093 static void bcm2836_arm_irqchip_dummy_op(struct irq_data *d)
0094 {
0095 }
0096 
0097 static struct irq_chip bcm2836_arm_irqchip_dummy = {
0098     .name       = "bcm2836-dummy",
0099     .irq_eoi    = bcm2836_arm_irqchip_dummy_op,
0100 };
0101 
0102 static int bcm2836_map(struct irq_domain *d, unsigned int irq,
0103                irq_hw_number_t hw)
0104 {
0105     struct irq_chip *chip;
0106 
0107     switch (hw) {
0108     case LOCAL_IRQ_MAILBOX0:
0109         chip = &bcm2836_arm_irqchip_dummy;
0110         break;
0111     case LOCAL_IRQ_CNTPSIRQ:
0112     case LOCAL_IRQ_CNTPNSIRQ:
0113     case LOCAL_IRQ_CNTHPIRQ:
0114     case LOCAL_IRQ_CNTVIRQ:
0115         chip = &bcm2836_arm_irqchip_timer;
0116         break;
0117     case LOCAL_IRQ_GPU_FAST:
0118         chip = &bcm2836_arm_irqchip_gpu;
0119         break;
0120     case LOCAL_IRQ_PMU_FAST:
0121         chip = &bcm2836_arm_irqchip_pmu;
0122         break;
0123     default:
0124         pr_warn_once("Unexpected hw irq: %lu\n", hw);
0125         return -EINVAL;
0126     }
0127 
0128     irq_set_percpu_devid(irq);
0129     irq_domain_set_info(d, irq, hw, chip, d->host_data,
0130                 handle_percpu_devid_irq, NULL, NULL);
0131     irq_set_status_flags(irq, IRQ_NOAUTOEN);
0132 
0133     return 0;
0134 }
0135 
0136 static void
0137 __exception_irq_entry bcm2836_arm_irqchip_handle_irq(struct pt_regs *regs)
0138 {
0139     int cpu = smp_processor_id();
0140     u32 stat;
0141 
0142     stat = readl_relaxed(intc.base + LOCAL_IRQ_PENDING0 + 4 * cpu);
0143     if (stat) {
0144         u32 hwirq = ffs(stat) - 1;
0145 
0146         generic_handle_domain_irq(intc.domain, hwirq);
0147     }
0148 }
0149 
0150 #ifdef CONFIG_SMP
0151 static struct irq_domain *ipi_domain;
0152 
0153 static void bcm2836_arm_irqchip_handle_ipi(struct irq_desc *desc)
0154 {
0155     struct irq_chip *chip = irq_desc_get_chip(desc);
0156     int cpu = smp_processor_id();
0157     u32 mbox_val;
0158 
0159     chained_irq_enter(chip, desc);
0160 
0161     mbox_val = readl_relaxed(intc.base + LOCAL_MAILBOX0_CLR0 + 16 * cpu);
0162     if (mbox_val) {
0163         int hwirq = ffs(mbox_val) - 1;
0164         generic_handle_domain_irq(ipi_domain, hwirq);
0165     }
0166 
0167     chained_irq_exit(chip, desc);
0168 }
0169 
0170 static void bcm2836_arm_irqchip_ipi_ack(struct irq_data *d)
0171 {
0172     int cpu = smp_processor_id();
0173 
0174     writel_relaxed(BIT(d->hwirq),
0175                intc.base + LOCAL_MAILBOX0_CLR0 + 16 * cpu);
0176 }
0177 
0178 static void bcm2836_arm_irqchip_ipi_send_mask(struct irq_data *d,
0179                           const struct cpumask *mask)
0180 {
0181     int cpu;
0182     void __iomem *mailbox0_base = intc.base + LOCAL_MAILBOX0_SET0;
0183 
0184     /*
0185      * Ensure that stores to normal memory are visible to the
0186      * other CPUs before issuing the IPI.
0187      */
0188     smp_wmb();
0189 
0190     for_each_cpu(cpu, mask)
0191         writel_relaxed(BIT(d->hwirq), mailbox0_base + 16 * cpu);
0192 }
0193 
0194 static struct irq_chip bcm2836_arm_irqchip_ipi = {
0195     .name       = "IPI",
0196     .irq_mask   = bcm2836_arm_irqchip_dummy_op,
0197     .irq_unmask = bcm2836_arm_irqchip_dummy_op,
0198     .irq_ack    = bcm2836_arm_irqchip_ipi_ack,
0199     .ipi_send_mask  = bcm2836_arm_irqchip_ipi_send_mask,
0200 };
0201 
0202 static int bcm2836_arm_irqchip_ipi_alloc(struct irq_domain *d,
0203                      unsigned int virq,
0204                      unsigned int nr_irqs, void *args)
0205 {
0206     int i;
0207 
0208     for (i = 0; i < nr_irqs; i++) {
0209         irq_set_percpu_devid(virq + i);
0210         irq_domain_set_info(d, virq + i, i, &bcm2836_arm_irqchip_ipi,
0211                     d->host_data,
0212                     handle_percpu_devid_irq,
0213                     NULL, NULL);
0214     }
0215 
0216     return 0;
0217 }
0218 
0219 static void bcm2836_arm_irqchip_ipi_free(struct irq_domain *d,
0220                      unsigned int virq,
0221                      unsigned int nr_irqs)
0222 {
0223     /* Not freeing IPIs */
0224 }
0225 
0226 static const struct irq_domain_ops ipi_domain_ops = {
0227     .alloc  = bcm2836_arm_irqchip_ipi_alloc,
0228     .free   = bcm2836_arm_irqchip_ipi_free,
0229 };
0230 
0231 static int bcm2836_cpu_starting(unsigned int cpu)
0232 {
0233     bcm2836_arm_irqchip_unmask_per_cpu_irq(LOCAL_MAILBOX_INT_CONTROL0, 0,
0234                            cpu);
0235     return 0;
0236 }
0237 
0238 static int bcm2836_cpu_dying(unsigned int cpu)
0239 {
0240     bcm2836_arm_irqchip_mask_per_cpu_irq(LOCAL_MAILBOX_INT_CONTROL0, 0,
0241                          cpu);
0242     return 0;
0243 }
0244 
0245 #define BITS_PER_MBOX   32
0246 
0247 static void __init bcm2836_arm_irqchip_smp_init(void)
0248 {
0249     struct irq_fwspec ipi_fwspec = {
0250         .fwnode     = intc.domain->fwnode,
0251         .param_count    = 1,
0252         .param      = {
0253             [0] = LOCAL_IRQ_MAILBOX0,
0254         },
0255     };
0256     int base_ipi, mux_irq;
0257 
0258     mux_irq = irq_create_fwspec_mapping(&ipi_fwspec);
0259     if (WARN_ON(mux_irq <= 0))
0260         return;
0261 
0262     ipi_domain = irq_domain_create_linear(intc.domain->fwnode,
0263                           BITS_PER_MBOX, &ipi_domain_ops,
0264                           NULL);
0265     if (WARN_ON(!ipi_domain))
0266         return;
0267 
0268     ipi_domain->flags |= IRQ_DOMAIN_FLAG_IPI_SINGLE;
0269     irq_domain_update_bus_token(ipi_domain, DOMAIN_BUS_IPI);
0270 
0271     base_ipi = __irq_domain_alloc_irqs(ipi_domain, -1, BITS_PER_MBOX,
0272                        NUMA_NO_NODE, NULL,
0273                        false, NULL);
0274 
0275     if (WARN_ON(!base_ipi))
0276         return;
0277 
0278     set_smp_ipi_range(base_ipi, BITS_PER_MBOX);
0279 
0280     irq_set_chained_handler_and_data(mux_irq,
0281                      bcm2836_arm_irqchip_handle_ipi, NULL);
0282 
0283     /* Unmask IPIs to the boot CPU. */
0284     cpuhp_setup_state(CPUHP_AP_IRQ_BCM2836_STARTING,
0285               "irqchip/bcm2836:starting", bcm2836_cpu_starting,
0286               bcm2836_cpu_dying);
0287 }
0288 #else
0289 #define bcm2836_arm_irqchip_smp_init()  do { } while(0)
0290 #endif
0291 
0292 static const struct irq_domain_ops bcm2836_arm_irqchip_intc_ops = {
0293     .xlate = irq_domain_xlate_onetwocell,
0294     .map = bcm2836_map,
0295 };
0296 
0297 /*
0298  * The LOCAL_IRQ_CNT* timer firings are based off of the external
0299  * oscillator with some scaling.  The firmware sets up CNTFRQ to
0300  * report 19.2Mhz, but doesn't set up the scaling registers.
0301  */
0302 static void bcm2835_init_local_timer_frequency(void)
0303 {
0304     /*
0305      * Set the timer to source from the 19.2Mhz crystal clock (bit
0306      * 8 unset), and only increment by 1 instead of 2 (bit 9
0307      * unset).
0308      */
0309     writel(0, intc.base + LOCAL_CONTROL);
0310 
0311     /*
0312      * Set the timer prescaler to 1:1 (timer freq = input freq *
0313      * 2**31 / prescaler)
0314      */
0315     writel(0x80000000, intc.base + LOCAL_PRESCALER);
0316 }
0317 
0318 static int __init bcm2836_arm_irqchip_l1_intc_of_init(struct device_node *node,
0319                               struct device_node *parent)
0320 {
0321     intc.base = of_iomap(node, 0);
0322     if (!intc.base) {
0323         panic("%pOF: unable to map local interrupt registers\n", node);
0324     }
0325 
0326     bcm2835_init_local_timer_frequency();
0327 
0328     intc.domain = irq_domain_add_linear(node, LAST_IRQ + 1,
0329                         &bcm2836_arm_irqchip_intc_ops,
0330                         NULL);
0331     if (!intc.domain)
0332         panic("%pOF: unable to create IRQ domain\n", node);
0333 
0334     irq_domain_update_bus_token(intc.domain, DOMAIN_BUS_WIRED);
0335 
0336     bcm2836_arm_irqchip_smp_init();
0337 
0338     set_handle_irq(bcm2836_arm_irqchip_handle_irq);
0339     return 0;
0340 }
0341 
0342 IRQCHIP_DECLARE(bcm2836_arm_irqchip_l1_intc, "brcm,bcm2836-l1-intc",
0343         bcm2836_arm_irqchip_l1_intc_of_init);