Path: blob/master/arch/cris/arch-v32/kernel/time.c
15125 views
/*1* linux/arch/cris/arch-v32/kernel/time.c2*3* Copyright (C) 2003-2010 Axis Communications AB4*5*/67#include <linux/timex.h>8#include <linux/time.h>9#include <linux/clocksource.h>10#include <linux/interrupt.h>11#include <linux/swap.h>12#include <linux/sched.h>13#include <linux/init.h>14#include <linux/threads.h>15#include <linux/cpufreq.h>16#include <asm/types.h>17#include <asm/signal.h>18#include <asm/io.h>19#include <asm/delay.h>20#include <asm/rtc.h>21#include <asm/irq.h>22#include <asm/irq_regs.h>2324#include <hwregs/reg_map.h>25#include <hwregs/reg_rdwr.h>26#include <hwregs/timer_defs.h>27#include <hwregs/intr_vect_defs.h>28#ifdef CONFIG_CRIS_MACH_ARTPEC329#include <hwregs/clkgen_defs.h>30#endif3132/* Watchdog defines */33#define ETRAX_WD_KEY_MASK 0x7F /* key is 7 bit */34#define ETRAX_WD_HZ 763 /* watchdog counts at 763 Hz */35/* Number of 763 counts before watchdog bites */36#define ETRAX_WD_CNT ((2*ETRAX_WD_HZ)/HZ + 1)3738/* Register the continuos readonly timer available in FS and ARTPEC-3. */39static cycle_t read_cont_rotime(struct clocksource *cs)40{41return (u32)REG_RD(timer, regi_timer0, r_time);42}4344static struct clocksource cont_rotime = {45.name = "crisv32_rotime",46.rating = 300,47.read = read_cont_rotime,48.mask = CLOCKSOURCE_MASK(32),49.shift = 10,50.flags = CLOCK_SOURCE_IS_CONTINUOUS,51};5253static int __init etrax_init_cont_rotime(void)54{55cont_rotime.mult = clocksource_khz2mult(100000, cont_rotime.shift);56clocksource_register(&cont_rotime);57return 0;58}59arch_initcall(etrax_init_cont_rotime);606162unsigned long timer_regs[NR_CPUS] =63{64regi_timer0,65#ifdef CONFIG_SMP66regi_timer267#endif68};6970extern int set_rtc_mmss(unsigned long nowtime);71extern int have_rtc;7273#ifdef CONFIG_CPU_FREQ74static int75cris_time_freq_notifier(struct notifier_block *nb, unsigned long val,76void *data);7778static struct notifier_block cris_time_freq_notifier_block = {79.notifier_call = cris_time_freq_notifier,80};81#endif8283unsigned long get_ns_in_jiffie(void)84{85reg_timer_r_tmr0_data data;86unsigned long ns;8788data = REG_RD(timer, regi_timer0, r_tmr0_data);89ns = (TIMER0_DIV - data) * 10;90return ns;91}929394/* From timer MDS describing the hardware watchdog:95* 4.3.1 Watchdog Operation96* The watchdog timer is an 8-bit timer with a configurable start value.97* Once started the watchdog counts downwards with a frequency of 763 Hz98* (100/131072 MHz). When the watchdog counts down to 1, it generates an99* NMI (Non Maskable Interrupt), and when it counts down to 0, it resets the100* chip.101*/102/* This gives us 1.3 ms to do something useful when the NMI comes */103104/* Right now, starting the watchdog is the same as resetting it */105#define start_watchdog reset_watchdog106107#if defined(CONFIG_ETRAX_WATCHDOG)108static short int watchdog_key = 42; /* arbitrary 7 bit number */109#endif110111/* Number of pages to consider "out of memory". It is normal that the memory112* is used though, so set this really low. */113#define WATCHDOG_MIN_FREE_PAGES 8114115void reset_watchdog(void)116{117#if defined(CONFIG_ETRAX_WATCHDOG)118reg_timer_rw_wd_ctrl wd_ctrl = { 0 };119120/* Only keep watchdog happy as long as we have memory left! */121if(nr_free_pages() > WATCHDOG_MIN_FREE_PAGES) {122/* Reset the watchdog with the inverse of the old key */123/* Invert key, which is 7 bits */124watchdog_key ^= ETRAX_WD_KEY_MASK;125wd_ctrl.cnt = ETRAX_WD_CNT;126wd_ctrl.cmd = regk_timer_start;127wd_ctrl.key = watchdog_key;128REG_WR(timer, regi_timer0, rw_wd_ctrl, wd_ctrl);129}130#endif131}132133/* stop the watchdog - we still need the correct key */134135void stop_watchdog(void)136{137#if defined(CONFIG_ETRAX_WATCHDOG)138reg_timer_rw_wd_ctrl wd_ctrl = { 0 };139watchdog_key ^= ETRAX_WD_KEY_MASK; /* invert key, which is 7 bits */140wd_ctrl.cnt = ETRAX_WD_CNT;141wd_ctrl.cmd = regk_timer_stop;142wd_ctrl.key = watchdog_key;143REG_WR(timer, regi_timer0, rw_wd_ctrl, wd_ctrl);144#endif145}146147extern void show_registers(struct pt_regs *regs);148149void handle_watchdog_bite(struct pt_regs *regs)150{151#if defined(CONFIG_ETRAX_WATCHDOG)152extern int cause_of_death;153154oops_in_progress = 1;155printk(KERN_WARNING "Watchdog bite\n");156157/* Check if forced restart or unexpected watchdog */158if (cause_of_death == 0xbedead) {159#ifdef CONFIG_CRIS_MACH_ARTPEC3160/* There is a bug in Artpec-3 (voodoo TR 78) that requires161* us to go to lower frequency for the reset to be reliable162*/163reg_clkgen_rw_clk_ctrl ctrl =164REG_RD(clkgen, regi_clkgen, rw_clk_ctrl);165ctrl.pll = 0;166REG_WR(clkgen, regi_clkgen, rw_clk_ctrl, ctrl);167#endif168while(1);169}170171/* Unexpected watchdog, stop the watchdog and dump registers. */172stop_watchdog();173printk(KERN_WARNING "Oops: bitten by watchdog\n");174show_registers(regs);175oops_in_progress = 0;176#ifndef CONFIG_ETRAX_WATCHDOG_NICE_DOGGY177reset_watchdog();178#endif179while(1) /* nothing */;180#endif181}182183/*184* timer_interrupt() needs to keep up the real-time clock,185* as well as call the "xtime_update()" routine every clocktick.186*/187extern void cris_do_profile(struct pt_regs *regs);188189static inline irqreturn_t timer_interrupt(int irq, void *dev_id)190{191struct pt_regs *regs = get_irq_regs();192int cpu = smp_processor_id();193reg_timer_r_masked_intr masked_intr;194reg_timer_rw_ack_intr ack_intr = { 0 };195196/* Check if the timer interrupt is for us (a tmr0 int) */197masked_intr = REG_RD(timer, timer_regs[cpu], r_masked_intr);198if (!masked_intr.tmr0)199return IRQ_NONE;200201/* Acknowledge the timer irq. */202ack_intr.tmr0 = 1;203REG_WR(timer, timer_regs[cpu], rw_ack_intr, ack_intr);204205/* Reset watchdog otherwise it resets us! */206reset_watchdog();207208/* Update statistics. */209update_process_times(user_mode(regs));210211cris_do_profile(regs); /* Save profiling information */212213/* The master CPU is responsible for the time keeping. */214if (cpu != 0)215return IRQ_HANDLED;216217/* Call the real timer interrupt handler */218xtime_update(1);219return IRQ_HANDLED;220}221222/* Timer is IRQF_SHARED so drivers can add stuff to the timer irq chain.223* It needs to be IRQF_DISABLED to make the jiffies update work properly.224*/225static struct irqaction irq_timer = {226.handler = timer_interrupt,227.flags = IRQF_SHARED | IRQF_DISABLED,228.name = "timer"229};230231void __init cris_timer_init(void)232{233int cpu = smp_processor_id();234reg_timer_rw_tmr0_ctrl tmr0_ctrl = { 0 };235reg_timer_rw_tmr0_div tmr0_div = TIMER0_DIV;236reg_timer_rw_intr_mask timer_intr_mask;237238/* Setup the etrax timers.239* Base frequency is 100MHz, divider 1000000 -> 100 HZ240* We use timer0, so timer1 is free.241* The trig timer is used by the fasttimer API if enabled.242*/243244tmr0_ctrl.op = regk_timer_ld;245tmr0_ctrl.freq = regk_timer_f100;246REG_WR(timer, timer_regs[cpu], rw_tmr0_div, tmr0_div);247REG_WR(timer, timer_regs[cpu], rw_tmr0_ctrl, tmr0_ctrl); /* Load */248tmr0_ctrl.op = regk_timer_run;249REG_WR(timer, timer_regs[cpu], rw_tmr0_ctrl, tmr0_ctrl); /* Start */250251/* Enable the timer irq. */252timer_intr_mask = REG_RD(timer, timer_regs[cpu], rw_intr_mask);253timer_intr_mask.tmr0 = 1;254REG_WR(timer, timer_regs[cpu], rw_intr_mask, timer_intr_mask);255}256257void __init time_init(void)258{259reg_intr_vect_rw_mask intr_mask;260261/* Probe for the RTC and read it if it exists.262* Before the RTC can be probed the loops_per_usec variable needs263* to be initialized to make usleep work. A better value for264* loops_per_usec is calculated by the kernel later once the265* clock has started.266*/267loops_per_usec = 50;268269if(RTC_INIT() < 0)270have_rtc = 0;271else272have_rtc = 1;273274/* Start CPU local timer. */275cris_timer_init();276277/* Enable the timer irq in global config. */278intr_mask = REG_RD_VECT(intr_vect, regi_irq, rw_mask, 1);279intr_mask.timer0 = 1;280REG_WR_VECT(intr_vect, regi_irq, rw_mask, 1, intr_mask);281282/* Now actually register the timer irq handler that calls283* timer_interrupt(). */284setup_irq(TIMER0_INTR_VECT, &irq_timer);285286/* Enable watchdog if we should use one. */287288#if defined(CONFIG_ETRAX_WATCHDOG)289printk(KERN_INFO "Enabling watchdog...\n");290start_watchdog();291292/* If we use the hardware watchdog, we want to trap it as an NMI293* and dump registers before it resets us. For this to happen, we294* must set the "m" NMI enable flag (which once set, is unset only295* when an NMI is taken). */296{297unsigned long flags;298local_save_flags(flags);299flags |= (1<<30); /* NMI M flag is at bit 30 */300local_irq_restore(flags);301}302#endif303304#ifdef CONFIG_CPU_FREQ305cpufreq_register_notifier(&cris_time_freq_notifier_block,306CPUFREQ_TRANSITION_NOTIFIER);307#endif308}309310#ifdef CONFIG_CPU_FREQ311static int312cris_time_freq_notifier(struct notifier_block *nb, unsigned long val,313void *data)314{315struct cpufreq_freqs *freqs = data;316if (val == CPUFREQ_POSTCHANGE) {317reg_timer_r_tmr0_data data;318reg_timer_rw_tmr0_div div = (freqs->new * 500) / HZ;319do {320data = REG_RD(timer, timer_regs[freqs->cpu],321r_tmr0_data);322} while (data > 20);323REG_WR(timer, timer_regs[freqs->cpu], rw_tmr0_div, div);324}325return 0;326}327#endif328329330