From patchwork Sun Jan 11 15:58:28 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Barry Song X-Patchwork-Id: 5606471 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 6E21DC058D for ; Sun, 11 Jan 2015 16:02:28 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id A8DA62054A for ; Sun, 11 Jan 2015 16:02:26 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id EA1F620546 for ; Sun, 11 Jan 2015 16:02:24 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1YAKv5-0002U6-I3; Sun, 11 Jan 2015 15:59:15 +0000 Received: from mail-pd0-x22f.google.com ([2607:f8b0:400e:c02::22f]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1YAKv0-0002Pe-17 for linux-arm-kernel@lists.infradead.org; Sun, 11 Jan 2015 15:59:12 +0000 Received: by mail-pd0-f175.google.com with SMTP id g10so26309996pdj.6 for ; Sun, 11 Jan 2015 07:58:48 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:sender:in-reply-to:references:from:date:message-id :subject:to:cc:content-type; bh=CRk2f70MmCNbfD+n/SVciRqj6a8VZVTYFWgHiot5ebM=; b=O/mbs0oqpd+ddciL0f6pgAXuVSk2vLvDpA/KGbTPlDFDaas9FqBDrl+owT7MfJZTI8 PbtK8IzCo35M/y7Xfcx4ChiJOaHMNA1ftNskn165BMsnS9Wcgt18GdN2afJv64NRA8MX qCKZdQLQiHugbBABa1+/BtVQzaPrEKEMAY4GkV0rIB2NJazYKGcrxYFpPyC1iyt4Sw2F REFqHTm8+PNvo7+1Gfy2nSO50HkQe3LADM8HFFL9ncwqsyQI4b4Rlvosg0ZoBWm5bYND 31MWtCtHoiI3RPqjgGRzJe724fRfZUlAW/R/dJt7HkOa8irVr7z8PacstoeF8mlWHeXY hOgA== X-Received: by 10.70.140.130 with SMTP id rg2mr38421255pdb.49.1420991928619; Sun, 11 Jan 2015 07:58:48 -0800 (PST) MIME-Version: 1.0 Received: by 10.66.180.201 with HTTP; Sun, 11 Jan 2015 07:58:28 -0800 (PST) In-Reply-To: <548F09B6.6010202@linaro.org> References: <1418659160-2115-1-git-send-email-thierry.reding@gmail.com> <548F09B6.6010202@linaro.org> From: Barry Song Date: Sun, 11 Jan 2015 23:58:28 +0800 X-Google-Sender-Auth: VoeB4CTcq7B0E8bMVas38tdTqEM Message-ID: Subject: Re: [PATCH] clocksource: sirf: Remove unused variable To: Daniel Lezcano X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20150111_075910_228160_4C194A66 X-CRM114-Status: GOOD ( 24.09 ) X-Spam-Score: -0.7 (/) Cc: DL-SHA-WorkGroupLinux , Thomas Gleixner , Thierry Reding , LKML , "linux-arm-kernel@lists.infradead.org" X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-4.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_MED, T_DKIM_INVALID, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP 2014-12-16 0:17 GMT+08:00 Daniel Lezcano : > On 12/15/2014 04:59 PM, Thierry Reding wrote: >> >> From: Thierry Reding >> >> Commit ef89af1f4380 ("clocksource: sirf: Remove hard-coded clock rate") >> removes all uses of the timer_div variable. Since the variable is no >> longer used it should be removed. >> >> Signed-off-by: Thierry Reding >> --- > > > Applied to my tree. Thanks! Daniel, i didn't find this commit in any tree in kernel.org. am i missing something? so i manually rebased "clocksource: marco: rename marco to atlas7" against this commit. can you help to apply the attached patch to your tree? i guess pulling by arm-soc will cause conflicts. > > -- Daniel > -barry From ffdf7a8a348cf3301fade30cc86398c80be3d1bd Mon Sep 17 00:00:00 2001 From: Barry Song Date: Sun, 11 Jan 2015 23:52:13 +0800 Subject: [PATCH] clocksource: marco: rename marco to atlas7 marco project is replaced by atlas7 and we should obliterate its all traces. Signed-off-by: Barry Song Acked-by: Arnd Bergmann Acked-by: Daniel Lezcano --- drivers/clocksource/Makefile | 2 +- drivers/clocksource/timer-atlas7.c | 306 ++++++++++++++++++++++++++++++++++++ drivers/clocksource/timer-marco.c | 306 ------------------------------------ 3 files changed, 307 insertions(+), 307 deletions(-) create mode 100644 drivers/clocksource/timer-atlas7.c delete mode 100644 drivers/clocksource/timer-marco.c diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile index 94d90b2..306bc47 100644 --- a/drivers/clocksource/Makefile +++ b/drivers/clocksource/Makefile @@ -18,7 +18,7 @@ obj-$(CONFIG_ARMADA_370_XP_TIMER) += time-armada-370-xp.o obj-$(CONFIG_ORION_TIMER) += time-orion.o obj-$(CONFIG_ARCH_BCM2835) += bcm2835_timer.o obj-$(CONFIG_ARCH_CLPS711X) += clps711x-timer.o -obj-$(CONFIG_ARCH_MARCO) += timer-marco.o +obj-$(CONFIG_ARCH_ATLAS7) += timer-atlas7.o obj-$(CONFIG_ARCH_MOXART) += moxart_timer.o obj-$(CONFIG_ARCH_MXS) += mxs_timer.o obj-$(CONFIG_ARCH_PXA) += pxa_timer.o diff --git a/drivers/clocksource/timer-atlas7.c b/drivers/clocksource/timer-atlas7.c new file mode 100644 index 0000000..60f9de3 --- /dev/null +++ b/drivers/clocksource/timer-atlas7.c @@ -0,0 +1,306 @@ +/* + * System timer for CSR SiRFprimaII + * + * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company. + * + * Licensed under GPLv2 or later. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SIRFSOC_TIMER_32COUNTER_0_CTRL 0x0000 +#define SIRFSOC_TIMER_32COUNTER_1_CTRL 0x0004 +#define SIRFSOC_TIMER_MATCH_0 0x0018 +#define SIRFSOC_TIMER_MATCH_1 0x001c +#define SIRFSOC_TIMER_COUNTER_0 0x0048 +#define SIRFSOC_TIMER_COUNTER_1 0x004c +#define SIRFSOC_TIMER_INTR_STATUS 0x0060 +#define SIRFSOC_TIMER_WATCHDOG_EN 0x0064 +#define SIRFSOC_TIMER_64COUNTER_CTRL 0x0068 +#define SIRFSOC_TIMER_64COUNTER_LO 0x006c +#define SIRFSOC_TIMER_64COUNTER_HI 0x0070 +#define SIRFSOC_TIMER_64COUNTER_LOAD_LO 0x0074 +#define SIRFSOC_TIMER_64COUNTER_LOAD_HI 0x0078 +#define SIRFSOC_TIMER_64COUNTER_RLATCHED_LO 0x007c +#define SIRFSOC_TIMER_64COUNTER_RLATCHED_HI 0x0080 + +#define SIRFSOC_TIMER_REG_CNT 6 + +static unsigned long atlas7_timer_rate; + +static const u32 sirfsoc_timer_reg_list[SIRFSOC_TIMER_REG_CNT] = { + SIRFSOC_TIMER_WATCHDOG_EN, + SIRFSOC_TIMER_32COUNTER_0_CTRL, + SIRFSOC_TIMER_32COUNTER_1_CTRL, + SIRFSOC_TIMER_64COUNTER_CTRL, + SIRFSOC_TIMER_64COUNTER_RLATCHED_LO, + SIRFSOC_TIMER_64COUNTER_RLATCHED_HI, +}; + +static u32 sirfsoc_timer_reg_val[SIRFSOC_TIMER_REG_CNT]; + +static void __iomem *sirfsoc_timer_base; + +/* disable count and interrupt */ +static inline void sirfsoc_timer_count_disable(int idx) +{ + writel_relaxed(readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_32COUNTER_0_CTRL + 4 * idx) & ~0x7, + sirfsoc_timer_base + SIRFSOC_TIMER_32COUNTER_0_CTRL + 4 * idx); +} + +/* enable count and interrupt */ +static inline void sirfsoc_timer_count_enable(int idx) +{ + writel_relaxed(readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_32COUNTER_0_CTRL + 4 * idx) | 0x3, + sirfsoc_timer_base + SIRFSOC_TIMER_32COUNTER_0_CTRL + 4 * idx); +} + +/* timer interrupt handler */ +static irqreturn_t sirfsoc_timer_interrupt(int irq, void *dev_id) +{ + struct clock_event_device *ce = dev_id; + int cpu = smp_processor_id(); + + /* clear timer interrupt */ + writel_relaxed(BIT(cpu), sirfsoc_timer_base + SIRFSOC_TIMER_INTR_STATUS); + + if (ce->mode == CLOCK_EVT_MODE_ONESHOT) + sirfsoc_timer_count_disable(cpu); + + ce->event_handler(ce); + + return IRQ_HANDLED; +} + +/* read 64-bit timer counter */ +static cycle_t sirfsoc_timer_read(struct clocksource *cs) +{ + u64 cycles; + + writel_relaxed((readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_CTRL) | + BIT(0)) & ~BIT(1), sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_CTRL); + + cycles = readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_RLATCHED_HI); + cycles = (cycles << 32) | readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_RLATCHED_LO); + + return cycles; +} + +static int sirfsoc_timer_set_next_event(unsigned long delta, + struct clock_event_device *ce) +{ + int cpu = smp_processor_id(); + + /* disable timer first, then modify the related registers */ + sirfsoc_timer_count_disable(cpu); + + writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_0 + + 4 * cpu); + writel_relaxed(delta, sirfsoc_timer_base + SIRFSOC_TIMER_MATCH_0 + + 4 * cpu); + + /* enable the tick */ + sirfsoc_timer_count_enable(cpu); + + return 0; +} + +static void sirfsoc_timer_set_mode(enum clock_event_mode mode, + struct clock_event_device *ce) +{ + switch (mode) { + case CLOCK_EVT_MODE_ONESHOT: + /* enable in set_next_event */ + break; + default: + break; + } + + sirfsoc_timer_count_disable(smp_processor_id()); +} + +static void sirfsoc_clocksource_suspend(struct clocksource *cs) +{ + int i; + + for (i = 0; i < SIRFSOC_TIMER_REG_CNT; i++) + sirfsoc_timer_reg_val[i] = readl_relaxed(sirfsoc_timer_base + sirfsoc_timer_reg_list[i]); +} + +static void sirfsoc_clocksource_resume(struct clocksource *cs) +{ + int i; + + for (i = 0; i < SIRFSOC_TIMER_REG_CNT - 2; i++) + writel_relaxed(sirfsoc_timer_reg_val[i], sirfsoc_timer_base + sirfsoc_timer_reg_list[i]); + + writel_relaxed(sirfsoc_timer_reg_val[SIRFSOC_TIMER_REG_CNT - 2], + sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_LOAD_LO); + writel_relaxed(sirfsoc_timer_reg_val[SIRFSOC_TIMER_REG_CNT - 1], + sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_LOAD_HI); + + writel_relaxed(readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_CTRL) | + BIT(1) | BIT(0), sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_CTRL); +} + +static struct clock_event_device __percpu *sirfsoc_clockevent; + +static struct clocksource sirfsoc_clocksource = { + .name = "sirfsoc_clocksource", + .rating = 200, + .mask = CLOCKSOURCE_MASK(64), + .flags = CLOCK_SOURCE_IS_CONTINUOUS, + .read = sirfsoc_timer_read, + .suspend = sirfsoc_clocksource_suspend, + .resume = sirfsoc_clocksource_resume, +}; + +static struct irqaction sirfsoc_timer_irq = { + .name = "sirfsoc_timer0", + .flags = IRQF_TIMER | IRQF_NOBALANCING, + .handler = sirfsoc_timer_interrupt, +}; + +static struct irqaction sirfsoc_timer1_irq = { + .name = "sirfsoc_timer1", + .flags = IRQF_TIMER | IRQF_NOBALANCING, + .handler = sirfsoc_timer_interrupt, +}; + +static int sirfsoc_local_timer_setup(struct clock_event_device *ce) +{ + int cpu = smp_processor_id(); + struct irqaction *action; + + if (cpu == 0) + action = &sirfsoc_timer_irq; + else + action = &sirfsoc_timer1_irq; + + ce->irq = action->irq; + ce->name = "local_timer"; + ce->features = CLOCK_EVT_FEAT_ONESHOT; + ce->rating = 200; + ce->set_mode = sirfsoc_timer_set_mode; + ce->set_next_event = sirfsoc_timer_set_next_event; + clockevents_calc_mult_shift(ce, atlas7_timer_rate, 60); + ce->max_delta_ns = clockevent_delta2ns(-2, ce); + ce->min_delta_ns = clockevent_delta2ns(2, ce); + ce->cpumask = cpumask_of(cpu); + + action->dev_id = ce; + BUG_ON(setup_irq(ce->irq, action)); + irq_force_affinity(action->irq, cpumask_of(cpu)); + + clockevents_register_device(ce); + return 0; +} + +static void sirfsoc_local_timer_stop(struct clock_event_device *ce) +{ + int cpu = smp_processor_id(); + + sirfsoc_timer_count_disable(1); + + if (cpu == 0) + remove_irq(sirfsoc_timer_irq.irq, &sirfsoc_timer_irq); + else + remove_irq(sirfsoc_timer1_irq.irq, &sirfsoc_timer1_irq); +} + +static int sirfsoc_cpu_notify(struct notifier_block *self, + unsigned long action, void *hcpu) +{ + /* + * Grab cpu pointer in each case to avoid spurious + * preemptible warnings + */ + switch (action & ~CPU_TASKS_FROZEN) { + case CPU_STARTING: + sirfsoc_local_timer_setup(this_cpu_ptr(sirfsoc_clockevent)); + break; + case CPU_DYING: + sirfsoc_local_timer_stop(this_cpu_ptr(sirfsoc_clockevent)); + break; + } + + return NOTIFY_OK; +} + +static struct notifier_block sirfsoc_cpu_nb = { + .notifier_call = sirfsoc_cpu_notify, +}; + +static void __init sirfsoc_clockevent_init(void) +{ + sirfsoc_clockevent = alloc_percpu(struct clock_event_device); + BUG_ON(!sirfsoc_clockevent); + + BUG_ON(register_cpu_notifier(&sirfsoc_cpu_nb)); + + /* Immediately configure the timer on the boot CPU */ + sirfsoc_local_timer_setup(this_cpu_ptr(sirfsoc_clockevent)); +} + +/* initialize the kernel jiffy timer source */ +static void __init sirfsoc_atlas7_timer_init(struct device_node *np) +{ + struct clk *clk; + + clk = of_clk_get(np, 0); + BUG_ON(IS_ERR(clk)); + + BUG_ON(clk_prepare_enable(clk)); + + atlas7_timer_rate = clk_get_rate(clk); + + /* timer dividers: 0, not divided */ + writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_CTRL); + writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_32COUNTER_0_CTRL); + writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_32COUNTER_1_CTRL); + + /* Initialize timer counters to 0 */ + writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_LOAD_LO); + writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_LOAD_HI); + writel_relaxed(readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_CTRL) | + BIT(1) | BIT(0), sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_CTRL); + writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_0); + writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_1); + + /* Clear all interrupts */ + writel_relaxed(0xFFFF, sirfsoc_timer_base + SIRFSOC_TIMER_INTR_STATUS); + + BUG_ON(clocksource_register_hz(&sirfsoc_clocksource, atlas7_timer_rate)); + + sirfsoc_clockevent_init(); +} + +static void __init sirfsoc_of_timer_init(struct device_node *np) +{ + sirfsoc_timer_base = of_iomap(np, 0); + if (!sirfsoc_timer_base) + panic("unable to map timer cpu registers\n"); + + sirfsoc_timer_irq.irq = irq_of_parse_and_map(np, 0); + if (!sirfsoc_timer_irq.irq) + panic("No irq passed for timer0 via DT\n"); + + sirfsoc_timer1_irq.irq = irq_of_parse_and_map(np, 1); + if (!sirfsoc_timer1_irq.irq) + panic("No irq passed for timer1 via DT\n"); + + sirfsoc_atlas7_timer_init(np); +} +CLOCKSOURCE_OF_DECLARE(sirfsoc_atlas7_timer, "sirf,atlas7-tick", sirfsoc_of_timer_init); diff --git a/drivers/clocksource/timer-marco.c b/drivers/clocksource/timer-marco.c deleted file mode 100644 index 3ddb81f..0000000 --- a/drivers/clocksource/timer-marco.c +++ /dev/null @@ -1,306 +0,0 @@ -/* - * System timer for CSR SiRFprimaII - * - * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company. - * - * Licensed under GPLv2 or later. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define SIRFSOC_TIMER_32COUNTER_0_CTRL 0x0000 -#define SIRFSOC_TIMER_32COUNTER_1_CTRL 0x0004 -#define SIRFSOC_TIMER_MATCH_0 0x0018 -#define SIRFSOC_TIMER_MATCH_1 0x001c -#define SIRFSOC_TIMER_COUNTER_0 0x0048 -#define SIRFSOC_TIMER_COUNTER_1 0x004c -#define SIRFSOC_TIMER_INTR_STATUS 0x0060 -#define SIRFSOC_TIMER_WATCHDOG_EN 0x0064 -#define SIRFSOC_TIMER_64COUNTER_CTRL 0x0068 -#define SIRFSOC_TIMER_64COUNTER_LO 0x006c -#define SIRFSOC_TIMER_64COUNTER_HI 0x0070 -#define SIRFSOC_TIMER_64COUNTER_LOAD_LO 0x0074 -#define SIRFSOC_TIMER_64COUNTER_LOAD_HI 0x0078 -#define SIRFSOC_TIMER_64COUNTER_RLATCHED_LO 0x007c -#define SIRFSOC_TIMER_64COUNTER_RLATCHED_HI 0x0080 - -#define SIRFSOC_TIMER_REG_CNT 6 - -static unsigned long marco_timer_rate; - -static const u32 sirfsoc_timer_reg_list[SIRFSOC_TIMER_REG_CNT] = { - SIRFSOC_TIMER_WATCHDOG_EN, - SIRFSOC_TIMER_32COUNTER_0_CTRL, - SIRFSOC_TIMER_32COUNTER_1_CTRL, - SIRFSOC_TIMER_64COUNTER_CTRL, - SIRFSOC_TIMER_64COUNTER_RLATCHED_LO, - SIRFSOC_TIMER_64COUNTER_RLATCHED_HI, -}; - -static u32 sirfsoc_timer_reg_val[SIRFSOC_TIMER_REG_CNT]; - -static void __iomem *sirfsoc_timer_base; - -/* disable count and interrupt */ -static inline void sirfsoc_timer_count_disable(int idx) -{ - writel_relaxed(readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_32COUNTER_0_CTRL + 4 * idx) & ~0x7, - sirfsoc_timer_base + SIRFSOC_TIMER_32COUNTER_0_CTRL + 4 * idx); -} - -/* enable count and interrupt */ -static inline void sirfsoc_timer_count_enable(int idx) -{ - writel_relaxed(readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_32COUNTER_0_CTRL + 4 * idx) | 0x3, - sirfsoc_timer_base + SIRFSOC_TIMER_32COUNTER_0_CTRL + 4 * idx); -} - -/* timer interrupt handler */ -static irqreturn_t sirfsoc_timer_interrupt(int irq, void *dev_id) -{ - struct clock_event_device *ce = dev_id; - int cpu = smp_processor_id(); - - /* clear timer interrupt */ - writel_relaxed(BIT(cpu), sirfsoc_timer_base + SIRFSOC_TIMER_INTR_STATUS); - - if (ce->mode == CLOCK_EVT_MODE_ONESHOT) - sirfsoc_timer_count_disable(cpu); - - ce->event_handler(ce); - - return IRQ_HANDLED; -} - -/* read 64-bit timer counter */ -static cycle_t sirfsoc_timer_read(struct clocksource *cs) -{ - u64 cycles; - - writel_relaxed((readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_CTRL) | - BIT(0)) & ~BIT(1), sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_CTRL); - - cycles = readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_RLATCHED_HI); - cycles = (cycles << 32) | readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_RLATCHED_LO); - - return cycles; -} - -static int sirfsoc_timer_set_next_event(unsigned long delta, - struct clock_event_device *ce) -{ - int cpu = smp_processor_id(); - - /* disable timer first, then modify the related registers */ - sirfsoc_timer_count_disable(cpu); - - writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_0 + - 4 * cpu); - writel_relaxed(delta, sirfsoc_timer_base + SIRFSOC_TIMER_MATCH_0 + - 4 * cpu); - - /* enable the tick */ - sirfsoc_timer_count_enable(cpu); - - return 0; -} - -static void sirfsoc_timer_set_mode(enum clock_event_mode mode, - struct clock_event_device *ce) -{ - switch (mode) { - case CLOCK_EVT_MODE_ONESHOT: - /* enable in set_next_event */ - break; - default: - break; - } - - sirfsoc_timer_count_disable(smp_processor_id()); -} - -static void sirfsoc_clocksource_suspend(struct clocksource *cs) -{ - int i; - - for (i = 0; i < SIRFSOC_TIMER_REG_CNT; i++) - sirfsoc_timer_reg_val[i] = readl_relaxed(sirfsoc_timer_base + sirfsoc_timer_reg_list[i]); -} - -static void sirfsoc_clocksource_resume(struct clocksource *cs) -{ - int i; - - for (i = 0; i < SIRFSOC_TIMER_REG_CNT - 2; i++) - writel_relaxed(sirfsoc_timer_reg_val[i], sirfsoc_timer_base + sirfsoc_timer_reg_list[i]); - - writel_relaxed(sirfsoc_timer_reg_val[SIRFSOC_TIMER_REG_CNT - 2], - sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_LOAD_LO); - writel_relaxed(sirfsoc_timer_reg_val[SIRFSOC_TIMER_REG_CNT - 1], - sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_LOAD_HI); - - writel_relaxed(readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_CTRL) | - BIT(1) | BIT(0), sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_CTRL); -} - -static struct clock_event_device __percpu *sirfsoc_clockevent; - -static struct clocksource sirfsoc_clocksource = { - .name = "sirfsoc_clocksource", - .rating = 200, - .mask = CLOCKSOURCE_MASK(64), - .flags = CLOCK_SOURCE_IS_CONTINUOUS, - .read = sirfsoc_timer_read, - .suspend = sirfsoc_clocksource_suspend, - .resume = sirfsoc_clocksource_resume, -}; - -static struct irqaction sirfsoc_timer_irq = { - .name = "sirfsoc_timer0", - .flags = IRQF_TIMER | IRQF_NOBALANCING, - .handler = sirfsoc_timer_interrupt, -}; - -static struct irqaction sirfsoc_timer1_irq = { - .name = "sirfsoc_timer1", - .flags = IRQF_TIMER | IRQF_NOBALANCING, - .handler = sirfsoc_timer_interrupt, -}; - -static int sirfsoc_local_timer_setup(struct clock_event_device *ce) -{ - int cpu = smp_processor_id(); - struct irqaction *action; - - if (cpu == 0) - action = &sirfsoc_timer_irq; - else - action = &sirfsoc_timer1_irq; - - ce->irq = action->irq; - ce->name = "local_timer"; - ce->features = CLOCK_EVT_FEAT_ONESHOT; - ce->rating = 200; - ce->set_mode = sirfsoc_timer_set_mode; - ce->set_next_event = sirfsoc_timer_set_next_event; - clockevents_calc_mult_shift(ce, marco_timer_rate, 60); - ce->max_delta_ns = clockevent_delta2ns(-2, ce); - ce->min_delta_ns = clockevent_delta2ns(2, ce); - ce->cpumask = cpumask_of(cpu); - - action->dev_id = ce; - BUG_ON(setup_irq(ce->irq, action)); - irq_force_affinity(action->irq, cpumask_of(cpu)); - - clockevents_register_device(ce); - return 0; -} - -static void sirfsoc_local_timer_stop(struct clock_event_device *ce) -{ - int cpu = smp_processor_id(); - - sirfsoc_timer_count_disable(1); - - if (cpu == 0) - remove_irq(sirfsoc_timer_irq.irq, &sirfsoc_timer_irq); - else - remove_irq(sirfsoc_timer1_irq.irq, &sirfsoc_timer1_irq); -} - -static int sirfsoc_cpu_notify(struct notifier_block *self, - unsigned long action, void *hcpu) -{ - /* - * Grab cpu pointer in each case to avoid spurious - * preemptible warnings - */ - switch (action & ~CPU_TASKS_FROZEN) { - case CPU_STARTING: - sirfsoc_local_timer_setup(this_cpu_ptr(sirfsoc_clockevent)); - break; - case CPU_DYING: - sirfsoc_local_timer_stop(this_cpu_ptr(sirfsoc_clockevent)); - break; - } - - return NOTIFY_OK; -} - -static struct notifier_block sirfsoc_cpu_nb = { - .notifier_call = sirfsoc_cpu_notify, -}; - -static void __init sirfsoc_clockevent_init(void) -{ - sirfsoc_clockevent = alloc_percpu(struct clock_event_device); - BUG_ON(!sirfsoc_clockevent); - - BUG_ON(register_cpu_notifier(&sirfsoc_cpu_nb)); - - /* Immediately configure the timer on the boot CPU */ - sirfsoc_local_timer_setup(this_cpu_ptr(sirfsoc_clockevent)); -} - -/* initialize the kernel jiffy timer source */ -static void __init sirfsoc_marco_timer_init(struct device_node *np) -{ - struct clk *clk; - - clk = of_clk_get(np, 0); - BUG_ON(IS_ERR(clk)); - - BUG_ON(clk_prepare_enable(clk)); - - marco_timer_rate = clk_get_rate(clk); - - /* timer dividers: 0, not divided */ - writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_CTRL); - writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_32COUNTER_0_CTRL); - writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_32COUNTER_1_CTRL); - - /* Initialize timer counters to 0 */ - writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_LOAD_LO); - writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_LOAD_HI); - writel_relaxed(readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_CTRL) | - BIT(1) | BIT(0), sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_CTRL); - writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_0); - writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_1); - - /* Clear all interrupts */ - writel_relaxed(0xFFFF, sirfsoc_timer_base + SIRFSOC_TIMER_INTR_STATUS); - - BUG_ON(clocksource_register_hz(&sirfsoc_clocksource, marco_timer_rate)); - - sirfsoc_clockevent_init(); -} - -static void __init sirfsoc_of_timer_init(struct device_node *np) -{ - sirfsoc_timer_base = of_iomap(np, 0); - if (!sirfsoc_timer_base) - panic("unable to map timer cpu registers\n"); - - sirfsoc_timer_irq.irq = irq_of_parse_and_map(np, 0); - if (!sirfsoc_timer_irq.irq) - panic("No irq passed for timer0 via DT\n"); - - sirfsoc_timer1_irq.irq = irq_of_parse_and_map(np, 1); - if (!sirfsoc_timer1_irq.irq) - panic("No irq passed for timer1 via DT\n"); - - sirfsoc_marco_timer_init(np); -} -CLOCKSOURCE_OF_DECLARE(sirfsoc_marco_timer, "sirf,marco-tick", sirfsoc_of_timer_init ); -- 1.7.9.5