From 8f65873e47784a390949f0d61e5692dbf2a8253e Mon Sep 17 00:00:00 2001 From: Graf Yang Date: Tue, 18 Nov 2008 17:48:22 +0800 Subject: Blackfin arch: SMP supporting patchset: Blackfin kernel and memory management code Blackfin dual core BF561 processor can support SMP like features. https://docs.blackfin.uclinux.org/doku.php?id=linux-kernel:smp-like In this patch, we provide SMP extend to Blackfin kernel and memory management code Singed-off-by: Graf Yang Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu --- arch/blackfin/kernel/time.c | 114 ++++++++++++++++++++++++++++++-------------- 1 file changed, 79 insertions(+), 35 deletions(-) (limited to 'arch/blackfin/kernel/time.c') diff --git a/arch/blackfin/kernel/time.c b/arch/blackfin/kernel/time.c index eb235232045..06de2ce67a9 100644 --- a/arch/blackfin/kernel/time.c +++ b/arch/blackfin/kernel/time.c @@ -34,9 +34,11 @@ #include #include #include +#include #include #include +#include /* This is an NTP setting */ #define TICK_SIZE (tick_nsec / 1000) @@ -46,11 +48,14 @@ static unsigned long gettimeoffset(void); static struct irqaction bfin_timer_irq = { .name = "BFIN Timer Tick", +#ifdef CONFIG_IRQ_PER_CPU + .flags = IRQF_DISABLED | IRQF_PERCPU, +#else .flags = IRQF_DISABLED +#endif }; -static void -time_sched_init(irq_handler_t timer_routine) +void setup_core_timer(void) { u32 tcount; @@ -71,12 +76,41 @@ time_sched_init(irq_handler_t timer_routine) CSYNC(); bfin_write_TCNTL(7); +} + +#ifdef CONFIG_TICK_SOURCE_SYSTMR0 +void setup_system_timer0(void) +{ + /* Power down the core timer, just to play safe. */ + bfin_write_TCNTL(0); + + disable_gptimers(TIMER0bit); + set_gptimer_status(0, TIMER_STATUS_TRUN0); + while (get_gptimer_status(0) & TIMER_STATUS_TRUN0) + udelay(10); + + set_gptimer_config(0, 0x59); /* IRQ enable, periodic, PWM_OUT, SCLKed, OUT PAD disabled */ + set_gptimer_period(TIMER0_id, get_sclk() / HZ); + set_gptimer_pwidth(TIMER0_id, 1); + SSYNC(); + enable_gptimers(TIMER0bit); +} +#endif +static void +time_sched_init(irqreturn_t(*timer_routine) (int, void *)) +{ +#ifdef CONFIG_TICK_SOURCE_SYSTMR0 + setup_system_timer0(); +#else + setup_core_timer(); +#endif bfin_timer_irq.handler = (irq_handler_t)timer_routine; - /* call setup_irq instead of request_irq because request_irq calls - * kmalloc which has not been initialized yet - */ +#ifdef CONFIG_TICK_SOURCE_SYSTMR0 + setup_irq(IRQ_TIMER0, &bfin_timer_irq); +#else setup_irq(IRQ_CORETMR, &bfin_timer_irq); +#endif } /* @@ -87,17 +121,23 @@ static unsigned long gettimeoffset(void) unsigned long offset; unsigned long clocks_per_jiffy; +#ifdef CONFIG_TICK_SOURCE_SYSTMR0 + clocks_per_jiffy = bfin_read_TIMER0_PERIOD(); + offset = bfin_read_TIMER0_COUNTER() / \ + (((clocks_per_jiffy + 1) * HZ) / USEC_PER_SEC); + + if ((get_gptimer_status(0) & TIMER_STATUS_TIMIL0) && offset < (100000 / HZ / 2)) + offset += (USEC_PER_SEC / HZ); +#else clocks_per_jiffy = bfin_read_TPERIOD(); - offset = - (clocks_per_jiffy - - bfin_read_TCOUNT()) / (((clocks_per_jiffy + 1) * HZ) / - USEC_PER_SEC); + offset = (clocks_per_jiffy - bfin_read_TCOUNT()) / \ + (((clocks_per_jiffy + 1) * HZ) / USEC_PER_SEC); /* Check if we just wrapped the counters and maybe missed a tick */ if ((bfin_read_ILAT() & (1 << IRQ_CORETMR)) - && (offset < (100000 / HZ / 2))) + && (offset < (100000 / HZ / 2))) offset += (USEC_PER_SEC / HZ); - +#endif return offset; } @@ -120,34 +160,38 @@ irqreturn_t timer_interrupt(int irq, void *dummy) static long last_rtc_update; write_seqlock(&xtime_lock); - - do_timer(1); - - profile_tick(CPU_PROFILING); - - /* - * If we have an externally synchronized Linux clock, then update - * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be - * called as close as possible to 500 ms before the new second starts. - */ - - if (ntp_synced() && - xtime.tv_sec > last_rtc_update + 660 && - (xtime.tv_nsec / NSEC_PER_USEC) >= - 500000 - ((unsigned)TICK_SIZE) / 2 - && (xtime.tv_nsec / NSEC_PER_USEC) <= - 500000 + ((unsigned)TICK_SIZE) / 2) { - if (set_rtc_mmss(xtime.tv_sec) == 0) - last_rtc_update = xtime.tv_sec; - else - /* Do it again in 60s. */ - last_rtc_update = xtime.tv_sec - 600; +#ifdef CONFIG_TICK_SOURCE_SYSTMR0 + if (get_gptimer_status(0) & TIMER_STATUS_TIMIL0) { +#endif + do_timer(1); + + + /* + * If we have an externally synchronized Linux clock, then update + * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be + * called as close as possible to 500 ms before the new second starts. + */ + + if (ntp_synced() && + xtime.tv_sec > last_rtc_update + 660 && + (xtime.tv_nsec / NSEC_PER_USEC) >= + 500000 - ((unsigned)TICK_SIZE) / 2 + && (xtime.tv_nsec / NSEC_PER_USEC) <= + 500000 + ((unsigned)TICK_SIZE) / 2) { + if (set_rtc_mmss(xtime.tv_sec) == 0) + last_rtc_update = xtime.tv_sec; + else + /* Do it again in 60s. */ + last_rtc_update = xtime.tv_sec - 600; + } +#ifdef CONFIG_TICK_SOURCE_SYSTMR0 + set_gptimer_status(0, TIMER_STATUS_TIMIL0); } +#endif write_sequnlock(&xtime_lock); -#ifndef CONFIG_SMP update_process_times(user_mode(get_irq_regs())); -#endif + profile_tick(CPU_PROFILING); return IRQ_HANDLED; } -- cgit v1.2.3 From 1b047d8cc58f7f8b50fb9c80b131ef054f091f1b Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Tue, 18 Nov 2008 17:48:22 +0800 Subject: Blackfin arch: cleanup the time.c code - make the code a bit more readable - kill of warnings/ifdef mess a bit Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu --- arch/blackfin/kernel/time.c | 101 ++++++++++++++++---------------------------- 1 file changed, 36 insertions(+), 65 deletions(-) (limited to 'arch/blackfin/kernel/time.c') diff --git a/arch/blackfin/kernel/time.c b/arch/blackfin/kernel/time.c index 06de2ce67a9..2ed440b773d 100644 --- a/arch/blackfin/kernel/time.c +++ b/arch/blackfin/kernel/time.c @@ -1,32 +1,11 @@ /* - * File: arch/blackfin/kernel/time.c - * Based on: none - original work - * Author: + * arch/blackfin/kernel/time.c * - * Created: - * Description: This file contains the bfin-specific time handling details. - * Most of the stuff is located in the machine specific files. - * FIXME: (This file is subject for removal) + * This file contains the Blackfin-specific time handling details. + * Most of the stuff is located in the machine specific files. * - * Modified: - * Copyright 2004-2008 Analog Devices Inc. - * - * Bugs: Enter bugs at http://blackfin.uclinux.org/ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see the file COPYING, or write - * to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * Copyright 2004-2008 Analog Devices Inc. + * Licensed under the GPL-2 or later. */ #include @@ -43,18 +22,33 @@ /* This is an NTP setting */ #define TICK_SIZE (tick_nsec / 1000) -static void time_sched_init(irq_handler_t timer_routine); -static unsigned long gettimeoffset(void); - static struct irqaction bfin_timer_irq = { - .name = "BFIN Timer Tick", + .name = "Blackfin Timer Tick", #ifdef CONFIG_IRQ_PER_CPU - .flags = IRQF_DISABLED | IRQF_PERCPU, + .flags = IRQF_DISABLED | IRQF_PERCPU, #else .flags = IRQF_DISABLED #endif }; +#ifdef CONFIG_TICK_SOURCE_SYSTMR0 +void setup_system_timer0(void) +{ + /* Power down the core timer, just to play safe. */ + bfin_write_TCNTL(0); + + disable_gptimers(TIMER0bit); + set_gptimer_status(0, TIMER_STATUS_TRUN0); + while (get_gptimer_status(0) & TIMER_STATUS_TRUN0) + udelay(10); + + set_gptimer_config(0, 0x59); /* IRQ enable, periodic, PWM_OUT, SCLKed, OUT PAD disabled */ + set_gptimer_period(TIMER0_id, get_sclk() / HZ); + set_gptimer_pwidth(TIMER0_id, 1); + SSYNC(); + enable_gptimers(TIMER0bit); +} +#else void setup_core_timer(void) { u32 tcount; @@ -63,10 +57,8 @@ void setup_core_timer(void) bfin_write_TCNTL(1); CSYNC(); - /* - * the TSCALE prescaler counter. - */ - bfin_write_TSCALE((TIME_SCALE - 1)); + /* the TSCALE prescaler counter */ + bfin_write_TSCALE(TIME_SCALE - 1); tcount = ((get_cclk() / (HZ * TIME_SCALE)) - 1); bfin_write_TPERIOD(tcount); @@ -77,24 +69,6 @@ void setup_core_timer(void) bfin_write_TCNTL(7); } - -#ifdef CONFIG_TICK_SOURCE_SYSTMR0 -void setup_system_timer0(void) -{ - /* Power down the core timer, just to play safe. */ - bfin_write_TCNTL(0); - - disable_gptimers(TIMER0bit); - set_gptimer_status(0, TIMER_STATUS_TRUN0); - while (get_gptimer_status(0) & TIMER_STATUS_TRUN0) - udelay(10); - - set_gptimer_config(0, 0x59); /* IRQ enable, periodic, PWM_OUT, SCLKed, OUT PAD disabled */ - set_gptimer_period(TIMER0_id, get_sclk() / HZ); - set_gptimer_pwidth(TIMER0_id, 1); - SSYNC(); - enable_gptimers(TIMER0bit); -} #endif static void @@ -102,13 +76,11 @@ time_sched_init(irqreturn_t(*timer_routine) (int, void *)) { #ifdef CONFIG_TICK_SOURCE_SYSTMR0 setup_system_timer0(); -#else - setup_core_timer(); -#endif - bfin_timer_irq.handler = (irq_handler_t)timer_routine; -#ifdef CONFIG_TICK_SOURCE_SYSTMR0 + bfin_timer_irq.handler = timer_routine; setup_irq(IRQ_TIMER0, &bfin_timer_irq); #else + setup_core_timer(); + bfin_timer_irq.handler = timer_routine; setup_irq(IRQ_CORETMR, &bfin_timer_irq); #endif } @@ -116,14 +88,15 @@ time_sched_init(irqreturn_t(*timer_routine) (int, void *)) /* * Should return useconds since last timer tick */ +#ifndef CONFIG_GENERIC_TIME static unsigned long gettimeoffset(void) { unsigned long offset; unsigned long clocks_per_jiffy; #ifdef CONFIG_TICK_SOURCE_SYSTMR0 - clocks_per_jiffy = bfin_read_TIMER0_PERIOD(); - offset = bfin_read_TIMER0_COUNTER() / \ + clocks_per_jiffy = bfin_read_TIMER0_PERIOD(); + offset = bfin_read_TIMER0_COUNTER() / \ (((clocks_per_jiffy + 1) * HZ) / USEC_PER_SEC); if ((get_gptimer_status(0) & TIMER_STATUS_TIMIL0) && offset < (100000 / HZ / 2)) @@ -131,7 +104,7 @@ static unsigned long gettimeoffset(void) #else clocks_per_jiffy = bfin_read_TPERIOD(); offset = (clocks_per_jiffy - bfin_read_TCOUNT()) / \ - (((clocks_per_jiffy + 1) * HZ) / USEC_PER_SEC); + (((clocks_per_jiffy + 1) * HZ) / USEC_PER_SEC); /* Check if we just wrapped the counters and maybe missed a tick */ if ((bfin_read_ILAT() & (1 << IRQ_CORETMR)) @@ -140,6 +113,7 @@ static unsigned long gettimeoffset(void) #endif return offset; } +#endif static inline int set_rtc_mmss(unsigned long nowtime) { @@ -151,9 +125,8 @@ static inline int set_rtc_mmss(unsigned long nowtime) * as well as call the "do_timer()" routine every clocktick */ #ifdef CONFIG_CORE_TIMER_IRQ_L1 -irqreturn_t timer_interrupt(int irq, void *dummy)__attribute__((l1_text)); +__attribute__((l1_text)) #endif - irqreturn_t timer_interrupt(int irq, void *dummy) { /* last time the cmos clock got updated */ @@ -165,13 +138,11 @@ irqreturn_t timer_interrupt(int irq, void *dummy) #endif do_timer(1); - /* * If we have an externally synchronized Linux clock, then update * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be * called as close as possible to 500 ms before the new second starts. */ - if (ntp_synced() && xtime.tv_sec > last_rtc_update + 660 && (xtime.tv_nsec / NSEC_PER_USEC) >= -- cgit v1.2.3 From a1ee74ca09cb8c5929bab0b16e0c58e7c85b9414 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Wed, 7 Jan 2009 23:14:38 +0800 Subject: Blackfin arch: add __init markings to Blackfin timer init functions Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu --- arch/blackfin/kernel/time.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'arch/blackfin/kernel/time.c') diff --git a/arch/blackfin/kernel/time.c b/arch/blackfin/kernel/time.c index 2ed440b773d..ec4dfa38eb0 100644 --- a/arch/blackfin/kernel/time.c +++ b/arch/blackfin/kernel/time.c @@ -32,7 +32,7 @@ static struct irqaction bfin_timer_irq = { }; #ifdef CONFIG_TICK_SOURCE_SYSTMR0 -void setup_system_timer0(void) +void __init setup_system_timer0(void) { /* Power down the core timer, just to play safe. */ bfin_write_TCNTL(0); @@ -49,7 +49,7 @@ void setup_system_timer0(void) enable_gptimers(TIMER0bit); } #else -void setup_core_timer(void) +void __init setup_core_timer(void) { u32 tcount; @@ -71,7 +71,7 @@ void setup_core_timer(void) } #endif -static void +static void __init time_sched_init(irqreturn_t(*timer_routine) (int, void *)) { #ifdef CONFIG_TICK_SOURCE_SYSTMR0 -- cgit v1.2.3 From 6a01f230339321292cf065551f8cf55361052461 Mon Sep 17 00:00:00 2001 From: Yi Li Date: Wed, 7 Jan 2009 23:14:39 +0800 Subject: Blackfin arch: merge adeos blackfin part to arch/blackfin/ [Mike Frysinger : - handle bf531/bf532/bf534/bf536 variants in ipipe.h - cleanup IPIPE logic for bfin_set_irq_handler() - cleanup ipipe asm code a bit and add missing ENDPROC() - simplify IPIPE code in trap_c - unify some of the IPIPE code and fix style - simplify DO_IRQ_L1 handling with ipipe code - revert IRQ_SW_INT# addition from ipipe merge - remove duplicate get_{c,s}clk() prototypes ] Signed-off-by: Yi Li Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu --- arch/blackfin/kernel/time.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'arch/blackfin/kernel/time.c') diff --git a/arch/blackfin/kernel/time.c b/arch/blackfin/kernel/time.c index ec4dfa38eb0..172b4c58846 100644 --- a/arch/blackfin/kernel/time.c +++ b/arch/blackfin/kernel/time.c @@ -31,7 +31,7 @@ static struct irqaction bfin_timer_irq = { #endif }; -#ifdef CONFIG_TICK_SOURCE_SYSTMR0 +#if defined(CONFIG_TICK_SOURCE_SYSTMR0) || defined(CONFIG_IPIPE) void __init setup_system_timer0(void) { /* Power down the core timer, just to play safe. */ @@ -74,7 +74,7 @@ void __init setup_core_timer(void) static void __init time_sched_init(irqreturn_t(*timer_routine) (int, void *)) { -#ifdef CONFIG_TICK_SOURCE_SYSTMR0 +#if defined(CONFIG_TICK_SOURCE_SYSTMR0) || defined(CONFIG_IPIPE) setup_system_timer0(); bfin_timer_irq.handler = timer_routine; setup_irq(IRQ_TIMER0, &bfin_timer_irq); @@ -94,7 +94,7 @@ static unsigned long gettimeoffset(void) unsigned long offset; unsigned long clocks_per_jiffy; -#ifdef CONFIG_TICK_SOURCE_SYSTMR0 +#if defined(CONFIG_TICK_SOURCE_SYSTMR0) || defined(CONFIG_IPIPE) clocks_per_jiffy = bfin_read_TIMER0_PERIOD(); offset = bfin_read_TIMER0_COUNTER() / \ (((clocks_per_jiffy + 1) * HZ) / USEC_PER_SEC); @@ -133,7 +133,8 @@ irqreturn_t timer_interrupt(int irq, void *dummy) static long last_rtc_update; write_seqlock(&xtime_lock); -#ifdef CONFIG_TICK_SOURCE_SYSTMR0 +#if defined(CONFIG_TICK_SOURCE_SYSTMR0) && !defined(CONFIG_IPIPE) +/* FIXME: Here TIMIL0 is not set when IPIPE enabled, why? */ if (get_gptimer_status(0) & TIMER_STATUS_TIMIL0) { #endif do_timer(1); @@ -155,13 +156,17 @@ irqreturn_t timer_interrupt(int irq, void *dummy) /* Do it again in 60s. */ last_rtc_update = xtime.tv_sec - 600; } -#ifdef CONFIG_TICK_SOURCE_SYSTMR0 +#if defined(CONFIG_TICK_SOURCE_SYSTMR0) && !defined(CONFIG_IPIPE) set_gptimer_status(0, TIMER_STATUS_TIMIL0); } #endif write_sequnlock(&xtime_lock); +#ifdef CONFIG_IPIPE + update_root_process_times(get_irq_regs()); +#else update_process_times(user_mode(get_irq_regs())); +#endif profile_tick(CPU_PROFILING); return IRQ_HANDLED; -- cgit v1.2.3