/* * tmr_group0_config: * group0_timer0: cpu0 local_timer, free running, 32K * group0_timer1: cpu1 local_timer, free running, 32K * group0_timer2: udelay timer, free running, 3.25M */ static void __init tmr_group0_config(void) { /* Select the configurable timer clock rate to be 3.25MHz */ __raw_writel(APBC_APBCLK | APBC_RST, APBC_PXA988_TIMERS); __raw_writel(APBC_APBCLK | APBC_FNCLK | APBC_FNCLKSEL(3), APBC_PXA988_TIMERS); __raw_writel(0x0, group0_base + TMR_CER); /* disable */ /* timer0:32K, timer1:32K, timer2:fast clock (3.25M) */ __raw_writel(TMR_CCR_CS_0(1) | TMR_CCR_CS_1(1) | TMR_CCR_CS_2(0), group0_base + TMR_CCR); /* set timer0/1/2 to free-running mode */ __raw_writel(0x7, group0_base + TMR_CMR); __raw_writel(0x0, group0_base + TMR_PLCR(0)); /* free-running */ __raw_writel(0x7, group0_base + TMR_ICR(0)); /* clear status */ __raw_writel(0x0, group0_base + TMR_IER(0)); /* disable irq */ __raw_writel(0x0, group0_base + TMR_PLCR(1)); /* free-running */ __raw_writel(0x7, group0_base + TMR_ICR(1)); /* clear status */ __raw_writel(0x0, group0_base + TMR_IER(1)); /* disable irq */ #ifdef CONFIG_ARCH_PROVIDES_UDELAY __raw_writel(0x0, group0_base + TMR_PLCR(2)); /* free-running */ __raw_writel(0x7, group0_base + TMR_ICR(2)); /* clear status */ __raw_writel(0x0, group0_base + TMR_IER(2)); /* disable irq */ /* enable timer2 */ __raw_writel(0x4, group0_base + TMR_CER); #endif }
/* * tmr_group1_config: * group1_timer0: cpu0 local_timer, free running, 32K * group1_timer1: cpu1 local_timer, free running, 32K * group1_timer2: clock source, free running, 32K */ static void __init tmr_group1_config(void) { /* Select the configurable timer clock rate to be 3.25MHz */ __raw_writel(APBC_APBCLK | APBC_RST, APBC_PXA988_TIMERS1); __raw_writel(APBC_APBCLK | APBC_FNCLK | APBC_FNCLKSEL(3), APBC_PXA988_TIMERS1); __raw_writel(0x0, group1_base + TMR_CER); /* disable */ /* timer0:32K, timer1:32K, timer2:32K */ __raw_writel(TMR_CCR_CS_0(1) | TMR_CCR_CS_1(1) | TMR_CCR_CS_2(2), group1_base + TMR_CCR); /* set timer0/1/2 to free-running mode */ __raw_writel(0x7, group1_base + TMR_CMR); __raw_writel(0x0, group1_base + TMR_PLCR(0)); /* free-running */ __raw_writel(0x7, group1_base + TMR_ICR(0)); /* clear status */ __raw_writel(0x0, group1_base + TMR_IER(0)); /* disable irq */ __raw_writel(0x0, group1_base + TMR_PLCR(1)); /* free-running */ __raw_writel(0x7, group1_base + TMR_ICR(1)); /* clear status */ __raw_writel(0x0, group1_base + TMR_IER(1)); /* disable irq */ __raw_writel(0x0, group1_base + TMR_PLCR(2)); /* free-running */ __raw_writel(0x7, group1_base + TMR_ICR(2)); /* clear status */ __raw_writel(0x0, group1_base + TMR_IER(2)); /* disable irq */ /* enable timer2 */ __raw_writel(0x4, group1_base + TMR_CER); }
static int timer_set_next_event(unsigned long delta, struct clock_event_device *dev) { unsigned long flags; local_irq_save(flags); /* * Disable timer 0. */ __raw_writel(0x02, mmp_timer_base + TMR_CER); /* * Clear and enable timer match 0 interrupt. */ __raw_writel(0x01, mmp_timer_base + TMR_ICR(0)); __raw_writel(0x01, mmp_timer_base + TMR_IER(0)); /* * Setup new clockevent timer value. */ __raw_writel(delta - 1, mmp_timer_base + TMR_TN_MM(0, 0)); /* * Enable timer 0. */ __raw_writel(0x03, mmp_timer_base + TMR_CER); local_irq_restore(flags); return 0; }
/* * tmr_group2_config: * group2_timer0: global clockevent when kernel boot up, free running, 32K * group2_timer1/2: reserved for trust zone, settings unchanged * NOTICE: * make sure trust zone won't change group2 config at the same time! */ static void __init tmr_group2_config(void) { u32 tmp; /* trust zone will init APBC_PXA1088_TIMERS2 prior to kernel */ #ifndef CONFIG_TZ_HYPERVISOR /* Select the configurable timer clock rate to be 3.25MHz */ __raw_writel(APBC_APBCLK | APBC_RST, APBC_PXA1088_TIMERS2); __raw_writel(APBC_APBCLK | APBC_FNCLK | APBC_FNCLKSEL(3), APBC_PXA1088_TIMERS2); #endif /* CONFIG_TZ_HYPERVISOR */ /* only disable timer0; timer1/2: unchanged */ tmp = __raw_readl(group2_base + TMR_CER); __raw_writel(tmp & (~0x1), group2_base + TMR_CER); /* timer0: 32K; timer1/2: unchanged */ tmp = __raw_readl(group2_base + TMR_CCR); __raw_writel((tmp & (~0x3)) | TMR_CCR_CS_0(1), group2_base + TMR_CCR); /* timer0: free-running mode; timer1/2: unchanged */ tmp = __raw_readl(group2_base + TMR_CMR); __raw_writel(tmp | 0x1, group2_base + TMR_CMR); __raw_writel(0x0, group2_base + TMR_PLCR(0)); /* free-running */ __raw_writel(0x7, group2_base + TMR_ICR(0)); /* clear status */ __raw_writel(0x0, group2_base + TMR_IER(0)); /* disable irq */ }
/* must protect with local irq disabled or spin_lock_irqsave held! */ static void reprogram_timer(void __iomem *base, u32 timern, unsigned long delta) { u32 tmp; u32 delay = 3; /* Disable timern */ tmp = __raw_readl(base + TMR_CER); __raw_writel(tmp & (~(0x1 << timern)), base + TMR_CER); /* switch to fast clock for quick operation */ tmp = __raw_readl(base + TMR_CCR); __raw_writel(tmp & (~(0x3 << timern * 2)), base + TMR_CCR); /* Clear pending interrupt status */ while (delay--) __raw_writel(0x1, base + TMR_ICR(timern)); /* enable the matching interrupt */ __raw_writel(0x1, base + TMR_IER(timern)); /* Setup new clockevent timer value */ __raw_writel(delta - 1, base + TMR_TN_MM(timern, 0)); /* switch back to 32K */ tmp = __raw_readl(base + TMR_CCR); __raw_writel((tmp & (~(0x3 << timern * 2))) | (0x1 << (timern * 2)), base + TMR_CCR); /* Enable timer */ tmp = __raw_readl(base + TMR_CER); __raw_writel(tmp | (0x1 << timern), base + TMR_CER); }
/* must protect with local irq disabled or spin_lock_irqsave held! */ static void disable_timer(void __iomem *base, u32 timern) { u32 tmp; u32 delay = 3; /* Disable timern */ tmp = __raw_readl(base + TMR_CER); __raw_writel(tmp & (~(0x1 << timern)), base + TMR_CER); /* switch to fast clock for quick operation */ tmp = __raw_readl(base + TMR_CCR); __raw_writel(tmp & (~(0x3 << timern * 2)), base + TMR_CCR); /* disable the matching interrupt */ __raw_writel(0, base + TMR_IER(timern)); /* Clear pending interrupt status */ while (delay--) __raw_writel(0x1, base + TMR_ICR(timern)); /* switch back to 32K */ tmp = __raw_readl(base + TMR_CCR); __raw_writel((tmp & (~(0x3 << timern * 2))) | (0x1 << (timern * 2)), base + TMR_CCR); }
static irqreturn_t timer_interrupt(int irq, void *dev_id) { struct clock_event_device *c = dev_id; /* disable and clear pending interrupt status */ __raw_writel(0x0, TIMERS_VIRT_BASE + TMR_IER(0)); __raw_writel(0x1, TIMERS_VIRT_BASE + TMR_ICR(0)); c->event_handler(c); return IRQ_HANDLED; }
static int timer_set_shutdown(struct clock_event_device *evt) { unsigned long flags; local_irq_save(flags); /* disable the matching interrupt */ __raw_writel(0x00, mmp_timer_base + TMR_IER(0)); local_irq_restore(flags); return 0; }
static void __init timer_config(void) { uint32_t ccr = __raw_readl(mmp_timer_base + TMR_CCR); __raw_writel(0x0, mmp_timer_base + TMR_CER); /* disable */ ccr &= (cpu_is_mmp2()) ? (TMR_CCR_CS_0(0) | TMR_CCR_CS_1(0)) : (TMR_CCR_CS_0(3) | TMR_CCR_CS_1(3)); __raw_writel(ccr, mmp_timer_base + TMR_CCR); /* set timer 0 to periodic mode, and timer 1 to free-running mode */ __raw_writel(0x2, mmp_timer_base + TMR_CMR); __raw_writel(0x1, mmp_timer_base + TMR_PLCR(0)); /* periodic */ __raw_writel(0x7, mmp_timer_base + TMR_ICR(0)); /* clear status */ __raw_writel(0x0, mmp_timer_base + TMR_IER(0)); __raw_writel(0x0, mmp_timer_base + TMR_PLCR(1)); /* free-running */ __raw_writel(0x7, mmp_timer_base + TMR_ICR(1)); /* clear status */ __raw_writel(0x0, mmp_timer_base + TMR_IER(1)); /* enable timer 1 counter */ __raw_writel(0x2, mmp_timer_base + TMR_CER); }
static void __init timer_config(void) { uint32_t ccr = __raw_readl(TIMERS_VIRT_BASE + TMR_CCR); __raw_writel(0x0, TIMERS_VIRT_BASE + TMR_CER); ccr &= (cpu_is_mmp2()) ? (TMR_CCR_CS_0(0) | TMR_CCR_CS_1(0)) : (TMR_CCR_CS_0(3) | TMR_CCR_CS_1(3)); __raw_writel(ccr, TIMERS_VIRT_BASE + TMR_CCR); __raw_writel(0x2, TIMERS_VIRT_BASE + TMR_CMR); __raw_writel(0x1, TIMERS_VIRT_BASE + TMR_PLCR(0)); __raw_writel(0x7, TIMERS_VIRT_BASE + TMR_ICR(0)); __raw_writel(0x0, TIMERS_VIRT_BASE + TMR_IER(0)); __raw_writel(0x0, TIMERS_VIRT_BASE + TMR_PLCR(1)); __raw_writel(0x7, TIMERS_VIRT_BASE + TMR_ICR(1)); __raw_writel(0x0, TIMERS_VIRT_BASE + TMR_IER(1)); __raw_writel(0x2, TIMERS_VIRT_BASE + TMR_CER); }
static int timer_set_next_event(unsigned long delta, struct clock_event_device *dev) { unsigned long flags, next; local_irq_save(flags); /* clear pending interrupt status and enable */ __raw_writel(0x01, TIMERS_VIRT_BASE + TMR_ICR(0)); __raw_writel(0x01, TIMERS_VIRT_BASE + TMR_IER(0)); next = timer_read() + delta; __raw_writel(next, TIMERS_VIRT_BASE + TMR_TN_MM(0, 0)); local_irq_restore(flags); return 0; }
static void timer_set_mode(enum clock_event_mode mode, struct clock_event_device *dev) { unsigned long flags; local_irq_save(flags); switch (mode) { case CLOCK_EVT_MODE_ONESHOT: case CLOCK_EVT_MODE_UNUSED: case CLOCK_EVT_MODE_SHUTDOWN: __raw_writel(0x00, TIMERS_VIRT_BASE + TMR_IER(0)); break; case CLOCK_EVT_MODE_RESUME: case CLOCK_EVT_MODE_PERIODIC: break; } local_irq_restore(flags); }
static int timer_set_next_event(unsigned long delta, struct clock_event_device *dev) { unsigned long flags; local_irq_save(flags); __raw_writel(0x02, TIMERS_VIRT_BASE + TMR_CER); __raw_writel(0x01, TIMERS_VIRT_BASE + TMR_ICR(0)); __raw_writel(0x01, TIMERS_VIRT_BASE + TMR_IER(0)); __raw_writel(delta - 1, TIMERS_VIRT_BASE + TMR_TN_MM(0, 0)); __raw_writel(0x03, TIMERS_VIRT_BASE + TMR_CER); local_irq_restore(flags); return 0; }
static void __init timer_config(void) { uint32_t ccr = __raw_readl(TIMERS_VIRT_BASE + TMR_CCR); uint32_t cer = __raw_readl(TIMERS_VIRT_BASE + TMR_CER); uint32_t cmr = __raw_readl(TIMERS_VIRT_BASE + TMR_CMR); __raw_writel(cer & ~0x1, TIMERS_VIRT_BASE + TMR_CER); /* disable */ ccr &= (cpu_is_mmp2()) ? TMR_CCR_CS_0(0) : TMR_CCR_CS_0(3); __raw_writel(ccr, TIMERS_VIRT_BASE + TMR_CCR); /* free-running mode */ __raw_writel(cmr | 0x01, TIMERS_VIRT_BASE + TMR_CMR); __raw_writel(0x0, TIMERS_VIRT_BASE + TMR_PLCR(0)); /* free-running */ __raw_writel(0x7, TIMERS_VIRT_BASE + TMR_ICR(0)); /* clear status */ __raw_writel(0x0, TIMERS_VIRT_BASE + TMR_IER(0)); /* enable timer counter */ __raw_writel(cer | 0x01, TIMERS_VIRT_BASE + TMR_CER); }