From patchwork Thu Jun 16 19:06:43 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marc Zyngier X-Patchwork-Id: 888312 Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) by demeter2.kernel.org (8.14.4/8.14.4) with ESMTP id p5GJ8awx008659 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Thu, 16 Jun 2011 19:08:57 GMT Received: from canuck.infradead.org ([2001:4978:20e::1]) by merlin.infradead.org with esmtps (Exim 4.76 #1 (Red Hat Linux)) id 1QXHvQ-0002ZZ-Pl; Thu, 16 Jun 2011 19:08:21 +0000 Received: from localhost ([127.0.0.1] helo=canuck.infradead.org) by canuck.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1QXHvP-0003ud-A9; Thu, 16 Jun 2011 19:08:19 +0000 Received: from casper.infradead.org ([2001:770:15f::2]) by canuck.infradead.org with esmtps (Exim 4.76 #1 (Red Hat Linux)) id 1QXHul-0003nl-Cs for linux-arm-kernel@canuck.infradead.org; Thu, 16 Jun 2011 19:07:39 +0000 Received: from service87.mimecast.com ([94.185.240.25]) by casper.infradead.org with smtp (Exim 4.76 #1 (Red Hat Linux)) id 1QXHug-0001HQ-7b for linux-arm-kernel@lists.infradead.org; Thu, 16 Jun 2011 19:07:37 +0000 Received: from cam-owa2.Emea.Arm.com (fw-tnat.cambridge.arm.com [217.140.96.21]) by service87.mimecast.com; Thu, 16 Jun 2011 20:07:25 +0100 Received: from localhost.localdomain ([10.1.255.212]) by cam-owa2.Emea.Arm.com with Microsoft SMTPSVC(6.0.3790.3959); Thu, 16 Jun 2011 20:06:56 +0100 From: Marc Zyngier To: linux-arm-kernel@lists.infradead.org Subject: [RFC PATCH 15/16] ARM: local timers: move msm to LOCAL_TIMER_DEVICES/MSM_TIMER Date: Thu, 16 Jun 2011 20:06:43 +0100 Message-Id: <1308251204-16719-16-git-send-email-marc.zyngier@arm.com> X-Mailer: git-send-email 1.7.0.4 In-Reply-To: <1308251204-16719-1-git-send-email-marc.zyngier@arm.com> References: <1308251204-16719-1-git-send-email-marc.zyngier@arm.com> X-OriginalArrivalTime: 16 Jun 2011 19:06:56.0936 (UTC) FILETIME=[8FDE5A80:01CC2C58] X-MC-Unique: 111061620072500201 X-CRM114-Version: 20090807-BlameThorstenAndJenny ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20110616_200734_383947_CBCA26CC X-CRM114-Status: GOOD ( 16.78 ) X-Spam-Score: -2.6 (--) X-Spam-Report: SpamAssassin version 3.3.2-r929478 on casper.infradead.org summary: Content analysis details: (-2.6 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -0.7 RCVD_IN_DNSWL_LOW RBL: Sender listed at http://www.dnswl.org/, low trust [94.185.240.25 listed in list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] Cc: Arnd Bergmann , Stephen Boyd , Bryan Huntsman , Daniel Walker , Thomas Gleixner , David Brown X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: linux-arm-kernel-bounces@lists.infradead.org Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.6 (demeter2.kernel.org [140.211.167.43]); Thu, 16 Jun 2011 19:08:57 +0000 (UTC) Convert the MSM platforms to use the new msm_timer driver. Add the platform device and register it as early platform device. In the process, timer.c is reduced to... erm... not a lot. Cc: David Brown Cc: Daniel Walker Cc: Bryan Huntsman Cc: Stephen Boyd Signed-off-by: Marc Zyngier --- arch/arm/mach-msm/Kconfig | 10 ++ arch/arm/mach-msm/timer.c | 290 ++------------------------------------------- 2 files changed, 18 insertions(+), 282 deletions(-) diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig index 1516896..65530ae 100644 --- a/arch/arm/mach-msm/Kconfig +++ b/arch/arm/mach-msm/Kconfig @@ -13,6 +13,8 @@ config ARCH_MSM7X00A select CPU_V6 select MSM_PROC_COMM select HAS_MSM_DEBUG_UART_PHYS + select LOCAL_TIMER_DEVICES + select MSM_TIMER config ARCH_MSM7X30 bool "MSM7x30" @@ -24,6 +26,8 @@ config ARCH_MSM7X30 select MSM_GPIOMUX select MSM_PROC_COMM select HAS_MSM_DEBUG_UART_PHYS + select LOCAL_TIMER_DEVICES + select MSM_TIMER config ARCH_QSD8X50 bool "QSD8X50" @@ -35,6 +39,8 @@ config ARCH_QSD8X50 select MSM_GPIOMUX select MSM_PROC_COMM select HAS_MSM_DEBUG_UART_PHYS + select LOCAL_TIMER_DEVICES + select MSM_TIMER config ARCH_MSM8X60 bool "MSM8X60" @@ -46,6 +52,8 @@ config ARCH_MSM8X60 select MSM_V2_TLMM select MSM_GPIOMUX select MSM_SCM if SMP + select LOCAL_TIMER_DEVICES + select MSM_TIMER config ARCH_MSM8960 bool "MSM8960" @@ -56,6 +64,8 @@ config ARCH_MSM8960 select MSM_V2_TLMM select MSM_GPIOMUX select MSM_SCM if SMP + select LOCAL_TIMER_DEVICES + select MSM_TIMER endchoice diff --git a/arch/arm/mach-msm/timer.c b/arch/arm/mach-msm/timer.c index b2747cc..0ce27cf 100644 --- a/arch/arm/mach-msm/timer.c +++ b/arch/arm/mach-msm/timer.c @@ -13,299 +13,25 @@ * */ -#include -#include -#include -#include -#include -#include -#include -#include +#include #include -#include -#include -#include -#define TIMER_MATCH_VAL 0x0000 -#define TIMER_COUNT_VAL 0x0004 -#define TIMER_ENABLE 0x0008 -#define TIMER_ENABLE_CLR_ON_MATCH_EN 2 -#define TIMER_ENABLE_EN 1 -#define TIMER_CLEAR 0x000C -#define DGT_CLK_CTL 0x0034 -enum { - DGT_CLK_CTL_DIV_1 = 0, - DGT_CLK_CTL_DIV_2 = 1, - DGT_CLK_CTL_DIV_3 = 2, - DGT_CLK_CTL_DIV_4 = 3, +static struct platform_device msm_timer_device = { + .name = "msm_timer", + .id = -1, }; -#define CSR_PROTECTION 0x0020 -#define CSR_PROTECTION_EN 1 -#define GPT_HZ 32768 - -enum timer_location { - LOCAL_TIMER = 0, - GLOBAL_TIMER = 1, -}; - -#define MSM_GLOBAL_TIMER MSM_CLOCK_DGT - -/* TODO: Remove these ifdefs */ -#if defined(CONFIG_ARCH_QSD8X50) -#define DGT_HZ (19200000 / 4) /* 19.2 MHz / 4 by default */ -#define MSM_DGT_SHIFT (0) -#elif defined(CONFIG_ARCH_MSM7X30) || defined(CONFIG_ARCH_MSM8X60) || \ - defined(CONFIG_ARCH_MSM8960) -#define DGT_HZ (24576000 / 4) /* 24.576 MHz (LPXO) / 4 by default */ -#define MSM_DGT_SHIFT (0) -#else -#define DGT_HZ 19200000 /* 19.2 MHz or 600 KHz after shift */ -#define MSM_DGT_SHIFT (5) -#endif - -struct msm_clock { - struct clock_event_device clockevent; - struct clocksource clocksource; - unsigned int irq; - void __iomem *regbase; - uint32_t freq; - uint32_t shift; - void __iomem *global_counter; - void __iomem *local_counter; -}; - -enum { - MSM_CLOCK_GPT, - MSM_CLOCK_DGT, - NR_TIMERS, -}; - - -static struct msm_clock msm_clocks[]; - -static irqreturn_t msm_timer_interrupt(int irq, void *dev_id) -{ - struct clock_event_device *evt = dev_id; - if (evt->event_handler == NULL) - return IRQ_HANDLED; - evt->event_handler(evt); - return IRQ_HANDLED; -} - -static cycle_t msm_read_timer_count(struct clocksource *cs) -{ - struct msm_clock *clk = container_of(cs, struct msm_clock, clocksource); - - return readl(clk->global_counter); -} - -static struct msm_clock *clockevent_to_clock(struct clock_event_device *evt) -{ -#ifdef CONFIG_SMP - int i; - for (i = 0; i < NR_TIMERS; i++) - if (evt == &(msm_clocks[i].clockevent)) - return &msm_clocks[i]; - return &msm_clocks[MSM_GLOBAL_TIMER]; -#else - return container_of(evt, struct msm_clock, clockevent); -#endif -} - -static int msm_timer_set_next_event(unsigned long cycles, - struct clock_event_device *evt) -{ - struct msm_clock *clock = clockevent_to_clock(evt); - uint32_t now = readl(clock->local_counter); - uint32_t alarm = now + (cycles << clock->shift); - - writel(alarm, clock->regbase + TIMER_MATCH_VAL); - return 0; -} - -static void msm_timer_set_mode(enum clock_event_mode mode, - struct clock_event_device *evt) -{ - struct msm_clock *clock = clockevent_to_clock(evt); - - switch (mode) { - case CLOCK_EVT_MODE_RESUME: - case CLOCK_EVT_MODE_PERIODIC: - break; - case CLOCK_EVT_MODE_ONESHOT: - writel(TIMER_ENABLE_EN, clock->regbase + TIMER_ENABLE); - break; - case CLOCK_EVT_MODE_UNUSED: - disable_irq(evt->irq); - /* fall through */ - case CLOCK_EVT_MODE_SHUTDOWN: - writel(0, clock->regbase + TIMER_ENABLE); - break; - } -} - -static struct msm_clock msm_clocks[] = { - [MSM_CLOCK_GPT] = { - .clockevent = { - .name = "gp_timer", - .features = CLOCK_EVT_FEAT_ONESHOT, - .shift = 32, - .rating = 200, - .set_next_event = msm_timer_set_next_event, - .set_mode = msm_timer_set_mode, - }, - .clocksource = { - .name = "gp_timer", - .rating = 200, - .read = msm_read_timer_count, - .mask = CLOCKSOURCE_MASK(32), - .flags = CLOCK_SOURCE_IS_CONTINUOUS, - }, - .irq = INT_GP_TIMER_EXP, - .freq = GPT_HZ, - }, - [MSM_CLOCK_DGT] = { - .clockevent = { - .name = "dg_timer", - .features = CLOCK_EVT_FEAT_ONESHOT, - .shift = 32 + MSM_DGT_SHIFT, - .rating = 300, - .set_next_event = msm_timer_set_next_event, - .set_mode = msm_timer_set_mode, - }, - .clocksource = { - .name = "dg_timer", - .rating = 300, - .read = msm_read_timer_count, - .mask = CLOCKSOURCE_MASK((32 - MSM_DGT_SHIFT)), - .flags = CLOCK_SOURCE_IS_CONTINUOUS, - }, - .irq = INT_DEBUG_TIMER_EXP, - .freq = DGT_HZ >> MSM_DGT_SHIFT, - .shift = MSM_DGT_SHIFT, - } +static struct platform_device *msm_early_devices[] = { + &msm_timer_device, }; static void __init msm_timer_init(void) { - int i; - int res; - int global_offset = 0; - - if (cpu_is_msm7x01()) { - msm_clocks[MSM_CLOCK_GPT].regbase = MSM_CSR_BASE; - msm_clocks[MSM_CLOCK_DGT].regbase = MSM_CSR_BASE + 0x10; - } else if (cpu_is_msm7x30()) { - msm_clocks[MSM_CLOCK_GPT].regbase = MSM_CSR_BASE + 0x04; - msm_clocks[MSM_CLOCK_DGT].regbase = MSM_CSR_BASE + 0x24; - } else if (cpu_is_qsd8x50()) { - msm_clocks[MSM_CLOCK_GPT].regbase = MSM_CSR_BASE; - msm_clocks[MSM_CLOCK_DGT].regbase = MSM_CSR_BASE + 0x10; - } else if (cpu_is_msm8x60() || cpu_is_msm8960()) { - msm_clocks[MSM_CLOCK_GPT].regbase = MSM_TMR_BASE + 0x04; - msm_clocks[MSM_CLOCK_DGT].regbase = MSM_TMR_BASE + 0x24; - - /* Use CPU0's timer as the global timer. */ - global_offset = MSM_TMR0_BASE - MSM_TMR_BASE; - } else - BUG(); - -#ifdef CONFIG_ARCH_MSM_SCORPIONMP - writel(DGT_CLK_CTL_DIV_4, MSM_TMR_BASE + DGT_CLK_CTL); -#endif - - for (i = 0; i < ARRAY_SIZE(msm_clocks); i++) { - struct msm_clock *clock = &msm_clocks[i]; - struct clock_event_device *ce = &clock->clockevent; - struct clocksource *cs = &clock->clocksource; - - clock->local_counter = clock->regbase + TIMER_COUNT_VAL; - clock->global_counter = clock->local_counter + global_offset; - - writel(0, clock->regbase + TIMER_ENABLE); - writel(0, clock->regbase + TIMER_CLEAR); - writel(~0, clock->regbase + TIMER_MATCH_VAL); - - ce->mult = div_sc(clock->freq, NSEC_PER_SEC, ce->shift); - /* allow at least 10 seconds to notice that the timer wrapped */ - ce->max_delta_ns = - clockevent_delta2ns(0xf0000000 >> clock->shift, ce); - /* 4 gets rounded down to 3 */ - ce->min_delta_ns = clockevent_delta2ns(4, ce); - ce->cpumask = cpumask_of(0); - - res = clocksource_register_hz(cs, clock->freq); - if (res) - printk(KERN_ERR "msm_timer_init: clocksource_register " - "failed for %s\n", cs->name); - - ce->irq = gic_ppi_to_vppi(clock->irq); - res = request_irq(ce->irq, msm_timer_interrupt, - IRQF_TIMER | IRQF_NOBALANCING | IRQF_TRIGGER_RISING, - ce->name, ce); - if (res) - pr_err("msm_timer_init: request_irq failed for %s\n", - ce->name); - - clockevents_register_device(ce); - } -} - -#ifdef CONFIG_SMP -int __cpuinit local_timer_setup(struct clock_event_device *evt) -{ - static bool local_timer_inited; - struct msm_clock *clock = &msm_clocks[MSM_GLOBAL_TIMER]; - int res; - - /* Use existing clock_event for cpu 0 */ - if (!smp_processor_id()) - return 0; - - writel(DGT_CLK_CTL_DIV_4, MSM_TMR_BASE + DGT_CLK_CTL); - - evt->irq = gic_ppi_to_vppi(clock->irq); - evt->name = "local_timer"; - evt->features = CLOCK_EVT_FEAT_ONESHOT; - evt->rating = clock->clockevent.rating; - evt->set_mode = msm_timer_set_mode; - evt->set_next_event = msm_timer_set_next_event; - evt->shift = clock->clockevent.shift; - evt->mult = div_sc(clock->freq, NSEC_PER_SEC, evt->shift); - evt->max_delta_ns = - clockevent_delta2ns(0xf0000000 >> clock->shift, evt); - evt->min_delta_ns = clockevent_delta2ns(4, evt); - - if (!local_timer_inited) { - writel(0, clock->regbase + TIMER_ENABLE); - writel(0, clock->regbase + TIMER_CLEAR); - writel(~0, clock->regbase + TIMER_MATCH_VAL); - - res = request_irq(evt->irq, msm_timer_interrupt, - IRQF_TIMER | IRQF_NOBALANCING | IRQF_TRIGGER_RISING, - clock->clockevent.name, evt); - if (res) { - pr_err("local_timer_setup: request_irq failed for %s\n", - clock->clockevent.name); - return res; - } - local_timer_inited = true; - } else - enable_irq(evt->irq); - - clockevents_register_device(evt); - return 0; -} - -inline int local_timer_ack(void) -{ - return 1; + early_platform_add_devices(msm_early_devices, + ARRAY_SIZE(msm_early_devices)); } -#endif - struct sys_timer msm_timer = { .init = msm_timer_init };