static void jz_clockevent_init(struct jz_timerevent *evt_dev) { struct clock_event_device *cd = &evt_dev->clkevt; struct clk *ext_clk = clk_get(NULL,"ext1"); spin_lock_init(&evt_dev->lock); evt_dev->rate = clk_get_rate(ext_clk) / CLKEVENT_DIV; clk_put(ext_clk); stoptimer(); tcu_writel(CH_TCSR(CLKEVENT_CH),CSRDIV(CLKEVENT_DIV) | CSR_EXT_EN); evt_dev->evt_action.handler = jz_timer_interrupt; evt_dev->evt_action.thread_fn = NULL; evt_dev->evt_action.flags = IRQF_DISABLED | IRQF_TIMER; evt_dev->evt_action.name = "jz-timerirq"; evt_dev->evt_action.dev_id = (void*)evt_dev; if(setup_irq(IRQ_TCU1, &evt_dev->evt_action) < 0) { pr_err("timer request irq error\n"); BUG(); } memset(cd,0,sizeof(struct clock_event_device)); cd->name = "jz-clockenvent"; cd->features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC; cd->shift = 10; cd->rating = 400; cd->set_mode = jz_set_mode; cd->set_next_event = jz_set_next_event; cd->irq = IRQ_TCU1; cd->cpumask = cpumask_of(0); clockevents_config_and_register(cd,evt_dev->rate,4,65536); printk("clockevents_config_and_register success.\n"); }
/* * @fn: request a tcu channel. * @tcu_chan: channel to request. * */ void tcu_timer_request(int tcu_chan) { tcu_channel = tcu_chan; REG32(CPM_IOBASE + CPM_CLKGR0) &= ~(1<<30); tcu_dump_reg(); tcu_save(); /* stop clear */ tcu_writel(TCU_TSCR,(1 << tcu_channel)); tcu_writel(TCU_TECR,(1 << tcu_channel)); tcu_writel(TCU_TMSR,(1 << tcu_channel)|(1 << (tcu_channel + 16))); tcu_writel(TCU_TFCR, (1 << tcu_channel) | (1 << (tcu_channel + 16))); tcu_writel(CH_TDHR(tcu_channel), 1); /* Mask interrupt */ /* RTC CLK, 32768 * DIV: 64. * TCOUNT: 1: 1.953125ms * */ tcu_writel(CH_TCSR(tcu_channel),CSRDIV(CLK_DIV) | CSR_RTC_EN); tcu_dump_reg(); }
void __cpuinit jzcpu_timer_setup(void) { int cpu = smp_processor_id(); struct jz_timerevent *evt = &per_cpu(jzclockevent, cpu); evt->cpu = cpu; evt->state = INIT; switch(cpu) { case 0: evt->state = FINI; evt->ch = 5; evt->irq = IRQ_TCU1; evt->count_addr = TCU_IOBASE + CH_TCNT(evt->ch); evt->latch_addr = TCU_IOBASE + CH_TDFR(evt->ch); evt->ctrl_addr = TCU_IOBASE; evt->config_addr = TCU_IOBASE + CH_TCSR(evt->ch); tcu_writel(CH_TDHR(evt->ch), 0xffff); tcu_writel(TCU_TMSR, ((1 << evt->ch) | (1 << (evt->ch + 16)))); break; case 1: evt->ch = 15; evt->irq = IRQ_TCU0; evt->count_addr = APB_OST_IOBASE + OSTCNTL; evt->latch_addr = APB_OST_IOBASE + OSTDR; evt->ctrl_addr = TCU_IOBASE; evt->config_addr = APB_OST_IOBASE + OSTCSR; apbost_writel(OSTCNTH, 0); break; } #ifdef CONFIG_HOTPLUG_CPU jz_set_cpu_affinity(evt->irq,0); #endif jz_clockevent_init(evt,cpu); }
static void reset_timer(int count) { unsigned int tcsr = tcu_readl(CH_TCSR(tcu_channel)); /* set count */ tcu_writel(CH_TDFR(tcu_channel),count); tcu_writel(CH_TDHR(tcu_channel),count/2); tcu_writel(TCU_TMCR , (1 << tcu_channel)); start_timer(); }
static void tcu_dump_reg_hex(void) { TCSM_PCHAR('G'); serial_put_hex(tcu_readl(CH_TCSR(tcu_channel))); serial_put_hex(tcu_readl(CH_TCNT(tcu_channel))); serial_put_hex(tcu_readl(TCU_TER)); serial_put_hex(tcu_readl(TCU_TFR)); serial_put_hex(tcu_readl(TCU_TMR)); serial_put_hex(tcu_readl(TCU_TSR)); serial_put_hex(tcu_readl(TCU_TSTR)); TCSM_PCHAR('H'); }
static void tcu_dump_reg(void) { printk("TCU_TCSR:%08x\n", tcu_readl(CH_TCSR(tcu_channel))); printk("TCU_TCNT:%08x\n", tcu_readl(CH_TCNT(tcu_channel))); printk("TCU_TER:%08x\n", tcu_readl(TCU_TER)); printk("TCU_TFR:%08x\n", tcu_readl(TCU_TFR)); printk("TCU_TMR:%08x\n", tcu_readl(TCU_TMR)); printk("TCU_TSR:%08x\n", tcu_readl(TCU_TSR)); printk("TCU_TSTR:%08x\n", tcu_readl(TCU_TSTR)); }
static inline void tcu_restore(void) { tcu_writel(CH_TCSR(tcu_channel), save_tcsr); }
static inline void tcu_save(void) { save_tcsr = tcu_readl(CH_TCSR(tcu_channel)); }