static void __init clocksource_init() { #if 1 disable_timer(1); putreg32(0, STLR_TIMER_GPTMCFG(1)); // Setup periodic timer with incrementing counter putreg32(TIMER_GPTMTAMR_TAMR_PERIODIC | TIMER_GPTMTAMR_TACDIR_UP, STLR_TIMER_GPTMTAMR(1)); putreg32(0xFFFFFFFF, STLR_TIMER_GPTMTAILR(1)); // Enable timer enable_timer(1); clocksource_calc_mult_shift(&sysclk_clocksource, CLOCK_TICK_RATE, 20); sysclk_clocksource.mask = CLOCKSOURCE_MASK(32); //sysclk_clocksource.mult = // clocksource_khz2mult(CLOCK_TICK_RATE / 1000, sysclk_clocksource.shift); #else clocksource_calc_mult_shift(&sysclk_clocksource, 4000000, 20); sysclk_clocksource.mask = CLOCKSOURCE_MASK(24); putreg32(0xFFFFFF, STLR_SYSTICK_RELOAD); putreg32(STLR_SYSTICK_CTRL_ENABLE | STLR_SYSTICK_CTRL_CLK_SRC_PIOSC_DIV_4, STLR_SYSTICK_CTRL); #endif clocksource_register(&sysclk_clocksource); }
void __init clksrc_dbx500_prcmu_init(void __iomem *base) { clksrc_dbx500_timer_base = base; /* * The A9 sub system expects the timer to be configured as * a continous looping timer. * The PRCMU should configure it but if it for some reason * don't we do it here. */ if (readl(clksrc_dbx500_timer_base + PRCMU_TIMER_MODE) != TIMER_MODE_CONTINOUS) { writel(TIMER_MODE_CONTINOUS, clksrc_dbx500_timer_base + PRCMU_TIMER_MODE); writel(TIMER_DOWNCOUNT_VAL, clksrc_dbx500_timer_base + PRCMU_TIMER_REF); } #ifdef CONFIG_CLKSRC_DBX500_PRCMU_SCHED_CLOCK setup_sched_clock(dbx500_prcmu_sched_clock_read, 32, RATE_32K); #endif clocksource_calc_mult_shift(&clocksource_dbx500_prcmu, RATE_32K, SCHED_CLOCK_MIN_WRAP); clocksource_register(&clocksource_dbx500_prcmu); boottime_activate(&boottime_timer); }
static struct device_t * cs_samsung_timer_probe(struct driver_t * drv, struct dtnode_t * n) { struct cs_samsung_timer_pdata_t * pdat; struct clocksource_t * cs; 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 channel = dt_read_int(n, "timer-channel", -1); u64_t rate; if(!search_clk(clk)) return NULL; if(channel < 0 || channel > 3) return NULL; pdat = malloc(sizeof(struct cs_samsung_timer_pdata_t)); if(!pdat) return NULL; cs = malloc(sizeof(struct clocksource_t)); if(!cs) { free(pdat); return NULL; } pdat->virt = virt; pdat->clk = strdup(clk); pdat->channel = channel; clk_enable(pdat->clk); rate = samsung_timer_calc_tin(pdat->virt, pdat->clk, pdat->channel, 13); clocksource_calc_mult_shift(&cs->mult, &cs->shift, rate, 1000000000ULL, 10); cs->name = alloc_device_name(dt_read_name(n), -1); cs->mask = CLOCKSOURCE_MASK(32); cs->read = cs_samsung_timer_read; cs->priv = pdat; samsung_timer_enable(pdat->virt, pdat->channel, 0); samsung_timer_count(pdat->virt, pdat->channel, 0xffffffff); samsung_timer_start(pdat->virt, pdat->channel, 0); if(!register_clocksource(&dev, cs)) { samsung_timer_stop(pdat->virt, pdat->channel); samsung_timer_disable(pdat->virt, pdat->channel); clk_disable(pdat->clk); free(pdat->clk); free_device_name(cs->name); free(cs->priv); free(cs); return NULL; } dev->driver = drv; return dev; }
static bool_t cs_init(struct clocksource_t * cs) { struct clocksource_pdata_t * pdat = (struct clocksource_pdata_t *)cs->priv; u64_t rate; s5p4418_timer_reset(); /* 75MHZ - 13.333...ns */ s5p4418_timer_enable(pdat->virt, CS_TIMER_CHANNEL, 0); rate = s5p4418_timer_calc_tin(pdat->virt, CS_TIMER_CHANNEL, 13); clocksource_calc_mult_shift(&cs->mult, &cs->shift, rate, 1000000000ULL, 10); s5p4418_timer_count(pdat->virt, CS_TIMER_CHANNEL, 0xffffffff); s5p4418_timer_start(pdat->virt, CS_TIMER_CHANNEL, 0); return TRUE; }
/* * Register the SysTick timer as a clocksource */ void cortex_m3_register_systick_clocksource(u32 systick_clk) { /* * Configure and enable the SysTick timer if it was not enabled * in the bootloader. */ CM3_SYSTICK->load = CM3_SYSTICK_LOAD_RELOAD_MSK; CM3_SYSTICK->val = 0; CM3_SYSTICK->ctrl |= CM3_SYSTICK_CTRL_EN; /* * Finalize clocksource initialization and register it */ clocksource_calc_mult_shift(&clocksource_systick, systick_clk, 4); clocksource_register(&clocksource_systick); }
/* * Start a clocksource using Timer2 in 32-bit mode */ static void __init timer_clocksource_init(void) { /* * No interrupts, periodic mode, load with the largest number * that fits into the 32-bit timer */ MSS_TIMER[1].tim_loadval = 0xFFFFFFFF; MSS_TIMER[1].tim_ctrl = TIMER_CTRL_ENBL; /* * Calculate shift and mult using a helper function. * Supposedly, this helper gets us best values for * conversion between time in nanoseconds and timer ticks */ clocksource_calc_mult_shift(&timer_2_clocksource, timer_ref_clk, 4); /* * Register the clocksource with the timekeeper */ clocksource_register(&timer_2_clocksource); }
static void __init pxa_timer_init(void) { unsigned long clock_tick_rate = get_clock_tick_rate(); OIER = 0; OSSR = OSSR_M0 | OSSR_M1 | OSSR_M2 | OSSR_M3; init_sched_clock(&cd, pxa_update_sched_clock, 32, clock_tick_rate); clocksource_calc_mult_shift(&cksrc_pxa_oscr0, clock_tick_rate, 4); clockevents_calc_mult_shift(&ckevt_pxa_osmr0, clock_tick_rate, 4); ckevt_pxa_osmr0.max_delta_ns = clockevent_delta2ns(0x7fffffff, &ckevt_pxa_osmr0); ckevt_pxa_osmr0.min_delta_ns = clockevent_delta2ns(MIN_OSCR_DELTA * 2, &ckevt_pxa_osmr0) + 1; ckevt_pxa_osmr0.cpumask = cpumask_of(0); setup_irq(IRQ_OST0, &pxa_ost0_irq); clocksource_register_hz(&cksrc_pxa_oscr0, clock_tick_rate); clockevents_register_device(&ckevt_pxa_osmr0); }
static void __init pxa_timer_init(void) { unsigned long clock_tick_rate = get_clock_tick_rate(); OIER = 0; OSSR = OSSR_M0 | OSSR_M1 | OSSR_M2 | OSSR_M3; set_oscr2ns_scale(clock_tick_rate); clocksource_calc_mult_shift(&cksrc_pxa_oscr0, CLOCK_TICK_RATE, 4); clockevents_calc_mult_shift(&ckevt_pxa_osmr0, CLOCK_TICK_RATE, 4); ckevt_pxa_osmr0.max_delta_ns = clockevent_delta2ns(0x7fffffff, &ckevt_pxa_osmr0); ckevt_pxa_osmr0.min_delta_ns = clockevent_delta2ns(MIN_OSCR_DELTA * 2, &ckevt_pxa_osmr0) + 1; ckevt_pxa_osmr0.cpumask = cpumask_of(0); clocksource_register(&cksrc_pxa_oscr0); clockevents_register_device(&ckevt_pxa_osmr0); setup_irq(IRQ_OST0, &pxa_ost0_irq); rtc_calib_init(); }
void __init nmdk_timer_init(void) { unsigned long rate; struct clk *clk0; struct clk *clk1; u32 cr; clk0 = clk_get_sys("mtu0", NULL); BUG_ON(IS_ERR(clk0)); clk1 = clk_get_sys("mtu1", NULL); BUG_ON(IS_ERR(clk1)); clk_enable(clk0); clk_enable(clk1); /* * Tick rate is 2.4MHz for Nomadik and 110MHz for ux500: * use a divide-by-16 counter if it's more than 16MHz */ cr = MTU_CRn_32BITS;; rate = clk_get_rate(clk0); if (rate > 16 << 20) { rate /= 16; cr |= MTU_CRn_PRESCALE_16; } else { cr |= MTU_CRn_PRESCALE_1; } clocksource_calc_mult_shift(&nmdk_clksrc, rate, MTU_MIN_RANGE); /* Timer 0 is the free running clocksource */ writel(cr, mtu_base + MTU_CR(0)); writel(0, mtu_base + MTU_LR(0)); writel(0, mtu_base + MTU_BGLR(0)); writel(cr | MTU_CRn_ENA, mtu_base + MTU_CR(0)); /* Now the scheduling clock is ready */ nmdk_clksrc.read = nmdk_read_timer; if (clocksource_register(&nmdk_clksrc)) pr_err("timer: failed to initialize clock source %s\n", nmdk_clksrc.name); /* Timer 1 is used for events, fix according to rate */ cr = MTU_CRn_32BITS; rate = clk_get_rate(clk1); if (rate > 16 << 20) { rate /= 16; cr |= MTU_CRn_PRESCALE_16; } else { cr |= MTU_CRn_PRESCALE_1; } clockevents_calc_mult_shift(&nmdk_clkevt, rate, MTU_MIN_RANGE); writel(cr | MTU_CRn_ONESHOT, mtu_base + MTU_CR(1)); /* off, currently */ nmdk_clkevt.max_delta_ns = clockevent_delta2ns(0xffffffff, &nmdk_clkevt); nmdk_clkevt.min_delta_ns = clockevent_delta2ns(0x00000002, &nmdk_clkevt); nmdk_clkevt.cpumask = cpumask_of(0); /* Register irq and clockevents */ setup_irq(IRQ_MTU0, &nmdk_timer_irq); clockevents_register_device(&nmdk_clkevt); }