Loading arch/cris/Kconfig +1 −0 Original line number Diff line number Diff line Loading @@ -55,6 +55,7 @@ config CRIS select IRQ_DOMAIN if ETRAX_ARCH_V32 select OF if ETRAX_ARCH_V32 select OF_EARLY_FLATTREE if ETRAX_ARCH_V32 select GENERIC_CLOCKEVENTS if ETRAX_ARCH_V32 config HZ int Loading arch/cris/arch-v32/kernel/time.c +85 −60 Original line number Diff line number Diff line Loading @@ -8,6 +8,7 @@ #include <linux/timex.h> #include <linux/time.h> #include <linux/clocksource.h> #include <linux/clockchips.h> #include <linux/interrupt.h> #include <linux/swap.h> #include <linux/sched.h> Loading Loading @@ -36,6 +37,8 @@ /* Number of 763 counts before watchdog bites */ #define ETRAX_WD_CNT ((2*ETRAX_WD_HZ)/HZ + 1) #define CRISV32_TIMER_FREQ (100000000lu) /* Register the continuos readonly timer available in FS and ARTPEC-3. */ static cycle_t read_cont_rotime(struct clocksource *cs) { Loading Loading @@ -186,81 +189,99 @@ void handle_watchdog_bite(struct pt_regs *regs) #endif } /* * timer_interrupt() needs to keep up the real-time clock, * as well as call the "xtime_update()" routine every clocktick. */ extern void cris_do_profile(struct pt_regs *regs); extern void cris_profile_sample(struct pt_regs *regs); static void __iomem *timer_base; static inline irqreturn_t timer_interrupt(int irq, void *dev_id) static void crisv32_clkevt_mode(enum clock_event_mode mode, struct clock_event_device *dev) { struct pt_regs *regs = get_irq_regs(); int cpu = smp_processor_id(); reg_timer_r_masked_intr masked_intr; reg_timer_rw_ack_intr ack_intr = { 0 }; /* Check if the timer interrupt is for us (a tmr0 int) */ masked_intr = REG_RD(timer, timer_regs[cpu], r_masked_intr); if (!masked_intr.tmr0) return IRQ_NONE; reg_timer_rw_tmr0_ctrl ctrl = { .op = regk_timer_hold, .freq = regk_timer_f100, }; /* Acknowledge the timer irq. */ ack_intr.tmr0 = 1; REG_WR(timer, timer_regs[cpu], rw_ack_intr, ack_intr); REG_WR(timer, timer_base, rw_tmr0_ctrl, ctrl); } /* Reset watchdog otherwise it resets us! */ reset_watchdog(); static int crisv32_clkevt_next_event(unsigned long evt, struct clock_event_device *dev) { reg_timer_rw_tmr0_ctrl ctrl = { .op = regk_timer_ld, .freq = regk_timer_f100, }; /* Update statistics. */ update_process_times(user_mode(regs)); REG_WR(timer, timer_base, rw_tmr0_div, evt); REG_WR(timer, timer_base, rw_tmr0_ctrl, ctrl); cris_do_profile(regs); /* Save profiling information */ ctrl.op = regk_timer_run; REG_WR(timer, timer_base, rw_tmr0_ctrl, ctrl); /* The master CPU is responsible for the time keeping. */ if (cpu != 0) return IRQ_HANDLED; return 0; } static irqreturn_t crisv32_timer_interrupt(int irq, void *dev_id) { struct clock_event_device *evt = dev_id; reg_timer_rw_tmr0_ctrl ctrl = { .op = regk_timer_hold, .freq = regk_timer_f100, }; reg_timer_rw_ack_intr ack = { .tmr0 = 1 }; reg_timer_r_masked_intr intr; intr = REG_RD(timer, timer_base, r_masked_intr); if (!intr.tmr0) return IRQ_NONE; REG_WR(timer, timer_base, rw_tmr0_ctrl, ctrl); REG_WR(timer, timer_base, rw_ack_intr, ack); reset_watchdog(); #ifdef CONFIG_SYSTEM_PROFILER cris_profile_sample(get_irq_regs()); #endif evt->event_handler(evt); /* Call the real timer interrupt handler */ xtime_update(1); return IRQ_HANDLED; } static struct clock_event_device crisv32_clockevent = { .name = "crisv32-timer", .rating = 300, .features = CLOCK_EVT_FEAT_ONESHOT, .set_mode = crisv32_clkevt_mode, .set_next_event = crisv32_clkevt_next_event, }; /* Timer is IRQF_SHARED so drivers can add stuff to the timer irq chain. */ static struct irqaction irq_timer = { .handler = timer_interrupt, .flags = IRQF_SHARED, .name = "timer" .handler = crisv32_timer_interrupt, .flags = IRQF_TIMER | IRQF_SHARED, .name = "crisv32-timer", .dev_id = &crisv32_clockevent, }; void __init cris_timer_init(void) static void __init crisv32_timer_init(void) { int cpu = smp_processor_id(); reg_timer_rw_tmr0_ctrl tmr0_ctrl = { 0 }; reg_timer_rw_tmr0_div tmr0_div = TIMER0_DIV; reg_timer_rw_intr_mask timer_intr_mask; reg_timer_rw_tmr0_ctrl ctrl = { .op = regk_timer_hold, .freq = regk_timer_f100, }; /* Setup the etrax timers. * Base frequency is 100MHz, divider 1000000 -> 100 HZ * We use timer0, so timer1 is free. * The trig timer is used by the fasttimer API if enabled. */ tmr0_ctrl.op = regk_timer_ld; tmr0_ctrl.freq = regk_timer_f100; REG_WR(timer, timer_regs[cpu], rw_tmr0_div, tmr0_div); REG_WR(timer, timer_regs[cpu], rw_tmr0_ctrl, tmr0_ctrl); /* Load */ tmr0_ctrl.op = regk_timer_run; REG_WR(timer, timer_regs[cpu], rw_tmr0_ctrl, tmr0_ctrl); /* Start */ REG_WR(timer, timer_base, rw_tmr0_ctrl, ctrl); /* Enable the timer irq. */ timer_intr_mask = REG_RD(timer, timer_regs[cpu], rw_intr_mask); timer_intr_mask = REG_RD(timer, timer_base, rw_intr_mask); timer_intr_mask.tmr0 = 1; REG_WR(timer, timer_regs[cpu], rw_intr_mask, timer_intr_mask); REG_WR(timer, timer_base, rw_intr_mask, timer_intr_mask); } void __init time_init(void) { reg_intr_vect_rw_mask intr_mask; int irq; int ret; /* Probe for the RTC and read it if it exists. * Before the RTC can be probed the loops_per_usec variable needs Loading @@ -270,17 +291,21 @@ void __init time_init(void) */ loops_per_usec = 50; /* Start CPU local timer. */ cris_timer_init(); irq = TIMER0_INTR_VECT; timer_base = (void __iomem *) regi_timer0; crisv32_timer_init(); crisv32_clockevent.cpumask = cpu_possible_mask; crisv32_clockevent.irq = irq; /* Enable the timer irq in global config. */ intr_mask = REG_RD_VECT(intr_vect, regi_irq, rw_mask, 1); intr_mask.timer0 = 1; REG_WR_VECT(intr_vect, regi_irq, rw_mask, 1, intr_mask); ret = setup_irq(irq, &irq_timer); if (ret) pr_warn("failed to setup irq %d\n", irq); /* Now actually register the timer irq handler that calls * timer_interrupt(). */ setup_irq(TIMER0_INTR_VECT, &irq_timer); clockevents_config_and_register(&crisv32_clockevent, CRISV32_TIMER_FREQ, 2, 0xffffffff); /* Enable watchdog if we should use one. */ Loading Loading
arch/cris/Kconfig +1 −0 Original line number Diff line number Diff line Loading @@ -55,6 +55,7 @@ config CRIS select IRQ_DOMAIN if ETRAX_ARCH_V32 select OF if ETRAX_ARCH_V32 select OF_EARLY_FLATTREE if ETRAX_ARCH_V32 select GENERIC_CLOCKEVENTS if ETRAX_ARCH_V32 config HZ int Loading
arch/cris/arch-v32/kernel/time.c +85 −60 Original line number Diff line number Diff line Loading @@ -8,6 +8,7 @@ #include <linux/timex.h> #include <linux/time.h> #include <linux/clocksource.h> #include <linux/clockchips.h> #include <linux/interrupt.h> #include <linux/swap.h> #include <linux/sched.h> Loading Loading @@ -36,6 +37,8 @@ /* Number of 763 counts before watchdog bites */ #define ETRAX_WD_CNT ((2*ETRAX_WD_HZ)/HZ + 1) #define CRISV32_TIMER_FREQ (100000000lu) /* Register the continuos readonly timer available in FS and ARTPEC-3. */ static cycle_t read_cont_rotime(struct clocksource *cs) { Loading Loading @@ -186,81 +189,99 @@ void handle_watchdog_bite(struct pt_regs *regs) #endif } /* * timer_interrupt() needs to keep up the real-time clock, * as well as call the "xtime_update()" routine every clocktick. */ extern void cris_do_profile(struct pt_regs *regs); extern void cris_profile_sample(struct pt_regs *regs); static void __iomem *timer_base; static inline irqreturn_t timer_interrupt(int irq, void *dev_id) static void crisv32_clkevt_mode(enum clock_event_mode mode, struct clock_event_device *dev) { struct pt_regs *regs = get_irq_regs(); int cpu = smp_processor_id(); reg_timer_r_masked_intr masked_intr; reg_timer_rw_ack_intr ack_intr = { 0 }; /* Check if the timer interrupt is for us (a tmr0 int) */ masked_intr = REG_RD(timer, timer_regs[cpu], r_masked_intr); if (!masked_intr.tmr0) return IRQ_NONE; reg_timer_rw_tmr0_ctrl ctrl = { .op = regk_timer_hold, .freq = regk_timer_f100, }; /* Acknowledge the timer irq. */ ack_intr.tmr0 = 1; REG_WR(timer, timer_regs[cpu], rw_ack_intr, ack_intr); REG_WR(timer, timer_base, rw_tmr0_ctrl, ctrl); } /* Reset watchdog otherwise it resets us! */ reset_watchdog(); static int crisv32_clkevt_next_event(unsigned long evt, struct clock_event_device *dev) { reg_timer_rw_tmr0_ctrl ctrl = { .op = regk_timer_ld, .freq = regk_timer_f100, }; /* Update statistics. */ update_process_times(user_mode(regs)); REG_WR(timer, timer_base, rw_tmr0_div, evt); REG_WR(timer, timer_base, rw_tmr0_ctrl, ctrl); cris_do_profile(regs); /* Save profiling information */ ctrl.op = regk_timer_run; REG_WR(timer, timer_base, rw_tmr0_ctrl, ctrl); /* The master CPU is responsible for the time keeping. */ if (cpu != 0) return IRQ_HANDLED; return 0; } static irqreturn_t crisv32_timer_interrupt(int irq, void *dev_id) { struct clock_event_device *evt = dev_id; reg_timer_rw_tmr0_ctrl ctrl = { .op = regk_timer_hold, .freq = regk_timer_f100, }; reg_timer_rw_ack_intr ack = { .tmr0 = 1 }; reg_timer_r_masked_intr intr; intr = REG_RD(timer, timer_base, r_masked_intr); if (!intr.tmr0) return IRQ_NONE; REG_WR(timer, timer_base, rw_tmr0_ctrl, ctrl); REG_WR(timer, timer_base, rw_ack_intr, ack); reset_watchdog(); #ifdef CONFIG_SYSTEM_PROFILER cris_profile_sample(get_irq_regs()); #endif evt->event_handler(evt); /* Call the real timer interrupt handler */ xtime_update(1); return IRQ_HANDLED; } static struct clock_event_device crisv32_clockevent = { .name = "crisv32-timer", .rating = 300, .features = CLOCK_EVT_FEAT_ONESHOT, .set_mode = crisv32_clkevt_mode, .set_next_event = crisv32_clkevt_next_event, }; /* Timer is IRQF_SHARED so drivers can add stuff to the timer irq chain. */ static struct irqaction irq_timer = { .handler = timer_interrupt, .flags = IRQF_SHARED, .name = "timer" .handler = crisv32_timer_interrupt, .flags = IRQF_TIMER | IRQF_SHARED, .name = "crisv32-timer", .dev_id = &crisv32_clockevent, }; void __init cris_timer_init(void) static void __init crisv32_timer_init(void) { int cpu = smp_processor_id(); reg_timer_rw_tmr0_ctrl tmr0_ctrl = { 0 }; reg_timer_rw_tmr0_div tmr0_div = TIMER0_DIV; reg_timer_rw_intr_mask timer_intr_mask; reg_timer_rw_tmr0_ctrl ctrl = { .op = regk_timer_hold, .freq = regk_timer_f100, }; /* Setup the etrax timers. * Base frequency is 100MHz, divider 1000000 -> 100 HZ * We use timer0, so timer1 is free. * The trig timer is used by the fasttimer API if enabled. */ tmr0_ctrl.op = regk_timer_ld; tmr0_ctrl.freq = regk_timer_f100; REG_WR(timer, timer_regs[cpu], rw_tmr0_div, tmr0_div); REG_WR(timer, timer_regs[cpu], rw_tmr0_ctrl, tmr0_ctrl); /* Load */ tmr0_ctrl.op = regk_timer_run; REG_WR(timer, timer_regs[cpu], rw_tmr0_ctrl, tmr0_ctrl); /* Start */ REG_WR(timer, timer_base, rw_tmr0_ctrl, ctrl); /* Enable the timer irq. */ timer_intr_mask = REG_RD(timer, timer_regs[cpu], rw_intr_mask); timer_intr_mask = REG_RD(timer, timer_base, rw_intr_mask); timer_intr_mask.tmr0 = 1; REG_WR(timer, timer_regs[cpu], rw_intr_mask, timer_intr_mask); REG_WR(timer, timer_base, rw_intr_mask, timer_intr_mask); } void __init time_init(void) { reg_intr_vect_rw_mask intr_mask; int irq; int ret; /* Probe for the RTC and read it if it exists. * Before the RTC can be probed the loops_per_usec variable needs Loading @@ -270,17 +291,21 @@ void __init time_init(void) */ loops_per_usec = 50; /* Start CPU local timer. */ cris_timer_init(); irq = TIMER0_INTR_VECT; timer_base = (void __iomem *) regi_timer0; crisv32_timer_init(); crisv32_clockevent.cpumask = cpu_possible_mask; crisv32_clockevent.irq = irq; /* Enable the timer irq in global config. */ intr_mask = REG_RD_VECT(intr_vect, regi_irq, rw_mask, 1); intr_mask.timer0 = 1; REG_WR_VECT(intr_vect, regi_irq, rw_mask, 1, intr_mask); ret = setup_irq(irq, &irq_timer); if (ret) pr_warn("failed to setup irq %d\n", irq); /* Now actually register the timer irq handler that calls * timer_interrupt(). */ setup_irq(TIMER0_INTR_VECT, &irq_timer); clockevents_config_and_register(&crisv32_clockevent, CRISV32_TIMER_FREQ, 2, 0xffffffff); /* Enable watchdog if we should use one. */ Loading