static int arm64_start_pmc(int cpu, int ri) { struct pmc_hw *phw; uint32_t config; struct pmc *pm; phw = &arm64_pcpu[cpu]->pc_arm64pmcs[ri]; pm = phw->phw_pmc; config = pm->pm_md.pm_arm64.pm_arm64_evsel; /* * Configure the event selection. */ WRITE_SPECIALREG(PMSELR_EL0, ri); WRITE_SPECIALREG(PMXEVTYPER_EL0, config); isb(); /* * Enable the PMC. */ arm64_interrupt_enable(ri); arm64_counter_enable(ri); return 0; }
static struct device_t * irq_pl192_probe(struct driver_t * drv, struct dtnode_t * n) { struct irq_pl192_pdata_t * pdat; struct irqchip_t * chip; struct device_t * dev; virtual_addr_t virt = phys_to_virt(dt_read_address(n)); u32_t id = (((read32(virt + 0xfec) & 0xff) << 24) | ((read32(virt + 0xfe8) & 0xff) << 16) | ((read32(virt + 0xfe4) & 0xff) << 8) | ((read32(virt + 0xfe0) & 0xff) << 0)); int base = dt_read_int(n, "interrupt-base", -1); int nirq = dt_read_int(n, "interrupt-count", -1); if(((id >> 12) & 0xff) != 0x41 || (id & 0xfff) != 0x192) return NULL; if((base < 0) || (nirq <= 0)) return NULL; pdat = malloc(sizeof(struct irq_pl192_pdata_t)); if(!pdat) return NULL; chip = malloc(sizeof(struct irqchip_t)); if(!chip) { free(pdat); return NULL; } pdat->virt = virt; pdat->base = base; pdat->nirq = nirq; chip->name = alloc_device_name(dt_read_name(n), -1); chip->base = pdat->base; chip->nirq = pdat->nirq; chip->handler = malloc(sizeof(struct irq_handler_t) * pdat->nirq); chip->enable = irq_pl192_enable; chip->disable = irq_pl192_disable; chip->settype = irq_pl192_settype; chip->dispatch = irq_pl192_dispatch; chip->priv = pdat; pl192_ctrl_init(pdat->virt); arm64_interrupt_enable(); if(!register_irqchip(&dev, chip)) { free_device_name(chip->name); free(chip->handler); free(chip->priv); free(chip); return NULL; } dev->driver = drv; return dev; }