static bool_t ce_init(struct clockevent_t * ce) { struct clockevent_pdata_t * pdat = (struct clockevent_pdata_t *)ce->priv; clockevent_calc_mult_shift(ce, arm64_timer_frequecy(), 10); ce->min_delta_ns = clockevent_delta2ns(ce, 0x1); ce->max_delta_ns = clockevent_delta2ns(ce, 0xffffffff); if(!request_irq(pdat->irq, ce_interrupt, IRQ_TYPE_NONE, ce)) return FALSE; arm64_timer_interrupt_disable(); return TRUE; }
static bool_t s5p4418_ce_init(struct clockevent_t * ce) { u64_t rate; s5p4418_timer_reset(); if(!request_irq("TIMER0", s5p4418_ce_interrupt, IRQ_TYPE_NONE, ce)) { LOG("can't request irq 'TIMER0'"); return FALSE; } /* 9.375MHZ - 107ns */ s5p4418_timer_enable(CE_TIMER_CHANNEL, 1); rate = s5p4418_timer_calc_tin(CE_TIMER_CHANNEL, 107); clockevent_calc_mult_shift(ce, rate, 10); ce->min_delta_ns = clockevent_delta2ns(ce, 0x1); ce->max_delta_ns = clockevent_delta2ns(ce, 0xffffffff); s5p4418_timer_count(CE_TIMER_CHANNEL, 0); s5p4418_timer_stop(CE_TIMER_CHANNEL); return TRUE; }
static struct device_t * ce_samsung_timer_probe(struct driver_t * drv, struct dtnode_t * n) { struct ce_samsung_timer_pdata_t * pdat; struct clockevent_t * ce; struct device_t * dev; virtual_addr_t virt = phys_to_virt(dt_read_address(n)); char * clk = dt_read_string(n, "clock-name", NULL); int irq = dt_read_int(n, "interrupt", -1); int channel = dt_read_int(n, "timer-channel", -1); u64_t rate; if(!search_clk(clk)) return NULL; if(!irq_is_valid(irq)) return NULL; if(channel < 0 || channel > 3) return NULL; pdat = malloc(sizeof(struct ce_samsung_timer_pdata_t)); if(!pdat) return NULL; ce = malloc(sizeof(struct clockevent_t)); if(!ce) { free(pdat); return NULL; } pdat->virt = virt; pdat->clk = strdup(clk); pdat->irq = irq; pdat->channel = channel; clk_enable(pdat->clk); rate = samsung_timer_calc_tin(pdat->virt, pdat->clk, pdat->channel, 107); clockevent_calc_mult_shift(ce, rate, 10); ce->name = alloc_device_name(dt_read_name(n), -1); ce->min_delta_ns = clockevent_delta2ns(ce, 0x1); ce->max_delta_ns = clockevent_delta2ns(ce, 0xffffffff); ce->next = ce_samsung_timer_next, ce->priv = pdat; if(!request_irq(pdat->irq, ce_samsung_timer_interrupt, IRQ_TYPE_NONE, ce)) { clk_disable(pdat->clk); free(pdat->clk); free(ce->priv); free(ce); return NULL; } samsung_timer_enable(pdat->virt, pdat->channel, 1); samsung_timer_count(pdat->virt, pdat->channel, 0); samsung_timer_stop(pdat->virt, pdat->channel); if(!register_clockevent(&dev, ce)) { samsung_timer_irq_clear(pdat->virt, pdat->channel); samsung_timer_stop(pdat->virt, pdat->channel); samsung_timer_disable(pdat->virt, pdat->channel); clk_disable(pdat->clk); free_irq(pdat->irq); free(pdat->clk); free_device_name(ce->name); free(ce->priv); free(ce); return NULL; } dev->driver = drv; return dev; }