int __cpuinit twd_clockchip_init(virtual_addr_t base, virtual_addr_t ref_counter_addr, u32 ref_counter_freq, u32 ppi_hirq) { int rc; u32 cpu = vmm_smp_processor_id(); struct twd_clockchip *cc = &this_cpu(twd_cc); memset(cc, 0, sizeof(struct twd_clockchip)); twd_caliberate_freq(base, ref_counter_addr, ref_counter_freq); vmm_sprintf(cc->name, "twd/%d", cpu); cc->base = base; cc->clkchip.name = cc->name; cc->clkchip.hirq = ppi_hirq; cc->clkchip.rating = 350; cc->clkchip.cpumask = vmm_cpumask_of(cpu); cc->clkchip.features = VMM_CLOCKCHIP_FEAT_PERIODIC | VMM_CLOCKCHIP_FEAT_ONESHOT; cc->clkchip.shift = 20; cc->clkchip.mult = vmm_clockchip_hz2mult(twd_freq_hz, cc->clkchip.shift); cc->clkchip.min_delta_ns = vmm_clockchip_delta2ns(0xF, &cc->clkchip); cc->clkchip.max_delta_ns = vmm_clockchip_delta2ns(0xFFFFFFFF, &cc->clkchip); cc->clkchip.set_mode = &twd_clockchip_set_mode; cc->clkchip.set_next_event = &twd_clockchip_set_next_event; cc->clkchip.expire = &twd_clockchip_expire; cc->clkchip.priv = cc; if (!cpu) { /* Register interrupt handler */ if ((rc = vmm_host_irq_register(ppi_hirq, "twd", &twd_clockchip_irq_handler, cc))) { return rc; } /* Mark interrupt as per-cpu */ if ((rc = vmm_host_irq_mark_per_cpu(ppi_hirq))) { return rc; } } /* Explicitly enable local timer PPI in GIC * Note: Local timer requires PPI support hence requires GIC */ gic_enable_ppi(ppi_hirq); return vmm_clockchip_register(&cc->clkchip); }
int __init omap3_gpt_clockchip_init(u32 gpt_num, physical_addr_t prm_pa) { int rc; struct omap3_gpt_clockchip *cc; if ((rc = omap3_gpt_instance_init(gpt_num, prm_pa, NULL))) { return rc; } omap3_gpt_write(gpt_num, OMAP3_GPT_TCLR, 0); cc = vmm_zalloc(sizeof(struct omap3_gpt_clockchip)); if (!cc) { return VMM_EFAIL; } cc->gpt_num = gpt_num; cc->clkchip.name = omap3_gpt_config[gpt_num].name; cc->clkchip.hirq = omap3_gpt_config[gpt_num].irq_no; cc->clkchip.rating = 200; cc->clkchip.cpumask = cpu_all_mask; cc->clkchip.features = VMM_CLOCKCHIP_FEAT_ONESHOT; cc->clkchip.mult = vmm_clockchip_hz2mult(omap3_gpt_config[gpt_num].clk_hz, 32); cc->clkchip.shift = 32; cc->clkchip.min_delta_ns = vmm_clockchip_delta2ns(0xF, &cc->clkchip); cc->clkchip.max_delta_ns = vmm_clockchip_delta2ns(0xFFFFFFFF, &cc->clkchip); cc->clkchip.set_mode = &omap3_gpt_clockchip_set_mode; cc->clkchip.set_next_event = &omap3_gpt_clockchip_set_next_event; cc->clkchip.expire = &omap3_gpt_clockchip_expire; cc->clkchip.priv = cc; /* Register interrupt handler */ rc = vmm_host_irq_register(omap3_gpt_config[gpt_num].irq_no, omap3_gpt_config[gpt_num].name, &omap3_gpt_clockevent_irq_handler, cc); if (rc) { return rc; } return vmm_clockchip_register(&cc->clkchip); }