From 5cccd37ea15970846a93b4b01fafd6e043bafe8e Mon Sep 17 00:00:00 2001 From: dmitry pervushin Date: Thu, 23 Apr 2009 12:24:13 +0100 Subject: [ARM] 5477/1: Freescale STMP platform support [6/10] Sources: common STMP3xxx platform support Signed-off-by: dmitry pervushin Signed-off-by: Russell King --- arch/arm/plat-stmp3xxx/timer.c | 172 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 172 insertions(+) create mode 100644 arch/arm/plat-stmp3xxx/timer.c (limited to 'arch/arm/plat-stmp3xxx/timer.c') diff --git a/arch/arm/plat-stmp3xxx/timer.c b/arch/arm/plat-stmp3xxx/timer.c new file mode 100644 index 000000000000..c916068f0cab --- /dev/null +++ b/arch/arm/plat-stmp3xxx/timer.c @@ -0,0 +1,172 @@ +/* + * System timer for Freescale STMP37XX/STMP378X + * + * Embedded Alley Solutions, Inc + * + * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved. + */ + +/* + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +static irqreturn_t +stmp3xxx_timer_interrupt(int irq, void *dev_id) +{ + struct clock_event_device *c = dev_id; + + if (HW_TIMROT_TIMCTRLn_RD(0) & (1<<15)) { + HW_TIMROT_TIMCTRLn_CLR(0, (1<<15)); + c->event_handler(c); + } else if (HW_TIMROT_TIMCTRLn_RD(1) & (1<<15)) { + HW_TIMROT_TIMCTRLn_CLR(1, (1<<15)); + HW_TIMROT_TIMCTRLn_CLR(1, BM_TIMROT_TIMCTRLn_IRQ_EN); + HW_TIMROT_TIMCOUNTn_WR(1, 0xFFFF); + } + + return IRQ_HANDLED; +} + +static cycle_t stmp3xxx_clock_read(void) +{ + return ~((HW_TIMROT_TIMCOUNTn_RD(1) & 0xFFFF0000) >> 16); +} + +static int +stmp3xxx_timrot_set_next_event(unsigned long delta, + struct clock_event_device *dev) +{ + HW_TIMROT_TIMCOUNTn_WR(0, delta); /* reload */ + return 0; +} + +static void +stmp3xxx_timrot_set_mode(enum clock_event_mode mode, + struct clock_event_device *dev) +{ +} + +static struct clock_event_device ckevt_timrot = { + .name = "timrot", + .features = CLOCK_EVT_FEAT_ONESHOT, + .shift = 32, + .set_next_event = stmp3xxx_timrot_set_next_event, + .set_mode = stmp3xxx_timrot_set_mode, +}; + +static struct clocksource cksrc_stmp3xxx = { + .name = "cksrc_stmp3xxx", + .rating = 250, + .read = stmp3xxx_clock_read, + .mask = CLOCKSOURCE_MASK(16), + .shift = 10, + .flags = CLOCK_SOURCE_IS_CONTINUOUS, +}; + +static struct irqaction stmp3xxx_timer_irq = { + .name = "stmp3xxx_timer", + .flags = IRQF_DISABLED | IRQF_TIMER, + .handler = stmp3xxx_timer_interrupt, + .dev_id = &ckevt_timrot, +}; + + +/* + * Set up timer interrupt, and return the current time in seconds. + */ +static void __init stmp3xxx_init_timer(void) +{ + cksrc_stmp3xxx.mult = clocksource_hz2mult(CLOCK_TICK_RATE, + cksrc_stmp3xxx.shift); + ckevt_timrot.mult = div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC, + ckevt_timrot.shift); + ckevt_timrot.min_delta_ns = clockevent_delta2ns(2, &ckevt_timrot); + ckevt_timrot.max_delta_ns = clockevent_delta2ns(0xFFF, &ckevt_timrot); + ckevt_timrot.cpumask = cpumask_of(0); + + HW_TIMROT_ROTCTRL_CLR(BM_TIMROT_ROTCTRL_SFTRST | + BM_TIMROT_ROTCTRL_CLKGATE); + HW_TIMROT_TIMCOUNTn_WR(0, 0); + HW_TIMROT_TIMCOUNTn_WR(1, 0); + + HW_TIMROT_TIMCTRLn_WR(0, + (BF_TIMROT_TIMCTRLn_SELECT(8) | /* 32 kHz */ + BF_TIMROT_TIMCTRLn_PRESCALE(0) | + BM_TIMROT_TIMCTRLn_RELOAD | + BM_TIMROT_TIMCTRLn_UPDATE | + BM_TIMROT_TIMCTRLn_IRQ_EN)); + HW_TIMROT_TIMCTRLn_WR(1, + (BF_TIMROT_TIMCTRLn_SELECT(8) | /* 32 kHz */ + BF_TIMROT_TIMCTRLn_PRESCALE(0) | + BM_TIMROT_TIMCTRLn_RELOAD | + BM_TIMROT_TIMCTRLn_UPDATE)); + + HW_TIMROT_TIMCOUNTn_WR(0, CLOCK_TICK_RATE / HZ - 1); + HW_TIMROT_TIMCOUNTn_WR(1, 0xFFFF); /* reload */ + + setup_irq(IRQ_TIMER0, &stmp3xxx_timer_irq); + + clocksource_register(&cksrc_stmp3xxx); + clockevents_register_device(&ckevt_timrot); +} + +#ifdef CONFIG_PM + +void stmp3xxx_suspend_timer(void) +{ + HW_TIMROT_TIMCTRLn_CLR(0, BM_TIMROT_TIMCTRLn_IRQ_EN); + HW_TIMROT_TIMCTRLn_CLR(0, (1<<15)); + HW_TIMROT_ROTCTRL_SET(BM_TIMROT_ROTCTRL_CLKGATE); +} + +void stmp3xxx_resume_timer(void) +{ + HW_TIMROT_ROTCTRL_CLR(BM_TIMROT_ROTCTRL_SFTRST | + BM_TIMROT_ROTCTRL_CLKGATE); + + + HW_TIMROT_TIMCTRLn_WR(0, + (BF_TIMROT_TIMCTRLn_SELECT(8) | /* 32 kHz */ + BF_TIMROT_TIMCTRLn_PRESCALE(0) | + BM_TIMROT_TIMCTRLn_UPDATE | + BM_TIMROT_TIMCTRLn_IRQ_EN)); + HW_TIMROT_TIMCTRLn_WR(1, + (BF_TIMROT_TIMCTRLn_SELECT(8) | /* 32 kHz */ + BF_TIMROT_TIMCTRLn_PRESCALE(0) | + BM_TIMROT_TIMCTRLn_RELOAD | + BM_TIMROT_TIMCTRLn_UPDATE)); + + HW_TIMROT_TIMCOUNTn_WR(0, CLOCK_TICK_RATE / HZ - 1); + HW_TIMROT_TIMCOUNTn_WR(1, 0xFFFF); /* reload */ +} + +#else + +#define stmp3xxx_suspend_timer NULL +#define stmp3xxx_resume_timer NULL + +#endif /* CONFIG_PM */ + +struct sys_timer stmp3xxx_timer = { + .init = stmp3xxx_init_timer, + .suspend = stmp3xxx_suspend_timer, + .resume = stmp3xxx_resume_timer, +}; -- cgit v1.2.2 From b4380b8e5888e5ef5872e43b610c9dac4bf253ac Mon Sep 17 00:00:00 2001 From: dmitry pervushin Date: Sun, 3 May 2009 16:49:26 +0100 Subject: [ARM] 5501/1: Freescale STMP: fix compilation warning To avoid compile-time warning, added parameter to the stmp3xxx_clock_read Signed-off-by: dmitry pervushin Signed-off-by: Russell King --- arch/arm/plat-stmp3xxx/timer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/arm/plat-stmp3xxx/timer.c') diff --git a/arch/arm/plat-stmp3xxx/timer.c b/arch/arm/plat-stmp3xxx/timer.c index c916068f0cab..7d872f0aee70 100644 --- a/arch/arm/plat-stmp3xxx/timer.c +++ b/arch/arm/plat-stmp3xxx/timer.c @@ -45,7 +45,7 @@ stmp3xxx_timer_interrupt(int irq, void *dev_id) return IRQ_HANDLED; } -static cycle_t stmp3xxx_clock_read(void) +static cycle_t stmp3xxx_clock_read(struct clocksource *cs) { return ~((HW_TIMROT_TIMCOUNTn_RD(1) & 0xFFFF0000) >> 16); } -- cgit v1.2.2 From 98f420b23a62e0c9df78c5851860d47bf1bc87dd Mon Sep 17 00:00:00 2001 From: dmitry pervushin Date: Sun, 31 May 2009 13:32:11 +0100 Subject: [ARM] 5532/1: Freescale STMP: register definitions [3/3] Replace HW_zzz register access macros by regular __raw_readl/__raw_writel calls Signed-off-by: dmitry pervushin Signed-off-by: Russell King --- arch/arm/plat-stmp3xxx/timer.c | 111 ++++++++++++++++++++++++----------------- 1 file changed, 64 insertions(+), 47 deletions(-) (limited to 'arch/arm/plat-stmp3xxx/timer.c') diff --git a/arch/arm/plat-stmp3xxx/timer.c b/arch/arm/plat-stmp3xxx/timer.c index 7d872f0aee70..063c7bc0e740 100644 --- a/arch/arm/plat-stmp3xxx/timer.c +++ b/arch/arm/plat-stmp3xxx/timer.c @@ -26,6 +26,7 @@ #include #include +#include #include static irqreturn_t @@ -33,13 +34,22 @@ stmp3xxx_timer_interrupt(int irq, void *dev_id) { struct clock_event_device *c = dev_id; - if (HW_TIMROT_TIMCTRLn_RD(0) & (1<<15)) { - HW_TIMROT_TIMCTRLn_CLR(0, (1<<15)); + /* timer 0 */ + if (__raw_readl(REGS_TIMROT_BASE + HW_TIMROT_TIMCTRL0) & + BM_TIMROT_TIMCTRLn_IRQ) { + stmp3xxx_clearl(BM_TIMROT_TIMCTRLn_IRQ, + REGS_TIMROT_BASE + HW_TIMROT_TIMCTRL0); c->event_handler(c); - } else if (HW_TIMROT_TIMCTRLn_RD(1) & (1<<15)) { - HW_TIMROT_TIMCTRLn_CLR(1, (1<<15)); - HW_TIMROT_TIMCTRLn_CLR(1, BM_TIMROT_TIMCTRLn_IRQ_EN); - HW_TIMROT_TIMCOUNTn_WR(1, 0xFFFF); + } + + /* timer 1 */ + else if (__raw_readl(REGS_TIMROT_BASE + HW_TIMROT_TIMCTRL1) + & BM_TIMROT_TIMCTRLn_IRQ) { + stmp3xxx_clearl(BM_TIMROT_TIMCTRLn_IRQ, + REGS_TIMROT_BASE + HW_TIMROT_TIMCTRL1); + stmp3xxx_clearl(BM_TIMROT_TIMCTRLn_IRQ_EN, + REGS_TIMROT_BASE + HW_TIMROT_TIMCTRL1); + __raw_writel(0xFFFF, REGS_TIMROT_BASE + HW_TIMROT_TIMCOUNT1); } return IRQ_HANDLED; @@ -47,14 +57,16 @@ stmp3xxx_timer_interrupt(int irq, void *dev_id) static cycle_t stmp3xxx_clock_read(struct clocksource *cs) { - return ~((HW_TIMROT_TIMCOUNTn_RD(1) & 0xFFFF0000) >> 16); + return ~((__raw_readl(REGS_TIMROT_BASE + HW_TIMROT_TIMCOUNT1) + & 0xFFFF0000) >> 16); } static int stmp3xxx_timrot_set_next_event(unsigned long delta, struct clock_event_device *dev) { - HW_TIMROT_TIMCOUNTn_WR(0, delta); /* reload */ + /* reload the timer */ + __raw_writel(delta, REGS_TIMROT_BASE + HW_TIMROT_TIMCOUNT0); return 0; } @@ -102,25 +114,29 @@ static void __init stmp3xxx_init_timer(void) ckevt_timrot.max_delta_ns = clockevent_delta2ns(0xFFF, &ckevt_timrot); ckevt_timrot.cpumask = cpumask_of(0); - HW_TIMROT_ROTCTRL_CLR(BM_TIMROT_ROTCTRL_SFTRST | - BM_TIMROT_ROTCTRL_CLKGATE); - HW_TIMROT_TIMCOUNTn_WR(0, 0); - HW_TIMROT_TIMCOUNTn_WR(1, 0); - - HW_TIMROT_TIMCTRLn_WR(0, - (BF_TIMROT_TIMCTRLn_SELECT(8) | /* 32 kHz */ - BF_TIMROT_TIMCTRLn_PRESCALE(0) | - BM_TIMROT_TIMCTRLn_RELOAD | - BM_TIMROT_TIMCTRLn_UPDATE | - BM_TIMROT_TIMCTRLn_IRQ_EN)); - HW_TIMROT_TIMCTRLn_WR(1, - (BF_TIMROT_TIMCTRLn_SELECT(8) | /* 32 kHz */ - BF_TIMROT_TIMCTRLn_PRESCALE(0) | - BM_TIMROT_TIMCTRLn_RELOAD | - BM_TIMROT_TIMCTRLn_UPDATE)); - - HW_TIMROT_TIMCOUNTn_WR(0, CLOCK_TICK_RATE / HZ - 1); - HW_TIMROT_TIMCOUNTn_WR(1, 0xFFFF); /* reload */ + stmp3xxx_reset_block(REGS_TIMROT_BASE, false); + + /* clear two timers */ + __raw_writel(0, REGS_TIMROT_BASE + HW_TIMROT_TIMCOUNT0); + __raw_writel(0, REGS_TIMROT_BASE + HW_TIMROT_TIMCOUNT1); + + /* configure them */ + __raw_writel( + (8 << BP_TIMROT_TIMCTRLn_SELECT) | /* 32 kHz */ + BM_TIMROT_TIMCTRLn_RELOAD | + BM_TIMROT_TIMCTRLn_UPDATE | + BM_TIMROT_TIMCTRLn_IRQ_EN, + REGS_TIMROT_BASE + HW_TIMROT_TIMCTRL0); + __raw_writel( + (8 << BP_TIMROT_TIMCTRLn_SELECT) | /* 32 kHz */ + BM_TIMROT_TIMCTRLn_RELOAD | + BM_TIMROT_TIMCTRLn_UPDATE | + BM_TIMROT_TIMCTRLn_IRQ_EN, + REGS_TIMROT_BASE + HW_TIMROT_TIMCTRL1); + + __raw_writel(CLOCK_TICK_RATE / HZ - 1, + REGS_TIMROT_BASE + HW_TIMROT_TIMCOUNT0); + __raw_writel(0xFFFF, REGS_TIMROT_BASE + HW_TIMROT_TIMCOUNT1); setup_irq(IRQ_TIMER0, &stmp3xxx_timer_irq); @@ -132,30 +148,31 @@ static void __init stmp3xxx_init_timer(void) void stmp3xxx_suspend_timer(void) { - HW_TIMROT_TIMCTRLn_CLR(0, BM_TIMROT_TIMCTRLn_IRQ_EN); - HW_TIMROT_TIMCTRLn_CLR(0, (1<<15)); - HW_TIMROT_ROTCTRL_SET(BM_TIMROT_ROTCTRL_CLKGATE); + stmp3xxx_clearl(BM_TIMROT_TIMCTRLn_IRQ_EN | BM_TIMROT_TIMCTRLn_IRQ, + REGS_TIMROT_BASE + HW_TIMROT_TIMCTRL0); + stmp3xxx_setl(BM_TIMROT_ROTCTRL_CLKGATE, + REGS_TIMROT_BASE + HW_TIMROT_ROTCTRL); } void stmp3xxx_resume_timer(void) { - HW_TIMROT_ROTCTRL_CLR(BM_TIMROT_ROTCTRL_SFTRST | - BM_TIMROT_ROTCTRL_CLKGATE); - - - HW_TIMROT_TIMCTRLn_WR(0, - (BF_TIMROT_TIMCTRLn_SELECT(8) | /* 32 kHz */ - BF_TIMROT_TIMCTRLn_PRESCALE(0) | - BM_TIMROT_TIMCTRLn_UPDATE | - BM_TIMROT_TIMCTRLn_IRQ_EN)); - HW_TIMROT_TIMCTRLn_WR(1, - (BF_TIMROT_TIMCTRLn_SELECT(8) | /* 32 kHz */ - BF_TIMROT_TIMCTRLn_PRESCALE(0) | - BM_TIMROT_TIMCTRLn_RELOAD | - BM_TIMROT_TIMCTRLn_UPDATE)); - - HW_TIMROT_TIMCOUNTn_WR(0, CLOCK_TICK_RATE / HZ - 1); - HW_TIMROT_TIMCOUNTn_WR(1, 0xFFFF); /* reload */ + stmp3xxx_clearl(BM_TIMROT_ROTCTRL_SFTRST | BM_TIMROT_ROTCTRL_CLKGATE, + REGS_TIMROT_BASE + HW_TIMROT_ROTCTRL); + __raw_writel( + 8 << BP_TIMROT_TIMCTRLn_SELECT | /* 32 kHz */ + BM_TIMROT_TIMCTRLn_RELOAD | + BM_TIMROT_TIMCTRLn_UPDATE | + BM_TIMROT_TIMCTRLn_IRQ_EN, + REGS_TIMROT_BASE + HW_TIMROT_TIMCTRL0); + __raw_writel( + 8 << BP_TIMROT_TIMCTRLn_SELECT | /* 32 kHz */ + BM_TIMROT_TIMCTRLn_RELOAD | + BM_TIMROT_TIMCTRLn_UPDATE | + BM_TIMROT_TIMCTRLn_IRQ_EN, + REGS_TIMROT_BASE + HW_TIMROT_TIMCTRL1); + __raw_writel(CLOCK_TICK_RATE / HZ - 1, + REGS_TIMROT_BASE + HW_TIMROT_TIMCOUNT0); + __raw_writel(0xFFFF, REGS_TIMROT_BASE + HW_TIMROT_TIMCOUNT1); } #else -- cgit v1.2.2