diff options
author | John Crispin <john@openwrt.org> | 2015-02-11 10:09:23 +0000 |
---|---|---|
committer | John Crispin <john@openwrt.org> | 2015-02-11 10:09:23 +0000 |
commit | 88ddb3746188037afd38d631f7a893587fa8bdf0 (patch) | |
tree | df4684db63441435126c4b6ff1fda4ce615e1ff0 /target/linux/ipq806x/patches/0004-clocksource-qcom-Move-clocksource-code-out-of-mach-m.patch | |
parent | ddcbef5766fa18f52e7a7d1928b25edc63e73937 (diff) | |
download | upstream-88ddb3746188037afd38d631f7a893587fa8bdf0.tar.gz upstream-88ddb3746188037afd38d631f7a893587fa8bdf0.tar.bz2 upstream-88ddb3746188037afd38d631f7a893587fa8bdf0.zip |
ipq806x: update target to v3.18
Patches in the ipq806x/patches folder were out of tree in v3.14. The
newest patch at the time was from June, so we can safely assume that
either the patches have been merged, or they have been rejected for
a good reason. If patches are seen missing, we'll cherry-pick them
on a per-needed basis.
This new kernel have been tested on AP148, which seems to works fine.
Signed-off-by: Mathieu Olivari <mathieu@codeaurora.org>
SVN-Revision: 44386
Diffstat (limited to 'target/linux/ipq806x/patches/0004-clocksource-qcom-Move-clocksource-code-out-of-mach-m.patch')
-rw-r--r-- | target/linux/ipq806x/patches/0004-clocksource-qcom-Move-clocksource-code-out-of-mach-m.patch | 771 |
1 files changed, 0 insertions, 771 deletions
diff --git a/target/linux/ipq806x/patches/0004-clocksource-qcom-Move-clocksource-code-out-of-mach-m.patch b/target/linux/ipq806x/patches/0004-clocksource-qcom-Move-clocksource-code-out-of-mach-m.patch deleted file mode 100644 index c726d3f982..0000000000 --- a/target/linux/ipq806x/patches/0004-clocksource-qcom-Move-clocksource-code-out-of-mach-m.patch +++ /dev/null @@ -1,771 +0,0 @@ -From 00009eabeb2074bef5c89e576a7a6d827c12c3d9 Mon Sep 17 00:00:00 2001 -From: Kumar Gala <galak@codeaurora.org> -Date: Wed, 29 Jan 2014 16:17:30 -0600 -Subject: [PATCH 004/182] clocksource: qcom: Move clocksource code out of - mach-msm - -We intend to share the clocksource code for MSM platforms between legacy -and multiplatform supported qcom SoCs. - -Acked-by: Olof Johansson <olof@lixom.net> -Signed-off-by: Kumar Gala <galak@codeaurora.org> ---- - arch/arm/mach-msm/Kconfig | 13 +- - arch/arm/mach-msm/Makefile | 1 - - arch/arm/mach-msm/timer.c | 333 -------------------------------------- - drivers/clocksource/Kconfig | 3 + - drivers/clocksource/Makefile | 1 + - drivers/clocksource/qcom-timer.c | 329 +++++++++++++++++++++++++++++++++++++ - 6 files changed, 338 insertions(+), 342 deletions(-) - delete mode 100644 arch/arm/mach-msm/timer.c - create mode 100644 drivers/clocksource/qcom-timer.c - ---- a/arch/arm/mach-msm/Kconfig -+++ b/arch/arm/mach-msm/Kconfig -@@ -21,7 +21,7 @@ config ARCH_MSM8X60 - select CPU_V7 - select HAVE_SMP - select MSM_SCM if SMP -- select MSM_TIMER -+ select CLKSRC_QCOM - - config ARCH_MSM8960 - bool "Enable support for MSM8960" -@@ -29,7 +29,7 @@ config ARCH_MSM8960 - select CPU_V7 - select HAVE_SMP - select MSM_SCM if SMP -- select MSM_TIMER -+ select CLKSRC_QCOM - - config ARCH_MSM8974 - bool "Enable support for MSM8974" -@@ -54,7 +54,7 @@ config ARCH_MSM7X00A - select MACH_TROUT if !MACH_HALIBUT - select MSM_PROC_COMM - select MSM_SMD -- select MSM_TIMER -+ select CLKSRC_QCOM - select MSM_SMD_PKG3 - - config ARCH_MSM7X30 -@@ -66,7 +66,7 @@ config ARCH_MSM7X30 - select MSM_GPIOMUX - select MSM_PROC_COMM - select MSM_SMD -- select MSM_TIMER -+ select CLKSRC_QCOM - select MSM_VIC - - config ARCH_QSD8X50 -@@ -78,7 +78,7 @@ config ARCH_QSD8X50 - select MSM_GPIOMUX - select MSM_PROC_COMM - select MSM_SMD -- select MSM_TIMER -+ select CLKSRC_QCOM - select MSM_VIC - - endchoice -@@ -153,7 +153,4 @@ config MSM_GPIOMUX - config MSM_SCM - bool - --config MSM_TIMER -- bool -- - endif ---- a/arch/arm/mach-msm/Makefile -+++ b/arch/arm/mach-msm/Makefile -@@ -1,4 +1,3 @@ --obj-$(CONFIG_MSM_TIMER) += timer.o - obj-$(CONFIG_MSM_PROC_COMM) += clock.o - - obj-$(CONFIG_MSM_VIC) += irq-vic.o ---- a/arch/arm/mach-msm/timer.c -+++ /dev/null -@@ -1,333 +0,0 @@ --/* -- * -- * Copyright (C) 2007 Google, Inc. -- * Copyright (c) 2009-2012, The Linux Foundation. All rights reserved. -- * -- * This software is licensed under the terms of the GNU General Public -- * License version 2, as published by the Free Software Foundation, and -- * may be copied, distributed, and modified under those terms. -- * -- * 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. -- * -- */ -- --#include <linux/clocksource.h> --#include <linux/clockchips.h> --#include <linux/cpu.h> --#include <linux/init.h> --#include <linux/interrupt.h> --#include <linux/irq.h> --#include <linux/io.h> --#include <linux/of.h> --#include <linux/of_address.h> --#include <linux/of_irq.h> --#include <linux/sched_clock.h> -- --#include <asm/mach/time.h> -- --#include "common.h" -- --#define TIMER_MATCH_VAL 0x0000 --#define TIMER_COUNT_VAL 0x0004 --#define TIMER_ENABLE 0x0008 --#define TIMER_ENABLE_CLR_ON_MATCH_EN BIT(1) --#define TIMER_ENABLE_EN BIT(0) --#define TIMER_CLEAR 0x000C --#define DGT_CLK_CTL 0x10 --#define DGT_CLK_CTL_DIV_4 0x3 --#define TIMER_STS_GPT0_CLR_PEND BIT(10) -- --#define GPT_HZ 32768 -- --#define MSM_DGT_SHIFT 5 -- --static void __iomem *event_base; --static void __iomem *sts_base; -- --static irqreturn_t msm_timer_interrupt(int irq, void *dev_id) --{ -- struct clock_event_device *evt = dev_id; -- /* Stop the timer tick */ -- if (evt->mode == CLOCK_EVT_MODE_ONESHOT) { -- u32 ctrl = readl_relaxed(event_base + TIMER_ENABLE); -- ctrl &= ~TIMER_ENABLE_EN; -- writel_relaxed(ctrl, event_base + TIMER_ENABLE); -- } -- evt->event_handler(evt); -- return IRQ_HANDLED; --} -- --static int msm_timer_set_next_event(unsigned long cycles, -- struct clock_event_device *evt) --{ -- u32 ctrl = readl_relaxed(event_base + TIMER_ENABLE); -- -- ctrl &= ~TIMER_ENABLE_EN; -- writel_relaxed(ctrl, event_base + TIMER_ENABLE); -- -- writel_relaxed(ctrl, event_base + TIMER_CLEAR); -- writel_relaxed(cycles, event_base + TIMER_MATCH_VAL); -- -- if (sts_base) -- while (readl_relaxed(sts_base) & TIMER_STS_GPT0_CLR_PEND) -- cpu_relax(); -- -- writel_relaxed(ctrl | TIMER_ENABLE_EN, event_base + TIMER_ENABLE); -- return 0; --} -- --static void msm_timer_set_mode(enum clock_event_mode mode, -- struct clock_event_device *evt) --{ -- u32 ctrl; -- -- ctrl = readl_relaxed(event_base + TIMER_ENABLE); -- ctrl &= ~(TIMER_ENABLE_EN | TIMER_ENABLE_CLR_ON_MATCH_EN); -- -- switch (mode) { -- case CLOCK_EVT_MODE_RESUME: -- case CLOCK_EVT_MODE_PERIODIC: -- break; -- case CLOCK_EVT_MODE_ONESHOT: -- /* Timer is enabled in set_next_event */ -- break; -- case CLOCK_EVT_MODE_UNUSED: -- case CLOCK_EVT_MODE_SHUTDOWN: -- break; -- } -- writel_relaxed(ctrl, event_base + TIMER_ENABLE); --} -- --static struct clock_event_device __percpu *msm_evt; -- --static void __iomem *source_base; -- --static notrace cycle_t msm_read_timer_count(struct clocksource *cs) --{ -- return readl_relaxed(source_base + TIMER_COUNT_VAL); --} -- --static notrace cycle_t msm_read_timer_count_shift(struct clocksource *cs) --{ -- /* -- * Shift timer count down by a constant due to unreliable lower bits -- * on some targets. -- */ -- return msm_read_timer_count(cs) >> MSM_DGT_SHIFT; --} -- --static struct clocksource msm_clocksource = { -- .name = "dg_timer", -- .rating = 300, -- .read = msm_read_timer_count, -- .mask = CLOCKSOURCE_MASK(32), -- .flags = CLOCK_SOURCE_IS_CONTINUOUS, --}; -- --static int msm_timer_irq; --static int msm_timer_has_ppi; -- --static int msm_local_timer_setup(struct clock_event_device *evt) --{ -- int cpu = smp_processor_id(); -- int err; -- -- evt->irq = msm_timer_irq; -- evt->name = "msm_timer"; -- evt->features = CLOCK_EVT_FEAT_ONESHOT; -- evt->rating = 200; -- evt->set_mode = msm_timer_set_mode; -- evt->set_next_event = msm_timer_set_next_event; -- evt->cpumask = cpumask_of(cpu); -- -- clockevents_config_and_register(evt, GPT_HZ, 4, 0xffffffff); -- -- if (msm_timer_has_ppi) { -- enable_percpu_irq(evt->irq, IRQ_TYPE_EDGE_RISING); -- } else { -- err = request_irq(evt->irq, msm_timer_interrupt, -- IRQF_TIMER | IRQF_NOBALANCING | -- IRQF_TRIGGER_RISING, "gp_timer", evt); -- if (err) -- pr_err("request_irq failed\n"); -- } -- -- return 0; --} -- --static void msm_local_timer_stop(struct clock_event_device *evt) --{ -- evt->set_mode(CLOCK_EVT_MODE_UNUSED, evt); -- disable_percpu_irq(evt->irq); --} -- --static int msm_timer_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: -- msm_local_timer_setup(this_cpu_ptr(msm_evt)); -- break; -- case CPU_DYING: -- msm_local_timer_stop(this_cpu_ptr(msm_evt)); -- break; -- } -- -- return NOTIFY_OK; --} -- --static struct notifier_block msm_timer_cpu_nb = { -- .notifier_call = msm_timer_cpu_notify, --}; -- --static u64 notrace msm_sched_clock_read(void) --{ -- return msm_clocksource.read(&msm_clocksource); --} -- --static void __init msm_timer_init(u32 dgt_hz, int sched_bits, int irq, -- bool percpu) --{ -- struct clocksource *cs = &msm_clocksource; -- int res = 0; -- -- msm_timer_irq = irq; -- msm_timer_has_ppi = percpu; -- -- msm_evt = alloc_percpu(struct clock_event_device); -- if (!msm_evt) { -- pr_err("memory allocation failed for clockevents\n"); -- goto err; -- } -- -- if (percpu) -- res = request_percpu_irq(irq, msm_timer_interrupt, -- "gp_timer", msm_evt); -- -- if (res) { -- pr_err("request_percpu_irq failed\n"); -- } else { -- res = register_cpu_notifier(&msm_timer_cpu_nb); -- if (res) { -- free_percpu_irq(irq, msm_evt); -- goto err; -- } -- -- /* Immediately configure the timer on the boot CPU */ -- msm_local_timer_setup(__this_cpu_ptr(msm_evt)); -- } -- --err: -- writel_relaxed(TIMER_ENABLE_EN, source_base + TIMER_ENABLE); -- res = clocksource_register_hz(cs, dgt_hz); -- if (res) -- pr_err("clocksource_register failed\n"); -- sched_clock_register(msm_sched_clock_read, sched_bits, dgt_hz); --} -- --#ifdef CONFIG_OF --static void __init msm_dt_timer_init(struct device_node *np) --{ -- u32 freq; -- int irq; -- struct resource res; -- u32 percpu_offset; -- void __iomem *base; -- void __iomem *cpu0_base; -- -- base = of_iomap(np, 0); -- if (!base) { -- pr_err("Failed to map event base\n"); -- return; -- } -- -- /* We use GPT0 for the clockevent */ -- irq = irq_of_parse_and_map(np, 1); -- if (irq <= 0) { -- pr_err("Can't get irq\n"); -- return; -- } -- -- /* We use CPU0's DGT for the clocksource */ -- if (of_property_read_u32(np, "cpu-offset", &percpu_offset)) -- percpu_offset = 0; -- -- if (of_address_to_resource(np, 0, &res)) { -- pr_err("Failed to parse DGT resource\n"); -- return; -- } -- -- cpu0_base = ioremap(res.start + percpu_offset, resource_size(&res)); -- if (!cpu0_base) { -- pr_err("Failed to map source base\n"); -- return; -- } -- -- if (of_property_read_u32(np, "clock-frequency", &freq)) { -- pr_err("Unknown frequency\n"); -- return; -- } -- -- event_base = base + 0x4; -- sts_base = base + 0x88; -- source_base = cpu0_base + 0x24; -- freq /= 4; -- writel_relaxed(DGT_CLK_CTL_DIV_4, source_base + DGT_CLK_CTL); -- -- msm_timer_init(freq, 32, irq, !!percpu_offset); --} --CLOCKSOURCE_OF_DECLARE(kpss_timer, "qcom,kpss-timer", msm_dt_timer_init); --CLOCKSOURCE_OF_DECLARE(scss_timer, "qcom,scss-timer", msm_dt_timer_init); --#endif -- --static int __init msm_timer_map(phys_addr_t addr, u32 event, u32 source, -- u32 sts) --{ -- void __iomem *base; -- -- base = ioremap(addr, SZ_256); -- if (!base) { -- pr_err("Failed to map timer base\n"); -- return -ENOMEM; -- } -- event_base = base + event; -- source_base = base + source; -- if (sts) -- sts_base = base + sts; -- -- return 0; --} -- --void __init msm7x01_timer_init(void) --{ -- struct clocksource *cs = &msm_clocksource; -- -- if (msm_timer_map(0xc0100000, 0x0, 0x10, 0x0)) -- return; -- cs->read = msm_read_timer_count_shift; -- cs->mask = CLOCKSOURCE_MASK((32 - MSM_DGT_SHIFT)); -- /* 600 KHz */ -- msm_timer_init(19200000 >> MSM_DGT_SHIFT, 32 - MSM_DGT_SHIFT, 7, -- false); --} -- --void __init msm7x30_timer_init(void) --{ -- if (msm_timer_map(0xc0100000, 0x4, 0x24, 0x80)) -- return; -- msm_timer_init(24576000 / 4, 32, 1, false); --} -- --void __init qsd8x50_timer_init(void) --{ -- if (msm_timer_map(0xAC100000, 0x0, 0x10, 0x34)) -- return; -- msm_timer_init(19200000 / 4, 32, 7, false); --} ---- a/drivers/clocksource/Kconfig -+++ b/drivers/clocksource/Kconfig -@@ -140,3 +140,6 @@ config VF_PIT_TIMER - bool - help - Support for Period Interrupt Timer on Freescale Vybrid Family SoCs. -+ -+config CLKSRC_QCOM -+ bool ---- a/drivers/clocksource/Makefile -+++ b/drivers/clocksource/Makefile -@@ -32,6 +32,7 @@ obj-$(CONFIG_CLKSRC_EFM32) += time-efm32 - obj-$(CONFIG_CLKSRC_EXYNOS_MCT) += exynos_mct.o - obj-$(CONFIG_CLKSRC_SAMSUNG_PWM) += samsung_pwm_timer.o - obj-$(CONFIG_VF_PIT_TIMER) += vf_pit_timer.o -+obj-$(CONFIG_CLKSRC_QCOM) += qcom-timer.o - - obj-$(CONFIG_ARM_ARCH_TIMER) += arm_arch_timer.o - obj-$(CONFIG_ARM_GLOBAL_TIMER) += arm_global_timer.o ---- /dev/null -+++ b/drivers/clocksource/qcom-timer.c -@@ -0,0 +1,329 @@ -+/* -+ * -+ * Copyright (C) 2007 Google, Inc. -+ * Copyright (c) 2009-2012,2014, The Linux Foundation. All rights reserved. -+ * -+ * This software is licensed under the terms of the GNU General Public -+ * License version 2, as published by the Free Software Foundation, and -+ * may be copied, distributed, and modified under those terms. -+ * -+ * 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. -+ * -+ */ -+ -+#include <linux/clocksource.h> -+#include <linux/clockchips.h> -+#include <linux/cpu.h> -+#include <linux/init.h> -+#include <linux/interrupt.h> -+#include <linux/irq.h> -+#include <linux/io.h> -+#include <linux/of.h> -+#include <linux/of_address.h> -+#include <linux/of_irq.h> -+#include <linux/sched_clock.h> -+ -+#define TIMER_MATCH_VAL 0x0000 -+#define TIMER_COUNT_VAL 0x0004 -+#define TIMER_ENABLE 0x0008 -+#define TIMER_ENABLE_CLR_ON_MATCH_EN BIT(1) -+#define TIMER_ENABLE_EN BIT(0) -+#define TIMER_CLEAR 0x000C -+#define DGT_CLK_CTL 0x10 -+#define DGT_CLK_CTL_DIV_4 0x3 -+#define TIMER_STS_GPT0_CLR_PEND BIT(10) -+ -+#define GPT_HZ 32768 -+ -+#define MSM_DGT_SHIFT 5 -+ -+static void __iomem *event_base; -+static void __iomem *sts_base; -+ -+static irqreturn_t msm_timer_interrupt(int irq, void *dev_id) -+{ -+ struct clock_event_device *evt = dev_id; -+ /* Stop the timer tick */ -+ if (evt->mode == CLOCK_EVT_MODE_ONESHOT) { -+ u32 ctrl = readl_relaxed(event_base + TIMER_ENABLE); -+ ctrl &= ~TIMER_ENABLE_EN; -+ writel_relaxed(ctrl, event_base + TIMER_ENABLE); -+ } -+ evt->event_handler(evt); -+ return IRQ_HANDLED; -+} -+ -+static int msm_timer_set_next_event(unsigned long cycles, -+ struct clock_event_device *evt) -+{ -+ u32 ctrl = readl_relaxed(event_base + TIMER_ENABLE); -+ -+ ctrl &= ~TIMER_ENABLE_EN; -+ writel_relaxed(ctrl, event_base + TIMER_ENABLE); -+ -+ writel_relaxed(ctrl, event_base + TIMER_CLEAR); -+ writel_relaxed(cycles, event_base + TIMER_MATCH_VAL); -+ -+ if (sts_base) -+ while (readl_relaxed(sts_base) & TIMER_STS_GPT0_CLR_PEND) -+ cpu_relax(); -+ -+ writel_relaxed(ctrl | TIMER_ENABLE_EN, event_base + TIMER_ENABLE); -+ return 0; -+} -+ -+static void msm_timer_set_mode(enum clock_event_mode mode, -+ struct clock_event_device *evt) -+{ -+ u32 ctrl; -+ -+ ctrl = readl_relaxed(event_base + TIMER_ENABLE); -+ ctrl &= ~(TIMER_ENABLE_EN | TIMER_ENABLE_CLR_ON_MATCH_EN); -+ -+ switch (mode) { -+ case CLOCK_EVT_MODE_RESUME: -+ case CLOCK_EVT_MODE_PERIODIC: -+ break; -+ case CLOCK_EVT_MODE_ONESHOT: -+ /* Timer is enabled in set_next_event */ -+ break; -+ case CLOCK_EVT_MODE_UNUSED: -+ case CLOCK_EVT_MODE_SHUTDOWN: -+ break; -+ } -+ writel_relaxed(ctrl, event_base + TIMER_ENABLE); -+} -+ -+static struct clock_event_device __percpu *msm_evt; -+ -+static void __iomem *source_base; -+ -+static notrace cycle_t msm_read_timer_count(struct clocksource *cs) -+{ -+ return readl_relaxed(source_base + TIMER_COUNT_VAL); -+} -+ -+static notrace cycle_t msm_read_timer_count_shift(struct clocksource *cs) -+{ -+ /* -+ * Shift timer count down by a constant due to unreliable lower bits -+ * on some targets. -+ */ -+ return msm_read_timer_count(cs) >> MSM_DGT_SHIFT; -+} -+ -+static struct clocksource msm_clocksource = { -+ .name = "dg_timer", -+ .rating = 300, -+ .read = msm_read_timer_count, -+ .mask = CLOCKSOURCE_MASK(32), -+ .flags = CLOCK_SOURCE_IS_CONTINUOUS, -+}; -+ -+static int msm_timer_irq; -+static int msm_timer_has_ppi; -+ -+static int msm_local_timer_setup(struct clock_event_device *evt) -+{ -+ int cpu = smp_processor_id(); -+ int err; -+ -+ evt->irq = msm_timer_irq; -+ evt->name = "msm_timer"; -+ evt->features = CLOCK_EVT_FEAT_ONESHOT; -+ evt->rating = 200; -+ evt->set_mode = msm_timer_set_mode; -+ evt->set_next_event = msm_timer_set_next_event; -+ evt->cpumask = cpumask_of(cpu); -+ -+ clockevents_config_and_register(evt, GPT_HZ, 4, 0xffffffff); -+ -+ if (msm_timer_has_ppi) { -+ enable_percpu_irq(evt->irq, IRQ_TYPE_EDGE_RISING); -+ } else { -+ err = request_irq(evt->irq, msm_timer_interrupt, -+ IRQF_TIMER | IRQF_NOBALANCING | -+ IRQF_TRIGGER_RISING, "gp_timer", evt); -+ if (err) -+ pr_err("request_irq failed\n"); -+ } -+ -+ return 0; -+} -+ -+static void msm_local_timer_stop(struct clock_event_device *evt) -+{ -+ evt->set_mode(CLOCK_EVT_MODE_UNUSED, evt); -+ disable_percpu_irq(evt->irq); -+} -+ -+static int msm_timer_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: -+ msm_local_timer_setup(this_cpu_ptr(msm_evt)); -+ break; -+ case CPU_DYING: -+ msm_local_timer_stop(this_cpu_ptr(msm_evt)); -+ break; -+ } -+ -+ return NOTIFY_OK; -+} -+ -+static struct notifier_block msm_timer_cpu_nb = { -+ .notifier_call = msm_timer_cpu_notify, -+}; -+ -+static u64 notrace msm_sched_clock_read(void) -+{ -+ return msm_clocksource.read(&msm_clocksource); -+} -+ -+static void __init msm_timer_init(u32 dgt_hz, int sched_bits, int irq, -+ bool percpu) -+{ -+ struct clocksource *cs = &msm_clocksource; -+ int res = 0; -+ -+ msm_timer_irq = irq; -+ msm_timer_has_ppi = percpu; -+ -+ msm_evt = alloc_percpu(struct clock_event_device); -+ if (!msm_evt) { -+ pr_err("memory allocation failed for clockevents\n"); -+ goto err; -+ } -+ -+ if (percpu) -+ res = request_percpu_irq(irq, msm_timer_interrupt, -+ "gp_timer", msm_evt); -+ -+ if (res) { -+ pr_err("request_percpu_irq failed\n"); -+ } else { -+ res = register_cpu_notifier(&msm_timer_cpu_nb); -+ if (res) { -+ free_percpu_irq(irq, msm_evt); -+ goto err; -+ } -+ -+ /* Immediately configure the timer on the boot CPU */ -+ msm_local_timer_setup(__this_cpu_ptr(msm_evt)); -+ } -+ -+err: -+ writel_relaxed(TIMER_ENABLE_EN, source_base + TIMER_ENABLE); -+ res = clocksource_register_hz(cs, dgt_hz); -+ if (res) -+ pr_err("clocksource_register failed\n"); -+ sched_clock_register(msm_sched_clock_read, sched_bits, dgt_hz); -+} -+ -+#ifdef CONFIG_OF -+static void __init msm_dt_timer_init(struct device_node *np) -+{ -+ u32 freq; -+ int irq; -+ struct resource res; -+ u32 percpu_offset; -+ void __iomem *base; -+ void __iomem *cpu0_base; -+ -+ base = of_iomap(np, 0); -+ if (!base) { -+ pr_err("Failed to map event base\n"); -+ return; -+ } -+ -+ /* We use GPT0 for the clockevent */ -+ irq = irq_of_parse_and_map(np, 1); -+ if (irq <= 0) { -+ pr_err("Can't get irq\n"); -+ return; -+ } -+ -+ /* We use CPU0's DGT for the clocksource */ -+ if (of_property_read_u32(np, "cpu-offset", &percpu_offset)) -+ percpu_offset = 0; -+ -+ if (of_address_to_resource(np, 0, &res)) { -+ pr_err("Failed to parse DGT resource\n"); -+ return; -+ } -+ -+ cpu0_base = ioremap(res.start + percpu_offset, resource_size(&res)); -+ if (!cpu0_base) { -+ pr_err("Failed to map source base\n"); -+ return; -+ } -+ -+ if (of_property_read_u32(np, "clock-frequency", &freq)) { -+ pr_err("Unknown frequency\n"); -+ return; -+ } -+ -+ event_base = base + 0x4; -+ sts_base = base + 0x88; -+ source_base = cpu0_base + 0x24; -+ freq /= 4; -+ writel_relaxed(DGT_CLK_CTL_DIV_4, source_base + DGT_CLK_CTL); -+ -+ msm_timer_init(freq, 32, irq, !!percpu_offset); -+} -+CLOCKSOURCE_OF_DECLARE(kpss_timer, "qcom,kpss-timer", msm_dt_timer_init); -+CLOCKSOURCE_OF_DECLARE(scss_timer, "qcom,scss-timer", msm_dt_timer_init); -+#endif -+ -+static int __init msm_timer_map(phys_addr_t addr, u32 event, u32 source, -+ u32 sts) -+{ -+ void __iomem *base; -+ -+ base = ioremap(addr, SZ_256); -+ if (!base) { -+ pr_err("Failed to map timer base\n"); -+ return -ENOMEM; -+ } -+ event_base = base + event; -+ source_base = base + source; -+ if (sts) -+ sts_base = base + sts; -+ -+ return 0; -+} -+ -+void __init msm7x01_timer_init(void) -+{ -+ struct clocksource *cs = &msm_clocksource; -+ -+ if (msm_timer_map(0xc0100000, 0x0, 0x10, 0x0)) -+ return; -+ cs->read = msm_read_timer_count_shift; -+ cs->mask = CLOCKSOURCE_MASK((32 - MSM_DGT_SHIFT)); -+ /* 600 KHz */ -+ msm_timer_init(19200000 >> MSM_DGT_SHIFT, 32 - MSM_DGT_SHIFT, 7, -+ false); -+} -+ -+void __init msm7x30_timer_init(void) -+{ -+ if (msm_timer_map(0xc0100000, 0x4, 0x24, 0x80)) -+ return; -+ msm_timer_init(24576000 / 4, 32, 1, false); -+} -+ -+void __init qsd8x50_timer_init(void) -+{ -+ if (msm_timer_map(0xAC100000, 0x0, 0x10, 0x34)) -+ return; -+ msm_timer_init(19200000 / 4, 32, 7, false); -+} |