|
@@ -30,19 +30,22 @@
|
|
|
|
|
|
#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_DIV_4 0x3
|
|
|
+#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)
|
|
|
{
|
|
@@ -67,6 +70,11 @@ static int msm_timer_set_next_event(unsigned long cycles,
|
|
|
|
|
|
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;
|
|
|
}
|
|
@@ -137,9 +145,6 @@ static int __cpuinit msm_local_timer_setup(struct clock_event_device *evt)
|
|
|
if (!smp_processor_id())
|
|
|
return 0;
|
|
|
|
|
|
- writel_relaxed(0, event_base + TIMER_ENABLE);
|
|
|
- writel_relaxed(0, event_base + TIMER_CLEAR);
|
|
|
- writel_relaxed(~0, event_base + TIMER_MATCH_VAL);
|
|
|
evt->irq = msm_clockevent.irq;
|
|
|
evt->name = "local_timer";
|
|
|
evt->features = msm_clockevent.features;
|
|
@@ -177,9 +182,6 @@ static void __init msm_timer_init(u32 dgt_hz, int sched_bits, int irq,
|
|
|
struct clocksource *cs = &msm_clocksource;
|
|
|
int res;
|
|
|
|
|
|
- writel_relaxed(0, event_base + TIMER_ENABLE);
|
|
|
- writel_relaxed(0, event_base + TIMER_CLEAR);
|
|
|
- writel_relaxed(~0, event_base + TIMER_MATCH_VAL);
|
|
|
ce->cpumask = cpumask_of(0);
|
|
|
ce->irq = irq;
|
|
|
|
|
@@ -217,13 +219,9 @@ err:
|
|
|
}
|
|
|
|
|
|
#ifdef CONFIG_OF
|
|
|
-static const struct of_device_id msm_dgt_match[] __initconst = {
|
|
|
- { .compatible = "qcom,msm-dgt" },
|
|
|
- { },
|
|
|
-};
|
|
|
-
|
|
|
-static const struct of_device_id msm_gpt_match[] __initconst = {
|
|
|
- { .compatible = "qcom,msm-gpt" },
|
|
|
+static const struct of_device_id msm_timer_match[] __initconst = {
|
|
|
+ { .compatible = "qcom,kpss-timer" },
|
|
|
+ { .compatible = "qcom,scss-timer" },
|
|
|
{ },
|
|
|
};
|
|
|
|
|
@@ -234,33 +232,29 @@ void __init msm_dt_timer_init(void)
|
|
|
int irq;
|
|
|
struct resource res;
|
|
|
u32 percpu_offset;
|
|
|
- void __iomem *dgt_clk_ctl;
|
|
|
+ void __iomem *base;
|
|
|
+ void __iomem *cpu0_base;
|
|
|
|
|
|
- np = of_find_matching_node(NULL, msm_gpt_match);
|
|
|
+ np = of_find_matching_node(NULL, msm_timer_match);
|
|
|
if (!np) {
|
|
|
- pr_err("Can't find GPT DT node\n");
|
|
|
+ pr_err("Can't find msm timer DT node\n");
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- event_base = of_iomap(np, 0);
|
|
|
- if (!event_base) {
|
|
|
+ base = of_iomap(np, 0);
|
|
|
+ if (!base) {
|
|
|
pr_err("Failed to map event base\n");
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- irq = irq_of_parse_and_map(np, 0);
|
|
|
+ /* 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;
|
|
|
}
|
|
|
- of_node_put(np);
|
|
|
-
|
|
|
- np = of_find_matching_node(NULL, msm_dgt_match);
|
|
|
- if (!np) {
|
|
|
- pr_err("Can't find DGT DT node\n");
|
|
|
- return;
|
|
|
- }
|
|
|
|
|
|
+ /* We use CPU0's DGT for the clocksource */
|
|
|
if (of_property_read_u32(np, "cpu-offset", &percpu_offset))
|
|
|
percpu_offset = 0;
|
|
|
|
|
@@ -269,45 +263,43 @@ void __init msm_dt_timer_init(void)
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- source_base = ioremap(res.start + percpu_offset, resource_size(&res));
|
|
|
- if (!source_base) {
|
|
|
+ cpu0_base = ioremap(res.start + percpu_offset, resource_size(&res));
|
|
|
+ if (!cpu0_base) {
|
|
|
pr_err("Failed to map source base\n");
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- if (!of_address_to_resource(np, 1, &res)) {
|
|
|
- dgt_clk_ctl = ioremap(res.start + percpu_offset,
|
|
|
- resource_size(&res));
|
|
|
- if (!dgt_clk_ctl) {
|
|
|
- pr_err("Failed to map DGT control base\n");
|
|
|
- return;
|
|
|
- }
|
|
|
- writel_relaxed(DGT_CLK_CTL_DIV_4, dgt_clk_ctl);
|
|
|
- iounmap(dgt_clk_ctl);
|
|
|
- }
|
|
|
-
|
|
|
if (of_property_read_u32(np, "clock-frequency", &freq)) {
|
|
|
pr_err("Unknown frequency\n");
|
|
|
return;
|
|
|
}
|
|
|
of_node_put(np);
|
|
|
|
|
|
+ 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);
|
|
|
}
|
|
|
#endif
|
|
|
|
|
|
-static int __init msm_timer_map(phys_addr_t event, phys_addr_t source)
|
|
|
+static int __init msm_timer_map(phys_addr_t addr, u32 event, u32 source,
|
|
|
+ u32 sts)
|
|
|
{
|
|
|
- event_base = ioremap(event, SZ_64);
|
|
|
- if (!event_base) {
|
|
|
- pr_err("Failed to map event base\n");
|
|
|
- return 1;
|
|
|
- }
|
|
|
- source_base = ioremap(source, SZ_64);
|
|
|
- if (!source_base) {
|
|
|
- pr_err("Failed to map source base\n");
|
|
|
- return 1;
|
|
|
+ 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;
|
|
|
}
|
|
|
|
|
@@ -315,7 +307,7 @@ void __init msm7x01_timer_init(void)
|
|
|
{
|
|
|
struct clocksource *cs = &msm_clocksource;
|
|
|
|
|
|
- if (msm_timer_map(0xc0100000, 0xc0100010))
|
|
|
+ if (msm_timer_map(0xc0100000, 0x0, 0x10, 0x0))
|
|
|
return;
|
|
|
cs->read = msm_read_timer_count_shift;
|
|
|
cs->mask = CLOCKSOURCE_MASK((32 - MSM_DGT_SHIFT));
|
|
@@ -326,14 +318,14 @@ void __init msm7x01_timer_init(void)
|
|
|
|
|
|
void __init msm7x30_timer_init(void)
|
|
|
{
|
|
|
- if (msm_timer_map(0xc0100004, 0xc0100024))
|
|
|
+ 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, 0xAC100010))
|
|
|
+ if (msm_timer_map(0xAC100000, 0x0, 0x10, 0x34))
|
|
|
return;
|
|
|
msm_timer_init(19200000 / 4, 32, 7, false);
|
|
|
}
|