/* Stop the TC channel */ static void stop_tc(int channel) { /* Disable the TC Clcok */ clk_disable(tc->clk[channel]); /* Disable the RC Compare interrupt */ __raw_writel((1<<4), tcaddr + ATMEL_TC_REG(channel, IDR)); /* Disable the RC C */ __raw_writel(AT91_TC_CLKDIS, tcaddr + ATMEL_TC_REG(channel, CCR)); }
static cycle_t tc_get_cycles(struct clocksource *cs) { unsigned long flags; u32 lower, upper; raw_local_irq_save(flags); do { upper = __raw_readl(tcaddr + ATMEL_TC_REG(1, CV)); lower = __raw_readl(tcaddr + ATMEL_TC_REG(0, CV)); } while (upper != __raw_readl(tcaddr + ATMEL_TC_REG(1, CV))); raw_local_irq_restore(flags); return (upper << 16) | lower; }
void tc_clksrc_suspend(struct clocksource *cs) { int i; for (i = 0; i < ARRAY_SIZE(tcb_cache); i++) { tcb_cache[i].cmr = readl(tcaddr + ATMEL_TC_REG(i, CMR)); tcb_cache[i].imr = readl(tcaddr + ATMEL_TC_REG(i, IMR)); tcb_cache[i].rc = readl(tcaddr + ATMEL_TC_REG(i, RC)); tcb_cache[i].clken = !!(readl(tcaddr + ATMEL_TC_REG(i, SR)) & ATMEL_TC_CLKSTA); } bmr_cache = readl(tcaddr + ATMEL_TC_BMR); }
/* Start the TC channel to provide the receive/send data clock */ static inline void start_tc(int channel, unsigned long baudrate) { unsigned long mck_rate_hz = 0; /* Enable the TC Clock in AT91_PMC_PCER(Can Read status from AT91_PMC_PCSR) */ clk_enable(tc->clk[channel]); /* Get the MCK */ mck_rate_hz = clk_get_rate(tc->clk[channel]); /* Clock Disable */ __raw_writel(AT91_TC_CLKDIS, tcaddr + ATMEL_TC_REG(channel, CCR)); /* All interrupt disable */ __raw_writel(0xFF, tcaddr + ATMEL_TC_REG(channel, IDR)); /* Choose External Clock1(MCK/2),RC Compare triger */ __raw_writel(AT91_TC_TIMER_CLOCK1| AT91_TC_CPCTRG, tcaddr + ATMEL_TC_REG(channel, CMR)); dbg_print("mck_rat_hz=%lu baudrate=%lu RC=%lu\n", mck_rate_hz, baudrate, mck_rate_hz/(2*baudrate)); /* Set the counter value */ __raw_writel((mck_rate_hz/(2*baudrate)), tcaddr + ATMEL_TC_REG(channel, RC)); /* RC compare interrupt enable */ __raw_writel((1<<4), tcaddr + ATMEL_TC_REG(channel, IER)); /* TC Channel clock enable */ __raw_writel((AT91_TC_CLKEN), tcaddr + ATMEL_TC_REG(channel, CCR)); /* Clear the TC Channel status */ __raw_readl(tcaddr + ATMEL_TC_REG(channel, SR)); /* TC channel software trigger enable */ __raw_writel((AT91_TC_SWTRG ), tcaddr + ATMEL_TC_REG(channel, CCR)); }
void tc_clksrc_resume(struct clocksource *cs) { int i; for (i = 0; i < ARRAY_SIZE(tcb_cache); i++) { /* Restore registers for the channel, RA and RB are not used */ writel(tcb_cache[i].cmr, tcaddr + ATMEL_TC_REG(i, CMR)); writel(tcb_cache[i].rc, tcaddr + ATMEL_TC_REG(i, RC)); writel(0, tcaddr + ATMEL_TC_REG(i, RA)); writel(0, tcaddr + ATMEL_TC_REG(i, RB)); /* Disable all the interrupts */ writel(0xff, tcaddr + ATMEL_TC_REG(i, IDR)); /* Reenable interrupts that were enabled before suspending */ writel(tcb_cache[i].imr, tcaddr + ATMEL_TC_REG(i, IER)); /* Start the clock if it was used */ if (tcb_cache[i].clken) writel(ATMEL_TC_CLKEN, tcaddr + ATMEL_TC_REG(i, CCR)); } /* Dual channel, chain channels */ writel(bmr_cache, tcaddr + ATMEL_TC_BMR); /* Finally, trigger all the channels*/ writel(ATMEL_TC_SYNC, tcaddr + ATMEL_TC_BCR); }
static u32 tc_get_cv32(void) { return __raw_readl(tcaddr + ATMEL_TC_REG(0, CV)); }
static cycle_t tc_get_cycles32(struct clocksource *cs) { return __raw_readl(tcaddr + ATMEL_TC_REG(0, CV)); }
static u64 tc_get_cycles32(struct clocksource *cs) { return readl_relaxed(tcaddr + ATMEL_TC_REG(0, CV)); }
/* Read the TC_SR register will clear the TC */ static void clear_tc(int channel) { __raw_readl(tcaddr + ATMEL_TC_REG(channel, SR)); }