From patchwork Thu Jun 16 19:06:39 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marc Zyngier X-Patchwork-Id: 888422 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 p5GJDdHR014454 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Thu, 16 Jun 2011 19:14:00 GMT Received: from canuck.infradead.org ([2001:4978:20e::1]) by merlin.infradead.org with esmtps (Exim 4.76 #1 (Red Hat Linux)) id 1QXI0M-0008Re-EQ; Thu, 16 Jun 2011 19:13:26 +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 1QXI0L-00054h-Rj; Thu, 16 Jun 2011 19:13:25 +0000 Received: from casper.infradead.org ([2001:770:15f::2]) by canuck.infradead.org with esmtps (Exim 4.76 #1 (Red Hat Linux)) id 1QXI0J-00054M-LL for linux-arm-kernel@canuck.infradead.org; Thu, 16 Jun 2011 19:13:23 +0000 Received: from service87.mimecast.com ([94.185.240.25]) by casper.infradead.org with smtp (Exim 4.76 #1 (Red Hat Linux)) id 1QXI0G-0001Y3-0t for linux-arm-kernel@lists.infradead.org; Thu, 16 Jun 2011 19:13:22 +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:45 +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:55 +0100 From: Marc Zyngier To: linux-arm-kernel@lists.infradead.org Subject: [RFC PATCH 11/16] ARM: local timers: move exynos4 to LOCAL_TIMER_DEVICES/EXYNOS_MCT/ARM_SMP_TWD Date: Thu, 16 Jun 2011 20:06:39 +0100 Message-Id: <1308251204-16719-12-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:55.0498 (UTC) FILETIME=[8F02EEA0:01CC2C58] X-MC-Unique: 111061620074500401 X-CRM114-Version: 20090807-BlameThorstenAndJenny ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20110616_201320_235750_84BD3F15 X-CRM114-Status: GOOD ( 21.79 ) 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: Thomas Gleixner , Kukjin Kim , Ben Dooks , Arnd Bergmann 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:14:00 +0000 (UTC) Convert the exynos4 platforms to use the new arm_smp_twd or exynos4_mct drivers, depending on the configuration. arch/arm/mach-exynos4/mct.c takes a major hit in the process. Add the platform devices and register them as early platform devices. Tested on a SMDK-v310 with TWD only. Cc: Kukjin Kim Cc: Ben Dooks Signed-off-by: Marc Zyngier --- arch/arm/mach-exynos4/Kconfig | 2 + arch/arm/mach-exynos4/Makefile | 1 - arch/arm/mach-exynos4/localtimer.c | 27 ----- arch/arm/mach-exynos4/mct.c | 197 ++--------------------------------- arch/arm/mach-exynos4/time.c | 33 +++++- arch/arm/plat-s5p/s5p-time.c | 1 - 6 files changed, 41 insertions(+), 220 deletions(-) delete mode 100644 arch/arm/mach-exynos4/localtimer.c diff --git a/arch/arm/mach-exynos4/Kconfig b/arch/arm/mach-exynos4/Kconfig index 1435fc3..0db7aa3 100644 --- a/arch/arm/mach-exynos4/Kconfig +++ b/arch/arm/mach-exynos4/Kconfig @@ -12,6 +12,8 @@ if ARCH_EXYNOS4 config CPU_EXYNOS4210 bool select S3C_PL330_DMA + select LOCAL_TIMER_DEVICES + select ARM_SMP_TWD if !EXYNOS4_MCT help Enable EXYNOS4210 CPU support diff --git a/arch/arm/mach-exynos4/Makefile b/arch/arm/mach-exynos4/Makefile index 1366995..b223972 100644 --- a/arch/arm/mach-exynos4/Makefile +++ b/arch/arm/mach-exynos4/Makefile @@ -23,7 +23,6 @@ ifeq ($(CONFIG_EXYNOS4_MCT),y) obj-y += mct.o else obj-y += time.o -obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o endif obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o diff --git a/arch/arm/mach-exynos4/localtimer.c b/arch/arm/mach-exynos4/localtimer.c deleted file mode 100644 index 315de6f..0000000 --- a/arch/arm/mach-exynos4/localtimer.c +++ /dev/null @@ -1,27 +0,0 @@ -/* linux/arch/arm/mach-exynos4/localtimer.c - * - * Cloned from linux/arch/arm/mach-realview/localtimer.c - * - * Copyright (C) 2002 ARM Ltd. - * All Rights Reserved - * - * 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. -*/ - -#include - -#include -#include -#include - -/* - * Setup the local clock events for a CPU. - */ -int __cpuinit local_timer_setup(struct clock_event_device *evt) -{ - evt->irq = gic_ppi_to_vppi(IRQ_LOCALTIMER); - twd_timer_setup(evt); - return 0; -} diff --git a/arch/arm/mach-exynos4/mct.c b/arch/arm/mach-exynos4/mct.c index 14ac10b..5aea222 100644 --- a/arch/arm/mach-exynos4/mct.c +++ b/arch/arm/mach-exynos4/mct.c @@ -10,7 +10,6 @@ * published by the Free Software Foundation. */ -#include #include #include #include @@ -18,7 +17,6 @@ #include #include #include -#include #include #include @@ -27,13 +25,6 @@ static unsigned long clk_cnt_per_tick; static unsigned long clk_rate; -struct mct_clock_event_device { - struct clock_event_device *evt; - void __iomem *base; -}; - -struct mct_clock_event_device mct_tick[2]; - static void exynos4_mct_write(unsigned int value, void *addr) { void __iomem *stat_addr; @@ -67,30 +58,6 @@ static void exynos4_mct_write(unsigned int value, void *addr) stat_addr = EXYNOS4_MCT_G_CNT_WSTAT; mask = 1 << 1; /* G_CNT_U write status */ break; - case (u32)(EXYNOS4_MCT_L0_BASE + MCT_L_TCON_OFFSET): - stat_addr = EXYNOS4_MCT_L0_BASE + MCT_L_WSTAT_OFFSET; - mask = 1 << 3; /* L0_TCON write status */ - break; - case (u32)(EXYNOS4_MCT_L1_BASE + MCT_L_TCON_OFFSET): - stat_addr = EXYNOS4_MCT_L1_BASE + MCT_L_WSTAT_OFFSET; - mask = 1 << 3; /* L1_TCON write status */ - break; - case (u32)(EXYNOS4_MCT_L0_BASE + MCT_L_TCNTB_OFFSET): - stat_addr = EXYNOS4_MCT_L0_BASE + MCT_L_WSTAT_OFFSET; - mask = 1 << 0; /* L0_TCNTB write status */ - break; - case (u32)(EXYNOS4_MCT_L1_BASE + MCT_L_TCNTB_OFFSET): - stat_addr = EXYNOS4_MCT_L1_BASE + MCT_L_WSTAT_OFFSET; - mask = 1 << 0; /* L1_TCNTB write status */ - break; - case (u32)(EXYNOS4_MCT_L0_BASE + MCT_L_ICNTB_OFFSET): - stat_addr = EXYNOS4_MCT_L0_BASE + MCT_L_WSTAT_OFFSET; - mask = 1 << 1; /* L0_ICNTB write status */ - break; - case (u32)(EXYNOS4_MCT_L1_BASE + MCT_L_ICNTB_OFFSET): - stat_addr = EXYNOS4_MCT_L1_BASE + MCT_L_WSTAT_OFFSET; - mask = 1 << 1; /* L1_ICNTB write status */ - break; default: return; } @@ -249,158 +216,6 @@ static void exynos4_clockevent_init(void) setup_irq(IRQ_MCT_G0, &mct_comp_event_irq); } -#ifdef CONFIG_LOCAL_TIMERS -/* Clock event handling */ -static void exynos4_mct_tick_stop(struct mct_clock_event_device *mevt) -{ - unsigned long tmp; - unsigned long mask = MCT_L_TCON_INT_START | MCT_L_TCON_TIMER_START; - void __iomem *addr = mevt->base + MCT_L_TCON_OFFSET; - - tmp = __raw_readl(addr); - if (tmp & mask) { - tmp &= ~mask; - exynos4_mct_write(tmp, addr); - } -} - -static void exynos4_mct_tick_start(unsigned long cycles, - struct mct_clock_event_device *mevt) -{ - unsigned long tmp; - - exynos4_mct_tick_stop(mevt); - - tmp = (1 << 31) | cycles; /* MCT_L_UPDATE_ICNTB */ - - /* update interrupt count buffer */ - exynos4_mct_write(tmp, mevt->base + MCT_L_ICNTB_OFFSET); - - /* enable MCT tick interrupt */ - exynos4_mct_write(0x1, mevt->base + MCT_L_INT_ENB_OFFSET); - - tmp = __raw_readl(mevt->base + MCT_L_TCON_OFFSET); - tmp |= MCT_L_TCON_INT_START | MCT_L_TCON_TIMER_START | - MCT_L_TCON_INTERVAL_MODE; - exynos4_mct_write(tmp, mevt->base + MCT_L_TCON_OFFSET); -} - -static int exynos4_tick_set_next_event(unsigned long cycles, - struct clock_event_device *evt) -{ - struct mct_clock_event_device *mevt = &mct_tick[smp_processor_id()]; - - exynos4_mct_tick_start(cycles, mevt); - - return 0; -} - -static inline void exynos4_tick_set_mode(enum clock_event_mode mode, - struct clock_event_device *evt) -{ - struct mct_clock_event_device *mevt = &mct_tick[smp_processor_id()]; - - exynos4_mct_tick_stop(mevt); - - switch (mode) { - case CLOCK_EVT_MODE_PERIODIC: - exynos4_mct_tick_start(clk_cnt_per_tick, mevt); - break; - - case CLOCK_EVT_MODE_ONESHOT: - case CLOCK_EVT_MODE_UNUSED: - case CLOCK_EVT_MODE_SHUTDOWN: - case CLOCK_EVT_MODE_RESUME: - break; - } -} - -static irqreturn_t exynos4_mct_tick_isr(int irq, void *dev_id) -{ - struct mct_clock_event_device *mevt = dev_id; - struct clock_event_device *evt = mevt->evt; - - /* - * This is for supporting oneshot mode. - * Mct would generate interrupt periodically - * without explicit stopping. - */ - if (evt->mode != CLOCK_EVT_MODE_PERIODIC) - exynos4_mct_tick_stop(mevt); - - /* Clear the MCT tick interrupt */ - exynos4_mct_write(0x1, mevt->base + MCT_L_INT_CSTAT_OFFSET); - - evt->event_handler(evt); - - return IRQ_HANDLED; -} - -static struct irqaction mct_tick0_event_irq = { - .name = "mct_tick0_irq", - .flags = IRQF_TIMER | IRQF_NOBALANCING, - .handler = exynos4_mct_tick_isr, -}; - -static struct irqaction mct_tick1_event_irq = { - .name = "mct_tick1_irq", - .flags = IRQF_TIMER | IRQF_NOBALANCING, - .handler = exynos4_mct_tick_isr, -}; - -static void exynos4_mct_tick_init(struct clock_event_device *evt) -{ - unsigned int cpu = smp_processor_id(); - - mct_tick[cpu].evt = evt; - - if (cpu == 0) { - mct_tick[cpu].base = EXYNOS4_MCT_L0_BASE; - evt->name = "mct_tick0"; - } else { - mct_tick[cpu].base = EXYNOS4_MCT_L1_BASE; - evt->name = "mct_tick1"; - } - - evt->cpumask = cpumask_of(cpu); - evt->set_next_event = exynos4_tick_set_next_event; - evt->set_mode = exynos4_tick_set_mode; - evt->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT; - evt->rating = 450; - - clockevents_calc_mult_shift(evt, clk_rate / 2, 5); - evt->max_delta_ns = - clockevent_delta2ns(0x7fffffff, evt); - evt->min_delta_ns = - clockevent_delta2ns(0xf, evt); - - clockevents_register_device(evt); - - exynos4_mct_write(0x1, mct_tick[cpu].base + MCT_L_TCNTB_OFFSET); - - if (cpu == 0) { - mct_tick0_event_irq.dev_id = &mct_tick[cpu]; - setup_irq(IRQ_MCT_L0, &mct_tick0_event_irq); - } else { - mct_tick1_event_irq.dev_id = &mct_tick[cpu]; - irq_set_affinity(IRQ_MCT1, cpumask_of(1)); - setup_irq(IRQ_MCT_L1, &mct_tick1_event_irq); - } -} - -/* Setup the local clock events for a CPU */ -void __cpuinit local_timer_setup(struct clock_event_device *evt) -{ - exynos4_mct_tick_init(evt); -} - -int local_timer_ack(void) -{ - return 0; -} - -#endif /* CONFIG_LOCAL_TIMERS */ - static void __init exynos4_timer_resources(void) { struct clk *mct_clk; @@ -409,11 +224,23 @@ static void __init exynos4_timer_resources(void) clk_rate = clk_get_rate(mct_clk); } +static struct platform_device exynos4_mct_device = { + .name = "exynos4_mct", + .id = -1, +}; + +static struct platform_device *exynos4_early_devices[] = { + &exynos4_mct_device, +}; + static void __init exynos4_timer_init(void) { exynos4_timer_resources(); exynos4_clocksource_init(); exynos4_clockevent_init(); + + early_platform_add_devices(exynos4_early_devices, + ARRAY_SIZE(exynos4_early_devices)); } struct sys_timer exynos4_timer = { diff --git a/arch/arm/mach-exynos4/time.c b/arch/arm/mach-exynos4/time.c index ebb8f38..be674d5 100644 --- a/arch/arm/mach-exynos4/time.c +++ b/arch/arm/mach-exynos4/time.c @@ -19,8 +19,6 @@ #include #include -#include - #include #include #include @@ -285,15 +283,38 @@ static void __init exynos4_timer_resources(void) clk_enable(tin4); } +static struct resource exynos4_twd_resources[] = { + { + .start = EXYNOS4_PA_COREPERI + 0x600, + .end = EXYNOS4_PA_COREPERI + 0x600 + 0x10, + .flags = IORESOURCE_MEM, + }, + { + .start = IRQ_LOCALTIMER, + .end = IRQ_LOCALTIMER, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device exynos4_twd_device = { + .name = "arm_smp_twd", + .id = -1, + .resource = exynos4_twd_resources, + .num_resources = ARRAY_SIZE(exynos4_twd_resources), +}; + +static struct platform_device *exynos4_early_devices[] = { + &exynos4_twd_device, +}; + static void __init exynos4_timer_init(void) { -#ifdef CONFIG_LOCAL_TIMERS - twd_base = S5P_VA_TWD; -#endif - exynos4_timer_resources(); exynos4_clockevent_init(); exynos4_clocksource_init(); + + early_platform_add_devices(exynos4_early_devices, + ARRAY_SIZE(exynos4_early_devices)); } struct sys_timer exynos4_timer = { diff --git a/arch/arm/plat-s5p/s5p-time.c b/arch/arm/plat-s5p/s5p-time.c index 899a8cc..f2a0915 100644 --- a/arch/arm/plat-s5p/s5p-time.c +++ b/arch/arm/plat-s5p/s5p-time.c @@ -18,7 +18,6 @@ #include #include -#include #include #include #include