static void nmdk_timer_delay_loop(unsigned long loops) { unsigned long bclock, now; bclock = ~readl(mtu_base + MTU_VAL(0)); do { now = ~readl(mtu_base + MTU_VAL(0)); /* If timer have been cleared (suspend) or wrapped we exit */ if (unlikely(now < bclock)) return; } while ((now - bclock) < loops); }
static u32 notrace nomadik_read_sched_clock(void) { if (unlikely(!mtu_base)) return 0; return -readl(mtu_base + MTU_VAL(0)); }
void __init nmdk_timer_init(void __iomem *base, int irq) { unsigned long rate; struct clk *clk0, *pclk0; mtu_base = base; pclk0 = clk_get_sys("mtu0", "apb_pclk"); BUG_ON(IS_ERR(pclk0)); BUG_ON(clk_prepare(pclk0) < 0); BUG_ON(clk_enable(pclk0) < 0); clk0 = clk_get_sys("mtu0", NULL); BUG_ON(IS_ERR(clk0)); BUG_ON(clk_prepare(clk0) < 0); BUG_ON(clk_enable(clk0) < 0); /* * Tick rate is 2.4MHz for Nomadik and 2.4Mhz, 100MHz or 133 MHz * for ux500. * Use a divide-by-16 counter if the tick rate is more than 32MHz. * At 32 MHz, the timer (with 32 bit counter) can be programmed * to wake-up at a max 127s a head in time. Dividing a 2.4 MHz timer * with 16 gives too low timer resolution. */ rate = clk_get_rate(clk0); if (rate > 32000000) { rate /= 16; clk_prescale = MTU_CRn_PRESCALE_16; } else { clk_prescale = MTU_CRn_PRESCALE_1; } /* Cycles for periodic mode */ nmdk_cycle = DIV_ROUND_CLOSEST(rate, HZ); /* Timer 0 is the free running clocksource */ nmdk_clksrc_reset(); if (clocksource_mmio_init(mtu_base + MTU_VAL(0), "mtu_0", rate, 200, 32, clocksource_mmio_readl_down)) pr_err("timer: failed to initialize clock source %s\n", "mtu_0"); #ifdef CONFIG_NOMADIK_MTU_SCHED_CLOCK setup_sched_clock(nomadik_read_sched_clock, 32, rate); #endif /* Timer 1 is used for events, register irq and clockevents */ setup_irq(irq, &nmdk_timer_irq); nmdk_clkevt.cpumask = cpumask_of(0); nmdk_clkevt.irq = irq; clockevents_config_and_register(&nmdk_clkevt, rate, 2, 0xffffffffU); mtu_delay_timer.read_current_timer = &nmdk_timer_read_current_timer; mtu_delay_timer.freq = rate; register_current_timer_delay(&mtu_delay_timer); }
/* Used to calibrate the delay */ int read_current_timer(unsigned long *timer_val) { if (prcmu_is_ulppll_disabled()) return -EINVAL; *timer_val = ~readl(mtu_base + MTU_VAL(0)); return 0; }
void __init nmdk_timer_init(void) { unsigned long rate; struct clk *clk0; u32 cr = MTU_CRn_32BITS; clk0 = clk_get_sys("mtu0", NULL); BUG_ON(IS_ERR(clk0)); clk_enable(clk0); /* * Tick rate is 2.4MHz for Nomadik and 2.4Mhz, 100MHz or 133 MHz * for ux500. * Use a divide-by-16 counter if the tick rate is more than 32MHz. * At 32 MHz, the timer (with 32 bit counter) can be programmed * to wake-up at a max 127s a head in time. Dividing a 2.4 MHz timer * with 16 gives too low timer resolution. */ rate = clk_get_rate(clk0); if (rate > 32000000) { rate /= 16; cr |= MTU_CRn_PRESCALE_16; } else { cr |= MTU_CRn_PRESCALE_1; } /* 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)); if (clocksource_mmio_init(mtu_base + MTU_VAL(0), "mtu_0", rate, 200, 32, clocksource_mmio_readl_down)) pr_err("timer: failed to initialize clock source %s\n", "mtu_0"); init_sched_clock(&cd, nomadik_update_sched_clock, 32, rate); /* Timer 1 is used for events */ 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); }
unsigned long long sched_clock(void) { unsigned long long v; if (unlikely(!mtu0_base)) return 0; v = cnt32_to_63(0xffffffff - readl(mtu0_base + MTU_VAL(1))); return (v * tclk2ns_scale) >> TCLK2NS_SCALE_FACTOR; }
unsigned long long notrace sched_clock(void) { u32 cyc; if (unlikely(!mtu_base)) return 0; cyc = -readl(mtu_base + MTU_VAL(0)); return cyc_to_sched_clock(&cd, cyc, (u32)~0); }
void __init nmdk_timer_init(void) { unsigned long rate; struct clk *clk0; int ret; clk0 = clk_get_sys("mtu0", NULL); BUG_ON(IS_ERR(clk0)); ret = clk_prepare_enable(clk0); BUG_ON(ret != 0); /* * Tick rate is 2.4MHz for Nomadik and 2.4Mhz, 100MHz or 133 MHz * for ux500. * Use a divide-by-16 counter if the tick rate is more than 32MHz. * At 32 MHz, the timer (with 32 bit counter) can be programmed * to wake-up at a max 127s a head in time. Dividing a 2.4 MHz timer * with 16 gives too low timer resolution. */ rate = clk_get_rate(clk0); if (rate > 32000000) { rate /= 16; clk_prescale = MTU_CRn_PRESCALE_16; } else { clk_prescale = MTU_CRn_PRESCALE_1; } nmdk_cycle = (rate + HZ/2) / HZ; /* Timer 0 is the free running clocksource */ nmdk_clksrc_reset(); if (clocksource_mmio_init(mtu_base + MTU_VAL(0), "mtu_0", rate, 200, 32, clocksource_mmio_readl_down)) pr_err("timer: failed to initialize clock source %s\n", "mtu_0"); #ifdef CONFIG_NOMADIK_MTU_SCHED_CLOCK setup_sched_clock(nomadik_read_sched_clock, 32, rate); #endif /* Timer 1 is used for events, register irq and clockevents */ setup_irq(IRQ_MTU0, &nmdk_timer_irq); nmdk_clkevt.cpumask = cpumask_of(0); clockevents_config_and_register(&nmdk_clkevt, rate, 2, 0xffffffffU); #ifdef ARCH_HAS_READ_CURRENT_TIMER set_delay_fn(nmdk_timer_delay_loop); #endif }
void __init nmdk_timer_init(void __iomem *base) { unsigned long rate; struct clk *clk0; mtu_base = base; clk0 = clk_get_sys("mtu0", NULL); BUG_ON(IS_ERR(clk0)); BUG_ON(clk_prepare(clk0) < 0); BUG_ON(clk_enable(clk0) < 0); rate = clk_get_rate(clk0); if (rate > 32000000) { rate /= 16; clk_prescale = MTU_CRn_PRESCALE_16; } else { clk_prescale = MTU_CRn_PRESCALE_1; } nmdk_cycle = (rate + HZ/2) / HZ; nmdk_clksrc_reset(); if (clocksource_mmio_init(mtu_base + MTU_VAL(0), "mtu_0", rate, 200, 32, clocksource_mmio_readl_down)) pr_err("timer: failed to initialize clock source %s\n", "mtu_0"); #ifdef CONFIG_NOMADIK_MTU_SCHED_CLOCK setup_sched_clock(nomadik_read_sched_clock, 32, rate); #endif setup_irq(IRQ_MTU0, &nmdk_timer_irq); nmdk_clkevt.cpumask = cpumask_of(0); clockevents_config_and_register(&nmdk_clkevt, rate, 2, 0xffffffffU); }
/* * clocksource: the MTU device is a decrementing counters, so we negate * the value being read. */ static cycle_t u8500_read_timer(struct clocksource *cs) { u32 count = readl(mtu0_base + MTU_VAL(1)); return ~count; }
static unsigned long nmdk_timer_read_current_timer(void) { return ~readl_relaxed(mtu_base + MTU_VAL(0)); }
static void notrace nomadik_update_sched_clock(void) { u32 cyc = -readl(mtu_base + MTU_VAL(0)); update_sched_clock(&cd, cyc, (u32)~0); }
/* Used to calibrate the delay */ int read_current_timer(unsigned long *timer_val) { *timer_val = ~readl(mtu_base + MTU_VAL(0)); return 0; }
/* clocksource: MTU decrements, so we negate the value being read. */ static cycle_t nmdk_read_timer(struct clocksource *cs) { return -readl(mtu_base + MTU_VAL(0)); }
void __init nmdk_timer_init(void) { unsigned long rate; struct clk *clk0; unsigned long min_delta_ticks; clk0 = clk_get_sys("mtu0", NULL); BUG_ON(IS_ERR(clk0)); clk_enable(clk0); /* * Tick rate is 2.4MHz for Nomadik and 2.4Mhz, 100MHz or 133 MHz * for ux500. * Use a divide-by-16 counter if the tick rate is more than 32MHz. * At 32 MHz, the timer (with 32 bit counter) can be programmed * to wake-up at a max 127s a head in time. Dividing a 2.4 MHz timer * with 16 gives too low timer resolution. */ rate = clk_get_rate(clk0); if (rate > 32000000) { rate /= 16; clk_prescale = MTU_CRn_PRESCALE_16; } else { clk_prescale = MTU_CRn_PRESCALE_1; } nmdk_cycle = (rate + HZ/2) / HZ; /* Timer 0 is the free running clocksource */ nmdk_clksrc_reset(); if (clocksource_mmio_init(mtu_base + MTU_VAL(0), "mtu_0", rate, 200, 32, clocksource_mmio_readl_down)) pr_err("timer: failed to initialize clock source %s\n", "mtu_0"); #ifdef CONFIG_NOMADIK_MTU_SCHED_CLOCK setup_sched_clock(nomadik_read_sched_clock, 32, rate); #endif /* Timer 1 is used for events */ clockevents_calc_mult_shift(&nmdk_clkevt, rate, MTU_MIN_RANGE); nmdk_clkevt.max_delta_ns = clockevent_delta2ns(0xffffffff, &nmdk_clkevt); /* When ulppll is disabled timer is working on 32kHz clock. */ min_delta_ticks = prcmu_is_ulppll_disabled()? 0x5 : 0x2; nmdk_clkevt.min_delta_ns = clockevent_delta2ns(min_delta_ticks, &nmdk_clkevt); nmdk_clkevt.cpumask = cpumask_of(0); /* Register irq and clockevents */ setup_irq(IRQ_MTU0, &nmdk_timer_irq); clockevents_register_device(&nmdk_clkevt); #ifdef ARCH_HAS_READ_CURRENT_TIMER if (!prcmu_is_ulppll_disabled()) set_delay_fn(nmdk_timer_delay_loop); #endif }