HRT support in Samsung S5P Platform
Subsystems (3)
PATCH 1/1 HRT support in Samsung S5P Platform
From: Madhav Singh <[email protected]>
Date: Mon, 19 Jul 2010 10:51:01 +0530
Subject: [PATCH] HRT support in Samsung Tree
This patch implements HRT support for Samsung plat-s5p. RTC has been used as CLOCKEVENT and SYSTIMER as CLOCKSOURCE.
--- arch/arm/mach-s5pv210/Kconfig | 9 + arch/arm/mach-s5pv210/include/mach/map.h | 4 + arch/arm/plat-s5p/clock.c | 15 + arch/arm/plat-s5p/cpu.c | 8 + arch/arm/plat-s5p/hr-time-rtc.c | 470 +++++++++++++++++++++++ arch/arm/plat-s5p/include/plat/regs-sys-timer.h | 63 +++ arch/arm/plat-samsung/include/plat/map-base.h | 2 + 7 files changed, 571 insertions(+), 0 deletions(-) create mode 100644 arch/arm/plat-s5p/hr-time-rtc.c create mode 100644 arch/arm/plat-s5p/include/plat/regs-sys-timer.h
arch/arm/mach-s5pv210/Kconfig +9 -0
@@ -101,4 +101,13 @@ config MACH_SMDKC110 Machine support for Samsung SMDKC110 S5PC110(MCP) is one of package option of S5PV210 +config MACH_S5PV210_HRT + bool "HRtimer and Dynamic Tick support" + select GENERIC_TIME + select GENERIC_CLOCKEVENTS + select HIGH_RES_TIMERS + default n + help + Support for HRtimer and Dynamic Tick system using RTC and SYSTEM timer + endif
arch/arm/mach-s5pv210/include/mach/map.h +4 -0
@@ -42,6 +42,10 @@#define S5P_PA_TIMER S5PV210_PA_TIMER#define S5PV210_PA_SYSTIMER (0xE2600000) +/*For RTC*/ +#define S5PC11X_PA_RTC (0xE2800000) +#define S3C_PA_RTC S5PC11X_PA_RTC +#define S5PV210_PA_WATCHDOG (0xE2700000)
arch/arm/plat-s5p/clock.c +15 -0
@@ -89,6 +89,19 @@ struct clk clk_arm = { .ctrlbit = 0, }; +/*For HRT*/ +struct clk clk_ext_xtal_rtc = { + .name ="XrtcXTI" , + .id =-1 , + .rate =32768 , +}; + +struct clk clk_ext_xtal_usb = { + .name ="XusbXTI" , + .id =-1 , + .rate =24000000 , +}; +/* Possible clock sources for APLL Mux */ static struct clk *clk_src_apll_list[] = { [0 ] = &clk_fin_apll,
@@ -149,6 +162,8 @@ static struct clk *s5p_clks[] __initdata = { &clk_arm, &clk_vpll, &clk_xusbxti, + &clk_ext_xtal_usb, + &clk_ext_xtal_rtc, };void __init s5p_register_clocks (unsigned long xtal_freq)
arch/arm/plat-s5p/cpu.c +8 -0
@@ -104,6 +104,14 @@ static struct map_desc s5p_iodesc[] __initdata = { .length = SZ_4K, .type = MT_DEVICE, }, +#if defined(CONFIG_MACH_S5PV210_HRT ) + { + .virtual = (unsigned long)S3C_VA_RTC, + .pfn = __phys_to_pfn(S3C_PA_RTC), + .length = SZ_4K, + .type = MT_DEVICE, + }, +#endif };/* read cpu identification code */
arch/arm/plat-s5p/hr-time-rtc.c new file +470 -0
470 lines not on this page · raw message
arch/arm/plat-s5p/include/plat/regs-sys-timer.h new file +63 -0
63 lines not on this page · raw message
arch/arm/plat-samsung/include/plat/map-base.h +2 -0
@@ -36,6 +36,8 @@#define S3C_VA_TIMER S3C_ADDR(0x00300000)/* timer block */ #define S3C_VA_WATCHDOG S3C_ADDR(0x00400000)/* watchdog */ #define S3C_VA_UART S3C_ADDR(0x01000000)/* UART */ +/*For RTC*/ +#define S3C_VA_RTC S3C_ADDR(0x00c00000)/* This is used for the CPU specific mappings that may be needed, so that * they do not need to directly used S3C_ADDR() and thus make it easier to
Signature · 1 line
1.6.0.4
PATCH 1/1 HRT support in Samsung S5P Platform
Quoted 78 lines · MADHAV SINGHCHAUHAN
From: Madhav Singh<[email protected]>
Date: Mon, 19 Jul 2010 10:51:01 +0530
Subject: [PATCH] HRT support in Samsung Tree
This patch implements HRT support for Samsung plat-s5p. RTC has been used as CLOCKEVENT and SYSTIMER as CLOCKSOURCE.Signed-off-by Madhav Chauhan<[email protected]>Signed-off-by Kyungmin Park<[email protected]>--- arch/arm/mach-s5pv210/Kconfig | 9 + arch/arm/mach-s5pv210/include/mach/map.h | 4 + arch/arm/plat-s5p/clock.c | 15 + arch/arm/plat-s5p/cpu.c | 8 + arch/arm/plat-s5p/hr-time-rtc.c | 470 +++++++++++++++++++++++ arch/arm/plat-s5p/include/plat/regs-sys-timer.h | 63 +++ arch/arm/plat-samsung/include/plat/map-base.h | 2 + 7 files changed, 571 insertions(+), 0 deletions(-)create mode 100644
arch/arm/plat-s5p/hr-time-rtc.ccreate mode 100644arch/arm/plat-s5p/include/plat/regs-sys-timer.harch/arm/mach-s5pv210/Kconfig +9
-0@@ -101,4 +101,13 @@ config MACH_SMDKC110 Machine support for Samsung SMDKC110 S5PC110(MCP) is one of package option of S5PV210 +config MACH_S5PV210_HRT + bool "HRtimer and Dynamic Tick support" + select GENERIC_TIME + select GENERIC_CLOCKEVENTS + select HIGH_RES_TIMERS + default n + help + Support for HRtimer and Dynamic Tick system using RTC and SYSTEM timer + endifarch/arm/mach-s5pv210/include/mach/map.h +4
-0@@ -42,6 +42,10 @@#define S5P_PA_TIMER S5PV210_PA_TIMER#define S5PV210_PA_SYSTIMER (0xE2600000) +/*For RTC*/ +#define S5PC11X_PA_RTC (0xE2800000) +#define S3C_PA_RTC S5PC11X_PA_RTC +#define S5PV210_PA_WATCHDOG (0xE2700000)arch/arm/plat-s5p/clock.c +13
-0@@ -89,6 +89,19 @@ struct clk clk_arm = { .ctrlbit = 0, }; +/*For HRT*/ +struct clk clk_ext_xtal_rtc = { + .name ="XrtcXTI" , + .id =-1 , + .rate =32768 , +}; + +struct clk clk_ext_xtal_usb = { + .name ="XusbXTI" , + .id =-1 , + .rate =24000000 , +}; +/* Possible clock sources for APLL Mux */ static struct clk *clk_src_apll_list[] = { [0 ] =&clk_fin_apll,
arch/arm/plat-s5p/clock.c static struct clk *s5p_clks[] __initdata = { · line 166
Quoted 5 lines
arch/arm/plat-s5p/clock.c +2
-0@@ -149,6 +162,8 @@ static struct clk *s5p_clks[] __initdata = { &clk_arm, &clk_vpll, &clk_xusbxti, + &clk_ext_xtal_usb, + &clk_ext_xtal_rtc,
I think you've invented clk_ext_xtal_usb which is already being used to feed the usb phyd.
Do we need the XrtcXTI as iirc, this has to be 32.768KHz?
Quoted 176 lines
arch/arm/plat-s5p/clock.c +0
-0};void __init s5p_register_clocks (unsigned long xtal_freq)arch/arm/plat-s5p/cpu.c +8
-0@@ -104,6 +104,14 @@ static struct map_desc s5p_iodesc[] __initdata = { .length = SZ_4K, .type = MT_DEVICE, }, +#if defined(CONFIG_MACH_S5PV210_HRT ) + { + .virtual = (unsigned long)S3C_VA_RTC, + .pfn = __phys_to_pfn(S3C_PA_RTC), + .length = SZ_4K, + .type = MT_DEVICE, + }, +#endif };/* read cpu identification code */ arch/arm/plat-s5p/hr-time-rtc.c new file +148
-0@@ -0,0 +1,470 @@ +/* +* linux/arch/arm/plat-s5p/hr-time-rtc.c +* +* S5PC11X Timers +* +* Copyright (c) 2006 Samsung Electronics +* Copyright (c) 2010 Samsung Electronics Madhav Chauhan<[email protected]> +* +* +* S5PC11X (and compatible) HRT support using RTC and SYSTEM TIMER +* +* 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, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/delay.h> +#include <linux/interrupt.h> +#include <linux/sched.h> +#include <linux/spinlock.h> +#include <linux/clk.h> +#include <linux/err.h> +#include <linux/clocksource.h> +#include <linux/clockchips.h> +#include <linux/io.h> +#include <asm/system.h> +#include <mach/hardware.h> +#include <asm/irq.h> +#include <asm/mach/irq.h> +#include <asm/mach/time.h> +#include <asm/mach-types.h> +#include <mach/map.h> +#include <plat/regs-timer.h> +#include <plat/regs-rtc.h> +#include <plat/regs-sys-timer.h> +#include <mach/regs-irq.h> +#include <mach/tick.h> +#include <plat/clock.h> +#include <plat/cpu.h> + +/*For SCHED_CLOCK*/ +static unsigned long long time_stamp; +static unsigned long long s5pc11x_sched_timer_overflows; +static unsigned long long old_overflows; +static cycle_t last_ticks; + +/* Sched timer interrupt is not processed right after +* timer counter expired +*/ +static unsigned int pending_irq; + +/* sched_timer_running +* 0 : sched timer stopped or not initialized +* 1 : sched timer started +*/ +static unsigned int sched_timer_running; + +void __iomem *rtc_base =S3C_VA_RTC ; +static struct clk *clk_event; +static struct clk *clk_sched; +static int tick_timer_mode;/* 0: oneshot, 1: autoreload */ + +#define RTC_CLOCK (32768) +#define RTC_DEFAULT_TICK ((RTC_CLOCK / HZ) - 1) + +/* +* Helper functions +* s5pc11x_systimer_read() : Read from System timer register +* s5pc11x_systimer_write(): Write to System timer register +* +*/ +static unsigned int s5pc11x_systimer_read (unsigned int *reg_offset) +{ +return __raw_readl (reg_offset); +} + +static unsigned int s5pc11x_systimer_write (unsigned int *reg_offset, +unsigned int value) +{ +unsigned int temp_regs; + +__raw_writel (value, reg_offset); + +if (reg_offset ==S3C_SYSTIMER_TCON ) { +while (!(__raw_readl (S3C_SYSTIMER_INT_CSTAT )& +S3C_SYSTIMER_INT_TCON )); + temp_regs =__raw_readl (S3C_SYSTIMER_INT_CSTAT ); + temp_regs |=S3C_SYSTIMER_INT_TCON ; +__raw_writel (temp_regs,S3C_SYSTIMER_INT_CSTAT ); + + }else if (reg_offset ==S3C_SYSTIMER_ICNTB ) { +while (!(__raw_readl (S3C_SYSTIMER_INT_CSTAT )& +S3C_SYSTIMER_INT_ICNTB )); + temp_regs =__raw_readl (S3C_SYSTIMER_INT_CSTAT ); + temp_regs |=S3C_SYSTIMER_INT_ICNTB ; +__raw_writel (temp_regs,S3C_SYSTIMER_INT_CSTAT ); + + }else if (reg_offset ==S3C_SYSTIMER_TCNTB ) { +while (!(__raw_readl (S3C_SYSTIMER_INT_CSTAT )& +S3C_SYSTIMER_INT_TCNTB )); + temp_regs =__raw_readl (S3C_SYSTIMER_INT_CSTAT ); + temp_regs |=S3C_SYSTIMER_INT_TCNTB ; +__raw_writel (temp_regs,S3C_SYSTIMER_INT_CSTAT ); + } + +return 0 ; +} + +static void s5pc11x_rtc_set_tick (int enabled) +{ +unsigned int tmp; + + tmp =__raw_readl (rtc_base +S3C2410_RTCCON )& ~S3C_RTCCON_TICEN ; +if (enabled) + tmp |=S3C_RTCCON_TICEN ; +__raw_writel (tmp, rtc_base +S3C2410_RTCCON ); +} + +static void s5pc11x_tick_timer_setup (void ); + +static void s5pc11x_tick_timer_start (unsigned long load_val, +int autoreset) +{ +unsigned int tmp; + + tmp =__raw_readl (rtc_base +S3C2410_RTCCON )& + ~(S3C_RTCCON_TICEN |S3C2410_RTCCON_RTCEN ); +__raw_writel (tmp, rtc_base +S3C2410_RTCCON ); + +__raw_writel (load_val, rtc_base +S3C2410_TICNT ); + + tmp |=S3C_RTCCON_TICEN ; + +__raw_writel (tmp, rtc_base +S3C2410_RTCCON ); +} +
arch/arm/plat-s5p/hr-time-rtc.c line 158
Quoted 10 lines
arch/arm/plat-s5p/hr-time-rtc.c new file +10
-0+static void s5pc11x_tick_timer_stop (void ) +{ +unsigned int tmp; + + tmp =__raw_readl (rtc_base +S3C2410_RTCCON )& + ~(S3C_RTCCON_TICEN |S3C2410_RTCCON_RTCEN ); + +__raw_writel (tmp, rtc_base +S3C2410_RTCCON ); + +}
Will have to think about the cross usage against the rtc driver.
Quoted 197 lines
arch/arm/plat-s5p/hr-time-rtc.c new file +197
-0+static void s5pc11x_sched_timer_start (unsigned long load_val, +int autoreset) +{ +unsigned long tcon; +unsigned long tcnt; +unsigned long tcfg; + +/* clock configuration setting and enable */ +struct clk *clk; + + tcnt =TICK_MAX ;/* default value for tcnt */ + +/* initialize system timer clock */ + tcfg =s5pc11x_systimer_read (S3C_SYSTIMER_TCFG ); + + tcfg&= ~S3C_SYSTIMER_TCLK_MASK ; + tcfg |=S3C_SYSTIMER_TCLK_USB ; + +s5pc11x_systimer_write (S3C_SYSTIMER_TCFG , tcfg); + +/* TCFG must not be changed at run-time. +* If you want to change TCFG, stop timer(TCON[0] = 0) +*/ +s5pc11x_systimer_write (S3C_SYSTIMER_TCON ,0 ); + +/* read the current timer configuration bits */ + tcon =s5pc11x_systimer_read (S3C_SYSTIMER_TCON ); + tcfg =s5pc11x_systimer_read (S3C_SYSTIMER_TCFG ); + + clk =clk_get (NULL ,"systimer" ); +if (IS_ERR (clk)) +panic ("failed to get clock[%s] for system timer" ,"systimer" ); + +clk_enable (clk); + +clk_put (clk); + + tcfg&= ~S3C_SYSTIMER_TCLK_MASK ; + tcfg |=S3C_SYSTIMER_TCLK_USB ; + tcfg&= ~S3C_SYSTIMER_PRESCALER_MASK ; + +/* check to see if timer is within 16bit range... */ +if (tcnt>TICK_MAX ) { +panic ("setup_timer: cannot configure timer!" ); +return ; + } + +s5pc11x_systimer_write (S3C_SYSTIMER_TCFG , tcfg); + +s5pc11x_systimer_write (S3C_SYSTIMER_TCNTB , tcnt); + +/* set timer con */ + tcon =S3C_SYSTIMER_INT_AUTO |S3C_SYSTIMER_START | +S3C_SYSTIMER_AUTO_RELOAD ; +s5pc11x_systimer_write (S3C_SYSTIMER_TCON , tcon); + + tcon |=S3C_SYSTIMER_INT_START ; +s5pc11x_systimer_write (S3C_SYSTIMER_TCON , tcon); + +/* Interrupt Start and Enable */ +s5pc11x_systimer_write (S3C_SYSTIMER_INT_CSTAT , + (S3C_SYSTIMER_INT_ICNTEIE | +S3C_SYSTIMER_INT_EN )); + sched_timer_running =1 ; +} + +/* +* RTC tick : count down to zero, interrupt, reload +*/ +static int s5pc11x_tick_set_next_event (unsigned long cycles, +struct clock_event_device *evt) +{ +if (cycles ==0 )/* Should be larger than 0 */ + cycles =1 ; +s5pc11x_tick_timer_start (cycles,0 ); +return 0 ; +} + +static void s5pc11x_tick_set_mode (enum clock_event_mode mode, +struct clock_event_device *evt) +{ +switch (mode) { +case CLOCK_EVT_MODE_PERIODIC : + tick_timer_mode =1 ; +break ; +case CLOCK_EVT_MODE_ONESHOT : +s5pc11x_tick_timer_stop (); + tick_timer_mode =0 ; +break ; +case CLOCK_EVT_MODE_UNUSED : +case CLOCK_EVT_MODE_SHUTDOWN : +/* Sched timer stopped */ + sched_timer_running =0 ; +/* Reset sched_clock variables after sleep/wakeup */ + last_ticks =0 ; + s5pc11x_sched_timer_overflows =0 ; + old_overflows =0 ; + pending_irq =0 ; +break ; +case CLOCK_EVT_MODE_RESUME : +s5pc11x_tick_timer_setup (); +s5pc11x_sched_timer_start (~0 ,1 ); +break ; + } +} + +static struct clock_event_device clockevent_tick_timer = { + .name ="S5PC110 event timer" , + .features =CLOCK_EVT_FEAT_PERIODIC |CLOCK_EVT_FEAT_ONESHOT , + .shift =32 , + .set_next_event = s5pc11x_tick_set_next_event, + .set_mode = s5pc11x_tick_set_mode, +}; + +irqreturn_t s5pc11x_tick_timer_interrupt (int irq,void *dev_id) +{ +struct clock_event_device *evt =&clockevent_tick_timer; + +__raw_writel (S3C_INTP_TIC , rtc_base +S3C_INTP ); +/* In case of oneshot mode */ +if (tick_timer_mode ==0 ) +s5pc11x_tick_timer_stop (); + + evt->event_handler (evt); + +return IRQ_HANDLED ; +} + +static struct irqaction s5pc11x_tick_timer_irq = { + .name ="rtc-tick" , + .flags =IRQF_DISABLED |IRQF_TIMER |IRQF_IRQPOLL , + .handler = s5pc11x_tick_timer_interrupt, +}; + +static void s5pc11x_init_dynamic_tick_timer (unsigned long rate) +{ + tick_timer_mode =1 ; + +s5pc11x_tick_timer_stop (); + +s5pc11x_tick_timer_start ((rate /HZ ) -1 ,1 ); + + clockevent_tick_timer.mult =div_sc (rate,NSEC_PER_SEC , + clockevent_tick_timer.shift); + clockevent_tick_timer.max_delta_ns = +clockevent_delta2ns (-1 ,&clockevent_tick_timer); + clockevent_tick_timer.min_delta_ns = +clockevent_delta2ns (1 ,&clockevent_tick_timer); + + clockevent_tick_timer.cpumask =cpumask_of (0 ); +clockevents_register_device (&clockevent_tick_timer); + +printk (KERN_INFO "mult[%u]\n" , clockevent_tick_timer.mult); +printk (KERN_INFO "max_delta_ns[%u]\n" , clockevent_tick_timer.max_delta_ns); +printk (KERN_INFO "min_delta_ns[%u]\n" , clockevent_tick_timer.min_delta_ns); +printk (KERN_INFO "rate[%lu]\n" , rate); +printk (KERN_INFO "HZ[%d]\n" ,HZ ); +} + + +/* +* --------------------------------------------------------------------------- +* SYSTEM TIMER ... free running 32-bit clock source and scheduler clock +* --------------------------------------------------------------------------- +*/ +irqreturn_t s5pc11x_sched_timer_interrupt (int irq,void *dev_id) +{ +volatile unsigned int temp_cstat; + + temp_cstat =s5pc11x_systimer_read (S3C_SYSTIMER_INT_CSTAT ); + temp_cstat |=S3C_SYSTIMER_INT_STATS ; + +s5pc11x_systimer_write (S3C_SYSTIMER_INT_CSTAT , temp_cstat); + +if (unlikely (pending_irq)) + pending_irq =0 ; +else + s5pc11x_sched_timer_overflows++; + +return IRQ_HANDLED ; +} + +struct irqaction s5pc11x_systimer_irq = { + .name ="System timer" , + .flags =IRQF_DISABLED , + .handler = s5pc11x_sched_timer_interrupt, +}; + + +static cycle_t s5pc11x_sched_timer_read (void ) +{ +return (cycle_t )~__raw_readl (S3C_SYSTIMER_TCNTO ); +} + +struct clocksource clocksource_s5pc11x = { + .name ="clock_source_systimer" , + .rating =300 ,
arch/arm/plat-s5p/hr-time-rtc.c line 366
Quoted 10 lines
arch/arm/plat-s5p/hr-time-rtc.c new file +10
-0+ .read = s5pc11x_sched_timer_read, + .mask = CLOCKSOURCE_MASK(32), + .shift = 20, + .flags = CLOCK_SOURCE_IS_CONTINUOUS, +}; + +static void s5pc11x_init_clocksource (unsigned long rate) +{ +static char err[]__initdata =KERN_ERR +"%s: can't register clocksource!\n" ;
yuck
Quoted 103 lines
arch/arm/plat-s5p/hr-time-rtc.c new file +103
-0+ clocksource_s5pc11x.mult + =clocksource_khz2mult (rate/1000 , clocksource_s5pc11x.shift); + + +s5pc11x_sched_timer_start (~0 ,1 ); + +if (clocksource_register (&clocksource_s5pc11x)) +printk (err, clocksource_s5pc11x.name); +} + +/* +* Returns current time from boot in nsecs. It's OK for this to wrap +* around for now, as it's just a relative time stamp. +*/ +unsigned long long sched_clock (void ) +{ +unsigned long irq_flags; +cycle_t ticks, elapsed_ticks =0 ; +unsigned long long increment =0 ; +unsigned int overflow_cnt =0 ; + +local_irq_save (irq_flags); + +if (likely (sched_timer_running)) { + overflow_cnt = (s5pc11x_sched_timer_overflows - old_overflows); + + ticks =s5pc11x_sched_timer_read (); + +if (overflow_cnt) { + increment = (overflow_cnt -1 ) * + (clocksource_cyc2ns (clocksource_s5pc11x.mask, + clocksource_s5pc11x.mult, clocksource_s5pc11x.shift)); + elapsed_ticks = (clocksource_s5pc11x.mask - last_ticks) + ticks; + }else { +if (unlikely (last_ticks> ticks)) { + pending_irq =1 ; + elapsed_ticks = (clocksource_s5pc11x.mask - last_ticks) + ticks; + s5pc11x_sched_timer_overflows++; + }else { + elapsed_ticks = (ticks - last_ticks); + } + } + + time_stamp += (clocksource_cyc2ns (elapsed_ticks, clocksource_s5pc11x.mult, clocksource_s5pc11x.shift) + increment); + + old_overflows = s5pc11x_sched_timer_overflows; + last_ticks = ticks; + } +local_irq_restore (irq_flags); + +return time_stamp; +} + +/* +* Event/Sched Timer initialization +*/ +static void s5pc11x_timer_setup (void ) +{ +unsigned long rate; +/* Setup event timer using XrtcXTI */ +if (clk_event ==NULL ) + clk_event =clk_get (NULL ,"XrtcXTI" ); +if (IS_ERR (clk_event)) +panic ("failed to get clock for event timer" ); + rate =clk_get_rate (clk_event); +s5pc11x_init_dynamic_tick_timer (rate); + +/* Setup sched-timer using XusbXTI */ +if (clk_sched ==NULL ) + clk_sched =clk_get (NULL ,"XusbXTI" ); +if (IS_ERR (clk_sched)) +panic ("failed to get clock for sched-timer" ); + rate =clk_get_rate (clk_sched); +s5pc11x_init_clocksource (rate); +} + +static void s5pc11x_tick_timer_setup (void ) +{ +unsigned long rate; + + rate =clk_get_rate (clk_event); +s5pc11x_tick_timer_start ((rate /HZ ) -1 ,1 ); +} + +static void __init s5pc11x_timer_init (void ) +{ +/* Initialize variables before starting each timers */ + last_ticks =0 ; + s5pc11x_sched_timer_overflows =0 ; + old_overflows =0 ; + time_stamp =0 ; + sched_timer_running =0 ; + pending_irq =0 ; +s5pc11x_timer_setup (); +setup_irq (IRQ_RTC_TIC ,&s5pc11x_tick_timer_irq); +setup_irq (IRQ_SYSTIMER ,&s5pc11x_systimer_irq); +} + + +struct sys_timer s3c24xx_timer = { + .init = s5pc11x_timer_init, +}; +
Signature · 3 lines
Ben Dooks, Design & Software Engineer, Simtec Electronics http://www.simtec.co.uk/
PATCH 1/1 HRT support in Samsung S5P Platform
In reply to MADHAV SINGHCHAUHANQuoted 9 lines · MADHAV SINGHCHAUHAN
From: Madhav Singh <[email protected]>
Date: Mon, 19 Jul 2010 10:51:01 +0530
Subject: [PATCH] HRT support in Samsung Tree
This patch implements HRT support for Samsung plat-s5p. RTC has been used as CLOCKEVENT and SYSTIMER as CLOCKSOURCE.Signed-off-by Madhav Chauhan <[email protected]>Signed-off-by Kyungmin Park <[email protected]>
Hi,
I'd like to say to MADHAV and Kyungmin....
Actually, your patch(code) is same with my team's code in git(git.kernel.org, kki_ap, 2.6.29-samsung, arch/arm/plat-s5pc11x/hr-time-rtc.c)
But I couldn't find any credits or comments about that.
If you copy some code from somewhere, please add credits and comments about that.
It's very important.
Review
Quoted 101 lines
--- arch/arm/mach-s5pv210/Kconfig | 9 + arch/arm/mach-s5pv210/include/mach/map.h | 4 + arch/arm/plat-s5p/clock.c | 15 + arch/arm/plat-s5p/cpu.c | 8 + arch/arm/plat-s5p/hr-time-rtc.c | 470 +++++++++++++++++++++++ arch/arm/plat-s5p/include/plat/regs-sys-timer.h | 63 +++ arch/arm/plat-samsung/include/plat/map-base.h | 2 + 7 files changed, 571 insertions(+), 0 deletions(-) create mode 100644 arch/arm/plat-s5p/hr-time-rtc.c create mode 100644 arch/arm/plat-s5p/include/plat/regs-sys-timer.harch/arm/mach-s5pv210/Kconfig +8
-0@@ -101,4 +101,13 @@ config MACH_SMDKC110 Machine support for Samsung SMDKC110 S5PC110(MCP) is one of package option of S5PV210 +config MACH_S5PV210_HRT + bool "HRtimer and Dynamic Tick support" + select GENERIC_TIME + select GENERIC_CLOCKEVENTS + select HIGH_RES_TIMERS + default n + help + Support for HRtimer and Dynamic Tick system using RTC andSYSTEM timer
arch/arm/mach-s5pv210/Kconfig +1
-0+ endifarch/arm/mach- renamed from arch/arm/mach-s5pv210/include/mach/map.h +0
-0
s5pv210/include/mach/map.h
index 17687f0..fd8e504 100644arch/arm/mach-s5pv210/include/mach/map.h +4
-0@@ -42,6 +42,10 @@#define S5P_PA_TIMER S5PV210_PA_TIMER#define S5PV210_PA_SYSTIMER (0xE2600000) +/*For RTC*/ +#define S5PC11X_PA_RTC (0xE2800000) +#define S3C_PA_RTC S5PC11X_PA_RTC +#define S5PV210_PA_WATCHDOG (0xE2700000)arch/arm/plat-s5p/clock.c +15
-0@@ -89,6 +89,19 @@ struct clk clk_arm = { .ctrlbit = 0, }; +/*For HRT*/ +struct clk clk_ext_xtal_rtc = { + .name ="XrtcXTI" , + .id =-1 , + .rate =32768 , +}; + +struct clk clk_ext_xtal_usb = { + .name ="XusbXTI" , + .id =-1 , + .rate =24000000 , +}; +/* Possible clock sources for APLL Mux */ static struct clk *clk_src_apll_list[] = { [0 ] = &clk_fin_apll,@@ -149,6 +162,8 @@ static struct clk *s5p_clks[] __initdata = { &clk_arm, &clk_vpll, &clk_xusbxti, + &clk_ext_xtal_usb, + &clk_ext_xtal_rtc, };void __init s5p_register_clocks (unsigned long xtal_freq)arch/arm/plat-s5p/cpu.c +8
-0@@ -104,6 +104,14 @@ static struct map_desc s5p_iodesc[] __initdata = { .length = SZ_4K, .type = MT_DEVICE, }, +#if defined(CONFIG_MACH_S5PV210_HRT ) + { + .virtual = (unsigned long)S3C_VA_RTC, + .pfn = __phys_to_pfn(S3C_PA_RTC), + .length = SZ_4K, + .type = MT_DEVICE, + }, +#endif };/* read cpu identification code */ (quoted diff) +0
-0
b/arch/arm/plat-s5p/hr-time-rtc.c
Quoted 22 lines
new file mode 100644
index 0000000..8decf4earch/arm/plat-s5p/hr-time-rtc.c new file +7
-0@@ -0,0 +1,470 @@ +/* +* linux/arch/arm/plat-s5p/hr-time-rtc.c +* +* S5PC11X Timers +* +* Copyright (c) 2006 Samsung Electronics +* Copyright (c) 2010 Samsung Electronics Madhav Chauhan <[email protected]>
+ *
+ *
+ * S5PC11X (and compatible) HRT support using RTC and SYSTEM TIMER
+ *
+ * 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.
+ *
Quoted 8 lines
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
USA
Quoted 158 lines
+ */
arch/arm/plat-s5p/hr-time-rtc.c new file +100
-0+ +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/delay.h> +#include <linux/interrupt.h> +#include <linux/sched.h> +#include <linux/spinlock.h> +#include <linux/clk.h> +#include <linux/err.h> +#include <linux/clocksource.h> +#include <linux/clockchips.h> +#include <linux/io.h> +#include <asm/system.h> +#include <mach/hardware.h> +#include <asm/irq.h> +#include <asm/mach/irq.h> +#include <asm/mach/time.h> +#include <asm/mach-types.h> +#include <mach/map.h> +#include <plat/regs-timer.h> +#include <plat/regs-rtc.h> +#include <plat/regs-sys-timer.h> +#include <mach/regs-irq.h> +#include <mach/tick.h> +#include <plat/clock.h> +#include <plat/cpu.h> + +/*For SCHED_CLOCK*/ +static unsigned long long time_stamp; +static unsigned long long s5pc11x_sched_timer_overflows; +static unsigned long long old_overflows; +static cycle_t last_ticks; + +/* Sched timer interrupt is not processed right after +* timer counter expired +*/ +static unsigned int pending_irq; + +/* sched_timer_running +* 0 : sched timer stopped or not initialized +* 1 : sched timer started +*/ +static unsigned int sched_timer_running; + +void __iomem *rtc_base =S3C_VA_RTC ; +static struct clk *clk_event; +static struct clk *clk_sched; +static int tick_timer_mode;/* 0: oneshot, 1: autoreload */ + +#define RTC_CLOCK (32768) +#define RTC_DEFAULT_TICK ((RTC_CLOCK / HZ) - 1) + +/* +* Helper functions +* s5pc11x_systimer_read() : Read from System timer register +* s5pc11x_systimer_write(): Write to System timer register +* +*/ +static unsigned int s5pc11x_systimer_read (unsigned int *reg_offset) +{ +return __raw_readl (reg_offset); +} + +static unsigned int s5pc11x_systimer_write (unsigned int *reg_offset, +unsigned int value) +{ +unsigned int temp_regs; + +__raw_writel (value, reg_offset); + +if (reg_offset ==S3C_SYSTIMER_TCON ) { +while (!(__raw_readl (S3C_SYSTIMER_INT_CSTAT ) & +S3C_SYSTIMER_INT_TCON )); + temp_regs =__raw_readl (S3C_SYSTIMER_INT_CSTAT ); + temp_regs |=S3C_SYSTIMER_INT_TCON ; +__raw_writel (temp_regs,S3C_SYSTIMER_INT_CSTAT ); + + }else if (reg_offset ==S3C_SYSTIMER_ICNTB ) { +while (!(__raw_readl (S3C_SYSTIMER_INT_CSTAT ) & +S3C_SYSTIMER_INT_ICNTB )); + temp_regs =__raw_readl (S3C_SYSTIMER_INT_CSTAT ); + temp_regs |=S3C_SYSTIMER_INT_ICNTB ; +__raw_writel (temp_regs,S3C_SYSTIMER_INT_CSTAT ); + + }else if (reg_offset ==S3C_SYSTIMER_TCNTB ) { +while (!(__raw_readl (S3C_SYSTIMER_INT_CSTAT ) & +S3C_SYSTIMER_INT_TCNTB )); + temp_regs =__raw_readl (S3C_SYSTIMER_INT_CSTAT ); + temp_regs |=S3C_SYSTIMER_INT_TCNTB ; +__raw_writel (temp_regs,S3C_SYSTIMER_INT_CSTAT ); + } + +return 0 ; +} + +static void s5pc11x_rtc_set_tick (int enabled) +{ +unsigned int tmp; + + tmp = __raw_readl(rtc_base + S3C2410_RTCCON) &~S3C_RTCCON_TICEN;
arch/arm/plat-s5p/hr-time-rtc.c new file +56
-0+if (enabled) + tmp |=S3C_RTCCON_TICEN ; +__raw_writel (tmp, rtc_base +S3C2410_RTCCON ); +} + +static void s5pc11x_tick_timer_setup (void ); + +static void s5pc11x_tick_timer_start (unsigned long load_val, +int autoreset) +{ +unsigned int tmp; + + tmp =__raw_readl (rtc_base +S3C2410_RTCCON ) & + ~(S3C_RTCCON_TICEN |S3C2410_RTCCON_RTCEN ); +__raw_writel (tmp, rtc_base +S3C2410_RTCCON ); + +__raw_writel (load_val, rtc_base +S3C2410_TICNT ); + + tmp |=S3C_RTCCON_TICEN ; + +__raw_writel (tmp, rtc_base +S3C2410_RTCCON ); +} + +static void s5pc11x_tick_timer_stop (void ) +{ +unsigned int tmp; + + tmp =__raw_readl (rtc_base +S3C2410_RTCCON ) & + ~(S3C_RTCCON_TICEN |S3C2410_RTCCON_RTCEN ); + +__raw_writel (tmp, rtc_base +S3C2410_RTCCON ); + +} + +static void s5pc11x_sched_timer_start (unsigned long load_val, +int autoreset) +{ +unsigned long tcon; +unsigned long tcnt; +unsigned long tcfg; + +/* clock configuration setting and enable */ +struct clk *clk; + + tcnt =TICK_MAX ;/* default value for tcnt */ + +/* initialize system timer clock */ + tcfg =s5pc11x_systimer_read (S3C_SYSTIMER_TCFG ); + + tcfg &= ~S3C_SYSTIMER_TCLK_MASK ; + tcfg |=S3C_SYSTIMER_TCLK_USB ; + +s5pc11x_systimer_write (S3C_SYSTIMER_TCFG , tcfg); + +/* TCFG must not be changed at run-time. +* If you want to change TCFG, stop timer(TCON[0] = 0)
arch/arm/plat-s5p/hr-time-rtc.c
Quoted 10 lines
arch/arm/plat-s5p/hr-time-rtc.c new file +10
-0+*/ +s5pc11x_systimer_write (S3C_SYSTIMER_TCON ,0 ); + +/* read the current timer configuration bits */ + tcon =s5pc11x_systimer_read (S3C_SYSTIMER_TCON ); + tcfg =s5pc11x_systimer_read (S3C_SYSTIMER_TCFG ); + + clk =clk_get (NULL ,"systimer" ); +if (IS_ERR (clk)) + panic("failed to get clock[%s] for system timer",
"systimer");
Quoted 126 lines
arch/arm/plat-s5p/hr-time-rtc.c new file +77
-0+ +clk_enable (clk); + +clk_put (clk); + + tcfg &= ~S3C_SYSTIMER_TCLK_MASK ; + tcfg |=S3C_SYSTIMER_TCLK_USB ; + tcfg &= ~S3C_SYSTIMER_PRESCALER_MASK ; + +/* check to see if timer is within 16bit range... */ +if (tcnt >TICK_MAX ) { +panic ("setup_timer: cannot configure timer!" ); +return ; + } + +s5pc11x_systimer_write (S3C_SYSTIMER_TCFG , tcfg); + +s5pc11x_systimer_write (S3C_SYSTIMER_TCNTB , tcnt); + +/* set timer con */ + tcon =S3C_SYSTIMER_INT_AUTO |S3C_SYSTIMER_START | +S3C_SYSTIMER_AUTO_RELOAD ; +s5pc11x_systimer_write (S3C_SYSTIMER_TCON , tcon); + + tcon |=S3C_SYSTIMER_INT_START ; +s5pc11x_systimer_write (S3C_SYSTIMER_TCON , tcon); + +/* Interrupt Start and Enable */ +s5pc11x_systimer_write (S3C_SYSTIMER_INT_CSTAT , + (S3C_SYSTIMER_INT_ICNTEIE | +S3C_SYSTIMER_INT_EN )); + sched_timer_running =1 ; +} + +/* +* RTC tick : count down to zero, interrupt, reload +*/ +static int s5pc11x_tick_set_next_event (unsigned long cycles, +struct clock_event_device *evt) +{ +if (cycles ==0 )/* Should be larger than 0 */ + cycles =1 ; +s5pc11x_tick_timer_start (cycles,0 ); +return 0 ; +} + +static void s5pc11x_tick_set_mode (enum clock_event_mode mode, +struct clock_event_device *evt) +{ +switch (mode) { +case CLOCK_EVT_MODE_PERIODIC : + tick_timer_mode =1 ; +break ; +case CLOCK_EVT_MODE_ONESHOT : +s5pc11x_tick_timer_stop (); + tick_timer_mode =0 ; +break ; +case CLOCK_EVT_MODE_UNUSED : +case CLOCK_EVT_MODE_SHUTDOWN : +/* Sched timer stopped */ + sched_timer_running =0 ; +/* Reset sched_clock variables after sleep/wakeup */ + last_ticks =0 ; + s5pc11x_sched_timer_overflows =0 ; + old_overflows =0 ; + pending_irq =0 ; +break ; +case CLOCK_EVT_MODE_RESUME : +s5pc11x_tick_timer_setup (); +s5pc11x_sched_timer_start (~0 ,1 ); +break ; + } +} + +static struct clock_event_device clockevent_tick_timer = { + .name ="S5PC110 event timer" , + .features = CLOCK_EVT_FEAT_PERIODIC |
CLOCK_EVT_FEAT_ONESHOT,arch/arm/plat-s5p/hr-time-rtc.c new file +45
-0+ .shift = 32, + .set_next_event = s5pc11x_tick_set_next_event, + .set_mode = s5pc11x_tick_set_mode, +}; + +irqreturn_t s5pc11x_tick_timer_interrupt (int irq,void *dev_id) +{ +struct clock_event_device *evt = &clockevent_tick_timer; + +__raw_writel (S3C_INTP_TIC , rtc_base +S3C_INTP ); +/* In case of oneshot mode */ +if (tick_timer_mode ==0 ) +s5pc11x_tick_timer_stop (); + + evt->event_handler (evt); + +return IRQ_HANDLED ; +} + +static struct irqaction s5pc11x_tick_timer_irq = { + .name ="rtc-tick" , + .flags =IRQF_DISABLED |IRQF_TIMER |IRQF_IRQPOLL , + .handler = s5pc11x_tick_timer_interrupt, +}; + +static void s5pc11x_init_dynamic_tick_timer (unsigned long rate) +{ + tick_timer_mode =1 ; + +s5pc11x_tick_timer_stop (); + +s5pc11x_tick_timer_start ((rate /HZ ) -1 ,1 ); + + clockevent_tick_timer.mult =div_sc (rate,NSEC_PER_SEC , + clockevent_tick_timer.shift); + clockevent_tick_timer.max_delta_ns = +clockevent_delta2ns (-1 , &clockevent_tick_timer); + clockevent_tick_timer.min_delta_ns = +clockevent_delta2ns (1 , &clockevent_tick_timer); + + clockevent_tick_timer.cpumask =cpumask_of (0 ); +clockevents_register_device (&clockevent_tick_timer); + +printk (KERN_INFO "mult[%u]\n" , clockevent_tick_timer.mult); + printk(KERN_INFO "max_delta_ns[%u]\n",clockevent_tick_timer.max_delta_ns);
arch/arm/plat-s5p/hr-time-rtc.c new file +1
-0+ printk(KERN_INFO "min_delta_ns[%u]\n",clockevent_tick_timer.min_delta_ns);
arch/arm/plat-s5p/hr-time-rtc.c
Quoted 7 lines
arch/arm/plat-s5p/hr-time-rtc.c new file +7
-0+printk (KERN_INFO "rate[%lu]\n" , rate); +printk (KERN_INFO "HZ[%d]\n" ,HZ ); +} + + +/* +*
---------------------------------------------------------------------------
Quoted 2 lines
+ * SYSTEM TIMER ... free running 32-bit clock source and scheduler clock
+ *
---------------------------------------------------------------------------
Quoted 36 lines
+ */
arch/arm/plat-s5p/hr-time-rtc.c new file +35
-0+irqreturn_t s5pc11x_sched_timer_interrupt (int irq,void *dev_id) +{ +volatile unsigned int temp_cstat; + + temp_cstat =s5pc11x_systimer_read (S3C_SYSTIMER_INT_CSTAT ); + temp_cstat |=S3C_SYSTIMER_INT_STATS ; + +s5pc11x_systimer_write (S3C_SYSTIMER_INT_CSTAT , temp_cstat); + +if (unlikely (pending_irq)) + pending_irq =0 ; +else + s5pc11x_sched_timer_overflows++; + +return IRQ_HANDLED ; +} + +struct irqaction s5pc11x_systimer_irq = { + .name ="System timer" , + .flags =IRQF_DISABLED , + .handler = s5pc11x_sched_timer_interrupt, +}; + + +static cycle_t s5pc11x_sched_timer_read (void ) +{ +return (cycle_t )~__raw_readl (S3C_SYSTIMER_TCNTO ); +} + +struct clocksource clocksource_s5pc11x = { + .name ="clock_source_systimer" , + .rating =300 , + .read = s5pc11x_sched_timer_read, + .mask =CLOCKSOURCE_MASK (32 ), + .shift =20 ,
arch/arm/plat-s5p/hr-time-rtc.c
Quoted 10 lines
arch/arm/plat-s5p/hr-time-rtc.c new file +10
-0+ .flags = CLOCK_SOURCE_IS_CONTINUOUS, +}; + +static void s5pc11x_init_clocksource (unsigned long rate) +{ +static char err[]__initdata =KERN_ERR +"%s: can't register clocksource!\n" ; + + clocksource_s5pc11x.mult + = clocksource_khz2mult(rate/1000,
clocksource_s5pc11x.shift);
Quoted 33 lines
arch/arm/plat-s5p/hr-time-rtc.c new file +23
-0+ + +s5pc11x_sched_timer_start (~0 ,1 ); + +if (clocksource_register (&clocksource_s5pc11x)) +printk (err, clocksource_s5pc11x.name); +} + +/* +* Returns current time from boot in nsecs. It's OK for this to wrap +* around for now, as it's just a relative time stamp. +*/ +unsigned long long sched_clock (void ) +{ +unsigned long irq_flags; +cycle_t ticks, elapsed_ticks =0 ; +unsigned long long increment =0 ; +unsigned int overflow_cnt =0 ; + +local_irq_save (irq_flags); + +if (likely (sched_timer_running)) { + overflow_cnt = (s5pc11x_sched_timer_overflows -
old_overflows);arch/arm/plat-s5p/hr-time-rtc.c new file +6
-0+ + ticks =s5pc11x_sched_timer_read (); + +if (overflow_cnt) { + increment = (overflow_cnt - 1) * +(clocksource_cyc2ns(clocksource_s5pc11x.mask,
arch/arm/plat-s5p/hr-time-rtc.c new file +1
-0+ clocksource_s5pc11x.mult,clocksource_s5pc11x.shift));
arch/arm/plat-s5p/hr-time-rtc.c
Quoted 1 line
arch/arm/plat-s5p/hr-time-rtc.c new file +1
-0+ elapsed_ticks = (clocksource_s5pc11x.mask -
last_ticks)
Review
Quoted 74 lines
+ ticks;
arch/arm/plat-s5p/hr-time-rtc.c new file +4
-0+ }else { +if (unlikely (last_ticks > ticks)) { + pending_irq =1 ; + elapsed_ticks = (clocksource_s5pc11x.mask -
last_ticks) + ticks;arch/arm/plat-s5p/hr-time-rtc.c new file +7
-0+ s5pc11x_sched_timer_overflows++; + }else { + elapsed_ticks = (ticks - last_ticks); + } + } + + time_stamp += (clocksource_cyc2ns(elapsed_ticks,clocksource_s5pc11x.mult, clocksource_s5pc11x.shift) + increment);
arch/arm/plat-s5p/hr-time-rtc.c new file +59
-0+ + old_overflows = s5pc11x_sched_timer_overflows; + last_ticks = ticks; + } +local_irq_restore (irq_flags); + +return time_stamp; +} + +/* +* Event/Sched Timer initialization +*/ +static void s5pc11x_timer_setup (void ) +{ +unsigned long rate; +/* Setup event timer using XrtcXTI */ +if (clk_event ==NULL ) + clk_event =clk_get (NULL ,"XrtcXTI" ); +if (IS_ERR (clk_event)) +panic ("failed to get clock for event timer" ); + rate =clk_get_rate (clk_event); +s5pc11x_init_dynamic_tick_timer (rate); + +/* Setup sched-timer using XusbXTI */ +if (clk_sched ==NULL ) + clk_sched =clk_get (NULL ,"XusbXTI" ); +if (IS_ERR (clk_sched)) +panic ("failed to get clock for sched-timer" ); + rate =clk_get_rate (clk_sched); +s5pc11x_init_clocksource (rate); +} + +static void s5pc11x_tick_timer_setup (void ) +{ +unsigned long rate; + + rate =clk_get_rate (clk_event); +s5pc11x_tick_timer_start ((rate /HZ ) -1 ,1 ); +} + +static void __init s5pc11x_timer_init (void ) +{ +/* Initialize variables before starting each timers */ + last_ticks =0 ; + s5pc11x_sched_timer_overflows =0 ; + old_overflows =0 ; + time_stamp =0 ; + sched_timer_running =0 ; + pending_irq =0 ; +s5pc11x_timer_setup (); +setup_irq (IRQ_RTC_TIC , &s5pc11x_tick_timer_irq); +setup_irq (IRQ_SYSTIMER , &s5pc11x_systimer_irq); +} + + +struct sys_timer s3c24xx_timer = { + .init = s5pc11x_timer_init, +}; +(quoted diff) +0
-0
b/arch/arm/plat-
Review
Quoted 70 lines
s5p/include/plat/regs-sys-timer.h
new file mode 100644
index 0000000..75e6267arch/arm/plat-s5p/include/plat/regs-sys-timer.h new file +63
-0@@ -0,0 +1,63 @@ +/* arch/arm/plat-s5pc1xx/include/plat/regs-sys-timer.h +* +* Copyright (c) 2008 Samsung Electronics +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* S5PC1XX System Timer configuration +*/ + +#ifndef __ASM_ARCH_REGS_SYS_TIMER_H +#define __ASM_ARCH_REGS_SYS_TIMER_H + +#define S3C_SYSTIMERREG (x) (S5P_VA_SYSTIMER + (x)) + +#define S3C_SYSTIMER_TCFG S3C_SYSTIMERREG(0x00) +#define S3C_SYSTIMER_TCON S3C_SYSTIMERREG(0x04) +#define S3C_SYSTIMER_TCNTB S3C_SYSTIMERREG(0x08) +#define S3C_SYSTIMER_TCNTO S3C_SYSTIMERREG(0x0c) + +#define S3C_SYSTIMER_TFCNTB S3C_SYSTIMERREG(0x10) +#define S3C_SYSTIMER_ICNTB S3C_SYSTIMERREG(0x18) +#define S3C_SYSTIMER_ICNTO S3C_SYSTIMERREG(0x1c) +#define S3C_SYSTIMER_INT_CSTAT S3C_SYSTIMERREG(0x20) + +/* Value for TCFG */ +#define S3C_SYSTIMER_TCLK_MASK (3<<12) +#define S3C_SYSTIMER_TCLK_XXTI (0<<12) +#define S3C_SYSTIMER_TCLK_RTC (1<<12) +#define S3C_SYSTIMER_TCLK_USB (2<<12) +#define S3C_SYSTIMER_TCLK_PCLK (3<<12) + +#define S3C_SYSTIMER_DIV_MASK (7<<8) +#define S3C_SYSTIMER_DIV_1 (0<<8) +#define S3C_SYSTIMER_DIV_2 (1<<8) +#define S3C_SYSTIMER_DIV_4 (2<<8) +#define S3C_SYSTIMER_DIV_8 (3<<8) +#define S3C_SYSTIMER_DIV_16 (4<<8) + +#define S3C_SYSTIMER_TARGET_HZ 200 +#define S3C_SYSTIMER_PRESCALER 5 +#define S3C_SYSTIMER_PRESCALER_MASK (0x3f<<0) + +/* value for TCON */ +#define S3C_SYSTIMER_INT_AUTO (1<<5) +#define S3C_SYSTIMER_INT_IMM (1<<4) +#define S3C_SYSTIMER_INT_START (1<<3) +#define S3C_SYSTIMER_AUTO_RELOAD (1<<2) +#define S3C_SYSTIMER_IMM_UPDATE (1<<1) +#define S3C_SYSTIMER_START (1<<0) + +/* Value for INT_CSTAT */ +#define S3C_SYSTIMER_INT_IWIE (1<<9) +#define S3C_SYSTIMER_INT_TWIE (1<<10) +#define S3C_SYSTIMER_INT_ICNTEIE (1<<6) +#define S3C_SYSTIMER_INT_TCON (1<<5) +#define S3C_SYSTIMER_INT_ICNTB (1<<4) +#define S3C_SYSTIMER_INT_TCNTB (1<<2) +#define S3C_SYSTIMER_INT_STATS (1<<1) +#define S3C_SYSTIMER_INT_EN (1<<0) + +#endif /* __ASM_ARCH_REGS_TIMER_H */ (quoted diff) +0
-0
b/arch/arm/plat-
arch/arm/plat-samsung/include/plat/map-base.h line 43
Quoted 13 lines
samsung/include/plat/map-base.h
index 250be31..ff766d9 100644arch/arm/plat-samsung/include/plat/map-base.h +2
-0@@ -36,6 +36,8 @@#define S3C_VA_TIMER S3C_ADDR(0x00300000)/* timer block */ #define S3C_VA_WATCHDOG S3C_ADDR(0x00400000)/* watchdog */ #define S3C_VA_UART S3C_ADDR(0x01000000)/* UART */ +/*For RTC*/ +#define S3C_VA_RTC S3C_ADDR(0x00c00000)/* This is used for the CPU specific mappings that may be needed, so that * they do not need to directly used S3C_ADDR() and thus make it easier
to
Quoted 3 lines
--
1.6.0.4
Thanks.
Best regards,
Kgene.
--
Kukjin Kim <[email protected]>, Senior Engineer, SW Solution Development Team, Samsung Electronics Co., Ltd.
PATCH 1/1 HRT support in Samsung S5P Platform
Quoted 15 lines · Kukjin Kim
Quoted 9 lines · MADHAV SINGHCHAUHAN
From: Madhav Singh <[email protected]>
Date: Mon, 19 Jul 2010 10:51:01 +0530
Subject: [PATCH] HRT support in Samsung Tree
This patch implements HRT support for Samsung plat-s5p. RTC has been used as CLOCKEVENT and SYSTIMER as CLOCKSOURCE.Signed-off-by Madhav Chauhan <[email protected]>Signed-off-by Kyungmin Park <[email protected]>Hi,
I'd like to say to MADHAV and Kyungmin....
Quoted 8 lines
Actually, your patch(code) is same with my team's code in
git(git.kernel.org, kki_ap, 2.6.29-samsung, arch/arm/plat-s5pc11x/hr-time-rtc.c)
But I couldn't find any credits or comments about that.If you copy some code from somewhere, please add credits and comments about that.
It's very important.
Right, it's my mistake can't check it. Madhav will add the credit and describe the original author.
I talked to Mr. Lee jaechul and get the permission to send the patch.
To Madhav,
Next time, Add the From: Jaechul Lee at commit message and signed-off-by.
Thank you,
Kyungmin Park
Quoted 701 lines
Quoted 101 lines
---
?arch/arm/mach-s5pv210/Kconfig ? ? ? ? ? ? ? ? ? | ? ?9 + ?arch/arm/mach-s5pv210/include/mach/map.h ? ? ? ?| ? ?4 + ?arch/arm/plat-s5p/clock.c ? ? ? ? ? ? ? ? ? ? ? | ? 15 + ?arch/arm/plat-s5p/cpu.c ? ? ? ? ? ? ? ? ? ? ? ? | ? ?8 + ?arch/arm/plat-s5p/hr-time-rtc.c ? ? ? ? ? ? ? ? | ?470+++++++++++++++++++++++
?arch/arm/plat-s5p/include/plat/regs-sys-timer.h | ? 63 +++ ?arch/arm/plat-samsung/include/plat/map-base.h ? | ? ?2 + ?7 files changed, 571 insertions(+), 0 deletions(-) ?create mode 100644arch/arm/plat-s5p/hr-time-rtc.c?create mode 100644arch/arm/plat-s5p/include/plat/regs-sys-timer.harch/arm/mach-s5pv210/Kconfig +0
-0@@ -101,4 +101,13 @@ config MACH_SMDKC110? ? ? ? Machine support for Samsung SMDKC110
? ? ? ? S5PC110(MCP) is one of package option of S5PV210+config
MACH_S5PV210_HRT
+ ? ? ? ?bool "HRtimer and Dynamic Tick support"
+ ? ? ? ?selectGENERIC_TIME
+ ? ? ? ?selectGENERIC_CLOCKEVENTS
+ ? ? ? ?selectHIGH_RES_TIMERS
+ ? ? ? ?default n
+ ? ? ? ?help
+ ? ? ? ? ?Support for HRtimer and Dynamic Tick system using RTC and SYSTEM timer
+
?endifarch/arm/mach- renamed from arch/arm/mach-s5pv210/include/mach/map.h +0
-0
s5pv210/include/mach/map.h
index 17687f0..fd8e504 100644arch/arm/mach-s5pv210/include/mach/map.h +0
-0@@ -42,6 +42,10 @@?#define
S5P_PA_TIMER? ? ? ?S5PV210_PA_TIMER?#define
S5PV210_PA_SYSTIMER?(0xE2600000)arch/arm/mach-s5pv210/include/mach/map.h +4
-0+/*For RTC*/ +#define S5PC11X_PA_RTC ? ? ? ? ? ? ? (0xE2800000) +#define S3C_PA_RTC ? ? ? ? ? S5PC11X_PA_RTC +?#define
S5PV210_PA_WATCHDOG?(0xE2700000)arch/arm/plat-s5p/clock.c +13
-0@@ -89,6 +89,19 @@ struct clk clk_arm = { ? ? ? .ctrlbit ? ? ? ?= 0, ?}; +/*For HRT*/ +struct clk clk_ext_xtal_rtc = { + ? ? .name ? ? ? ? ? = "XrtcXTI", + ? ? .id ? ? ? ? ? ? = -1, + ? ? .rate ? ? ? ? ? = 32768, +}; + +struct clk clk_ext_xtal_usb = { + ? ? .name ? ? ? ? ? = "XusbXTI", + ? ? .id ? ? ? ? ? ? = -1, + ? ? .rate ? ? ? ? ? = 24000000, +}; +?/* Possible clock sources for APLL Mux */
?static struct clk *clk_src_apll_list[] = {
? ? ? [0] =&clk_fin_apll,arch/arm/plat-s5p/clock.c +2
-0@@ -149,6 +162,8 @@ static struct clk *s5p_clks[] __initdata = { ? ? ? &clk_arm, ? ? ? &clk_vpll, ? ? ? &clk_xusbxti, + ? ? &clk_ext_xtal_usb, + ? ? &clk_ext_xtal_rtc, ?}; ?void __init s5p_register_clocks(unsigned long xtal_freq)arch/arm/plat-s5p/cpu.c +8
-0@@ -104,6 +104,14 @@ static struct map_desc s5p_iodesc[] __initdata = { ? ? ? ? ? ? ? .length ? ? ? ? = SZ_4K, ? ? ? ? ? ? ? .type ? ? ? ? ? = MT_DEVICE, ? ? ? }, +#if defined(CONFIG_MACH_S5PV210_HRT) + ? ? { + ? ? ? ? ? ? .virtual ? ? ? ?= (unsigned long)S3C_VA_RTC, + ? ? ? ? ? ? .pfn ? ? ? ? ? ?= __phys_to_pfn(S3C_PA_RTC), + ? ? ? ? ? ? .length ? ? ? ? = SZ_4K, + ? ? ? ? ? ? .type ? ? ? ? ? = MT_DEVICE, + ? ? }, +#endif ?};?/* read cpu identification code */
Review
Quoted 1 line
(quoted diff) +0
-0
b/arch/arm/plat-s5p/hr-time-rtc.cQuoted 22 lines
new file mode 100644
index 0000000..8decf4earch/arm/plat-s5p/hr-time-rtc.c new file +7
-0@@ -0,0 +1,470 @@ +/* +* linux/arch/arm/plat-s5p/hr-time-rtc.c +* +* S5PC11X Timers +* +* Copyright (c) 2006 Samsung Electronics +* Copyright (c) 2010 Samsung Electronics Madhav Chauhan <[email protected]>
+ *
+ *
+ * S5PC11X (and compatible) HRT support using RTC and SYSTEM TIMER
+ *
+ * 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.
+ *Quoted 8 lines
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA ?02111-1307USA
Quoted 158 lines
+ */
arch/arm/plat-s5p/hr-time-rtc.c new file +100
-0+ +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/delay.h> +#include <linux/interrupt.h> +#include <linux/sched.h> +#include <linux/spinlock.h> +#include <linux/clk.h> +#include <linux/err.h> +#include <linux/clocksource.h> +#include <linux/clockchips.h> +#include <linux/io.h> +#include <asm/system.h> +#include <mach/hardware.h> +#include <asm/irq.h> +#include <asm/mach/irq.h> +#include <asm/mach/time.h> +#include <asm/mach-types.h> +#include <mach/map.h> +#include <plat/regs-timer.h> +#include <plat/regs-rtc.h> +#include <plat/regs-sys-timer.h> +#include <mach/regs-irq.h> +#include <mach/tick.h> +#include <plat/clock.h> +#include <plat/cpu.h> + +/*For SCHED_CLOCK*/ +static unsigned long long time_stamp; +static unsigned long long s5pc11x_sched_timer_overflows; +static unsigned long long old_overflows; +static cycle_t last_ticks; + +/* Sched timer interrupt is not processed right after +* timer counter expired +*/ +static unsigned int pending_irq; + +/* sched_timer_running +* 0 : sched timer stopped or not initialized +* 1 : sched timer started +*/ +static unsigned int sched_timer_running; + +void __iomem *rtc_base = ? ? S3C_VA_RTC; +static struct clk *clk_event; +static struct clk *clk_sched; +static int tick_timer_mode; ?/* 0: oneshot, 1: autoreload */ + +#define RTC_CLOCK ? ? ? ? ? ?(32768) +#define RTC_DEFAULT_TICK ? ? ((RTC_CLOCK / HZ) - 1) + +/* +* Helper functions +* s5pc11x_systimer_read() : Read from System timer register +* s5pc11x_systimer_write(): Write to System timer register +* +*/ +static unsigned int s5pc11x_systimer_read (unsigned int *reg_offset) +{ + ? ? return __raw_readl(reg_offset); +} + +static unsigned int s5pc11x_systimer_write (unsigned int *reg_offset, + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? unsigned int value) +{ + ? ? unsigned int temp_regs; + + ? ? __raw_writel(value, reg_offset); + + ? ? if (reg_offset == S3C_SYSTIMER_TCON) { + ? ? ? ? ? ? while (!(__raw_readl(S3C_SYSTIMER_INT_CSTAT) & + ? ? ? ? ? ? ? ? ? ? ? ? ? ? S3C_SYSTIMER_INT_TCON)); + ? ? ? ? ? ? temp_regs = __raw_readl(S3C_SYSTIMER_INT_CSTAT); + ? ? ? ? ? ? temp_regs |= S3C_SYSTIMER_INT_TCON; + ? ? ? ? ? ? __raw_writel(temp_regs, S3C_SYSTIMER_INT_CSTAT); + + ? ? } else if (reg_offset == S3C_SYSTIMER_ICNTB) { + ? ? ? ? ? ? while (!(__raw_readl(S3C_SYSTIMER_INT_CSTAT) & + ? ? ? ? ? ? ? ? ? ? ? ? ? ? S3C_SYSTIMER_INT_ICNTB)); + ? ? ? ? ? ? temp_regs = __raw_readl(S3C_SYSTIMER_INT_CSTAT); + ? ? ? ? ? ? temp_regs |= S3C_SYSTIMER_INT_ICNTB; + ? ? ? ? ? ? __raw_writel(temp_regs, S3C_SYSTIMER_INT_CSTAT); + + ? ? } else if (reg_offset == S3C_SYSTIMER_TCNTB) { + ? ? ? ? ? ? while (!(__raw_readl(S3C_SYSTIMER_INT_CSTAT) & + ? ? ? ? ? ? ? ? ? ? ? ? ? ? S3C_SYSTIMER_INT_TCNTB)); + ? ? ? ? ? ? temp_regs = __raw_readl(S3C_SYSTIMER_INT_CSTAT); + ? ? ? ? ? ? temp_regs |= S3C_SYSTIMER_INT_TCNTB; + ? ? ? ? ? ? __raw_writel(temp_regs, S3C_SYSTIMER_INT_CSTAT); + ? ? } + + ? ? return 0; +} + +static void s5pc11x_rtc_set_tick (int enabled) +{ + ? ? unsigned int tmp; + + ? ? tmp = __raw_readl(rtc_base + S3C2410_RTCCON) &~S3C_RTCCON_TICEN;
+ ? ? if (enabled)
+ ? ? ? ? ? ? tmp |=S3C_RTCCON_TICEN;
+ ? ?__raw_writel(tmp, rtc_base + S3C2410_RTCCON);arch/arm/plat-s5p/hr-time-rtc.c new file +53
-0+} + +static void s5pc11x_tick_timer_setup (void ); + +static void s5pc11x_tick_timer_start (unsigned long load_val, + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? int autoreset) +{ + ? ? unsigned int tmp; + + ? ? tmp = __raw_readl(rtc_base + S3C2410_RTCCON) & + ? ? ? ? ? ? ~(S3C_RTCCON_TICEN | S3C2410_RTCCON_RTCEN); + ? ? __raw_writel(tmp, rtc_base + S3C2410_RTCCON); + + ? ? __raw_writel(load_val, rtc_base + S3C2410_TICNT); + + ? ? tmp |= S3C_RTCCON_TICEN; + + ? ? __raw_writel(tmp, rtc_base + S3C2410_RTCCON); +} + +static ?void s5pc11x_tick_timer_stop(void) +{ + ? ? unsigned int tmp; + + ? ? tmp = __raw_readl(rtc_base + S3C2410_RTCCON) & + ? ? ? ? ? ? ~(S3C_RTCCON_TICEN | S3C2410_RTCCON_RTCEN); + + ? ? __raw_writel(tmp, rtc_base + S3C2410_RTCCON); + +} + +static void s5pc11x_sched_timer_start (unsigned long load_val, + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? int autoreset) +{ + ? ? unsigned long tcon; + ? ? unsigned long tcnt; + ? ? unsigned long tcfg; + + ? ? /* clock configuration setting and enable */ + ? ? struct clk *clk; + + ? ? tcnt = TICK_MAX; ?/* default value for tcnt */ + + ? ? /* initialize system timer clock */ + ? ? tcfg = s5pc11x_systimer_read(S3C_SYSTIMER_TCFG); + + ? ? tcfg &= ~S3C_SYSTIMER_TCLK_MASK; + ? ? tcfg |= S3C_SYSTIMER_TCLK_USB; + + ? ? s5pc11x_systimer_write(S3C_SYSTIMER_TCFG, tcfg); + + ? ? /* TCFG must not be changed at run-time. +? ? ?* If you want to change TCFG, stop timer(TCON[0] = 0) arch/arm/plat-s5p/hr-time-rtc.c
Quoted 10 lines
arch/arm/plat-s5p/hr-time-rtc.c new file +10
-0+? ? ?*/ + ? ? s5pc11x_systimer_write(S3C_SYSTIMER_TCON, 0); + + ? ? /* read the current timer configuration bits */ + ? ? tcon = s5pc11x_systimer_read(S3C_SYSTIMER_TCON); + ? ? tcfg = s5pc11x_systimer_read(S3C_SYSTIMER_TCFG); + + ? ? clk = clk_get(NULL, "systimer"); + ? ? if (IS_ERR(clk)) + ? ? ? ? ? ? panic("failed to get clock[%s] for system timer","systimer");
Quoted 128 lines
arch/arm/plat-s5p/hr-time-rtc.c new file +77
-0+ + ? ? clk_enable(clk); + + ? ? clk_put(clk); + + ? ? tcfg &= ~S3C_SYSTIMER_TCLK_MASK; + ? ? tcfg |= S3C_SYSTIMER_TCLK_USB; + ? ? tcfg &= ~S3C_SYSTIMER_PRESCALER_MASK; + + ? ? /* check to see if timer is within 16bit range... */ + ? ? if (tcnt > TICK_MAX) { + ? ? ? ? ? ? panic("setup_timer: cannot configure timer!"); + ? ? ? ? ? ? return; + ? ? } + + ? ? s5pc11x_systimer_write(S3C_SYSTIMER_TCFG, tcfg); + + ? ? s5pc11x_systimer_write(S3C_SYSTIMER_TCNTB, tcnt); + + ? ? /* set timer con */ + ? ? tcon = ?S3C_SYSTIMER_INT_AUTO | S3C_SYSTIMER_START | + ? ? ? ? ? ? ? ? ? ? S3C_SYSTIMER_AUTO_RELOAD; + ? ? s5pc11x_systimer_write(S3C_SYSTIMER_TCON, tcon); + + ? ? tcon |= S3C_SYSTIMER_INT_START; + ? ? s5pc11x_systimer_write(S3C_SYSTIMER_TCON, tcon); + + ? ? /* Interrupt Start and Enable */ + ? ? s5pc11x_systimer_write(S3C_SYSTIMER_INT_CSTAT, + ? ? ? ? ? ? ? ? ? ? ? ? ? ? (S3C_SYSTIMER_INT_ICNTEIE | + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? S3C_SYSTIMER_INT_EN)); + ? ? sched_timer_running = 1; +} + +/* +* RTC tick : count down to zero, interrupt, reload +*/ +static int s5pc11x_tick_set_next_event (unsigned long cycles, + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?struct clock_event_device *evt) +{ + ? ? if ?(cycles == 0) ? ? ? /* Should be larger than 0 */ + ? ? ? ? ? ? cycles = 1; + ? ? s5pc11x_tick_timer_start(cycles, 0); + ? ? return 0; +} + +static void s5pc11x_tick_set_mode (enum clock_event_mode mode, + ? ? ? ? ? ? ? ? ? ? ? ? ? struct clock_event_device *evt) +{ + ? ? switch (mode) { + ? ? case CLOCK_EVT_MODE_PERIODIC: + ? ? ? ? ? ? tick_timer_mode = 1; + ? ? ? ? ? ? break; + ? ? case CLOCK_EVT_MODE_ONESHOT: + ? ? ? ? ? ? s5pc11x_tick_timer_stop(); + ? ? ? ? ? ? tick_timer_mode = 0; + ? ? ? ? ? ? break; + ? ? case CLOCK_EVT_MODE_UNUSED: + ? ? case CLOCK_EVT_MODE_SHUTDOWN: + ? ? ? ? ? ? /* Sched timer stopped */ + ? ? ? ? ? ? sched_timer_running = 0; + ? ? ? ? ? ? /* Reset sched_clock variables after sleep/wakeup */ + ? ? ? ? ? ? last_ticks = 0; + ? ? ? ? ? ? s5pc11x_sched_timer_overflows = 0; + ? ? ? ? ? ? old_overflows = 0; + ? ? ? ? ? ? pending_irq = 0; + ? ? ? ? ? ? break; + ? ? case CLOCK_EVT_MODE_RESUME: + ? ? ? ? ? ? s5pc11x_tick_timer_setup(); + ? ? ? ? ? ? s5pc11x_sched_timer_start(~0, 1); + ? ? ? ? ? ? break; + ? ? } +} + +static struct clock_event_device clockevent_tick_timer = { + ? ? .name ? ? ? ? ? = "S5PC110 event timer", + ? ? .features ? ? ? = CLOCK_EVT_FEAT_PERIODIC |
CLOCK_EVT_FEAT_ONESHOT,
+ ? ? .shift ? ? ? ? ?= 32,
+ ? ? .set_next_event =s5pc11x_tick_set_next_event,
+ ? ? .set_mode ? ? ? =s5pc11x_tick_set_mode,arch/arm/plat-s5p/hr-time-rtc.c new file +42
-0+}; + +irqreturn_t s5pc11x_tick_timer_interrupt (int irq,void *dev_id) +{ + ? ? struct clock_event_device *evt = &clockevent_tick_timer; + + ? ? __raw_writel(S3C_INTP_TIC, rtc_base + S3C_INTP); + ? ? /* In case of oneshot mode */ + ? ? if (tick_timer_mode == 0) + ? ? ? ? ? ? s5pc11x_tick_timer_stop(); + + ? ? evt->event_handler(evt); + + ? ? return IRQ_HANDLED; +} + +static struct irqaction s5pc11x_tick_timer_irq = { + ? ? .name ? ? ? ? ? = "rtc-tick", + ? ? .flags ? ? ? ? ?= IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, + ? ? .handler ? ? ? ?= s5pc11x_tick_timer_interrupt, +}; + +static void ?s5pc11x_init_dynamic_tick_timer(unsigned long rate) +{ + ? ? tick_timer_mode = 1; + + ? ? s5pc11x_tick_timer_stop(); + + ? ? s5pc11x_tick_timer_start((rate / HZ) - 1, 1); + + ? ? clockevent_tick_timer.mult = div_sc(rate, NSEC_PER_SEC, + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? clockevent_tick_timer.shift); + ? ? clockevent_tick_timer.max_delta_ns = + ? ? ? ? ? ? clockevent_delta2ns(-1, &clockevent_tick_timer); + ? ? clockevent_tick_timer.min_delta_ns = + ? ? ? ? ? ? clockevent_delta2ns(1, &clockevent_tick_timer); + + ? ? clockevent_tick_timer.cpumask = cpumask_of(0); + ? ? clockevents_register_device(&clockevent_tick_timer); + + ? ? printk(KERN_INFO "mult[%u]\n", clockevent_tick_timer.mult); + ? ? printk(KERN_INFO "max_delta_ns[%u]\n",clockevent_tick_timer.max_delta_ns);
+ ? ?printk(KERN_INFO "min_delta_ns[%u]\n", clockevent_tick_timer.min_delta_ns);
+ ? ?printk(KERN_INFO "rate[%lu]\n", rate);
+ ? ?printk(KERN_INFO "HZ[%d]\n", HZ);arch/arm/plat-s5p/hr-time-rtc.c line 82
Quoted 5 lines
arch/arm/plat-s5p/hr-time-rtc.c new file +5
-0+} + + +/* +* ---------------------------------------------------------------------------
Quoted 2 lines
+ * SYSTEM TIMER ... free running 32-bit clock source and scheduler clock
+ *---------------------------------------------------------------------------
Quoted 36 lines
+ */
arch/arm/plat-s5p/hr-time-rtc.c new file +35
-0+irqreturn_t s5pc11x_sched_timer_interrupt (int irq,void *dev_id) +{ + ? ? volatile unsigned int temp_cstat; + + ? ? temp_cstat = s5pc11x_systimer_read(S3C_SYSTIMER_INT_CSTAT); + ? ? temp_cstat |= S3C_SYSTIMER_INT_STATS; + + ? ? s5pc11x_systimer_write(S3C_SYSTIMER_INT_CSTAT, temp_cstat); + + ? ? if (unlikely(pending_irq)) + ? ? ? ? ? ? pending_irq = 0; + ? ? else + ? ? ? ? ? ? s5pc11x_sched_timer_overflows++; + + ? ? return IRQ_HANDLED; +} + +struct irqaction s5pc11x_systimer_irq = { + ? ? .name ? ? ? ? ? = "System timer", + ? ? .flags ? ? ? ? ?= IRQF_DISABLED , + ? ? .handler ? ? ? ?= s5pc11x_sched_timer_interrupt, +}; + + +static cycle_t s5pc11x_sched_timer_read (void ) +{ + ? ? return (cycle_t)~__raw_readl(S3C_SYSTIMER_TCNTO); +} + +struct clocksource clocksource_s5pc11x = { + ? ? .name ? ? ? ? ? = "clock_source_systimer", + ? ? .rating ? ? ? ? = 300, + ? ? .read ? ? ? ? ? = s5pc11x_sched_timer_read, + ? ? .mask ? ? ? ? ? = CLOCKSOURCE_MASK(32), + ? ? .shift ? ? ? ? ?= 20,arch/arm/plat-s5p/hr-time-rtc.c
Quoted 10 lines
arch/arm/plat-s5p/hr-time-rtc.c new file +10
-0+ ? ? .flags ? ? ? ? ?= CLOCK_SOURCE_IS_CONTINUOUS, +}; + +static void s5pc11x_init_clocksource (unsigned long rate) +{ + ? ? static char err[] __initdata = KERN_ERR + ? ? ? ? ? ? ? ? ? ? "%s: can't register clocksource!\n"; + + ? ? clocksource_s5pc11x.mult + ? ? ? ? ? ? = clocksource_khz2mult(rate/1000,clocksource_s5pc11x.shift);
Quoted 30 lines
arch/arm/plat-s5p/hr-time-rtc.c new file +23
-0+ + + ? ? s5pc11x_sched_timer_start(~0, 1); + + ? ? if (clocksource_register(&clocksource_s5pc11x)) + ? ? ? ? ? ? printk(err, clocksource_s5pc11x.name); +} + +/* +* Returns current time from boot in nsecs. It's OK for this to wrap +* around for now, as it's just a relative time stamp. +*/ +unsigned long long sched_clock (void ) +{ + ? ? unsigned long irq_flags; + ? ? cycle_t ticks, elapsed_ticks = 0; + ? ? unsigned long long increment = 0; + ? ? unsigned int overflow_cnt = 0; + + ? ? local_irq_save(irq_flags); + + ? ? if (likely(sched_timer_running)) { + ? ? ? ? ? ? overflow_cnt = (s5pc11x_sched_timer_overflows -
old_overflows);arch/arm/plat-s5p/hr-time-rtc.c new file +6
-0+ + ? ? ? ? ? ? ticks = s5pc11x_sched_timer_read(); + + ? ? ? ? ? ? if (overflow_cnt) { + ? ? ? ? ? ? ? ? ? ? increment = (overflow_cnt - 1) * +Quoted 4 lines
? ? ? (clocksource_cyc2ns(clocksource_s5pc11x.mask,
+ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? clocksource_s5pc11x.mult, clocksource_s5pc11x.shift));
+ ? ? ? ? ? ? ? ? ? ?elapsed_ticks= (clocksource_s5pc11x.mask -
last_ticks)Review
Quoted 74 lines
+ ticks;
+ ? ? ? ? ? ? } else {
+ ? ? ? ? ? ? ? ? ? ? if (unlikely(last_ticks > ticks)) {
+ ? ? ? ? ? ? ? ? ? ? ? ? ? ?pending_irq= 1;
+ ? ? ? ? ? ? ? ? ? ? ? ? ? ?elapsed_ticks= (clocksource_s5pc11x.mask -last_ticks) + ticks;
+ ? ? ? ? ? ? ? ? ? ? ? ? ? ? s5pc11x_sched_timer_overflows++;
+ ? ? ? ? ? ? ? ? ? ? } else {
+ ? ? ? ? ? ? ? ? ? ? ? ? ? ?elapsed_ticks= (ticks -last_ticks);
+ ? ? ? ? ? ? ? ? ? ? }
+ ? ? ? ? ? ? }
+
+ ? ? ? ? ? ?time_stamp+= (clocksource_cyc2ns(elapsed_ticks, clocksource_s5pc11x.mult, clocksource_s5pc11x.shift)+ increment);arch/arm/plat-s5p/hr-time-rtc.c new file +59
-0+ + ? ? ? ? ? ? old_overflows = s5pc11x_sched_timer_overflows; + ? ? ? ? ? ? last_ticks = ticks; + ? ? } + ? ? local_irq_restore(irq_flags); + + ? ? return time_stamp; +} + +/* +* ?Event/Sched Timer initialization +*/ +static void s5pc11x_timer_setup (void ) +{ + ? ? unsigned long rate; + ? ? /* Setup event timer using XrtcXTI */ + ? ? if (clk_event == NULL) + ? ? ? ? ? ? clk_event = clk_get(NULL, "XrtcXTI"); + ? ? if (IS_ERR(clk_event)) + ? ? ? ? ? ? panic("failed to get clock for event timer"); + ? ? rate = clk_get_rate(clk_event); + ? ? s5pc11x_init_dynamic_tick_timer(rate); + + ? ? /* Setup sched-timer using XusbXTI */ + ? ? if (clk_sched == NULL) + ? ? ? ? ? ? clk_sched = clk_get(NULL, "XusbXTI"); + ? ? if (IS_ERR(clk_sched)) + ? ? ? ? ? ? panic("failed to get clock for sched-timer"); + ? ? rate = clk_get_rate(clk_sched); + ? ? s5pc11x_init_clocksource(rate); +} + +static void s5pc11x_tick_timer_setup (void ) +{ + ? ? unsigned long rate; + + ? ? rate = clk_get_rate(clk_event); + ? ? s5pc11x_tick_timer_start((rate / HZ) - 1, 1); +} + +static void __init s5pc11x_timer_init (void ) +{ + ? ? /* Initialize variables before starting each timers */ + ? ? last_ticks = 0; + ? ? s5pc11x_sched_timer_overflows = 0; + ? ? old_overflows = 0; + ? ? time_stamp = 0; + ? ? sched_timer_running = 0; + ? ? pending_irq = 0; + ? ? s5pc11x_timer_setup(); + ? ? setup_irq(IRQ_RTC_TIC, &s5pc11x_tick_timer_irq); + ? ? setup_irq(IRQ_SYSTIMER, &s5pc11x_systimer_irq); +} + + +struct sys_timer s3c24xx_timer = { + ? ? .init ? ? ? ? ? = s5pc11x_timer_init, +}; +(quoted diff) +0
-0b/arch/arm/plat-
Review
Quoted 70 lines
s5p/include/plat/regs-sys-timer.h
new file mode 100644
index 0000000..75e6267arch/arm/plat-s5p/include/plat/regs-sys-timer.h new file +63
-0@@ -0,0 +1,63 @@ +/* arch/arm/plat-s5pc1xx/include/plat/regs-sys-timer.h +* +* Copyright (c) 2008 Samsung Electronics +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* S5PC1XX System Timer configuration +*/ + +#ifndef __ASM_ARCH_REGS_SYS_TIMER_H +#define __ASM_ARCH_REGS_SYS_TIMER_H + +#define S3C_SYSTIMERREG (x) ? ? ? ? ? (S5P_VA_SYSTIMER + (x)) + +#define S3C_SYSTIMER_TCFG ? ? ? ? ? ?S3C_SYSTIMERREG(0x00) +#define S3C_SYSTIMER_TCON ? ? ? ? ? ?S3C_SYSTIMERREG(0x04) +#define S3C_SYSTIMER_TCNTB ? ? ? ? ? S3C_SYSTIMERREG(0x08) +#define S3C_SYSTIMER_TCNTO ? ? ? ? ? S3C_SYSTIMERREG(0x0c) + +#define S3C_SYSTIMER_TFCNTB ? ? ? ? ?S3C_SYSTIMERREG(0x10) +#define S3C_SYSTIMER_ICNTB ? ? ? ? ? S3C_SYSTIMERREG(0x18) +#define S3C_SYSTIMER_ICNTO ? ? ? ? ? S3C_SYSTIMERREG(0x1c) +#define S3C_SYSTIMER_INT_CSTAT ? ? ? S3C_SYSTIMERREG(0x20) + +/* Value for TCFG */ +#define S3C_SYSTIMER_TCLK_MASK ? ? ? ? ? ? ? (3<<12) +#define S3C_SYSTIMER_TCLK_XXTI ? ? ? ? ? ? ? (0<<12) +#define S3C_SYSTIMER_TCLK_RTC ? ? ? ? ? ? ? ?(1<<12) +#define S3C_SYSTIMER_TCLK_USB ? ? ? ? ? ? ? ?(2<<12) +#define S3C_SYSTIMER_TCLK_PCLK ? ? ? ? ? ? ? (3<<12) + +#define S3C_SYSTIMER_DIV_MASK ? ? ? ? ? ? ? ?(7<<8) +#define S3C_SYSTIMER_DIV_1 ? ? ? ? ? (0<<8) +#define S3C_SYSTIMER_DIV_2 ? ? ? ? ? (1<<8) +#define S3C_SYSTIMER_DIV_4 ? ? ? ? ? (2<<8) +#define S3C_SYSTIMER_DIV_8 ? ? ? ? ? (3<<8) +#define S3C_SYSTIMER_DIV_16 ? ? ? ? ?(4<<8) + +#define S3C_SYSTIMER_TARGET_HZ ? ? ? ? ? ? ? 200 +#define S3C_SYSTIMER_PRESCALER ? ? ? ? ? ? ? 5 +#define S3C_SYSTIMER_PRESCALER_MASK ?(0x3f<<0) + +/* value for TCON */ +#define S3C_SYSTIMER_INT_AUTO ? ? ? ? ? ? ? ?(1<<5) +#define S3C_SYSTIMER_INT_IMM ? ? ? ? (1<<4) +#define S3C_SYSTIMER_INT_START ? ? ? ? ? ? ? (1<<3) +#define S3C_SYSTIMER_AUTO_RELOAD ? ? (1<<2) +#define S3C_SYSTIMER_IMM_UPDATE ? ? ? ? ? ? ?(1<<1) +#define S3C_SYSTIMER_START ? ? ? ? ? (1<<0) + +/* Value for INT_CSTAT */ +#define S3C_SYSTIMER_INT_IWIE ? ? ? ? ? ? ? ?(1<<9) +#define S3C_SYSTIMER_INT_TWIE ? ? ? ? ? ? ? ?(1<<10) +#define S3C_SYSTIMER_INT_ICNTEIE ? ? (1<<6) +#define S3C_SYSTIMER_INT_TCON ? ? ? ? ? ? ? ?(1<<5) +#define S3C_SYSTIMER_INT_ICNTB ? ? ? ? ? ? ? (1<<4) +#define S3C_SYSTIMER_INT_TCNTB ? ? ? ? ? ? ? (1<<2) +#define S3C_SYSTIMER_INT_STATS ? ? ? ? ? ? ? (1<<1) +#define S3C_SYSTIMER_INT_EN ? ? ? ? ?(1<<0) + +#endif /* ?__ASM_ARCH_REGS_TIMER_H */ (quoted diff) +0
-0b/arch/arm/plat-
Quoted 11 lines
samsung/include/plat/map-base.h
index 250be31..ff766d9 100644arch/arm/plat-samsung/include/plat/map-base.h +0
-0@@ -36,6 +36,8 @@?#define
S3C_VA_TIMERS3C_ADDR(0x00300000)? ?/* timer block */ ?#defineS3C_VA_WATCHDOG? ? ?S3C_ADDR(0x00400000) ? ?/* watchdog */ ?#defineS3C_VA_UART?S3C_ADDR(0x01000000) ? ?/* UART */arch/arm/plat-samsung/include/plat/map-base.h +2
-0+/*For RTC*/ +#define S3C_VA_RTC ? S3C_ADDR(0x00c00000)Quoted 2 lines
?/* This is used for the CPU specific mappings that may be needed, so that ? * they do not need to directly used
S3C_ADDR()and thus make it easierto
Quoted 3 lines
--
1.6.0.4Thanks.
Best regards,
Kgene.
--
Kukjin Kim <[email protected]>, Senior Engineer, SW Solution Development Team, Samsung Electronics Co., Ltd._______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel at lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
PATCH 1/1 HRT support in Samsung S5P Platform
Quoted 25 lines · Kyungmin Park
Quoted 15 lines · Kukjin Kim
Quoted 9 lines · MADHAV SINGHCHAUHAN
From: Madhav Singh <[email protected]>
Date: Mon, 19 Jul 2010 10:51:01 +0530
Subject: [PATCH] HRT support in Samsung Tree
This patch implements HRT support for Samsung plat-s5p. RTC has been used as CLOCKEVENT and SYSTIMER as CLOCKSOURCE.Signed-off-by Madhav Chauhan <[email protected]>Signed-off-by Kyungmin Park <[email protected]>Hi,
I'd like to say to MADHAV and Kyungmin....
Quoted 8 lines
Actually, your patch(code) is same with my team's code in
git(git.kernel.org, kki_ap, 2.6.29-samsung, arch/arm/plat-s5pc11x/hr-time-rtc.c)
But I couldn't find any credits or comments about that.If you copy some code from somewhere, please add credits and comments about that.
It's very important.
Quoted 7 lines
Right, it's my mistake can't check it. Madhav will add the credit and describe the original author.
I talked to Mr. Lee jaechul and get the permission to send the patch.To Madhav,
Next time, Add the From: Jaechul Lee at commit message and signed-off-by.
Actually it should be mentioned in the credits in source code itself if this submission
is not much more than cleanup and polish.
PATCH 1/1 HRT support in Samsung S5P Platform
In reply to MADHAV SINGHCHAUHANarch/arm/mach-s5pv210/Kconfig config MACH_SMDKC110 · line 109
Quoted 6 lines · MADHAV SINGHCHAUHAN
arch/arm/mach-s5pv210/Kconfig +6
-0+config MACH_S5PV210_HRT + bool "HRtimer and Dynamic Tick support" + select GENERIC_TIME + select GENERIC_CLOCKEVENTS + select HIGH_RES_TIMERS + default n
Please avoid 'default n'.
arch/arm/plat-s5p/hr-time-rtc.c line 70
Quoted 3 lines
arch/arm/plat-s5p/hr-time-rtc.c new file +3
-0+static unsigned int sched_timer_running; + +void __iomem *rtc_base =S3C_VA_RTC ;
static?