[PATCH]HRT support in Samsung S5P Platform

Kyungmin Park kyungmin.park at samsung.com
Thu Jul 22 02:10:28 EDT 2010


On Wed, Jul 21, 2010 at 9:06 PM, Kukjin Kim <kgene.kim at samsung.com> wrote:
> MADHAV SINGHCHAUHAN wrote:
>>
>> From: Madhav Singh <singh.madhav at samsung.com>
>> 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 <singh.madhav at samsung.com>
>> Signed-off-by: Kyungmin Park <kyungmin.park at samsung.com>
>
> 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.

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
>
>> ---
>>  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
>>
>> diff --git a/arch/arm/mach-s5pv210/Kconfig b/arch/arm/mach-s5pv210/Kconfig
>> index 631019a..9d8698e 100644
>> --- a/arch/arm/mach-s5pv210/Kconfig
>> +++ b/arch/arm/mach-s5pv210/Kconfig
>> @@ -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
>> diff --git a/arch/arm/mach-s5pv210/include/mach/map.h b/arch/arm/mach-
>> s5pv210/include/mach/map.h
>> index 17687f0..fd8e504 100644
>> --- a/arch/arm/mach-s5pv210/include/mach/map.h
>> +++ b/arch/arm/mach-s5pv210/include/mach/map.h
>> @@ -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)
>>
>> diff --git a/arch/arm/plat-s5p/clock.c b/arch/arm/plat-s5p/clock.c
>> index b5e2552..1e2a6f4 100644
>> --- a/arch/arm/plat-s5p/clock.c
>> +++ b/arch/arm/plat-s5p/clock.c
>> @@ -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)
>> diff --git a/arch/arm/plat-s5p/cpu.c b/arch/arm/plat-s5p/cpu.c
>> index 75cb8c3..83ae862 100644
>> --- a/arch/arm/plat-s5p/cpu.c
>> +++ b/arch/arm/plat-s5p/cpu.c
>> @@ -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 */
>> diff --git a/arch/arm/plat-s5p/hr-time-rtc.c
> b/arch/arm/plat-s5p/hr-time-rtc.c
>> new file mode 100644
>> index 0000000..8decf4e
>> --- /dev/null
>> +++ b/arch/arm/plat-s5p/hr-time-rtc.c
>> @@ -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
>> <singh.madhav at samsung.com>
>> + *
>> + *
>> + * 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);
>> +}
>> +
>> +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)
>> +      */
>> +     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,
>> +     .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";
>> +
>> +     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,
>> +};
>> +
>> diff --git a/arch/arm/plat-s5p/include/plat/regs-sys-timer.h
> b/arch/arm/plat-
>> s5p/include/plat/regs-sys-timer.h
>> new file mode 100644
>> index 0000000..75e6267
>> --- /dev/null
>> +++ b/arch/arm/plat-s5p/include/plat/regs-sys-timer.h
>> @@ -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 */
>> diff --git a/arch/arm/plat-samsung/include/plat/map-base.h
> b/arch/arm/plat-
>> samsung/include/plat/map-base.h
>> index 250be31..ff766d9 100644
>> --- a/arch/arm/plat-samsung/include/plat/map-base.h
>> +++ b/arch/arm/plat-samsung/include/plat/map-base.h
>> @@ -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
>> --
>> 1.6.0.4
>>
>
>
> Thanks.
>
> Best regards,
> Kgene.
> --
> Kukjin Kim <kgene.kim at samsung.com>, 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
>



More information about the linux-arm-kernel mailing list