aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-11-01 23:18:05 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2011-11-01 23:18:05 -0400
commitac5761a650d22dd7dfad4d417463a0981d2da0a4 (patch)
treec01a46a889dde74fbbb05d3b2da22387bb4875c6 /arch/arm
parent25498e5b3df931a3d52a6e0642ae242e4ee19488 (diff)
parenteed1e576507b52e03e549e0c9e0c747978122403 (diff)
Merge branch 'next/timer' of git://git.linaro.org/people/arnd/arm-soc
* 'next/timer' of git://git.linaro.org/people/arnd/arm-soc: clocksource: fixup ux500 build problems ARM: omap: use __devexit_p in dmtimer driver ARM: ux500: Reprogram timers upon resume ARM: plat-nomadik: timer: Export reset functions ARM: plat-nomadik: timer: Add support for periodic timers ARM: ux500: Move timer code to separate file ARM: ux500: add support for clocksource DBX500 PRCMU clocksource: add DBX500 PRCMU Timer support ARM: plat-nomadik: MTU sched_clock as an option ARM: OMAP: dmtimer: add error handling to export APIs ARM: OMAP: dmtimer: low-power mode support ARM: OMAP: dmtimer: skip reserved timers ARM: OMAP: dmtimer: pm_runtime support ARM: OMAP: dmtimer: switch-over to platform device driver ARM: OMAP: dmtimer: platform driver ARM: OMAP2+: dmtimer: convert to platform devices ARM: OMAP1: dmtimer: conversion to platform devices ARM: OMAP2+: dmtimer: add device names to flck nodes ARM: OMAP: Add support for dmtimer v2 ip
Diffstat (limited to 'arch/arm')
-rw-r--r--arch/arm/mach-omap1/Makefile2
-rw-r--r--arch/arm/mach-omap1/timer.c173
-rw-r--r--arch/arm/mach-omap2/clock2420_data.c48
-rw-r--r--arch/arm/mach-omap2/clock2430_data.c48
-rw-r--r--arch/arm/mach-omap2/clock3xxx_data.c36
-rw-r--r--arch/arm/mach-omap2/clock44xx_data.c33
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_2420_data.c22
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_2430_data.c22
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_3xxx_data.c27
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_44xx_data.c22
-rw-r--r--arch/arm/mach-omap2/timer.c194
-rw-r--r--arch/arm/mach-ux500/Makefile2
-rw-r--r--arch/arm/mach-ux500/cpu.c29
-rw-r--r--arch/arm/mach-ux500/include/mach/db5500-regs.h2
-rw-r--r--arch/arm/mach-ux500/include/mach/db8500-regs.h3
-rw-r--r--arch/arm/mach-ux500/timer.c68
-rw-r--r--arch/arm/plat-nomadik/Kconfig8
-rw-r--r--arch/arm/plat-nomadik/include/plat/mtu.h47
-rw-r--r--arch/arm/plat-nomadik/timer.c138
-rw-r--r--arch/arm/plat-omap/dmtimer.c713
-rw-r--r--arch/arm/plat-omap/include/plat/dmtimer.h233
21 files changed, 1376 insertions, 494 deletions
diff --git a/arch/arm/mach-omap1/Makefile b/arch/arm/mach-omap1/Makefile
index 5b114d1558c8..11c85cd2731a 100644
--- a/arch/arm/mach-omap1/Makefile
+++ b/arch/arm/mach-omap1/Makefile
@@ -4,7 +4,7 @@
4 4
5# Common support 5# Common support
6obj-y := io.o id.o sram.o time.o irq.o mux.o flash.o serial.o devices.o dma.o 6obj-y := io.o id.o sram.o time.o irq.o mux.o flash.o serial.o devices.o dma.o
7obj-y += clock.o clock_data.o opp_data.o reset.o pm_bus.o 7obj-y += clock.o clock_data.o opp_data.o reset.o pm_bus.o timer.o
8 8
9obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o 9obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o
10 10
diff --git a/arch/arm/mach-omap1/timer.c b/arch/arm/mach-omap1/timer.c
new file mode 100644
index 000000000000..6e90665a7c47
--- /dev/null
+++ b/arch/arm/mach-omap1/timer.c
@@ -0,0 +1,173 @@
1/**
2 * OMAP1 Dual-Mode Timers - platform device registration
3 *
4 * Contains first level initialization routines which internally
5 * generates timer device information and registers with linux
6 * device model. It also has low level function to chnage the timer
7 * input clock source.
8 *
9 * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
10 * Tarun Kanti DebBarma <tarun.kanti@ti.com>
11 * Thara Gopinath <thara@ti.com>
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License version 2 as
15 * published by the Free Software Foundation.
16 *
17 * This program is distributed "as is" WITHOUT ANY WARRANTY of any
18 * kind, whether express or implied; without even the implied warranty
19 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 */
22
23#include <linux/clk.h>
24#include <linux/io.h>
25#include <linux/err.h>
26#include <linux/slab.h>
27#include <linux/platform_device.h>
28
29#include <mach/irqs.h>
30
31#include <plat/dmtimer.h>
32
33#define OMAP1610_GPTIMER1_BASE 0xfffb1400
34#define OMAP1610_GPTIMER2_BASE 0xfffb1c00
35#define OMAP1610_GPTIMER3_BASE 0xfffb2400
36#define OMAP1610_GPTIMER4_BASE 0xfffb2c00
37#define OMAP1610_GPTIMER5_BASE 0xfffb3400
38#define OMAP1610_GPTIMER6_BASE 0xfffb3c00
39#define OMAP1610_GPTIMER7_BASE 0xfffb7400
40#define OMAP1610_GPTIMER8_BASE 0xfffbd400
41
42#define OMAP1_DM_TIMER_COUNT 8
43
44static int omap1_dm_timer_set_src(struct platform_device *pdev,
45 int source)
46{
47 int n = (pdev->id - 1) << 1;
48 u32 l;
49
50 l = __raw_readl(MOD_CONF_CTRL_1) & ~(0x03 << n);
51 l |= source << n;
52 __raw_writel(l, MOD_CONF_CTRL_1);
53
54 return 0;
55}
56
57
58int __init omap1_dm_timer_init(void)
59{
60 int i;
61 int ret;
62 struct dmtimer_platform_data *pdata;
63 struct platform_device *pdev;
64
65 if (!cpu_is_omap16xx())
66 return 0;
67
68 for (i = 1; i <= OMAP1_DM_TIMER_COUNT; i++) {
69 struct resource res[2];
70 u32 base, irq;
71
72 switch (i) {
73 case 1:
74 base = OMAP1610_GPTIMER1_BASE;
75 irq = INT_1610_GPTIMER1;
76 break;
77 case 2:
78 base = OMAP1610_GPTIMER2_BASE;
79 irq = INT_1610_GPTIMER2;
80 break;
81 case 3:
82 base = OMAP1610_GPTIMER3_BASE;
83 irq = INT_1610_GPTIMER3;
84 break;
85 case 4:
86 base = OMAP1610_GPTIMER4_BASE;
87 irq = INT_1610_GPTIMER4;
88 break;
89 case 5:
90 base = OMAP1610_GPTIMER5_BASE;
91 irq = INT_1610_GPTIMER5;
92 break;
93 case 6:
94 base = OMAP1610_GPTIMER6_BASE;
95 irq = INT_1610_GPTIMER6;
96 break;
97 case 7:
98 base = OMAP1610_GPTIMER7_BASE;
99 irq = INT_1610_GPTIMER7;
100 break;
101 case 8:
102 base = OMAP1610_GPTIMER8_BASE;
103 irq = INT_1610_GPTIMER8;
104 break;
105 default:
106 /*
107 * not supposed to reach here.
108 * this is to remove warning.
109 */
110 return -EINVAL;
111 }
112
113 pdev = platform_device_alloc("omap_timer", i);
114 if (!pdev) {
115 pr_err("%s: Failed to device alloc for dmtimer%d\n",
116 __func__, i);
117 return -ENOMEM;
118 }
119
120 memset(res, 0, 2 * sizeof(struct resource));
121 res[0].start = base;
122 res[0].end = base + 0x46;
123 res[0].flags = IORESOURCE_MEM;
124 res[1].start = irq;
125 res[1].end = irq;
126 res[1].flags = IORESOURCE_IRQ;
127 ret = platform_device_add_resources(pdev, res,
128 ARRAY_SIZE(res));
129 if (ret) {
130 dev_err(&pdev->dev, "%s: Failed to add resources.\n",
131 __func__);
132 goto err_free_pdev;
133 }
134
135 pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
136 if (!pdata) {
137 dev_err(&pdev->dev, "%s: Failed to allocate pdata.\n",
138 __func__);
139 ret = -ENOMEM;
140 goto err_free_pdata;
141 }
142
143 pdata->set_timer_src = omap1_dm_timer_set_src;
144 pdata->needs_manual_reset = 1;
145
146 ret = platform_device_add_data(pdev, pdata, sizeof(*pdata));
147 if (ret) {
148 dev_err(&pdev->dev, "%s: Failed to add platform data.\n",
149 __func__);
150 goto err_free_pdata;
151 }
152
153 ret = platform_device_add(pdev);
154 if (ret) {
155 dev_err(&pdev->dev, "%s: Failed to add platform device.\n",
156 __func__);
157 goto err_free_pdata;
158 }
159
160 dev_dbg(&pdev->dev, " Registered.\n");
161 }
162
163 return 0;
164
165err_free_pdata:
166 kfree(pdata);
167
168err_free_pdev:
169 platform_device_unregister(pdev);
170
171 return ret;
172}
173arch_initcall(omap1_dm_timer_init);
diff --git a/arch/arm/mach-omap2/clock2420_data.c b/arch/arm/mach-omap2/clock2420_data.c
index debc040872f1..14a6277dd184 100644
--- a/arch/arm/mach-omap2/clock2420_data.c
+++ b/arch/arm/mach-omap2/clock2420_data.c
@@ -1898,6 +1898,54 @@ static struct omap_clk omap2420_clks[] = {
1898 CLK(NULL, "pka_ick", &pka_ick, CK_242X), 1898 CLK(NULL, "pka_ick", &pka_ick, CK_242X),
1899 CLK(NULL, "usb_fck", &usb_fck, CK_242X), 1899 CLK(NULL, "usb_fck", &usb_fck, CK_242X),
1900 CLK("musb-hdrc", "fck", &osc_ck, CK_242X), 1900 CLK("musb-hdrc", "fck", &osc_ck, CK_242X),
1901 CLK("omap_timer.1", "fck", &gpt1_fck, CK_242X),
1902 CLK("omap_timer.2", "fck", &gpt2_fck, CK_242X),
1903 CLK("omap_timer.3", "fck", &gpt3_fck, CK_242X),
1904 CLK("omap_timer.4", "fck", &gpt4_fck, CK_242X),
1905 CLK("omap_timer.5", "fck", &gpt5_fck, CK_242X),
1906 CLK("omap_timer.6", "fck", &gpt6_fck, CK_242X),
1907 CLK("omap_timer.7", "fck", &gpt7_fck, CK_242X),
1908 CLK("omap_timer.8", "fck", &gpt8_fck, CK_242X),
1909 CLK("omap_timer.9", "fck", &gpt9_fck, CK_242X),
1910 CLK("omap_timer.10", "fck", &gpt10_fck, CK_242X),
1911 CLK("omap_timer.11", "fck", &gpt11_fck, CK_242X),
1912 CLK("omap_timer.12", "fck", &gpt12_fck, CK_242X),
1913 CLK("omap_timer.1", "32k_ck", &func_32k_ck, CK_243X),
1914 CLK("omap_timer.2", "32k_ck", &func_32k_ck, CK_243X),
1915 CLK("omap_timer.3", "32k_ck", &func_32k_ck, CK_243X),
1916 CLK("omap_timer.4", "32k_ck", &func_32k_ck, CK_243X),
1917 CLK("omap_timer.5", "32k_ck", &func_32k_ck, CK_243X),
1918 CLK("omap_timer.6", "32k_ck", &func_32k_ck, CK_243X),
1919 CLK("omap_timer.7", "32k_ck", &func_32k_ck, CK_243X),
1920 CLK("omap_timer.8", "32k_ck", &func_32k_ck, CK_243X),
1921 CLK("omap_timer.9", "32k_ck", &func_32k_ck, CK_243X),
1922 CLK("omap_timer.10", "32k_ck", &func_32k_ck, CK_243X),
1923 CLK("omap_timer.11", "32k_ck", &func_32k_ck, CK_243X),
1924 CLK("omap_timer.12", "32k_ck", &func_32k_ck, CK_243X),
1925 CLK("omap_timer.1", "sys_ck", &sys_ck, CK_243X),
1926 CLK("omap_timer.2", "sys_ck", &sys_ck, CK_243X),
1927 CLK("omap_timer.3", "sys_ck", &sys_ck, CK_243X),
1928 CLK("omap_timer.4", "sys_ck", &sys_ck, CK_243X),
1929 CLK("omap_timer.5", "sys_ck", &sys_ck, CK_243X),
1930 CLK("omap_timer.6", "sys_ck", &sys_ck, CK_243X),
1931 CLK("omap_timer.7", "sys_ck", &sys_ck, CK_243X),
1932 CLK("omap_timer.8", "sys_ck", &sys_ck, CK_243X),
1933 CLK("omap_timer.9", "sys_ck", &sys_ck, CK_243X),
1934 CLK("omap_timer.10", "sys_ck", &sys_ck, CK_243X),
1935 CLK("omap_timer.11", "sys_ck", &sys_ck, CK_243X),
1936 CLK("omap_timer.12", "sys_ck", &sys_ck, CK_243X),
1937 CLK("omap_timer.1", "alt_ck", &alt_ck, CK_243X),
1938 CLK("omap_timer.2", "alt_ck", &alt_ck, CK_243X),
1939 CLK("omap_timer.3", "alt_ck", &alt_ck, CK_243X),
1940 CLK("omap_timer.4", "alt_ck", &alt_ck, CK_243X),
1941 CLK("omap_timer.5", "alt_ck", &alt_ck, CK_243X),
1942 CLK("omap_timer.6", "alt_ck", &alt_ck, CK_243X),
1943 CLK("omap_timer.7", "alt_ck", &alt_ck, CK_243X),
1944 CLK("omap_timer.8", "alt_ck", &alt_ck, CK_243X),
1945 CLK("omap_timer.9", "alt_ck", &alt_ck, CK_243X),
1946 CLK("omap_timer.10", "alt_ck", &alt_ck, CK_243X),
1947 CLK("omap_timer.11", "alt_ck", &alt_ck, CK_243X),
1948 CLK("omap_timer.12", "alt_ck", &alt_ck, CK_243X),
1901}; 1949};
1902 1950
1903/* 1951/*
diff --git a/arch/arm/mach-omap2/clock2430_data.c b/arch/arm/mach-omap2/clock2430_data.c
index 96a942e42db1..ea6717cfa3c8 100644
--- a/arch/arm/mach-omap2/clock2430_data.c
+++ b/arch/arm/mach-omap2/clock2430_data.c
@@ -1998,6 +1998,54 @@ static struct omap_clk omap2430_clks[] = {
1998 CLK(NULL, "mdm_intc_ick", &mdm_intc_ick, CK_243X), 1998 CLK(NULL, "mdm_intc_ick", &mdm_intc_ick, CK_243X),
1999 CLK("omap_hsmmc.0", "mmchsdb_fck", &mmchsdb1_fck, CK_243X), 1999 CLK("omap_hsmmc.0", "mmchsdb_fck", &mmchsdb1_fck, CK_243X),
2000 CLK("omap_hsmmc.1", "mmchsdb_fck", &mmchsdb2_fck, CK_243X), 2000 CLK("omap_hsmmc.1", "mmchsdb_fck", &mmchsdb2_fck, CK_243X),
2001 CLK("omap_timer.1", "fck", &gpt1_fck, CK_243X),
2002 CLK("omap_timer.2", "fck", &gpt2_fck, CK_243X),
2003 CLK("omap_timer.3", "fck", &gpt3_fck, CK_243X),
2004 CLK("omap_timer.4", "fck", &gpt4_fck, CK_243X),
2005 CLK("omap_timer.5", "fck", &gpt5_fck, CK_243X),
2006 CLK("omap_timer.6", "fck", &gpt6_fck, CK_243X),
2007 CLK("omap_timer.7", "fck", &gpt7_fck, CK_243X),
2008 CLK("omap_timer.8", "fck", &gpt8_fck, CK_243X),
2009 CLK("omap_timer.9", "fck", &gpt9_fck, CK_243X),
2010 CLK("omap_timer.10", "fck", &gpt10_fck, CK_243X),
2011 CLK("omap_timer.11", "fck", &gpt11_fck, CK_243X),
2012 CLK("omap_timer.12", "fck", &gpt12_fck, CK_243X),
2013 CLK("omap_timer.1", "32k_ck", &func_32k_ck, CK_243X),
2014 CLK("omap_timer.2", "32k_ck", &func_32k_ck, CK_243X),
2015 CLK("omap_timer.3", "32k_ck", &func_32k_ck, CK_243X),
2016 CLK("omap_timer.4", "32k_ck", &func_32k_ck, CK_243X),
2017 CLK("omap_timer.5", "32k_ck", &func_32k_ck, CK_243X),
2018 CLK("omap_timer.6", "32k_ck", &func_32k_ck, CK_243X),
2019 CLK("omap_timer.7", "32k_ck", &func_32k_ck, CK_243X),
2020 CLK("omap_timer.8", "32k_ck", &func_32k_ck, CK_243X),
2021 CLK("omap_timer.9", "32k_ck", &func_32k_ck, CK_243X),
2022 CLK("omap_timer.10", "32k_ck", &func_32k_ck, CK_243X),
2023 CLK("omap_timer.11", "32k_ck", &func_32k_ck, CK_243X),
2024 CLK("omap_timer.12", "32k_ck", &func_32k_ck, CK_243X),
2025 CLK("omap_timer.1", "sys_ck", &sys_ck, CK_243X),
2026 CLK("omap_timer.2", "sys_ck", &sys_ck, CK_243X),
2027 CLK("omap_timer.3", "sys_ck", &sys_ck, CK_243X),
2028 CLK("omap_timer.4", "sys_ck", &sys_ck, CK_243X),
2029 CLK("omap_timer.5", "sys_ck", &sys_ck, CK_243X),
2030 CLK("omap_timer.6", "sys_ck", &sys_ck, CK_243X),
2031 CLK("omap_timer.7", "sys_ck", &sys_ck, CK_243X),
2032 CLK("omap_timer.8", "sys_ck", &sys_ck, CK_243X),
2033 CLK("omap_timer.9", "sys_ck", &sys_ck, CK_243X),
2034 CLK("omap_timer.10", "sys_ck", &sys_ck, CK_243X),
2035 CLK("omap_timer.11", "sys_ck", &sys_ck, CK_243X),
2036 CLK("omap_timer.12", "sys_ck", &sys_ck, CK_243X),
2037 CLK("omap_timer.1", "alt_ck", &alt_ck, CK_243X),
2038 CLK("omap_timer.2", "alt_ck", &alt_ck, CK_243X),
2039 CLK("omap_timer.3", "alt_ck", &alt_ck, CK_243X),
2040 CLK("omap_timer.4", "alt_ck", &alt_ck, CK_243X),
2041 CLK("omap_timer.5", "alt_ck", &alt_ck, CK_243X),
2042 CLK("omap_timer.6", "alt_ck", &alt_ck, CK_243X),
2043 CLK("omap_timer.7", "alt_ck", &alt_ck, CK_243X),
2044 CLK("omap_timer.8", "alt_ck", &alt_ck, CK_243X),
2045 CLK("omap_timer.9", "alt_ck", &alt_ck, CK_243X),
2046 CLK("omap_timer.10", "alt_ck", &alt_ck, CK_243X),
2047 CLK("omap_timer.11", "alt_ck", &alt_ck, CK_243X),
2048 CLK("omap_timer.12", "alt_ck", &alt_ck, CK_243X),
2001}; 2049};
2002 2050
2003/* 2051/*
diff --git a/arch/arm/mach-omap2/clock3xxx_data.c b/arch/arm/mach-omap2/clock3xxx_data.c
index dadb8c6c0115..65dd363163bc 100644
--- a/arch/arm/mach-omap2/clock3xxx_data.c
+++ b/arch/arm/mach-omap2/clock3xxx_data.c
@@ -3464,6 +3464,42 @@ static struct omap_clk omap3xxx_clks[] = {
3464 CLK("musb-am35x", "fck", &hsotgusb_fck_am35xx, CK_AM35XX), 3464 CLK("musb-am35x", "fck", &hsotgusb_fck_am35xx, CK_AM35XX),
3465 CLK(NULL, "hecc_ck", &hecc_ck, CK_AM35XX), 3465 CLK(NULL, "hecc_ck", &hecc_ck, CK_AM35XX),
3466 CLK(NULL, "uart4_ick", &uart4_ick_am35xx, CK_AM35XX), 3466 CLK(NULL, "uart4_ick", &uart4_ick_am35xx, CK_AM35XX),
3467 CLK("omap_timer.1", "fck", &gpt1_fck, CK_3XXX),
3468 CLK("omap_timer.2", "fck", &gpt2_fck, CK_3XXX),
3469 CLK("omap_timer.3", "fck", &gpt3_fck, CK_3XXX),
3470 CLK("omap_timer.4", "fck", &gpt4_fck, CK_3XXX),
3471 CLK("omap_timer.5", "fck", &gpt5_fck, CK_3XXX),
3472 CLK("omap_timer.6", "fck", &gpt6_fck, CK_3XXX),
3473 CLK("omap_timer.7", "fck", &gpt7_fck, CK_3XXX),
3474 CLK("omap_timer.8", "fck", &gpt8_fck, CK_3XXX),
3475 CLK("omap_timer.9", "fck", &gpt9_fck, CK_3XXX),
3476 CLK("omap_timer.10", "fck", &gpt10_fck, CK_3XXX),
3477 CLK("omap_timer.11", "fck", &gpt11_fck, CK_3XXX),
3478 CLK("omap_timer.12", "fck", &gpt12_fck, CK_3XXX),
3479 CLK("omap_timer.1", "32k_ck", &omap_32k_fck, CK_3XXX),
3480 CLK("omap_timer.2", "32k_ck", &omap_32k_fck, CK_3XXX),
3481 CLK("omap_timer.3", "32k_ck", &omap_32k_fck, CK_3XXX),
3482 CLK("omap_timer.4", "32k_ck", &omap_32k_fck, CK_3XXX),
3483 CLK("omap_timer.5", "32k_ck", &omap_32k_fck, CK_3XXX),
3484 CLK("omap_timer.6", "32k_ck", &omap_32k_fck, CK_3XXX),
3485 CLK("omap_timer.7", "32k_ck", &omap_32k_fck, CK_3XXX),
3486 CLK("omap_timer.8", "32k_ck", &omap_32k_fck, CK_3XXX),
3487 CLK("omap_timer.9", "32k_ck", &omap_32k_fck, CK_3XXX),
3488 CLK("omap_timer.10", "32k_ck", &omap_32k_fck, CK_3XXX),
3489 CLK("omap_timer.11", "32k_ck", &omap_32k_fck, CK_3XXX),
3490 CLK("omap_timer.12", "32k_ck", &omap_32k_fck, CK_3XXX),
3491 CLK("omap_timer.1", "sys_ck", &sys_ck, CK_3XXX),
3492 CLK("omap_timer.2", "sys_ck", &sys_ck, CK_3XXX),
3493 CLK("omap_timer.3", "sys_ck", &sys_ck, CK_3XXX),
3494 CLK("omap_timer.4", "sys_ck", &sys_ck, CK_3XXX),
3495 CLK("omap_timer.5", "sys_ck", &sys_ck, CK_3XXX),
3496 CLK("omap_timer.6", "sys_ck", &sys_ck, CK_3XXX),
3497 CLK("omap_timer.7", "sys_ck", &sys_ck, CK_3XXX),
3498 CLK("omap_timer.8", "sys_ck", &sys_ck, CK_3XXX),
3499 CLK("omap_timer.9", "sys_ck", &sys_ck, CK_3XXX),
3500 CLK("omap_timer.10", "sys_ck", &sys_ck, CK_3XXX),
3501 CLK("omap_timer.11", "sys_ck", &sys_ck, CK_3XXX),
3502 CLK("omap_timer.12", "sys_ck", &sys_ck, CK_3XXX),
3467}; 3503};
3468 3504
3469 3505
diff --git a/arch/arm/mach-omap2/clock44xx_data.c b/arch/arm/mach-omap2/clock44xx_data.c
index c0b6fbda3408..946bf04a956d 100644
--- a/arch/arm/mach-omap2/clock44xx_data.c
+++ b/arch/arm/mach-omap2/clock44xx_data.c
@@ -3363,6 +3363,39 @@ static struct omap_clk omap44xx_clks[] = {
3363 CLK("usbhs-omap.0", "usbhost_ick", &dummy_ck, CK_443X), 3363 CLK("usbhs-omap.0", "usbhost_ick", &dummy_ck, CK_443X),
3364 CLK("usbhs-omap.0", "usbtll_fck", &dummy_ck, CK_443X), 3364 CLK("usbhs-omap.0", "usbtll_fck", &dummy_ck, CK_443X),
3365 CLK("omap_wdt", "ick", &dummy_ck, CK_443X), 3365 CLK("omap_wdt", "ick", &dummy_ck, CK_443X),
3366 CLK("omap_timer.1", "fck", &timer1_fck, CK_443X),
3367 CLK("omap_timer.2", "fck", &timer2_fck, CK_443X),
3368 CLK("omap_timer.3", "fck", &timer3_fck, CK_443X),
3369 CLK("omap_timer.4", "fck", &timer4_fck, CK_443X),
3370 CLK("omap_timer.5", "fck", &timer5_fck, CK_443X),
3371 CLK("omap_timer.6", "fck", &timer6_fck, CK_443X),
3372 CLK("omap_timer.7", "fck", &timer7_fck, CK_443X),
3373 CLK("omap_timer.8", "fck", &timer8_fck, CK_443X),
3374 CLK("omap_timer.9", "fck", &timer9_fck, CK_443X),
3375 CLK("omap_timer.10", "fck", &timer10_fck, CK_443X),
3376 CLK("omap_timer.11", "fck", &timer11_fck, CK_443X),
3377 CLK("omap_timer.1", "32k_ck", &sys_32k_ck, CK_443X),
3378 CLK("omap_timer.2", "32k_ck", &sys_32k_ck, CK_443X),
3379 CLK("omap_timer.3", "32k_ck", &sys_32k_ck, CK_443X),
3380 CLK("omap_timer.4", "32k_ck", &sys_32k_ck, CK_443X),
3381 CLK("omap_timer.5", "32k_ck", &sys_32k_ck, CK_443X),
3382 CLK("omap_timer.6", "32k_ck", &sys_32k_ck, CK_443X),
3383 CLK("omap_timer.7", "32k_ck", &sys_32k_ck, CK_443X),
3384 CLK("omap_timer.8", "32k_ck", &sys_32k_ck, CK_443X),
3385 CLK("omap_timer.9", "32k_ck", &sys_32k_ck, CK_443X),
3386 CLK("omap_timer.10", "32k_ck", &sys_32k_ck, CK_443X),
3387 CLK("omap_timer.11", "32k_ck", &sys_32k_ck, CK_443X),
3388 CLK("omap_timer.1", "sys_ck", &sys_clkin_ck, CK_443X),
3389 CLK("omap_timer.2", "sys_ck", &sys_clkin_ck, CK_443X),
3390 CLK("omap_timer.3", "sys_ck", &sys_clkin_ck, CK_443X),
3391 CLK("omap_timer.4", "sys_ck", &sys_clkin_ck, CK_443X),
3392 CLK("omap_timer.9", "sys_ck", &sys_clkin_ck, CK_443X),
3393 CLK("omap_timer.10", "sys_ck", &sys_clkin_ck, CK_443X),
3394 CLK("omap_timer.11", "sys_ck", &sys_clkin_ck, CK_443X),
3395 CLK("omap_timer.5", "sys_ck", &syc_clk_div_ck, CK_443X),
3396 CLK("omap_timer.6", "sys_ck", &syc_clk_div_ck, CK_443X),
3397 CLK("omap_timer.7", "sys_ck", &syc_clk_div_ck, CK_443X),
3398 CLK("omap_timer.8", "sys_ck", &syc_clk_div_ck, CK_443X),
3366}; 3399};
3367 3400
3368int __init omap4xxx_clk_init(void) 3401int __init omap4xxx_clk_init(void)
diff --git a/arch/arm/mach-omap2/omap_hwmod_2420_data.c b/arch/arm/mach-omap2/omap_hwmod_2420_data.c
index b6ea69a5c2f8..6d7206213525 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2420_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2420_data.c
@@ -269,6 +269,16 @@ static struct omap_hwmod omap2420_iva_hwmod = {
269 .masters_cnt = ARRAY_SIZE(omap2420_iva_masters), 269 .masters_cnt = ARRAY_SIZE(omap2420_iva_masters),
270}; 270};
271 271
272/* always-on timers dev attribute */
273static struct omap_timer_capability_dev_attr capability_alwon_dev_attr = {
274 .timer_capability = OMAP_TIMER_ALWON,
275};
276
277/* pwm timers dev attribute */
278static struct omap_timer_capability_dev_attr capability_pwm_dev_attr = {
279 .timer_capability = OMAP_TIMER_HAS_PWM,
280};
281
272/* timer1 */ 282/* timer1 */
273static struct omap_hwmod omap2420_timer1_hwmod; 283static struct omap_hwmod omap2420_timer1_hwmod;
274 284
@@ -309,6 +319,7 @@ static struct omap_hwmod omap2420_timer1_hwmod = {
309 .idlest_idle_bit = OMAP24XX_ST_GPT1_SHIFT, 319 .idlest_idle_bit = OMAP24XX_ST_GPT1_SHIFT,
310 }, 320 },
311 }, 321 },
322 .dev_attr = &capability_alwon_dev_attr,
312 .slaves = omap2420_timer1_slaves, 323 .slaves = omap2420_timer1_slaves,
313 .slaves_cnt = ARRAY_SIZE(omap2420_timer1_slaves), 324 .slaves_cnt = ARRAY_SIZE(omap2420_timer1_slaves),
314 .class = &omap2xxx_timer_hwmod_class, 325 .class = &omap2xxx_timer_hwmod_class,
@@ -345,6 +356,7 @@ static struct omap_hwmod omap2420_timer2_hwmod = {
345 .idlest_idle_bit = OMAP24XX_ST_GPT2_SHIFT, 356 .idlest_idle_bit = OMAP24XX_ST_GPT2_SHIFT,
346 }, 357 },
347 }, 358 },
359 .dev_attr = &capability_alwon_dev_attr,
348 .slaves = omap2420_timer2_slaves, 360 .slaves = omap2420_timer2_slaves,
349 .slaves_cnt = ARRAY_SIZE(omap2420_timer2_slaves), 361 .slaves_cnt = ARRAY_SIZE(omap2420_timer2_slaves),
350 .class = &omap2xxx_timer_hwmod_class, 362 .class = &omap2xxx_timer_hwmod_class,
@@ -381,6 +393,7 @@ static struct omap_hwmod omap2420_timer3_hwmod = {
381 .idlest_idle_bit = OMAP24XX_ST_GPT3_SHIFT, 393 .idlest_idle_bit = OMAP24XX_ST_GPT3_SHIFT,
382 }, 394 },
383 }, 395 },
396 .dev_attr = &capability_alwon_dev_attr,
384 .slaves = omap2420_timer3_slaves, 397 .slaves = omap2420_timer3_slaves,
385 .slaves_cnt = ARRAY_SIZE(omap2420_timer3_slaves), 398 .slaves_cnt = ARRAY_SIZE(omap2420_timer3_slaves),
386 .class = &omap2xxx_timer_hwmod_class, 399 .class = &omap2xxx_timer_hwmod_class,
@@ -417,6 +430,7 @@ static struct omap_hwmod omap2420_timer4_hwmod = {
417 .idlest_idle_bit = OMAP24XX_ST_GPT4_SHIFT, 430 .idlest_idle_bit = OMAP24XX_ST_GPT4_SHIFT,
418 }, 431 },
419 }, 432 },
433 .dev_attr = &capability_alwon_dev_attr,
420 .slaves = omap2420_timer4_slaves, 434 .slaves = omap2420_timer4_slaves,
421 .slaves_cnt = ARRAY_SIZE(omap2420_timer4_slaves), 435 .slaves_cnt = ARRAY_SIZE(omap2420_timer4_slaves),
422 .class = &omap2xxx_timer_hwmod_class, 436 .class = &omap2xxx_timer_hwmod_class,
@@ -453,6 +467,7 @@ static struct omap_hwmod omap2420_timer5_hwmod = {
453 .idlest_idle_bit = OMAP24XX_ST_GPT5_SHIFT, 467 .idlest_idle_bit = OMAP24XX_ST_GPT5_SHIFT,
454 }, 468 },
455 }, 469 },
470 .dev_attr = &capability_alwon_dev_attr,
456 .slaves = omap2420_timer5_slaves, 471 .slaves = omap2420_timer5_slaves,
457 .slaves_cnt = ARRAY_SIZE(omap2420_timer5_slaves), 472 .slaves_cnt = ARRAY_SIZE(omap2420_timer5_slaves),
458 .class = &omap2xxx_timer_hwmod_class, 473 .class = &omap2xxx_timer_hwmod_class,
@@ -490,6 +505,7 @@ static struct omap_hwmod omap2420_timer6_hwmod = {
490 .idlest_idle_bit = OMAP24XX_ST_GPT6_SHIFT, 505 .idlest_idle_bit = OMAP24XX_ST_GPT6_SHIFT,
491 }, 506 },
492 }, 507 },
508 .dev_attr = &capability_alwon_dev_attr,
493 .slaves = omap2420_timer6_slaves, 509 .slaves = omap2420_timer6_slaves,
494 .slaves_cnt = ARRAY_SIZE(omap2420_timer6_slaves), 510 .slaves_cnt = ARRAY_SIZE(omap2420_timer6_slaves),
495 .class = &omap2xxx_timer_hwmod_class, 511 .class = &omap2xxx_timer_hwmod_class,
@@ -526,6 +542,7 @@ static struct omap_hwmod omap2420_timer7_hwmod = {
526 .idlest_idle_bit = OMAP24XX_ST_GPT7_SHIFT, 542 .idlest_idle_bit = OMAP24XX_ST_GPT7_SHIFT,
527 }, 543 },
528 }, 544 },
545 .dev_attr = &capability_alwon_dev_attr,
529 .slaves = omap2420_timer7_slaves, 546 .slaves = omap2420_timer7_slaves,
530 .slaves_cnt = ARRAY_SIZE(omap2420_timer7_slaves), 547 .slaves_cnt = ARRAY_SIZE(omap2420_timer7_slaves),
531 .class = &omap2xxx_timer_hwmod_class, 548 .class = &omap2xxx_timer_hwmod_class,
@@ -562,6 +579,7 @@ static struct omap_hwmod omap2420_timer8_hwmod = {
562 .idlest_idle_bit = OMAP24XX_ST_GPT8_SHIFT, 579 .idlest_idle_bit = OMAP24XX_ST_GPT8_SHIFT,
563 }, 580 },
564 }, 581 },
582 .dev_attr = &capability_alwon_dev_attr,
565 .slaves = omap2420_timer8_slaves, 583 .slaves = omap2420_timer8_slaves,
566 .slaves_cnt = ARRAY_SIZE(omap2420_timer8_slaves), 584 .slaves_cnt = ARRAY_SIZE(omap2420_timer8_slaves),
567 .class = &omap2xxx_timer_hwmod_class, 585 .class = &omap2xxx_timer_hwmod_class,
@@ -598,6 +616,7 @@ static struct omap_hwmod omap2420_timer9_hwmod = {
598 .idlest_idle_bit = OMAP24XX_ST_GPT9_SHIFT, 616 .idlest_idle_bit = OMAP24XX_ST_GPT9_SHIFT,
599 }, 617 },
600 }, 618 },
619 .dev_attr = &capability_pwm_dev_attr,
601 .slaves = omap2420_timer9_slaves, 620 .slaves = omap2420_timer9_slaves,
602 .slaves_cnt = ARRAY_SIZE(omap2420_timer9_slaves), 621 .slaves_cnt = ARRAY_SIZE(omap2420_timer9_slaves),
603 .class = &omap2xxx_timer_hwmod_class, 622 .class = &omap2xxx_timer_hwmod_class,
@@ -634,6 +653,7 @@ static struct omap_hwmod omap2420_timer10_hwmod = {
634 .idlest_idle_bit = OMAP24XX_ST_GPT10_SHIFT, 653 .idlest_idle_bit = OMAP24XX_ST_GPT10_SHIFT,
635 }, 654 },
636 }, 655 },
656 .dev_attr = &capability_pwm_dev_attr,
637 .slaves = omap2420_timer10_slaves, 657 .slaves = omap2420_timer10_slaves,
638 .slaves_cnt = ARRAY_SIZE(omap2420_timer10_slaves), 658 .slaves_cnt = ARRAY_SIZE(omap2420_timer10_slaves),
639 .class = &omap2xxx_timer_hwmod_class, 659 .class = &omap2xxx_timer_hwmod_class,
@@ -670,6 +690,7 @@ static struct omap_hwmod omap2420_timer11_hwmod = {
670 .idlest_idle_bit = OMAP24XX_ST_GPT11_SHIFT, 690 .idlest_idle_bit = OMAP24XX_ST_GPT11_SHIFT,
671 }, 691 },
672 }, 692 },
693 .dev_attr = &capability_pwm_dev_attr,
673 .slaves = omap2420_timer11_slaves, 694 .slaves = omap2420_timer11_slaves,
674 .slaves_cnt = ARRAY_SIZE(omap2420_timer11_slaves), 695 .slaves_cnt = ARRAY_SIZE(omap2420_timer11_slaves),
675 .class = &omap2xxx_timer_hwmod_class, 696 .class = &omap2xxx_timer_hwmod_class,
@@ -706,6 +727,7 @@ static struct omap_hwmod omap2420_timer12_hwmod = {
706 .idlest_idle_bit = OMAP24XX_ST_GPT12_SHIFT, 727 .idlest_idle_bit = OMAP24XX_ST_GPT12_SHIFT,
707 }, 728 },
708 }, 729 },
730 .dev_attr = &capability_pwm_dev_attr,
709 .slaves = omap2420_timer12_slaves, 731 .slaves = omap2420_timer12_slaves,
710 .slaves_cnt = ARRAY_SIZE(omap2420_timer12_slaves), 732 .slaves_cnt = ARRAY_SIZE(omap2420_timer12_slaves),
711 .class = &omap2xxx_timer_hwmod_class, 733 .class = &omap2xxx_timer_hwmod_class,
diff --git a/arch/arm/mach-omap2/omap_hwmod_2430_data.c b/arch/arm/mach-omap2/omap_hwmod_2430_data.c
index 56de8d616313..a2580d01c3ff 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2430_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2430_data.c
@@ -343,6 +343,16 @@ static struct omap_hwmod omap2430_iva_hwmod = {
343 .masters_cnt = ARRAY_SIZE(omap2430_iva_masters), 343 .masters_cnt = ARRAY_SIZE(omap2430_iva_masters),
344}; 344};
345 345
346/* always-on timers dev attribute */
347static struct omap_timer_capability_dev_attr capability_alwon_dev_attr = {
348 .timer_capability = OMAP_TIMER_ALWON,
349};
350
351/* pwm timers dev attribute */
352static struct omap_timer_capability_dev_attr capability_pwm_dev_attr = {
353 .timer_capability = OMAP_TIMER_HAS_PWM,
354};
355
346/* timer1 */ 356/* timer1 */
347static struct omap_hwmod omap2430_timer1_hwmod; 357static struct omap_hwmod omap2430_timer1_hwmod;
348 358
@@ -383,6 +393,7 @@ static struct omap_hwmod omap2430_timer1_hwmod = {
383 .idlest_idle_bit = OMAP24XX_ST_GPT1_SHIFT, 393 .idlest_idle_bit = OMAP24XX_ST_GPT1_SHIFT,
384 }, 394 },
385 }, 395 },
396 .dev_attr = &capability_alwon_dev_attr,
386 .slaves = omap2430_timer1_slaves, 397 .slaves = omap2430_timer1_slaves,
387 .slaves_cnt = ARRAY_SIZE(omap2430_timer1_slaves), 398 .slaves_cnt = ARRAY_SIZE(omap2430_timer1_slaves),
388 .class = &omap2xxx_timer_hwmod_class, 399 .class = &omap2xxx_timer_hwmod_class,
@@ -419,6 +430,7 @@ static struct omap_hwmod omap2430_timer2_hwmod = {
419 .idlest_idle_bit = OMAP24XX_ST_GPT2_SHIFT, 430 .idlest_idle_bit = OMAP24XX_ST_GPT2_SHIFT,
420 }, 431 },
421 }, 432 },
433 .dev_attr = &capability_alwon_dev_attr,
422 .slaves = omap2430_timer2_slaves, 434 .slaves = omap2430_timer2_slaves,
423 .slaves_cnt = ARRAY_SIZE(omap2430_timer2_slaves), 435 .slaves_cnt = ARRAY_SIZE(omap2430_timer2_slaves),
424 .class = &omap2xxx_timer_hwmod_class, 436 .class = &omap2xxx_timer_hwmod_class,
@@ -455,6 +467,7 @@ static struct omap_hwmod omap2430_timer3_hwmod = {
455 .idlest_idle_bit = OMAP24XX_ST_GPT3_SHIFT, 467 .idlest_idle_bit = OMAP24XX_ST_GPT3_SHIFT,
456 }, 468 },
457 }, 469 },
470 .dev_attr = &capability_alwon_dev_attr,
458 .slaves = omap2430_timer3_slaves, 471 .slaves = omap2430_timer3_slaves,
459 .slaves_cnt = ARRAY_SIZE(omap2430_timer3_slaves), 472 .slaves_cnt = ARRAY_SIZE(omap2430_timer3_slaves),
460 .class = &omap2xxx_timer_hwmod_class, 473 .class = &omap2xxx_timer_hwmod_class,
@@ -491,6 +504,7 @@ static struct omap_hwmod omap2430_timer4_hwmod = {
491 .idlest_idle_bit = OMAP24XX_ST_GPT4_SHIFT, 504 .idlest_idle_bit = OMAP24XX_ST_GPT4_SHIFT,
492 }, 505 },
493 }, 506 },
507 .dev_attr = &capability_alwon_dev_attr,
494 .slaves = omap2430_timer4_slaves, 508 .slaves = omap2430_timer4_slaves,
495 .slaves_cnt = ARRAY_SIZE(omap2430_timer4_slaves), 509 .slaves_cnt = ARRAY_SIZE(omap2430_timer4_slaves),
496 .class = &omap2xxx_timer_hwmod_class, 510 .class = &omap2xxx_timer_hwmod_class,
@@ -527,6 +541,7 @@ static struct omap_hwmod omap2430_timer5_hwmod = {
527 .idlest_idle_bit = OMAP24XX_ST_GPT5_SHIFT, 541 .idlest_idle_bit = OMAP24XX_ST_GPT5_SHIFT,
528 }, 542 },
529 }, 543 },
544 .dev_attr = &capability_alwon_dev_attr,
530 .slaves = omap2430_timer5_slaves, 545 .slaves = omap2430_timer5_slaves,
531 .slaves_cnt = ARRAY_SIZE(omap2430_timer5_slaves), 546 .slaves_cnt = ARRAY_SIZE(omap2430_timer5_slaves),
532 .class = &omap2xxx_timer_hwmod_class, 547 .class = &omap2xxx_timer_hwmod_class,
@@ -563,6 +578,7 @@ static struct omap_hwmod omap2430_timer6_hwmod = {
563 .idlest_idle_bit = OMAP24XX_ST_GPT6_SHIFT, 578 .idlest_idle_bit = OMAP24XX_ST_GPT6_SHIFT,
564 }, 579 },
565 }, 580 },
581 .dev_attr = &capability_alwon_dev_attr,
566 .slaves = omap2430_timer6_slaves, 582 .slaves = omap2430_timer6_slaves,
567 .slaves_cnt = ARRAY_SIZE(omap2430_timer6_slaves), 583 .slaves_cnt = ARRAY_SIZE(omap2430_timer6_slaves),
568 .class = &omap2xxx_timer_hwmod_class, 584 .class = &omap2xxx_timer_hwmod_class,
@@ -599,6 +615,7 @@ static struct omap_hwmod omap2430_timer7_hwmod = {
599 .idlest_idle_bit = OMAP24XX_ST_GPT7_SHIFT, 615 .idlest_idle_bit = OMAP24XX_ST_GPT7_SHIFT,
600 }, 616 },
601 }, 617 },
618 .dev_attr = &capability_alwon_dev_attr,
602 .slaves = omap2430_timer7_slaves, 619 .slaves = omap2430_timer7_slaves,
603 .slaves_cnt = ARRAY_SIZE(omap2430_timer7_slaves), 620 .slaves_cnt = ARRAY_SIZE(omap2430_timer7_slaves),
604 .class = &omap2xxx_timer_hwmod_class, 621 .class = &omap2xxx_timer_hwmod_class,
@@ -635,6 +652,7 @@ static struct omap_hwmod omap2430_timer8_hwmod = {
635 .idlest_idle_bit = OMAP24XX_ST_GPT8_SHIFT, 652 .idlest_idle_bit = OMAP24XX_ST_GPT8_SHIFT,
636 }, 653 },
637 }, 654 },
655 .dev_attr = &capability_alwon_dev_attr,
638 .slaves = omap2430_timer8_slaves, 656 .slaves = omap2430_timer8_slaves,
639 .slaves_cnt = ARRAY_SIZE(omap2430_timer8_slaves), 657 .slaves_cnt = ARRAY_SIZE(omap2430_timer8_slaves),
640 .class = &omap2xxx_timer_hwmod_class, 658 .class = &omap2xxx_timer_hwmod_class,
@@ -671,6 +689,7 @@ static struct omap_hwmod omap2430_timer9_hwmod = {
671 .idlest_idle_bit = OMAP24XX_ST_GPT9_SHIFT, 689 .idlest_idle_bit = OMAP24XX_ST_GPT9_SHIFT,
672 }, 690 },
673 }, 691 },
692 .dev_attr = &capability_pwm_dev_attr,
674 .slaves = omap2430_timer9_slaves, 693 .slaves = omap2430_timer9_slaves,
675 .slaves_cnt = ARRAY_SIZE(omap2430_timer9_slaves), 694 .slaves_cnt = ARRAY_SIZE(omap2430_timer9_slaves),
676 .class = &omap2xxx_timer_hwmod_class, 695 .class = &omap2xxx_timer_hwmod_class,
@@ -707,6 +726,7 @@ static struct omap_hwmod omap2430_timer10_hwmod = {
707 .idlest_idle_bit = OMAP24XX_ST_GPT10_SHIFT, 726 .idlest_idle_bit = OMAP24XX_ST_GPT10_SHIFT,
708 }, 727 },
709 }, 728 },
729 .dev_attr = &capability_pwm_dev_attr,
710 .slaves = omap2430_timer10_slaves, 730 .slaves = omap2430_timer10_slaves,
711 .slaves_cnt = ARRAY_SIZE(omap2430_timer10_slaves), 731 .slaves_cnt = ARRAY_SIZE(omap2430_timer10_slaves),
712 .class = &omap2xxx_timer_hwmod_class, 732 .class = &omap2xxx_timer_hwmod_class,
@@ -743,6 +763,7 @@ static struct omap_hwmod omap2430_timer11_hwmod = {
743 .idlest_idle_bit = OMAP24XX_ST_GPT11_SHIFT, 763 .idlest_idle_bit = OMAP24XX_ST_GPT11_SHIFT,
744 }, 764 },
745 }, 765 },
766 .dev_attr = &capability_pwm_dev_attr,
746 .slaves = omap2430_timer11_slaves, 767 .slaves = omap2430_timer11_slaves,
747 .slaves_cnt = ARRAY_SIZE(omap2430_timer11_slaves), 768 .slaves_cnt = ARRAY_SIZE(omap2430_timer11_slaves),
748 .class = &omap2xxx_timer_hwmod_class, 769 .class = &omap2xxx_timer_hwmod_class,
@@ -779,6 +800,7 @@ static struct omap_hwmod omap2430_timer12_hwmod = {
779 .idlest_idle_bit = OMAP24XX_ST_GPT12_SHIFT, 800 .idlest_idle_bit = OMAP24XX_ST_GPT12_SHIFT,
780 }, 801 },
781 }, 802 },
803 .dev_attr = &capability_pwm_dev_attr,
782 .slaves = omap2430_timer12_slaves, 804 .slaves = omap2430_timer12_slaves,
783 .slaves_cnt = ARRAY_SIZE(omap2430_timer12_slaves), 805 .slaves_cnt = ARRAY_SIZE(omap2430_timer12_slaves),
784 .class = &omap2xxx_timer_hwmod_class, 806 .class = &omap2xxx_timer_hwmod_class,
diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
index ab35acbc2d1d..2e4852d9574f 100644
--- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
@@ -564,6 +564,21 @@ static struct omap_hwmod_class omap3xxx_timer_hwmod_class = {
564 .rev = OMAP_TIMER_IP_VERSION_1, 564 .rev = OMAP_TIMER_IP_VERSION_1,
565}; 565};
566 566
567/* secure timers dev attribute */
568static struct omap_timer_capability_dev_attr capability_secure_dev_attr = {
569 .timer_capability = OMAP_TIMER_SECURE,
570};
571
572/* always-on timers dev attribute */
573static struct omap_timer_capability_dev_attr capability_alwon_dev_attr = {
574 .timer_capability = OMAP_TIMER_ALWON,
575};
576
577/* pwm timers dev attribute */
578static struct omap_timer_capability_dev_attr capability_pwm_dev_attr = {
579 .timer_capability = OMAP_TIMER_HAS_PWM,
580};
581
567/* timer1 */ 582/* timer1 */
568static struct omap_hwmod omap3xxx_timer1_hwmod; 583static struct omap_hwmod omap3xxx_timer1_hwmod;
569 584
@@ -604,6 +619,7 @@ static struct omap_hwmod omap3xxx_timer1_hwmod = {
604 .idlest_idle_bit = OMAP3430_ST_GPT1_SHIFT, 619 .idlest_idle_bit = OMAP3430_ST_GPT1_SHIFT,
605 }, 620 },
606 }, 621 },
622 .dev_attr = &capability_alwon_dev_attr,
607 .slaves = omap3xxx_timer1_slaves, 623 .slaves = omap3xxx_timer1_slaves,
608 .slaves_cnt = ARRAY_SIZE(omap3xxx_timer1_slaves), 624 .slaves_cnt = ARRAY_SIZE(omap3xxx_timer1_slaves),
609 .class = &omap3xxx_timer_1ms_hwmod_class, 625 .class = &omap3xxx_timer_1ms_hwmod_class,
@@ -649,6 +665,7 @@ static struct omap_hwmod omap3xxx_timer2_hwmod = {
649 .idlest_idle_bit = OMAP3430_ST_GPT2_SHIFT, 665 .idlest_idle_bit = OMAP3430_ST_GPT2_SHIFT,
650 }, 666 },
651 }, 667 },
668 .dev_attr = &capability_alwon_dev_attr,
652 .slaves = omap3xxx_timer2_slaves, 669 .slaves = omap3xxx_timer2_slaves,
653 .slaves_cnt = ARRAY_SIZE(omap3xxx_timer2_slaves), 670 .slaves_cnt = ARRAY_SIZE(omap3xxx_timer2_slaves),
654 .class = &omap3xxx_timer_1ms_hwmod_class, 671 .class = &omap3xxx_timer_1ms_hwmod_class,
@@ -694,6 +711,7 @@ static struct omap_hwmod omap3xxx_timer3_hwmod = {
694 .idlest_idle_bit = OMAP3430_ST_GPT3_SHIFT, 711 .idlest_idle_bit = OMAP3430_ST_GPT3_SHIFT,
695 }, 712 },
696 }, 713 },
714 .dev_attr = &capability_alwon_dev_attr,
697 .slaves = omap3xxx_timer3_slaves, 715 .slaves = omap3xxx_timer3_slaves,
698 .slaves_cnt = ARRAY_SIZE(omap3xxx_timer3_slaves), 716 .slaves_cnt = ARRAY_SIZE(omap3xxx_timer3_slaves),
699 .class = &omap3xxx_timer_hwmod_class, 717 .class = &omap3xxx_timer_hwmod_class,
@@ -739,6 +757,7 @@ static struct omap_hwmod omap3xxx_timer4_hwmod = {
739 .idlest_idle_bit = OMAP3430_ST_GPT4_SHIFT, 757 .idlest_idle_bit = OMAP3430_ST_GPT4_SHIFT,
740 }, 758 },
741 }, 759 },
760 .dev_attr = &capability_alwon_dev_attr,
742 .slaves = omap3xxx_timer4_slaves, 761 .slaves = omap3xxx_timer4_slaves,
743 .slaves_cnt = ARRAY_SIZE(omap3xxx_timer4_slaves), 762 .slaves_cnt = ARRAY_SIZE(omap3xxx_timer4_slaves),
744 .class = &omap3xxx_timer_hwmod_class, 763 .class = &omap3xxx_timer_hwmod_class,
@@ -784,6 +803,7 @@ static struct omap_hwmod omap3xxx_timer5_hwmod = {
784 .idlest_idle_bit = OMAP3430_ST_GPT5_SHIFT, 803 .idlest_idle_bit = OMAP3430_ST_GPT5_SHIFT,
785 }, 804 },
786 }, 805 },
806 .dev_attr = &capability_alwon_dev_attr,
787 .slaves = omap3xxx_timer5_slaves, 807 .slaves = omap3xxx_timer5_slaves,
788 .slaves_cnt = ARRAY_SIZE(omap3xxx_timer5_slaves), 808 .slaves_cnt = ARRAY_SIZE(omap3xxx_timer5_slaves),
789 .class = &omap3xxx_timer_hwmod_class, 809 .class = &omap3xxx_timer_hwmod_class,
@@ -829,6 +849,7 @@ static struct omap_hwmod omap3xxx_timer6_hwmod = {
829 .idlest_idle_bit = OMAP3430_ST_GPT6_SHIFT, 849 .idlest_idle_bit = OMAP3430_ST_GPT6_SHIFT,
830 }, 850 },
831 }, 851 },
852 .dev_attr = &capability_alwon_dev_attr,
832 .slaves = omap3xxx_timer6_slaves, 853 .slaves = omap3xxx_timer6_slaves,
833 .slaves_cnt = ARRAY_SIZE(omap3xxx_timer6_slaves), 854 .slaves_cnt = ARRAY_SIZE(omap3xxx_timer6_slaves),
834 .class = &omap3xxx_timer_hwmod_class, 855 .class = &omap3xxx_timer_hwmod_class,
@@ -874,6 +895,7 @@ static struct omap_hwmod omap3xxx_timer7_hwmod = {
874 .idlest_idle_bit = OMAP3430_ST_GPT7_SHIFT, 895 .idlest_idle_bit = OMAP3430_ST_GPT7_SHIFT,
875 }, 896 },
876 }, 897 },
898 .dev_attr = &capability_alwon_dev_attr,
877 .slaves = omap3xxx_timer7_slaves, 899 .slaves = omap3xxx_timer7_slaves,
878 .slaves_cnt = ARRAY_SIZE(omap3xxx_timer7_slaves), 900 .slaves_cnt = ARRAY_SIZE(omap3xxx_timer7_slaves),
879 .class = &omap3xxx_timer_hwmod_class, 901 .class = &omap3xxx_timer_hwmod_class,
@@ -919,6 +941,7 @@ static struct omap_hwmod omap3xxx_timer8_hwmod = {
919 .idlest_idle_bit = OMAP3430_ST_GPT8_SHIFT, 941 .idlest_idle_bit = OMAP3430_ST_GPT8_SHIFT,
920 }, 942 },
921 }, 943 },
944 .dev_attr = &capability_pwm_dev_attr,
922 .slaves = omap3xxx_timer8_slaves, 945 .slaves = omap3xxx_timer8_slaves,
923 .slaves_cnt = ARRAY_SIZE(omap3xxx_timer8_slaves), 946 .slaves_cnt = ARRAY_SIZE(omap3xxx_timer8_slaves),
924 .class = &omap3xxx_timer_hwmod_class, 947 .class = &omap3xxx_timer_hwmod_class,
@@ -964,6 +987,7 @@ static struct omap_hwmod omap3xxx_timer9_hwmod = {
964 .idlest_idle_bit = OMAP3430_ST_GPT9_SHIFT, 987 .idlest_idle_bit = OMAP3430_ST_GPT9_SHIFT,
965 }, 988 },
966 }, 989 },
990 .dev_attr = &capability_pwm_dev_attr,
967 .slaves = omap3xxx_timer9_slaves, 991 .slaves = omap3xxx_timer9_slaves,
968 .slaves_cnt = ARRAY_SIZE(omap3xxx_timer9_slaves), 992 .slaves_cnt = ARRAY_SIZE(omap3xxx_timer9_slaves),
969 .class = &omap3xxx_timer_hwmod_class, 993 .class = &omap3xxx_timer_hwmod_class,
@@ -1000,6 +1024,7 @@ static struct omap_hwmod omap3xxx_timer10_hwmod = {
1000 .idlest_idle_bit = OMAP3430_ST_GPT10_SHIFT, 1024 .idlest_idle_bit = OMAP3430_ST_GPT10_SHIFT,
1001 }, 1025 },
1002 }, 1026 },
1027 .dev_attr = &capability_pwm_dev_attr,
1003 .slaves = omap3xxx_timer10_slaves, 1028 .slaves = omap3xxx_timer10_slaves,
1004 .slaves_cnt = ARRAY_SIZE(omap3xxx_timer10_slaves), 1029 .slaves_cnt = ARRAY_SIZE(omap3xxx_timer10_slaves),
1005 .class = &omap3xxx_timer_1ms_hwmod_class, 1030 .class = &omap3xxx_timer_1ms_hwmod_class,
@@ -1036,6 +1061,7 @@ static struct omap_hwmod omap3xxx_timer11_hwmod = {
1036 .idlest_idle_bit = OMAP3430_ST_GPT11_SHIFT, 1061 .idlest_idle_bit = OMAP3430_ST_GPT11_SHIFT,
1037 }, 1062 },
1038 }, 1063 },
1064 .dev_attr = &capability_pwm_dev_attr,
1039 .slaves = omap3xxx_timer11_slaves, 1065 .slaves = omap3xxx_timer11_slaves,
1040 .slaves_cnt = ARRAY_SIZE(omap3xxx_timer11_slaves), 1066 .slaves_cnt = ARRAY_SIZE(omap3xxx_timer11_slaves),
1041 .class = &omap3xxx_timer_hwmod_class, 1067 .class = &omap3xxx_timer_hwmod_class,
@@ -1085,6 +1111,7 @@ static struct omap_hwmod omap3xxx_timer12_hwmod = {
1085 .idlest_idle_bit = OMAP3430_ST_GPT12_SHIFT, 1111 .idlest_idle_bit = OMAP3430_ST_GPT12_SHIFT,
1086 }, 1112 },
1087 }, 1113 },
1114 .dev_attr = &capability_secure_dev_attr,
1088 .slaves = omap3xxx_timer12_slaves, 1115 .slaves = omap3xxx_timer12_slaves,
1089 .slaves_cnt = ARRAY_SIZE(omap3xxx_timer12_slaves), 1116 .slaves_cnt = ARRAY_SIZE(omap3xxx_timer12_slaves),
1090 .class = &omap3xxx_timer_hwmod_class, 1117 .class = &omap3xxx_timer_hwmod_class,
diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
index fd1074a024b8..7695e5d43316 100644
--- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
@@ -29,6 +29,7 @@
29#include <plat/mcbsp.h> 29#include <plat/mcbsp.h>
30#include <plat/mmc.h> 30#include <plat/mmc.h>
31#include <plat/i2c.h> 31#include <plat/i2c.h>
32#include <plat/dmtimer.h>
32 33
33#include "omap_hwmod_common_data.h" 34#include "omap_hwmod_common_data.h"
34 35
@@ -4201,6 +4202,16 @@ static struct omap_hwmod_class omap44xx_timer_hwmod_class = {
4201 .sysc = &omap44xx_timer_sysc, 4202 .sysc = &omap44xx_timer_sysc,
4202}; 4203};
4203 4204
4205/* always-on timers dev attribute */
4206static struct omap_timer_capability_dev_attr capability_alwon_dev_attr = {
4207 .timer_capability = OMAP_TIMER_ALWON,
4208};
4209
4210/* pwm timers dev attribute */
4211static struct omap_timer_capability_dev_attr capability_pwm_dev_attr = {
4212 .timer_capability = OMAP_TIMER_HAS_PWM,
4213};
4214
4204/* timer1 */ 4215/* timer1 */
4205static struct omap_hwmod omap44xx_timer1_hwmod; 4216static struct omap_hwmod omap44xx_timer1_hwmod;
4206static struct omap_hwmod_irq_info omap44xx_timer1_irqs[] = { 4217static struct omap_hwmod_irq_info omap44xx_timer1_irqs[] = {
@@ -4244,6 +4255,7 @@ static struct omap_hwmod omap44xx_timer1_hwmod = {
4244 .modulemode = MODULEMODE_SWCTRL, 4255 .modulemode = MODULEMODE_SWCTRL,
4245 }, 4256 },
4246 }, 4257 },
4258 .dev_attr = &capability_alwon_dev_attr,
4247 .slaves = omap44xx_timer1_slaves, 4259 .slaves = omap44xx_timer1_slaves,
4248 .slaves_cnt = ARRAY_SIZE(omap44xx_timer1_slaves), 4260 .slaves_cnt = ARRAY_SIZE(omap44xx_timer1_slaves),
4249}; 4261};
@@ -4291,6 +4303,7 @@ static struct omap_hwmod omap44xx_timer2_hwmod = {
4291 .modulemode = MODULEMODE_SWCTRL, 4303 .modulemode = MODULEMODE_SWCTRL,
4292 }, 4304 },
4293 }, 4305 },
4306 .dev_attr = &capability_alwon_dev_attr,
4294 .slaves = omap44xx_timer2_slaves, 4307 .slaves = omap44xx_timer2_slaves,
4295 .slaves_cnt = ARRAY_SIZE(omap44xx_timer2_slaves), 4308 .slaves_cnt = ARRAY_SIZE(omap44xx_timer2_slaves),
4296}; 4309};
@@ -4338,6 +4351,7 @@ static struct omap_hwmod omap44xx_timer3_hwmod = {
4338 .modulemode = MODULEMODE_SWCTRL, 4351 .modulemode = MODULEMODE_SWCTRL,
4339 }, 4352 },
4340 }, 4353 },
4354 .dev_attr = &capability_alwon_dev_attr,
4341 .slaves = omap44xx_timer3_slaves, 4355 .slaves = omap44xx_timer3_slaves,
4342 .slaves_cnt = ARRAY_SIZE(omap44xx_timer3_slaves), 4356 .slaves_cnt = ARRAY_SIZE(omap44xx_timer3_slaves),
4343}; 4357};
@@ -4385,6 +4399,7 @@ static struct omap_hwmod omap44xx_timer4_hwmod = {
4385 .modulemode = MODULEMODE_SWCTRL, 4399 .modulemode = MODULEMODE_SWCTRL,
4386 }, 4400 },
4387 }, 4401 },
4402 .dev_attr = &capability_alwon_dev_attr,
4388 .slaves = omap44xx_timer4_slaves, 4403 .slaves = omap44xx_timer4_slaves,
4389 .slaves_cnt = ARRAY_SIZE(omap44xx_timer4_slaves), 4404 .slaves_cnt = ARRAY_SIZE(omap44xx_timer4_slaves),
4390}; 4405};
@@ -4451,6 +4466,7 @@ static struct omap_hwmod omap44xx_timer5_hwmod = {
4451 .modulemode = MODULEMODE_SWCTRL, 4466 .modulemode = MODULEMODE_SWCTRL,
4452 }, 4467 },
4453 }, 4468 },
4469 .dev_attr = &capability_alwon_dev_attr,
4454 .slaves = omap44xx_timer5_slaves, 4470 .slaves = omap44xx_timer5_slaves,
4455 .slaves_cnt = ARRAY_SIZE(omap44xx_timer5_slaves), 4471 .slaves_cnt = ARRAY_SIZE(omap44xx_timer5_slaves),
4456}; 4472};
@@ -4518,6 +4534,7 @@ static struct omap_hwmod omap44xx_timer6_hwmod = {
4518 .modulemode = MODULEMODE_SWCTRL, 4534 .modulemode = MODULEMODE_SWCTRL,
4519 }, 4535 },
4520 }, 4536 },
4537 .dev_attr = &capability_alwon_dev_attr,
4521 .slaves = omap44xx_timer6_slaves, 4538 .slaves = omap44xx_timer6_slaves,
4522 .slaves_cnt = ARRAY_SIZE(omap44xx_timer6_slaves), 4539 .slaves_cnt = ARRAY_SIZE(omap44xx_timer6_slaves),
4523}; 4540};
@@ -4584,6 +4601,7 @@ static struct omap_hwmod omap44xx_timer7_hwmod = {
4584 .modulemode = MODULEMODE_SWCTRL, 4601 .modulemode = MODULEMODE_SWCTRL,
4585 }, 4602 },
4586 }, 4603 },
4604 .dev_attr = &capability_alwon_dev_attr,
4587 .slaves = omap44xx_timer7_slaves, 4605 .slaves = omap44xx_timer7_slaves,
4588 .slaves_cnt = ARRAY_SIZE(omap44xx_timer7_slaves), 4606 .slaves_cnt = ARRAY_SIZE(omap44xx_timer7_slaves),
4589}; 4607};
@@ -4650,6 +4668,7 @@ static struct omap_hwmod omap44xx_timer8_hwmod = {
4650 .modulemode = MODULEMODE_SWCTRL, 4668 .modulemode = MODULEMODE_SWCTRL,
4651 }, 4669 },
4652 }, 4670 },
4671 .dev_attr = &capability_pwm_dev_attr,
4653 .slaves = omap44xx_timer8_slaves, 4672 .slaves = omap44xx_timer8_slaves,
4654 .slaves_cnt = ARRAY_SIZE(omap44xx_timer8_slaves), 4673 .slaves_cnt = ARRAY_SIZE(omap44xx_timer8_slaves),
4655}; 4674};
@@ -4697,6 +4716,7 @@ static struct omap_hwmod omap44xx_timer9_hwmod = {
4697 .modulemode = MODULEMODE_SWCTRL, 4716 .modulemode = MODULEMODE_SWCTRL,
4698 }, 4717 },
4699 }, 4718 },
4719 .dev_attr = &capability_pwm_dev_attr,
4700 .slaves = omap44xx_timer9_slaves, 4720 .slaves = omap44xx_timer9_slaves,
4701 .slaves_cnt = ARRAY_SIZE(omap44xx_timer9_slaves), 4721 .slaves_cnt = ARRAY_SIZE(omap44xx_timer9_slaves),
4702}; 4722};
@@ -4744,6 +4764,7 @@ static struct omap_hwmod omap44xx_timer10_hwmod = {
4744 .modulemode = MODULEMODE_SWCTRL, 4764 .modulemode = MODULEMODE_SWCTRL,
4745 }, 4765 },
4746 }, 4766 },
4767 .dev_attr = &capability_pwm_dev_attr,
4747 .slaves = omap44xx_timer10_slaves, 4768 .slaves = omap44xx_timer10_slaves,
4748 .slaves_cnt = ARRAY_SIZE(omap44xx_timer10_slaves), 4769 .slaves_cnt = ARRAY_SIZE(omap44xx_timer10_slaves),
4749}; 4770};
@@ -4791,6 +4812,7 @@ static struct omap_hwmod omap44xx_timer11_hwmod = {
4791 .modulemode = MODULEMODE_SWCTRL, 4812 .modulemode = MODULEMODE_SWCTRL,
4792 }, 4813 },
4793 }, 4814 },
4815 .dev_attr = &capability_pwm_dev_attr,
4794 .slaves = omap44xx_timer11_slaves, 4816 .slaves = omap44xx_timer11_slaves,
4795 .slaves_cnt = ARRAY_SIZE(omap44xx_timer11_slaves), 4817 .slaves_cnt = ARRAY_SIZE(omap44xx_timer11_slaves),
4796}; 4818};
diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c
index cf1de7d2630d..1140e98c9773 100644
--- a/arch/arm/mach-omap2/timer.c
+++ b/arch/arm/mach-omap2/timer.c
@@ -35,6 +35,7 @@
35#include <linux/irq.h> 35#include <linux/irq.h>
36#include <linux/clocksource.h> 36#include <linux/clocksource.h>
37#include <linux/clockchips.h> 37#include <linux/clockchips.h>
38#include <linux/slab.h>
38 39
39#include <asm/mach/time.h> 40#include <asm/mach/time.h>
40#include <plat/dmtimer.h> 41#include <plat/dmtimer.h>
@@ -42,6 +43,10 @@
42#include <asm/sched_clock.h> 43#include <asm/sched_clock.h>
43#include <plat/common.h> 44#include <plat/common.h>
44#include <plat/omap_hwmod.h> 45#include <plat/omap_hwmod.h>
46#include <plat/omap_device.h>
47#include <plat/omap-pm.h>
48
49#include "powerdomain.h"
45 50
46/* Parent clocks, eventually these will come from the clock framework */ 51/* Parent clocks, eventually these will come from the clock framework */
47 52
@@ -67,7 +72,7 @@
67/* MAX_GPTIMER_ID: number of GPTIMERs on the chip */ 72/* MAX_GPTIMER_ID: number of GPTIMERs on the chip */
68#define MAX_GPTIMER_ID 12 73#define MAX_GPTIMER_ID 12
69 74
70u32 sys_timer_reserved; 75static u32 sys_timer_reserved;
71 76
72/* Clockevent code */ 77/* Clockevent code */
73 78
@@ -78,7 +83,7 @@ static irqreturn_t omap2_gp_timer_interrupt(int irq, void *dev_id)
78{ 83{
79 struct clock_event_device *evt = &clockevent_gpt; 84 struct clock_event_device *evt = &clockevent_gpt;
80 85
81 __omap_dm_timer_write_status(clkev.io_base, OMAP_TIMER_INT_OVERFLOW); 86 __omap_dm_timer_write_status(&clkev, OMAP_TIMER_INT_OVERFLOW);
82 87
83 evt->event_handler(evt); 88 evt->event_handler(evt);
84 return IRQ_HANDLED; 89 return IRQ_HANDLED;
@@ -93,7 +98,7 @@ static struct irqaction omap2_gp_timer_irq = {
93static int omap2_gp_timer_set_next_event(unsigned long cycles, 98static int omap2_gp_timer_set_next_event(unsigned long cycles,
94 struct clock_event_device *evt) 99 struct clock_event_device *evt)
95{ 100{
96 __omap_dm_timer_load_start(clkev.io_base, OMAP_TIMER_CTRL_ST, 101 __omap_dm_timer_load_start(&clkev, OMAP_TIMER_CTRL_ST,
97 0xffffffff - cycles, 1); 102 0xffffffff - cycles, 1);
98 103
99 return 0; 104 return 0;
@@ -104,16 +109,16 @@ static void omap2_gp_timer_set_mode(enum clock_event_mode mode,
104{ 109{
105 u32 period; 110 u32 period;
106 111
107 __omap_dm_timer_stop(clkev.io_base, 1, clkev.rate); 112 __omap_dm_timer_stop(&clkev, 1, clkev.rate);
108 113
109 switch (mode) { 114 switch (mode) {
110 case CLOCK_EVT_MODE_PERIODIC: 115 case CLOCK_EVT_MODE_PERIODIC:
111 period = clkev.rate / HZ; 116 period = clkev.rate / HZ;
112 period -= 1; 117 period -= 1;
113 /* Looks like we need to first set the load value separately */ 118 /* Looks like we need to first set the load value separately */
114 __omap_dm_timer_write(clkev.io_base, OMAP_TIMER_LOAD_REG, 119 __omap_dm_timer_write(&clkev, OMAP_TIMER_LOAD_REG,
115 0xffffffff - period, 1); 120 0xffffffff - period, 1);
116 __omap_dm_timer_load_start(clkev.io_base, 121 __omap_dm_timer_load_start(&clkev,
117 OMAP_TIMER_CTRL_AR | OMAP_TIMER_CTRL_ST, 122 OMAP_TIMER_CTRL_AR | OMAP_TIMER_CTRL_ST,
118 0xffffffff - period, 1); 123 0xffffffff - period, 1);
119 break; 124 break;
@@ -189,7 +194,8 @@ static int __init omap_dm_timer_init_one(struct omap_dm_timer *timer,
189 clk_put(src); 194 clk_put(src);
190 } 195 }
191 } 196 }
192 __omap_dm_timer_reset(timer->io_base, 1, 1); 197 __omap_dm_timer_init_regs(timer);
198 __omap_dm_timer_reset(timer, 1, 1);
193 timer->posted = 1; 199 timer->posted = 1;
194 200
195 timer->rate = clk_get_rate(timer->fclk); 201 timer->rate = clk_get_rate(timer->fclk);
@@ -210,7 +216,7 @@ static void __init omap2_gp_clockevent_init(int gptimer_id,
210 omap2_gp_timer_irq.dev_id = (void *)&clkev; 216 omap2_gp_timer_irq.dev_id = (void *)&clkev;
211 setup_irq(clkev.irq, &omap2_gp_timer_irq); 217 setup_irq(clkev.irq, &omap2_gp_timer_irq);
212 218
213 __omap_dm_timer_int_enable(clkev.io_base, OMAP_TIMER_INT_OVERFLOW); 219 __omap_dm_timer_int_enable(&clkev, OMAP_TIMER_INT_OVERFLOW);
214 220
215 clockevent_gpt.mult = div_sc(clkev.rate, NSEC_PER_SEC, 221 clockevent_gpt.mult = div_sc(clkev.rate, NSEC_PER_SEC,
216 clockevent_gpt.shift); 222 clockevent_gpt.shift);
@@ -251,7 +257,7 @@ static struct omap_dm_timer clksrc;
251static DEFINE_CLOCK_DATA(cd); 257static DEFINE_CLOCK_DATA(cd);
252static cycle_t clocksource_read_cycles(struct clocksource *cs) 258static cycle_t clocksource_read_cycles(struct clocksource *cs)
253{ 259{
254 return (cycle_t)__omap_dm_timer_read_counter(clksrc.io_base, 1); 260 return (cycle_t)__omap_dm_timer_read_counter(&clksrc, 1);
255} 261}
256 262
257static struct clocksource clocksource_gpt = { 263static struct clocksource clocksource_gpt = {
@@ -266,7 +272,7 @@ static void notrace dmtimer_update_sched_clock(void)
266{ 272{
267 u32 cyc; 273 u32 cyc;
268 274
269 cyc = __omap_dm_timer_read_counter(clksrc.io_base, 1); 275 cyc = __omap_dm_timer_read_counter(&clksrc, 1);
270 276
271 update_sched_clock(&cd, cyc, (u32)~0); 277 update_sched_clock(&cd, cyc, (u32)~0);
272} 278}
@@ -276,7 +282,7 @@ unsigned long long notrace sched_clock(void)
276 u32 cyc = 0; 282 u32 cyc = 0;
277 283
278 if (clksrc.reserved) 284 if (clksrc.reserved)
279 cyc = __omap_dm_timer_read_counter(clksrc.io_base, 1); 285 cyc = __omap_dm_timer_read_counter(&clksrc, 1);
280 286
281 return cyc_to_sched_clock(&cd, cyc, (u32)~0); 287 return cyc_to_sched_clock(&cd, cyc, (u32)~0);
282} 288}
@@ -293,7 +299,7 @@ static void __init omap2_gp_clocksource_init(int gptimer_id,
293 pr_info("OMAP clocksource: GPTIMER%d at %lu Hz\n", 299 pr_info("OMAP clocksource: GPTIMER%d at %lu Hz\n",
294 gptimer_id, clksrc.rate); 300 gptimer_id, clksrc.rate);
295 301
296 __omap_dm_timer_load_start(clksrc.io_base, 302 __omap_dm_timer_load_start(&clksrc,
297 OMAP_TIMER_CTRL_ST | OMAP_TIMER_CTRL_AR, 0, 1); 303 OMAP_TIMER_CTRL_ST | OMAP_TIMER_CTRL_AR, 0, 1);
298 init_sched_clock(&cd, dmtimer_update_sched_clock, 32, clksrc.rate); 304 init_sched_clock(&cd, dmtimer_update_sched_clock, 32, clksrc.rate);
299 305
@@ -341,3 +347,167 @@ static void __init omap4_timer_init(void)
341} 347}
342OMAP_SYS_TIMER(4) 348OMAP_SYS_TIMER(4)
343#endif 349#endif
350
351/**
352 * omap2_dm_timer_set_src - change the timer input clock source
353 * @pdev: timer platform device pointer
354 * @source: array index of parent clock source
355 */
356static int omap2_dm_timer_set_src(struct platform_device *pdev, int source)
357{
358 int ret;
359 struct dmtimer_platform_data *pdata = pdev->dev.platform_data;
360 struct clk *fclk, *parent;
361 char *parent_name = NULL;
362
363 fclk = clk_get(&pdev->dev, "fck");
364 if (IS_ERR_OR_NULL(fclk)) {
365 dev_err(&pdev->dev, "%s: %d: clk_get() FAILED\n",
366 __func__, __LINE__);
367 return -EINVAL;
368 }
369
370 switch (source) {
371 case OMAP_TIMER_SRC_SYS_CLK:
372 parent_name = "sys_ck";
373 break;
374
375 case OMAP_TIMER_SRC_32_KHZ:
376 parent_name = "32k_ck";
377 break;
378
379 case OMAP_TIMER_SRC_EXT_CLK:
380 if (pdata->timer_ip_version == OMAP_TIMER_IP_VERSION_1) {
381 parent_name = "alt_ck";
382 break;
383 }
384 dev_err(&pdev->dev, "%s: %d: invalid clk src.\n",
385 __func__, __LINE__);
386 clk_put(fclk);
387 return -EINVAL;
388 }
389
390 parent = clk_get(&pdev->dev, parent_name);
391 if (IS_ERR_OR_NULL(parent)) {
392 dev_err(&pdev->dev, "%s: %d: clk_get() %s FAILED\n",
393 __func__, __LINE__, parent_name);
394 clk_put(fclk);
395 return -EINVAL;
396 }
397
398 ret = clk_set_parent(fclk, parent);
399 if (IS_ERR_VALUE(ret)) {
400 dev_err(&pdev->dev, "%s: clk_set_parent() to %s FAILED\n",
401 __func__, parent_name);
402 ret = -EINVAL;
403 }
404
405 clk_put(parent);
406 clk_put(fclk);
407
408 return ret;
409}
410
411struct omap_device_pm_latency omap2_dmtimer_latency[] = {
412 {
413 .deactivate_func = omap_device_idle_hwmods,
414 .activate_func = omap_device_enable_hwmods,
415 .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
416 },
417};
418
419/**
420 * omap_timer_init - build and register timer device with an
421 * associated timer hwmod
422 * @oh: timer hwmod pointer to be used to build timer device
423 * @user: parameter that can be passed from calling hwmod API
424 *
425 * Called by omap_hwmod_for_each_by_class to register each of the timer
426 * devices present in the system. The number of timer devices is known
427 * by parsing through the hwmod database for a given class name. At the
428 * end of function call memory is allocated for timer device and it is
429 * registered to the framework ready to be proved by the driver.
430 */
431static int __init omap_timer_init(struct omap_hwmod *oh, void *unused)
432{
433 int id;
434 int ret = 0;
435 char *name = "omap_timer";
436 struct dmtimer_platform_data *pdata;
437 struct omap_device *od;
438 struct omap_timer_capability_dev_attr *timer_dev_attr;
439 struct powerdomain *pwrdm;
440
441 pr_debug("%s: %s\n", __func__, oh->name);
442
443 /* on secure device, do not register secure timer */
444 timer_dev_attr = oh->dev_attr;
445 if (omap_type() != OMAP2_DEVICE_TYPE_GP && timer_dev_attr)
446 if (timer_dev_attr->timer_capability == OMAP_TIMER_SECURE)
447 return ret;
448
449 pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
450 if (!pdata) {
451 pr_err("%s: No memory for [%s]\n", __func__, oh->name);
452 return -ENOMEM;
453 }
454
455 /*
456 * Extract the IDs from name field in hwmod database
457 * and use the same for constructing ids' for the
458 * timer devices. In a way, we are avoiding usage of
459 * static variable witin the function to do the same.
460 * CAUTION: We have to be careful and make sure the
461 * name in hwmod database does not change in which case
462 * we might either make corresponding change here or
463 * switch back static variable mechanism.
464 */
465 sscanf(oh->name, "timer%2d", &id);
466
467 pdata->set_timer_src = omap2_dm_timer_set_src;
468 pdata->timer_ip_version = oh->class->rev;
469
470 /* Mark clocksource and clockevent timers as reserved */
471 if ((sys_timer_reserved >> (id - 1)) & 0x1)
472 pdata->reserved = 1;
473
474 pwrdm = omap_hwmod_get_pwrdm(oh);
475 pdata->loses_context = pwrdm_can_ever_lose_context(pwrdm);
476#ifdef CONFIG_PM
477 pdata->get_context_loss_count = omap_pm_get_dev_context_loss_count;
478#endif
479 od = omap_device_build(name, id, oh, pdata, sizeof(*pdata),
480 omap2_dmtimer_latency,
481 ARRAY_SIZE(omap2_dmtimer_latency),
482 0);
483
484 if (IS_ERR(od)) {
485 pr_err("%s: Can't build omap_device for %s: %s.\n",
486 __func__, name, oh->name);
487 ret = -EINVAL;
488 }
489
490 kfree(pdata);
491
492 return ret;
493}
494
495/**
496 * omap2_dm_timer_init - top level regular device initialization
497 *
498 * Uses dedicated hwmod api to parse through hwmod database for
499 * given class name and then build and register the timer device.
500 */
501static int __init omap2_dm_timer_init(void)
502{
503 int ret;
504
505 ret = omap_hwmod_for_each_by_class("timer", omap_timer_init, NULL);
506 if (unlikely(ret)) {
507 pr_err("%s: device registration failed.\n", __func__);
508 return -EINVAL;
509 }
510
511 return 0;
512}
513arch_initcall(omap2_dm_timer_init);
diff --git a/arch/arm/mach-ux500/Makefile b/arch/arm/mach-ux500/Makefile
index 9fd00a6d4248..6bd2f451c185 100644
--- a/arch/arm/mach-ux500/Makefile
+++ b/arch/arm/mach-ux500/Makefile
@@ -3,7 +3,7 @@
3# 3#
4 4
5obj-y := clock.o cpu.o devices.o devices-common.o \ 5obj-y := clock.o cpu.o devices.o devices-common.o \
6 id.o usb.o 6 id.o usb.o timer.o
7obj-$(CONFIG_CACHE_L2X0) += cache-l2x0.o 7obj-$(CONFIG_CACHE_L2X0) += cache-l2x0.o
8obj-$(CONFIG_UX500_SOC_DB5500) += cpu-db5500.o dma-db5500.o 8obj-$(CONFIG_UX500_SOC_DB5500) += cpu-db5500.o dma-db5500.o
9obj-$(CONFIG_UX500_SOC_DB8500) += cpu-db8500.o devices-db8500.o 9obj-$(CONFIG_UX500_SOC_DB8500) += cpu-db8500.o devices-db8500.o
diff --git a/arch/arm/mach-ux500/cpu.c b/arch/arm/mach-ux500/cpu.c
index 252e8b3c5706..1405d0eb7edb 100644
--- a/arch/arm/mach-ux500/cpu.c
+++ b/arch/arm/mach-ux500/cpu.c
@@ -10,12 +10,12 @@
10#include <linux/clk.h> 10#include <linux/clk.h>
11#include <linux/mfd/db8500-prcmu.h> 11#include <linux/mfd/db8500-prcmu.h>
12#include <linux/mfd/db5500-prcmu.h> 12#include <linux/mfd/db5500-prcmu.h>
13#include <linux/clksrc-dbx500-prcmu.h>
13 14
14#include <asm/hardware/gic.h> 15#include <asm/hardware/gic.h>
15#include <asm/mach/map.h> 16#include <asm/mach/map.h>
16#include <asm/localtimer.h> 17#include <asm/localtimer.h>
17 18
18#include <plat/mtu.h>
19#include <mach/hardware.h> 19#include <mach/hardware.h>
20#include <mach/setup.h> 20#include <mach/setup.h>
21#include <mach/devices.h> 21#include <mach/devices.h>
@@ -50,30 +50,3 @@ void __init ux500_init_irq(void)
50 prcmu_early_init(); 50 prcmu_early_init();
51 clk_init(); 51 clk_init();
52} 52}
53
54static void __init ux500_timer_init(void)
55{
56#ifdef CONFIG_LOCAL_TIMERS
57 /* Setup the local timer base */
58 if (cpu_is_u5500())
59 twd_base = __io_address(U5500_TWD_BASE);
60 else if (cpu_is_u8500())
61 twd_base = __io_address(U8500_TWD_BASE);
62 else
63 ux500_unknown_soc();
64#endif
65 if (cpu_is_u5500())
66 mtu_base = __io_address(U5500_MTU0_BASE);
67 else if (cpu_is_u8500ed())
68 mtu_base = __io_address(U8500_MTU0_BASE_ED);
69 else if (cpu_is_u8500())
70 mtu_base = __io_address(U8500_MTU0_BASE);
71 else
72 ux500_unknown_soc();
73
74 nmdk_timer_init();
75}
76
77struct sys_timer ux500_timer = {
78 .init = ux500_timer_init,
79};
diff --git a/arch/arm/mach-ux500/include/mach/db5500-regs.h b/arch/arm/mach-ux500/include/mach/db5500-regs.h
index 6ad983294103..994b5fe6f85a 100644
--- a/arch/arm/mach-ux500/include/mach/db5500-regs.h
+++ b/arch/arm/mach-ux500/include/mach/db5500-regs.h
@@ -61,6 +61,8 @@
61#define U5500_SCR_BASE (U5500_PER4_BASE + 0x5000) 61#define U5500_SCR_BASE (U5500_PER4_BASE + 0x5000)
62#define U5500_DMC_BASE (U5500_PER4_BASE + 0x6000) 62#define U5500_DMC_BASE (U5500_PER4_BASE + 0x6000)
63#define U5500_PRCMU_BASE (U5500_PER4_BASE + 0x7000) 63#define U5500_PRCMU_BASE (U5500_PER4_BASE + 0x7000)
64#define U5500_PRCMU_TIMER_3_BASE (U5500_PER4_BASE + 0x07338)
65#define U5500_PRCMU_TIMER_4_BASE (U5500_PER4_BASE + 0x07450)
64#define U5500_MSP1_BASE (U5500_PER4_BASE + 0x9000) 66#define U5500_MSP1_BASE (U5500_PER4_BASE + 0x9000)
65#define U5500_GPIO2_BASE (U5500_PER4_BASE + 0xA000) 67#define U5500_GPIO2_BASE (U5500_PER4_BASE + 0xA000)
66#define U5500_CDETECT_BASE (U5500_PER4_BASE + 0xF000) 68#define U5500_CDETECT_BASE (U5500_PER4_BASE + 0xF000)
diff --git a/arch/arm/mach-ux500/include/mach/db8500-regs.h b/arch/arm/mach-ux500/include/mach/db8500-regs.h
index 049997109cf9..751b0e6938d4 100644
--- a/arch/arm/mach-ux500/include/mach/db8500-regs.h
+++ b/arch/arm/mach-ux500/include/mach/db8500-regs.h
@@ -102,10 +102,13 @@
102#define U8500_SCR_BASE (U8500_PER4_BASE + 0x05000) 102#define U8500_SCR_BASE (U8500_PER4_BASE + 0x05000)
103#define U8500_DMC_BASE (U8500_PER4_BASE + 0x06000) 103#define U8500_DMC_BASE (U8500_PER4_BASE + 0x06000)
104#define U8500_PRCMU_BASE (U8500_PER4_BASE + 0x07000) 104#define U8500_PRCMU_BASE (U8500_PER4_BASE + 0x07000)
105#define U8500_PRCMU_TIMER_3_BASE (U8500_PER4_BASE + 0x07338)
106#define U8500_PRCMU_TIMER_4_BASE (U8500_PER4_BASE + 0x07450)
105#define U8500_PRCMU_TCDM_BASE_V1 (U8500_PER4_BASE + 0x0f000) 107#define U8500_PRCMU_TCDM_BASE_V1 (U8500_PER4_BASE + 0x0f000)
106#define U8500_PRCMU_TCDM_BASE (U8500_PER4_BASE + 0x68000) 108#define U8500_PRCMU_TCDM_BASE (U8500_PER4_BASE + 0x68000)
107#define U8500_PRCMU_TCPM_BASE (U8500_PER4_BASE + 0x60000) 109#define U8500_PRCMU_TCPM_BASE (U8500_PER4_BASE + 0x60000)
108 110
111
109/* per3 base addresses */ 112/* per3 base addresses */
110#define U8500_FSMC_BASE (U8500_PER3_BASE + 0x0000) 113#define U8500_FSMC_BASE (U8500_PER3_BASE + 0x0000)
111#define U8500_SSP0_BASE (U8500_PER3_BASE + 0x2000) 114#define U8500_SSP0_BASE (U8500_PER3_BASE + 0x2000)
diff --git a/arch/arm/mach-ux500/timer.c b/arch/arm/mach-ux500/timer.c
new file mode 100644
index 000000000000..aea467d04ff7
--- /dev/null
+++ b/arch/arm/mach-ux500/timer.c
@@ -0,0 +1,68 @@
1/*
2 * Copyright (C) ST-Ericsson SA 2011
3 *
4 * License Terms: GNU General Public License v2
5 * Author: Mattias Wallin <mattias.wallin@stericsson.com> for ST-Ericsson
6 */
7#include <linux/io.h>
8#include <linux/errno.h>
9#include <linux/clksrc-dbx500-prcmu.h>
10
11#include <asm/localtimer.h>
12
13#include <plat/mtu.h>
14
15#include <mach/setup.h>
16#include <mach/hardware.h>
17
18static void __init ux500_timer_init(void)
19{
20 void __iomem *prcmu_timer_base;
21
22 if (cpu_is_u5500()) {
23#ifdef CONFIG_LOCAL_TIMERS
24 twd_base = __io_address(U5500_TWD_BASE);
25#endif
26 mtu_base = __io_address(U5500_MTU0_BASE);
27 prcmu_timer_base = __io_address(U5500_PRCMU_TIMER_3_BASE);
28 } else if (cpu_is_u8500()) {
29#ifdef CONFIG_LOCAL_TIMERS
30 twd_base = __io_address(U8500_TWD_BASE);
31#endif
32 mtu_base = __io_address(U8500_MTU0_BASE);
33 prcmu_timer_base = __io_address(U8500_PRCMU_TIMER_4_BASE);
34 } else {
35 ux500_unknown_soc();
36 }
37
38 /*
39 * Here we register the timerblocks active in the system.
40 * Localtimers (twd) is started when both cpu is up and running.
41 * MTU register a clocksource, clockevent and sched_clock.
42 * Since the MTU is located in the VAPE power domain
43 * it will be cleared in sleep which makes it unsuitable.
44 * We however need it as a timer tick (clockevent)
45 * during boot to calibrate delay until twd is started.
46 * RTC-RTT have problems as timer tick during boot since it is
47 * depending on delay which is not yet calibrated. RTC-RTT is in the
48 * always-on powerdomain and is used as clockevent instead of twd when
49 * sleeping.
50 * The PRCMU timer 4(3 for DB5500) register a clocksource and
51 * sched_clock with higher rating then MTU since is always-on.
52 *
53 */
54
55 nmdk_timer_init();
56 clksrc_dbx500_prcmu_init(prcmu_timer_base);
57}
58
59static void ux500_timer_reset(void)
60{
61 nmdk_clkevt_reset();
62 nmdk_clksrc_reset();
63}
64
65struct sys_timer ux500_timer = {
66 .init = ux500_timer_init,
67 .resume = ux500_timer_reset,
68};
diff --git a/arch/arm/plat-nomadik/Kconfig b/arch/arm/plat-nomadik/Kconfig
index ce659015535e..bca4914b4b9d 100644
--- a/arch/arm/plat-nomadik/Kconfig
+++ b/arch/arm/plat-nomadik/Kconfig
@@ -15,10 +15,16 @@ if PLAT_NOMADIK
15 15
16config HAS_MTU 16config HAS_MTU
17 bool 17 bool
18 select HAVE_SCHED_CLOCK
19 help 18 help
20 Support for Multi Timer Unit. MTU provides access 19 Support for Multi Timer Unit. MTU provides access
21 to multiple interrupt generating programmable 20 to multiple interrupt generating programmable
22 32-bit free running decrementing counters. 21 32-bit free running decrementing counters.
23 22
23config NOMADIK_MTU_SCHED_CLOCK
24 bool
25 depends on HAS_MTU
26 select HAVE_SCHED_CLOCK
27 help
28 Use the Multi Timer Unit as the sched_clock.
29
24endif 30endif
diff --git a/arch/arm/plat-nomadik/include/plat/mtu.h b/arch/arm/plat-nomadik/include/plat/mtu.h
index 65704a3d4241..6508e7694a4b 100644
--- a/arch/arm/plat-nomadik/include/plat/mtu.h
+++ b/arch/arm/plat-nomadik/include/plat/mtu.h
@@ -1,54 +1,11 @@
1#ifndef __PLAT_MTU_H 1#ifndef __PLAT_MTU_H
2#define __PLAT_MTU_H 2#define __PLAT_MTU_H
3 3
4/*
5 * Guaranteed runtime conversion range in seconds for
6 * the clocksource and clockevent.
7 */
8#define MTU_MIN_RANGE 4
9
10/* should be set by the platform code */ 4/* should be set by the platform code */
11extern void __iomem *mtu_base; 5extern void __iomem *mtu_base;
12 6
13/* 7void nmdk_clkevt_reset(void);
14 * The MTU device hosts four different counters, with 4 set of 8void nmdk_clksrc_reset(void);
15 * registers. These are register names.
16 */
17
18#define MTU_IMSC 0x00 /* Interrupt mask set/clear */
19#define MTU_RIS 0x04 /* Raw interrupt status */
20#define MTU_MIS 0x08 /* Masked interrupt status */
21#define MTU_ICR 0x0C /* Interrupt clear register */
22
23/* per-timer registers take 0..3 as argument */
24#define MTU_LR(x) (0x10 + 0x10 * (x) + 0x00) /* Load value */
25#define MTU_VAL(x) (0x10 + 0x10 * (x) + 0x04) /* Current value */
26#define MTU_CR(x) (0x10 + 0x10 * (x) + 0x08) /* Control reg */
27#define MTU_BGLR(x) (0x10 + 0x10 * (x) + 0x0c) /* At next overflow */
28
29/* bits for the control register */
30#define MTU_CRn_ENA 0x80
31#define MTU_CRn_PERIODIC 0x40 /* if 0 = free-running */
32#define MTU_CRn_PRESCALE_MASK 0x0c
33#define MTU_CRn_PRESCALE_1 0x00
34#define MTU_CRn_PRESCALE_16 0x04
35#define MTU_CRn_PRESCALE_256 0x08
36#define MTU_CRn_32BITS 0x02
37#define MTU_CRn_ONESHOT 0x01 /* if 0 = wraps reloading from BGLR*/
38
39/* Other registers are usual amba/primecell registers, currently not used */
40#define MTU_ITCR 0xff0
41#define MTU_ITOP 0xff4
42
43#define MTU_PERIPH_ID0 0xfe0
44#define MTU_PERIPH_ID1 0xfe4
45#define MTU_PERIPH_ID2 0xfe8
46#define MTU_PERIPH_ID3 0xfeC
47
48#define MTU_PCELL0 0xff0
49#define MTU_PCELL1 0xff4
50#define MTU_PCELL2 0xff8
51#define MTU_PCELL3 0xffC
52 9
53#endif /* __PLAT_MTU_H */ 10#endif /* __PLAT_MTU_H */
54 11
diff --git a/arch/arm/plat-nomadik/timer.c b/arch/arm/plat-nomadik/timer.c
index ef74e157a9d5..30b6433d910d 100644
--- a/arch/arm/plat-nomadik/timer.c
+++ b/arch/arm/plat-nomadik/timer.c
@@ -21,10 +21,59 @@
21#include <asm/mach/time.h> 21#include <asm/mach/time.h>
22#include <asm/sched_clock.h> 22#include <asm/sched_clock.h>
23 23
24#include <plat/mtu.h> 24/*
25 * Guaranteed runtime conversion range in seconds for
26 * the clocksource and clockevent.
27 */
28#define MTU_MIN_RANGE 4
29
30/*
31 * The MTU device hosts four different counters, with 4 set of
32 * registers. These are register names.
33 */
34
35#define MTU_IMSC 0x00 /* Interrupt mask set/clear */
36#define MTU_RIS 0x04 /* Raw interrupt status */
37#define MTU_MIS 0x08 /* Masked interrupt status */
38#define MTU_ICR 0x0C /* Interrupt clear register */
39
40/* per-timer registers take 0..3 as argument */
41#define MTU_LR(x) (0x10 + 0x10 * (x) + 0x00) /* Load value */
42#define MTU_VAL(x) (0x10 + 0x10 * (x) + 0x04) /* Current value */
43#define MTU_CR(x) (0x10 + 0x10 * (x) + 0x08) /* Control reg */
44#define MTU_BGLR(x) (0x10 + 0x10 * (x) + 0x0c) /* At next overflow */
45
46/* bits for the control register */
47#define MTU_CRn_ENA 0x80
48#define MTU_CRn_PERIODIC 0x40 /* if 0 = free-running */
49#define MTU_CRn_PRESCALE_MASK 0x0c
50#define MTU_CRn_PRESCALE_1 0x00
51#define MTU_CRn_PRESCALE_16 0x04
52#define MTU_CRn_PRESCALE_256 0x08
53#define MTU_CRn_32BITS 0x02
54#define MTU_CRn_ONESHOT 0x01 /* if 0 = wraps reloading from BGLR*/
55
56/* Other registers are usual amba/primecell registers, currently not used */
57#define MTU_ITCR 0xff0
58#define MTU_ITOP 0xff4
59
60#define MTU_PERIPH_ID0 0xfe0
61#define MTU_PERIPH_ID1 0xfe4
62#define MTU_PERIPH_ID2 0xfe8
63#define MTU_PERIPH_ID3 0xfeC
64
65#define MTU_PCELL0 0xff0
66#define MTU_PCELL1 0xff4
67#define MTU_PCELL2 0xff8
68#define MTU_PCELL3 0xffC
69
70static bool clkevt_periodic;
71static u32 clk_prescale;
72static u32 nmdk_cycle; /* write-once */
25 73
26void __iomem *mtu_base; /* Assigned by machine code */ 74void __iomem *mtu_base; /* Assigned by machine code */
27 75
76#ifdef CONFIG_NOMADIK_MTU_SCHED_CLOCK
28/* 77/*
29 * Override the global weak sched_clock symbol with this 78 * Override the global weak sched_clock symbol with this
30 * local implementation which uses the clocksource to get some 79 * local implementation which uses the clocksource to get some
@@ -48,32 +97,56 @@ static void notrace nomadik_update_sched_clock(void)
48 u32 cyc = -readl(mtu_base + MTU_VAL(0)); 97 u32 cyc = -readl(mtu_base + MTU_VAL(0));
49 update_sched_clock(&cd, cyc, (u32)~0); 98 update_sched_clock(&cd, cyc, (u32)~0);
50} 99}
100#endif
51 101
52/* Clockevent device: use one-shot mode */ 102/* Clockevent device: use one-shot mode */
103static int nmdk_clkevt_next(unsigned long evt, struct clock_event_device *ev)
104{
105 writel(1 << 1, mtu_base + MTU_IMSC);
106 writel(evt, mtu_base + MTU_LR(1));
107 /* Load highest value, enable device, enable interrupts */
108 writel(MTU_CRn_ONESHOT | clk_prescale |
109 MTU_CRn_32BITS | MTU_CRn_ENA,
110 mtu_base + MTU_CR(1));
111
112 return 0;
113}
114
115void nmdk_clkevt_reset(void)
116{
117 if (clkevt_periodic) {
118
119 /* Timer: configure load and background-load, and fire it up */
120 writel(nmdk_cycle, mtu_base + MTU_LR(1));
121 writel(nmdk_cycle, mtu_base + MTU_BGLR(1));
122
123 writel(MTU_CRn_PERIODIC | clk_prescale |
124 MTU_CRn_32BITS | MTU_CRn_ENA,
125 mtu_base + MTU_CR(1));
126 writel(1 << 1, mtu_base + MTU_IMSC);
127 } else {
128 /* Generate an interrupt to start the clockevent again */
129 (void) nmdk_clkevt_next(nmdk_cycle, NULL);
130 }
131}
132
53static void nmdk_clkevt_mode(enum clock_event_mode mode, 133static void nmdk_clkevt_mode(enum clock_event_mode mode,
54 struct clock_event_device *dev) 134 struct clock_event_device *dev)
55{ 135{
56 u32 cr;
57 136
58 switch (mode) { 137 switch (mode) {
59 case CLOCK_EVT_MODE_PERIODIC: 138 case CLOCK_EVT_MODE_PERIODIC:
60 pr_err("%s: periodic mode not supported\n", __func__); 139 clkevt_periodic = true;
140 nmdk_clkevt_reset();
61 break; 141 break;
62 case CLOCK_EVT_MODE_ONESHOT: 142 case CLOCK_EVT_MODE_ONESHOT:
63 /* Load highest value, enable device, enable interrupts */ 143 clkevt_periodic = false;
64 cr = readl(mtu_base + MTU_CR(1));
65 writel(0, mtu_base + MTU_LR(1));
66 writel(cr | MTU_CRn_ENA, mtu_base + MTU_CR(1));
67 writel(1 << 1, mtu_base + MTU_IMSC);
68 break; 144 break;
69 case CLOCK_EVT_MODE_SHUTDOWN: 145 case CLOCK_EVT_MODE_SHUTDOWN:
70 case CLOCK_EVT_MODE_UNUSED: 146 case CLOCK_EVT_MODE_UNUSED:
71 /* disable irq */
72 writel(0, mtu_base + MTU_IMSC); 147 writel(0, mtu_base + MTU_IMSC);
73 /* disable timer */ 148 /* disable timer */
74 cr = readl(mtu_base + MTU_CR(1)); 149 writel(0, mtu_base + MTU_CR(1));
75 cr &= ~MTU_CRn_ENA;
76 writel(cr, mtu_base + MTU_CR(1));
77 /* load some high default value */ 150 /* load some high default value */
78 writel(0xffffffff, mtu_base + MTU_LR(1)); 151 writel(0xffffffff, mtu_base + MTU_LR(1));
79 break; 152 break;
@@ -82,16 +155,9 @@ static void nmdk_clkevt_mode(enum clock_event_mode mode,
82 } 155 }
83} 156}
84 157
85static int nmdk_clkevt_next(unsigned long evt, struct clock_event_device *ev)
86{
87 /* writing the value has immediate effect */
88 writel(evt, mtu_base + MTU_LR(1));
89 return 0;
90}
91
92static struct clock_event_device nmdk_clkevt = { 158static struct clock_event_device nmdk_clkevt = {
93 .name = "mtu_1", 159 .name = "mtu_1",
94 .features = CLOCK_EVT_FEAT_ONESHOT, 160 .features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC,
95 .rating = 200, 161 .rating = 200,
96 .set_mode = nmdk_clkevt_mode, 162 .set_mode = nmdk_clkevt_mode,
97 .set_next_event = nmdk_clkevt_next, 163 .set_next_event = nmdk_clkevt_next,
@@ -116,11 +182,23 @@ static struct irqaction nmdk_timer_irq = {
116 .dev_id = &nmdk_clkevt, 182 .dev_id = &nmdk_clkevt,
117}; 183};
118 184
185void nmdk_clksrc_reset(void)
186{
187 /* Disable */
188 writel(0, mtu_base + MTU_CR(0));
189
190 /* ClockSource: configure load and background-load, and fire it up */
191 writel(nmdk_cycle, mtu_base + MTU_LR(0));
192 writel(nmdk_cycle, mtu_base + MTU_BGLR(0));
193
194 writel(clk_prescale | MTU_CRn_32BITS | MTU_CRn_ENA,
195 mtu_base + MTU_CR(0));
196}
197
119void __init nmdk_timer_init(void) 198void __init nmdk_timer_init(void)
120{ 199{
121 unsigned long rate; 200 unsigned long rate;
122 struct clk *clk0; 201 struct clk *clk0;
123 u32 cr = MTU_CRn_32BITS;
124 202
125 clk0 = clk_get_sys("mtu0", NULL); 203 clk0 = clk_get_sys("mtu0", NULL);
126 BUG_ON(IS_ERR(clk0)); 204 BUG_ON(IS_ERR(clk0));
@@ -138,30 +216,28 @@ void __init nmdk_timer_init(void)
138 rate = clk_get_rate(clk0); 216 rate = clk_get_rate(clk0);
139 if (rate > 32000000) { 217 if (rate > 32000000) {
140 rate /= 16; 218 rate /= 16;
141 cr |= MTU_CRn_PRESCALE_16; 219 clk_prescale = MTU_CRn_PRESCALE_16;
142 } else { 220 } else {
143 cr |= MTU_CRn_PRESCALE_1; 221 clk_prescale = MTU_CRn_PRESCALE_1;
144 } 222 }
145 223
224 nmdk_cycle = (rate + HZ/2) / HZ;
225
226
146 /* Timer 0 is the free running clocksource */ 227 /* Timer 0 is the free running clocksource */
147 writel(cr, mtu_base + MTU_CR(0)); 228 nmdk_clksrc_reset();
148 writel(0, mtu_base + MTU_LR(0));
149 writel(0, mtu_base + MTU_BGLR(0));
150 writel(cr | MTU_CRn_ENA, mtu_base + MTU_CR(0));
151 229
152 if (clocksource_mmio_init(mtu_base + MTU_VAL(0), "mtu_0", 230 if (clocksource_mmio_init(mtu_base + MTU_VAL(0), "mtu_0",
153 rate, 200, 32, clocksource_mmio_readl_down)) 231 rate, 200, 32, clocksource_mmio_readl_down))
154 pr_err("timer: failed to initialize clock source %s\n", 232 pr_err("timer: failed to initialize clock source %s\n",
155 "mtu_0"); 233 "mtu_0");
156 234#ifdef CONFIG_NOMADIK_MTU_SCHED_CLOCK
157 init_sched_clock(&cd, nomadik_update_sched_clock, 32, rate); 235 init_sched_clock(&cd, nomadik_update_sched_clock, 32, rate);
158 236#endif
159 /* Timer 1 is used for events */ 237 /* Timer 1 is used for events */
160 238
161 clockevents_calc_mult_shift(&nmdk_clkevt, rate, MTU_MIN_RANGE); 239 clockevents_calc_mult_shift(&nmdk_clkevt, rate, MTU_MIN_RANGE);
162 240
163 writel(cr | MTU_CRn_ONESHOT, mtu_base + MTU_CR(1)); /* off, currently */
164
165 nmdk_clkevt.max_delta_ns = 241 nmdk_clkevt.max_delta_ns =
166 clockevent_delta2ns(0xffffffff, &nmdk_clkevt); 242 clockevent_delta2ns(0xffffffff, &nmdk_clkevt);
167 nmdk_clkevt.min_delta_ns = 243 nmdk_clkevt.min_delta_ns =
diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c
index 75a847dd776a..2def4e1990ed 100644
--- a/arch/arm/plat-omap/dmtimer.c
+++ b/arch/arm/plat-omap/dmtimer.c
@@ -3,6 +3,12 @@
3 * 3 *
4 * OMAP Dual-Mode Timers 4 * OMAP Dual-Mode Timers
5 * 5 *
6 * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
7 * Tarun Kanti DebBarma <tarun.kanti@ti.com>
8 * Thara Gopinath <thara@ti.com>
9 *
10 * dmtimer adaptation to platform_driver.
11 *
6 * Copyright (C) 2005 Nokia Corporation 12 * Copyright (C) 2005 Nokia Corporation
7 * OMAP2 support by Juha Yrjola 13 * OMAP2 support by Juha Yrjola
8 * API improvements and OMAP2 clock framework support by Timo Teras 14 * API improvements and OMAP2 clock framework support by Timo Teras
@@ -29,168 +35,80 @@
29 * 675 Mass Ave, Cambridge, MA 02139, USA. 35 * 675 Mass Ave, Cambridge, MA 02139, USA.
30 */ 36 */
31 37
32#include <linux/init.h>
33#include <linux/spinlock.h>
34#include <linux/errno.h>
35#include <linux/list.h>
36#include <linux/clk.h>
37#include <linux/delay.h>
38#include <linux/io.h> 38#include <linux/io.h>
39#include <linux/module.h> 39#include <linux/slab.h>
40#include <mach/hardware.h> 40#include <linux/err.h>
41#include <plat/dmtimer.h> 41#include <linux/pm_runtime.h>
42#include <mach/irqs.h>
43
44static int dm_timer_count;
45
46#ifdef CONFIG_ARCH_OMAP1
47static struct omap_dm_timer omap1_dm_timers[] = {
48 { .phys_base = 0xfffb1400, .irq = INT_1610_GPTIMER1 },
49 { .phys_base = 0xfffb1c00, .irq = INT_1610_GPTIMER2 },
50 { .phys_base = 0xfffb2400, .irq = INT_1610_GPTIMER3 },
51 { .phys_base = 0xfffb2c00, .irq = INT_1610_GPTIMER4 },
52 { .phys_base = 0xfffb3400, .irq = INT_1610_GPTIMER5 },
53 { .phys_base = 0xfffb3c00, .irq = INT_1610_GPTIMER6 },
54 { .phys_base = 0xfffb7400, .irq = INT_1610_GPTIMER7 },
55 { .phys_base = 0xfffbd400, .irq = INT_1610_GPTIMER8 },
56};
57
58static const int omap1_dm_timer_count = ARRAY_SIZE(omap1_dm_timers);
59
60#else
61#define omap1_dm_timers NULL
62#define omap1_dm_timer_count 0
63#endif /* CONFIG_ARCH_OMAP1 */
64
65#ifdef CONFIG_ARCH_OMAP2
66static struct omap_dm_timer omap2_dm_timers[] = {
67 { .phys_base = 0x48028000, .irq = INT_24XX_GPTIMER1 },
68 { .phys_base = 0x4802a000, .irq = INT_24XX_GPTIMER2 },
69 { .phys_base = 0x48078000, .irq = INT_24XX_GPTIMER3 },
70 { .phys_base = 0x4807a000, .irq = INT_24XX_GPTIMER4 },
71 { .phys_base = 0x4807c000, .irq = INT_24XX_GPTIMER5 },
72 { .phys_base = 0x4807e000, .irq = INT_24XX_GPTIMER6 },
73 { .phys_base = 0x48080000, .irq = INT_24XX_GPTIMER7 },
74 { .phys_base = 0x48082000, .irq = INT_24XX_GPTIMER8 },
75 { .phys_base = 0x48084000, .irq = INT_24XX_GPTIMER9 },
76 { .phys_base = 0x48086000, .irq = INT_24XX_GPTIMER10 },
77 { .phys_base = 0x48088000, .irq = INT_24XX_GPTIMER11 },
78 { .phys_base = 0x4808a000, .irq = INT_24XX_GPTIMER12 },
79};
80
81static const char *omap2_dm_source_names[] __initdata = {
82 "sys_ck",
83 "func_32k_ck",
84 "alt_ck",
85 NULL
86};
87
88static struct clk *omap2_dm_source_clocks[3];
89static const int omap2_dm_timer_count = ARRAY_SIZE(omap2_dm_timers);
90
91#else
92#define omap2_dm_timers NULL
93#define omap2_dm_timer_count 0
94#define omap2_dm_source_names NULL
95#define omap2_dm_source_clocks NULL
96#endif /* CONFIG_ARCH_OMAP2 */
97
98#ifdef CONFIG_ARCH_OMAP3
99static struct omap_dm_timer omap3_dm_timers[] = {
100 { .phys_base = 0x48318000, .irq = INT_24XX_GPTIMER1 },
101 { .phys_base = 0x49032000, .irq = INT_24XX_GPTIMER2 },
102 { .phys_base = 0x49034000, .irq = INT_24XX_GPTIMER3 },
103 { .phys_base = 0x49036000, .irq = INT_24XX_GPTIMER4 },
104 { .phys_base = 0x49038000, .irq = INT_24XX_GPTIMER5 },
105 { .phys_base = 0x4903A000, .irq = INT_24XX_GPTIMER6 },
106 { .phys_base = 0x4903C000, .irq = INT_24XX_GPTIMER7 },
107 { .phys_base = 0x4903E000, .irq = INT_24XX_GPTIMER8 },
108 { .phys_base = 0x49040000, .irq = INT_24XX_GPTIMER9 },
109 { .phys_base = 0x48086000, .irq = INT_24XX_GPTIMER10 },
110 { .phys_base = 0x48088000, .irq = INT_24XX_GPTIMER11 },
111 { .phys_base = 0x48304000, .irq = INT_34XX_GPT12_IRQ },
112};
113
114static const char *omap3_dm_source_names[] __initdata = {
115 "sys_ck",
116 "omap_32k_fck",
117 NULL
118};
119
120static struct clk *omap3_dm_source_clocks[2];
121static const int omap3_dm_timer_count = ARRAY_SIZE(omap3_dm_timers);
122 42
123#else 43#include <plat/dmtimer.h>
124#define omap3_dm_timers NULL
125#define omap3_dm_timer_count 0
126#define omap3_dm_source_names NULL
127#define omap3_dm_source_clocks NULL
128#endif /* CONFIG_ARCH_OMAP3 */
129
130#ifdef CONFIG_ARCH_OMAP4
131static struct omap_dm_timer omap4_dm_timers[] = {
132 { .phys_base = 0x4a318000, .irq = OMAP44XX_IRQ_GPT1 },
133 { .phys_base = 0x48032000, .irq = OMAP44XX_IRQ_GPT2 },
134 { .phys_base = 0x48034000, .irq = OMAP44XX_IRQ_GPT3 },
135 { .phys_base = 0x48036000, .irq = OMAP44XX_IRQ_GPT4 },
136 { .phys_base = 0x40138000, .irq = OMAP44XX_IRQ_GPT5 },
137 { .phys_base = 0x4013a000, .irq = OMAP44XX_IRQ_GPT6 },
138 { .phys_base = 0x4013a000, .irq = OMAP44XX_IRQ_GPT7 },
139 { .phys_base = 0x4013e000, .irq = OMAP44XX_IRQ_GPT8 },
140 { .phys_base = 0x4803e000, .irq = OMAP44XX_IRQ_GPT9 },
141 { .phys_base = 0x48086000, .irq = OMAP44XX_IRQ_GPT10 },
142 { .phys_base = 0x48088000, .irq = OMAP44XX_IRQ_GPT11 },
143 { .phys_base = 0x4a320000, .irq = OMAP44XX_IRQ_GPT12 },
144};
145static const char *omap4_dm_source_names[] __initdata = {
146 "sys_clkin_ck",
147 "sys_32k_ck",
148 NULL
149};
150static struct clk *omap4_dm_source_clocks[2];
151static const int omap4_dm_timer_count = ARRAY_SIZE(omap4_dm_timers);
152
153#else
154#define omap4_dm_timers NULL
155#define omap4_dm_timer_count 0
156#define omap4_dm_source_names NULL
157#define omap4_dm_source_clocks NULL
158#endif /* CONFIG_ARCH_OMAP4 */
159
160static struct omap_dm_timer *dm_timers;
161static const char **dm_source_names;
162static struct clk **dm_source_clocks;
163 44
164static spinlock_t dm_timer_lock; 45static LIST_HEAD(omap_timer_list);
46static DEFINE_SPINLOCK(dm_timer_lock);
165 47
166/* 48/**
167 * Reads timer registers in posted and non-posted mode. The posted mode bit 49 * omap_dm_timer_read_reg - read timer registers in posted and non-posted mode
168 * is encoded in reg. Note that in posted mode write pending bit must be 50 * @timer: timer pointer over which read operation to perform
169 * checked. Otherwise a read of a non completed write will produce an error. 51 * @reg: lowest byte holds the register offset
52 *
53 * The posted mode bit is encoded in reg. Note that in posted mode write
54 * pending bit must be checked. Otherwise a read of a non completed write
55 * will produce an error.
170 */ 56 */
171static inline u32 omap_dm_timer_read_reg(struct omap_dm_timer *timer, u32 reg) 57static inline u32 omap_dm_timer_read_reg(struct omap_dm_timer *timer, u32 reg)
172{ 58{
173 return __omap_dm_timer_read(timer->io_base, reg, timer->posted); 59 WARN_ON((reg & 0xff) < _OMAP_TIMER_WAKEUP_EN_OFFSET);
60 return __omap_dm_timer_read(timer, reg, timer->posted);
174} 61}
175 62
176/* 63/**
177 * Writes timer registers in posted and non-posted mode. The posted mode bit 64 * omap_dm_timer_write_reg - write timer registers in posted and non-posted mode
178 * is encoded in reg. Note that in posted mode the write pending bit must be 65 * @timer: timer pointer over which write operation is to perform
179 * checked. Otherwise a write on a register which has a pending write will be 66 * @reg: lowest byte holds the register offset
180 * lost. 67 * @value: data to write into the register
68 *
69 * The posted mode bit is encoded in reg. Note that in posted mode the write
70 * pending bit must be checked. Otherwise a write on a register which has a
71 * pending write will be lost.
181 */ 72 */
182static void omap_dm_timer_write_reg(struct omap_dm_timer *timer, u32 reg, 73static void omap_dm_timer_write_reg(struct omap_dm_timer *timer, u32 reg,
183 u32 value) 74 u32 value)
184{ 75{
185 __omap_dm_timer_write(timer->io_base, reg, value, timer->posted); 76 WARN_ON((reg & 0xff) < _OMAP_TIMER_WAKEUP_EN_OFFSET);
77 __omap_dm_timer_write(timer, reg, value, timer->posted);
78}
79
80static void omap_timer_restore_context(struct omap_dm_timer *timer)
81{
82 omap_dm_timer_write_reg(timer, OMAP_TIMER_OCP_CFG_OFFSET,
83 timer->context.tiocp_cfg);
84 if (timer->revision > 1)
85 __raw_writel(timer->context.tistat, timer->sys_stat);
86
87 __raw_writel(timer->context.tisr, timer->irq_stat);
88 omap_dm_timer_write_reg(timer, OMAP_TIMER_WAKEUP_EN_REG,
89 timer->context.twer);
90 omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG,
91 timer->context.tcrr);
92 omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG,
93 timer->context.tldr);
94 omap_dm_timer_write_reg(timer, OMAP_TIMER_MATCH_REG,
95 timer->context.tmar);
96 omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG,
97 timer->context.tsicr);
98 __raw_writel(timer->context.tier, timer->irq_ena);
99 omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG,
100 timer->context.tclr);
186} 101}
187 102
188static void omap_dm_timer_wait_for_reset(struct omap_dm_timer *timer) 103static void omap_dm_timer_wait_for_reset(struct omap_dm_timer *timer)
189{ 104{
190 int c; 105 int c;
191 106
107 if (!timer->sys_stat)
108 return;
109
192 c = 0; 110 c = 0;
193 while (!(omap_dm_timer_read_reg(timer, OMAP_TIMER_SYS_STAT_REG) & 1)) { 111 while (!(__raw_readl(timer->sys_stat) & 1)) {
194 c++; 112 c++;
195 if (c > 100000) { 113 if (c > 100000) {
196 printk(KERN_ERR "Timer failed to reset\n"); 114 printk(KERN_ERR "Timer failed to reset\n");
@@ -201,53 +119,65 @@ static void omap_dm_timer_wait_for_reset(struct omap_dm_timer *timer)
201 119
202static void omap_dm_timer_reset(struct omap_dm_timer *timer) 120static void omap_dm_timer_reset(struct omap_dm_timer *timer)
203{ 121{
204 int autoidle = 0, wakeup = 0; 122 omap_dm_timer_enable(timer);
205 123 if (timer->pdev->id != 1) {
206 if (!cpu_class_is_omap2() || timer != &dm_timers[0]) {
207 omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG, 0x06); 124 omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG, 0x06);
208 omap_dm_timer_wait_for_reset(timer); 125 omap_dm_timer_wait_for_reset(timer);
209 } 126 }
210 omap_dm_timer_set_source(timer, OMAP_TIMER_SRC_32_KHZ);
211
212 /* Enable autoidle on OMAP2+ */
213 if (cpu_class_is_omap2())
214 autoidle = 1;
215
216 /*
217 * Enable wake-up on OMAP2 CPUs.
218 */
219 if (cpu_class_is_omap2())
220 wakeup = 1;
221 127
222 __omap_dm_timer_reset(timer->io_base, autoidle, wakeup); 128 __omap_dm_timer_reset(timer, 0, 0);
129 omap_dm_timer_disable(timer);
223 timer->posted = 1; 130 timer->posted = 1;
224} 131}
225 132
226void omap_dm_timer_prepare(struct omap_dm_timer *timer) 133int omap_dm_timer_prepare(struct omap_dm_timer *timer)
227{ 134{
228 omap_dm_timer_enable(timer); 135 struct dmtimer_platform_data *pdata = timer->pdev->dev.platform_data;
229 omap_dm_timer_reset(timer); 136 int ret;
137
138 timer->fclk = clk_get(&timer->pdev->dev, "fck");
139 if (WARN_ON_ONCE(IS_ERR_OR_NULL(timer->fclk))) {
140 timer->fclk = NULL;
141 dev_err(&timer->pdev->dev, ": No fclk handle.\n");
142 return -EINVAL;
143 }
144
145 if (pdata->needs_manual_reset)
146 omap_dm_timer_reset(timer);
147
148 ret = omap_dm_timer_set_source(timer, OMAP_TIMER_SRC_32_KHZ);
149
150 timer->posted = 1;
151 return ret;
230} 152}
231 153
232struct omap_dm_timer *omap_dm_timer_request(void) 154struct omap_dm_timer *omap_dm_timer_request(void)
233{ 155{
234 struct omap_dm_timer *timer = NULL; 156 struct omap_dm_timer *timer = NULL, *t;
235 unsigned long flags; 157 unsigned long flags;
236 int i; 158 int ret = 0;
237 159
238 spin_lock_irqsave(&dm_timer_lock, flags); 160 spin_lock_irqsave(&dm_timer_lock, flags);
239 for (i = 0; i < dm_timer_count; i++) { 161 list_for_each_entry(t, &omap_timer_list, node) {
240 if (dm_timers[i].reserved) 162 if (t->reserved)
241 continue; 163 continue;
242 164
243 timer = &dm_timers[i]; 165 timer = t;
244 timer->reserved = 1; 166 timer->reserved = 1;
245 break; 167 break;
246 } 168 }
169
170 if (timer) {
171 ret = omap_dm_timer_prepare(timer);
172 if (ret) {
173 timer->reserved = 0;
174 timer = NULL;
175 }
176 }
247 spin_unlock_irqrestore(&dm_timer_lock, flags); 177 spin_unlock_irqrestore(&dm_timer_lock, flags);
248 178
249 if (timer != NULL) 179 if (!timer)
250 omap_dm_timer_prepare(timer); 180 pr_debug("%s: timer request failed!\n", __func__);
251 181
252 return timer; 182 return timer;
253} 183}
@@ -255,74 +185,65 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_request);
255 185
256struct omap_dm_timer *omap_dm_timer_request_specific(int id) 186struct omap_dm_timer *omap_dm_timer_request_specific(int id)
257{ 187{
258 struct omap_dm_timer *timer; 188 struct omap_dm_timer *timer = NULL, *t;
259 unsigned long flags; 189 unsigned long flags;
190 int ret = 0;
260 191
261 spin_lock_irqsave(&dm_timer_lock, flags); 192 spin_lock_irqsave(&dm_timer_lock, flags);
262 if (id <= 0 || id > dm_timer_count || dm_timers[id-1].reserved) { 193 list_for_each_entry(t, &omap_timer_list, node) {
263 spin_unlock_irqrestore(&dm_timer_lock, flags); 194 if (t->pdev->id == id && !t->reserved) {
264 printk("BUG: warning at %s:%d/%s(): unable to get timer %d\n", 195 timer = t;
265 __FILE__, __LINE__, __func__, id); 196 timer->reserved = 1;
266 dump_stack(); 197 break;
267 return NULL; 198 }
268 } 199 }
269 200
270 timer = &dm_timers[id-1]; 201 if (timer) {
271 timer->reserved = 1; 202 ret = omap_dm_timer_prepare(timer);
203 if (ret) {
204 timer->reserved = 0;
205 timer = NULL;
206 }
207 }
272 spin_unlock_irqrestore(&dm_timer_lock, flags); 208 spin_unlock_irqrestore(&dm_timer_lock, flags);
273 209
274 omap_dm_timer_prepare(timer); 210 if (!timer)
211 pr_debug("%s: timer%d request failed!\n", __func__, id);
275 212
276 return timer; 213 return timer;
277} 214}
278EXPORT_SYMBOL_GPL(omap_dm_timer_request_specific); 215EXPORT_SYMBOL_GPL(omap_dm_timer_request_specific);
279 216
280void omap_dm_timer_free(struct omap_dm_timer *timer) 217int omap_dm_timer_free(struct omap_dm_timer *timer)
281{ 218{
282 omap_dm_timer_enable(timer); 219 if (unlikely(!timer))
283 omap_dm_timer_reset(timer); 220 return -EINVAL;
284 omap_dm_timer_disable(timer); 221
222 clk_put(timer->fclk);
285 223
286 WARN_ON(!timer->reserved); 224 WARN_ON(!timer->reserved);
287 timer->reserved = 0; 225 timer->reserved = 0;
226 return 0;
288} 227}
289EXPORT_SYMBOL_GPL(omap_dm_timer_free); 228EXPORT_SYMBOL_GPL(omap_dm_timer_free);
290 229
291void omap_dm_timer_enable(struct omap_dm_timer *timer) 230void omap_dm_timer_enable(struct omap_dm_timer *timer)
292{ 231{
293 if (timer->enabled) 232 pm_runtime_get_sync(&timer->pdev->dev);
294 return;
295
296#ifdef CONFIG_ARCH_OMAP2PLUS
297 if (cpu_class_is_omap2()) {
298 clk_enable(timer->fclk);
299 clk_enable(timer->iclk);
300 }
301#endif
302
303 timer->enabled = 1;
304} 233}
305EXPORT_SYMBOL_GPL(omap_dm_timer_enable); 234EXPORT_SYMBOL_GPL(omap_dm_timer_enable);
306 235
307void omap_dm_timer_disable(struct omap_dm_timer *timer) 236void omap_dm_timer_disable(struct omap_dm_timer *timer)
308{ 237{
309 if (!timer->enabled) 238 pm_runtime_put(&timer->pdev->dev);
310 return;
311
312#ifdef CONFIG_ARCH_OMAP2PLUS
313 if (cpu_class_is_omap2()) {
314 clk_disable(timer->iclk);
315 clk_disable(timer->fclk);
316 }
317#endif
318
319 timer->enabled = 0;
320} 239}
321EXPORT_SYMBOL_GPL(omap_dm_timer_disable); 240EXPORT_SYMBOL_GPL(omap_dm_timer_disable);
322 241
323int omap_dm_timer_get_irq(struct omap_dm_timer *timer) 242int omap_dm_timer_get_irq(struct omap_dm_timer *timer)
324{ 243{
325 return timer->irq; 244 if (timer)
245 return timer->irq;
246 return -EINVAL;
326} 247}
327EXPORT_SYMBOL_GPL(omap_dm_timer_get_irq); 248EXPORT_SYMBOL_GPL(omap_dm_timer_get_irq);
328 249
@@ -334,24 +255,29 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_get_irq);
334 */ 255 */
335__u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask) 256__u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask)
336{ 257{
337 int i; 258 int i = 0;
259 struct omap_dm_timer *timer = NULL;
260 unsigned long flags;
338 261
339 /* If ARMXOR cannot be idled this function call is unnecessary */ 262 /* If ARMXOR cannot be idled this function call is unnecessary */
340 if (!(inputmask & (1 << 1))) 263 if (!(inputmask & (1 << 1)))
341 return inputmask; 264 return inputmask;
342 265
343 /* If any active timer is using ARMXOR return modified mask */ 266 /* If any active timer is using ARMXOR return modified mask */
344 for (i = 0; i < dm_timer_count; i++) { 267 spin_lock_irqsave(&dm_timer_lock, flags);
268 list_for_each_entry(timer, &omap_timer_list, node) {
345 u32 l; 269 u32 l;
346 270
347 l = omap_dm_timer_read_reg(&dm_timers[i], OMAP_TIMER_CTRL_REG); 271 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
348 if (l & OMAP_TIMER_CTRL_ST) { 272 if (l & OMAP_TIMER_CTRL_ST) {
349 if (((omap_readl(MOD_CONF_CTRL_1) >> (i * 2)) & 0x03) == 0) 273 if (((omap_readl(MOD_CONF_CTRL_1) >> (i * 2)) & 0x03) == 0)
350 inputmask &= ~(1 << 1); 274 inputmask &= ~(1 << 1);
351 else 275 else
352 inputmask &= ~(1 << 2); 276 inputmask &= ~(1 << 2);
353 } 277 }
278 i++;
354 } 279 }
280 spin_unlock_irqrestore(&dm_timer_lock, flags);
355 281
356 return inputmask; 282 return inputmask;
357} 283}
@@ -361,7 +287,9 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_modify_idlect_mask);
361 287
362struct clk *omap_dm_timer_get_fclk(struct omap_dm_timer *timer) 288struct clk *omap_dm_timer_get_fclk(struct omap_dm_timer *timer)
363{ 289{
364 return timer->fclk; 290 if (timer)
291 return timer->fclk;
292 return NULL;
365} 293}
366EXPORT_SYMBOL_GPL(omap_dm_timer_get_fclk); 294EXPORT_SYMBOL_GPL(omap_dm_timer_get_fclk);
367 295
@@ -375,70 +303,91 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_modify_idlect_mask);
375 303
376#endif 304#endif
377 305
378void omap_dm_timer_trigger(struct omap_dm_timer *timer) 306int omap_dm_timer_trigger(struct omap_dm_timer *timer)
379{ 307{
308 if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) {
309 pr_err("%s: timer not available or enabled.\n", __func__);
310 return -EINVAL;
311 }
312
380 omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0); 313 omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0);
314 return 0;
381} 315}
382EXPORT_SYMBOL_GPL(omap_dm_timer_trigger); 316EXPORT_SYMBOL_GPL(omap_dm_timer_trigger);
383 317
384void omap_dm_timer_start(struct omap_dm_timer *timer) 318int omap_dm_timer_start(struct omap_dm_timer *timer)
385{ 319{
386 u32 l; 320 u32 l;
387 321
322 if (unlikely(!timer))
323 return -EINVAL;
324
325 omap_dm_timer_enable(timer);
326
327 if (timer->loses_context) {
328 u32 ctx_loss_cnt_after =
329 timer->get_context_loss_count(&timer->pdev->dev);
330 if (ctx_loss_cnt_after != timer->ctx_loss_count)
331 omap_timer_restore_context(timer);
332 }
333
388 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); 334 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
389 if (!(l & OMAP_TIMER_CTRL_ST)) { 335 if (!(l & OMAP_TIMER_CTRL_ST)) {
390 l |= OMAP_TIMER_CTRL_ST; 336 l |= OMAP_TIMER_CTRL_ST;
391 omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l); 337 omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
392 } 338 }
339
340 /* Save the context */
341 timer->context.tclr = l;
342 return 0;
393} 343}
394EXPORT_SYMBOL_GPL(omap_dm_timer_start); 344EXPORT_SYMBOL_GPL(omap_dm_timer_start);
395 345
396void omap_dm_timer_stop(struct omap_dm_timer *timer) 346int omap_dm_timer_stop(struct omap_dm_timer *timer)
397{ 347{
398 unsigned long rate = 0; 348 unsigned long rate = 0;
349 struct dmtimer_platform_data *pdata = timer->pdev->dev.platform_data;
399 350
400#ifdef CONFIG_ARCH_OMAP2PLUS 351 if (unlikely(!timer))
401 rate = clk_get_rate(timer->fclk); 352 return -EINVAL;
402#endif
403 353
404 __omap_dm_timer_stop(timer->io_base, timer->posted, rate); 354 if (!pdata->needs_manual_reset)
355 rate = clk_get_rate(timer->fclk);
356
357 __omap_dm_timer_stop(timer, timer->posted, rate);
358
359 return 0;
405} 360}
406EXPORT_SYMBOL_GPL(omap_dm_timer_stop); 361EXPORT_SYMBOL_GPL(omap_dm_timer_stop);
407 362
408#ifdef CONFIG_ARCH_OMAP1
409
410int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source) 363int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
411{ 364{
412 int n = (timer - dm_timers) << 1; 365 int ret;
413 u32 l; 366 struct dmtimer_platform_data *pdata;
414
415 l = omap_readl(MOD_CONF_CTRL_1) & ~(0x03 << n);
416 l |= source << n;
417 omap_writel(l, MOD_CONF_CTRL_1);
418 367
419 return 0; 368 if (unlikely(!timer))
420} 369 return -EINVAL;
421EXPORT_SYMBOL_GPL(omap_dm_timer_set_source);
422 370
423#else 371 pdata = timer->pdev->dev.platform_data;
424 372
425int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
426{
427 if (source < 0 || source >= 3) 373 if (source < 0 || source >= 3)
428 return -EINVAL; 374 return -EINVAL;
429 375
430 return __omap_dm_timer_set_source(timer->fclk, 376 ret = pdata->set_timer_src(timer->pdev, source);
431 dm_source_clocks[source]); 377
378 return ret;
432} 379}
433EXPORT_SYMBOL_GPL(omap_dm_timer_set_source); 380EXPORT_SYMBOL_GPL(omap_dm_timer_set_source);
434 381
435#endif 382int omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload,
436
437void omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload,
438 unsigned int load) 383 unsigned int load)
439{ 384{
440 u32 l; 385 u32 l;
441 386
387 if (unlikely(!timer))
388 return -EINVAL;
389
390 omap_dm_timer_enable(timer);
442 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); 391 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
443 if (autoreload) 392 if (autoreload)
444 l |= OMAP_TIMER_CTRL_AR; 393 l |= OMAP_TIMER_CTRL_AR;
@@ -448,15 +397,32 @@ void omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload,
448 omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load); 397 omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load);
449 398
450 omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0); 399 omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0);
400 /* Save the context */
401 timer->context.tclr = l;
402 timer->context.tldr = load;
403 omap_dm_timer_disable(timer);
404 return 0;
451} 405}
452EXPORT_SYMBOL_GPL(omap_dm_timer_set_load); 406EXPORT_SYMBOL_GPL(omap_dm_timer_set_load);
453 407
454/* Optimized set_load which removes costly spin wait in timer_start */ 408/* Optimized set_load which removes costly spin wait in timer_start */
455void omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int autoreload, 409int omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int autoreload,
456 unsigned int load) 410 unsigned int load)
457{ 411{
458 u32 l; 412 u32 l;
459 413
414 if (unlikely(!timer))
415 return -EINVAL;
416
417 omap_dm_timer_enable(timer);
418
419 if (timer->loses_context) {
420 u32 ctx_loss_cnt_after =
421 timer->get_context_loss_count(&timer->pdev->dev);
422 if (ctx_loss_cnt_after != timer->ctx_loss_count)
423 omap_timer_restore_context(timer);
424 }
425
460 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); 426 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
461 if (autoreload) { 427 if (autoreload) {
462 l |= OMAP_TIMER_CTRL_AR; 428 l |= OMAP_TIMER_CTRL_AR;
@@ -466,15 +432,25 @@ void omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int autoreload,
466 } 432 }
467 l |= OMAP_TIMER_CTRL_ST; 433 l |= OMAP_TIMER_CTRL_ST;
468 434
469 __omap_dm_timer_load_start(timer->io_base, l, load, timer->posted); 435 __omap_dm_timer_load_start(timer, l, load, timer->posted);
436
437 /* Save the context */
438 timer->context.tclr = l;
439 timer->context.tldr = load;
440 timer->context.tcrr = load;
441 return 0;
470} 442}
471EXPORT_SYMBOL_GPL(omap_dm_timer_set_load_start); 443EXPORT_SYMBOL_GPL(omap_dm_timer_set_load_start);
472 444
473void omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable, 445int omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable,
474 unsigned int match) 446 unsigned int match)
475{ 447{
476 u32 l; 448 u32 l;
477 449
450 if (unlikely(!timer))
451 return -EINVAL;
452
453 omap_dm_timer_enable(timer);
478 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); 454 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
479 if (enable) 455 if (enable)
480 l |= OMAP_TIMER_CTRL_CE; 456 l |= OMAP_TIMER_CTRL_CE;
@@ -482,14 +458,24 @@ void omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable,
482 l &= ~OMAP_TIMER_CTRL_CE; 458 l &= ~OMAP_TIMER_CTRL_CE;
483 omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l); 459 omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
484 omap_dm_timer_write_reg(timer, OMAP_TIMER_MATCH_REG, match); 460 omap_dm_timer_write_reg(timer, OMAP_TIMER_MATCH_REG, match);
461
462 /* Save the context */
463 timer->context.tclr = l;
464 timer->context.tmar = match;
465 omap_dm_timer_disable(timer);
466 return 0;
485} 467}
486EXPORT_SYMBOL_GPL(omap_dm_timer_set_match); 468EXPORT_SYMBOL_GPL(omap_dm_timer_set_match);
487 469
488void omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on, 470int omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on,
489 int toggle, int trigger) 471 int toggle, int trigger)
490{ 472{
491 u32 l; 473 u32 l;
492 474
475 if (unlikely(!timer))
476 return -EINVAL;
477
478 omap_dm_timer_enable(timer);
493 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); 479 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
494 l &= ~(OMAP_TIMER_CTRL_GPOCFG | OMAP_TIMER_CTRL_SCPWM | 480 l &= ~(OMAP_TIMER_CTRL_GPOCFG | OMAP_TIMER_CTRL_SCPWM |
495 OMAP_TIMER_CTRL_PT | (0x03 << 10)); 481 OMAP_TIMER_CTRL_PT | (0x03 << 10));
@@ -499,13 +485,22 @@ void omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on,
499 l |= OMAP_TIMER_CTRL_PT; 485 l |= OMAP_TIMER_CTRL_PT;
500 l |= trigger << 10; 486 l |= trigger << 10;
501 omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l); 487 omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
488
489 /* Save the context */
490 timer->context.tclr = l;
491 omap_dm_timer_disable(timer);
492 return 0;
502} 493}
503EXPORT_SYMBOL_GPL(omap_dm_timer_set_pwm); 494EXPORT_SYMBOL_GPL(omap_dm_timer_set_pwm);
504 495
505void omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int prescaler) 496int omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int prescaler)
506{ 497{
507 u32 l; 498 u32 l;
508 499
500 if (unlikely(!timer))
501 return -EINVAL;
502
503 omap_dm_timer_enable(timer);
509 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); 504 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
510 l &= ~(OMAP_TIMER_CTRL_PRE | (0x07 << 2)); 505 l &= ~(OMAP_TIMER_CTRL_PRE | (0x07 << 2));
511 if (prescaler >= 0x00 && prescaler <= 0x07) { 506 if (prescaler >= 0x00 && prescaler <= 0x07) {
@@ -513,13 +508,28 @@ void omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int prescaler)
513 l |= prescaler << 2; 508 l |= prescaler << 2;
514 } 509 }
515 omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l); 510 omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
511
512 /* Save the context */
513 timer->context.tclr = l;
514 omap_dm_timer_disable(timer);
515 return 0;
516} 516}
517EXPORT_SYMBOL_GPL(omap_dm_timer_set_prescaler); 517EXPORT_SYMBOL_GPL(omap_dm_timer_set_prescaler);
518 518
519void omap_dm_timer_set_int_enable(struct omap_dm_timer *timer, 519int omap_dm_timer_set_int_enable(struct omap_dm_timer *timer,
520 unsigned int value) 520 unsigned int value)
521{ 521{
522 __omap_dm_timer_int_enable(timer->io_base, value); 522 if (unlikely(!timer))
523 return -EINVAL;
524
525 omap_dm_timer_enable(timer);
526 __omap_dm_timer_int_enable(timer, value);
527
528 /* Save the context */
529 timer->context.tier = value;
530 timer->context.twer = value;
531 omap_dm_timer_disable(timer);
532 return 0;
523} 533}
524EXPORT_SYMBOL_GPL(omap_dm_timer_set_int_enable); 534EXPORT_SYMBOL_GPL(omap_dm_timer_set_int_enable);
525 535
@@ -527,40 +537,61 @@ unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer)
527{ 537{
528 unsigned int l; 538 unsigned int l;
529 539
530 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_STAT_REG); 540 if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) {
541 pr_err("%s: timer not available or enabled.\n", __func__);
542 return 0;
543 }
544
545 l = __raw_readl(timer->irq_stat);
531 546
532 return l; 547 return l;
533} 548}
534EXPORT_SYMBOL_GPL(omap_dm_timer_read_status); 549EXPORT_SYMBOL_GPL(omap_dm_timer_read_status);
535 550
536void omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value) 551int omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value)
537{ 552{
538 __omap_dm_timer_write_status(timer->io_base, value); 553 if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev)))
554 return -EINVAL;
555
556 __omap_dm_timer_write_status(timer, value);
557 /* Save the context */
558 timer->context.tisr = value;
559 return 0;
539} 560}
540EXPORT_SYMBOL_GPL(omap_dm_timer_write_status); 561EXPORT_SYMBOL_GPL(omap_dm_timer_write_status);
541 562
542unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer) 563unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer)
543{ 564{
544 return __omap_dm_timer_read_counter(timer->io_base, timer->posted); 565 if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) {
566 pr_err("%s: timer not iavailable or enabled.\n", __func__);
567 return 0;
568 }
569
570 return __omap_dm_timer_read_counter(timer, timer->posted);
545} 571}
546EXPORT_SYMBOL_GPL(omap_dm_timer_read_counter); 572EXPORT_SYMBOL_GPL(omap_dm_timer_read_counter);
547 573
548void omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int value) 574int omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int value)
549{ 575{
576 if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) {
577 pr_err("%s: timer not available or enabled.\n", __func__);
578 return -EINVAL;
579 }
580
550 omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG, value); 581 omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG, value);
582
583 /* Save the context */
584 timer->context.tcrr = value;
585 return 0;
551} 586}
552EXPORT_SYMBOL_GPL(omap_dm_timer_write_counter); 587EXPORT_SYMBOL_GPL(omap_dm_timer_write_counter);
553 588
554int omap_dm_timers_active(void) 589int omap_dm_timers_active(void)
555{ 590{
556 int i; 591 struct omap_dm_timer *timer;
557
558 for (i = 0; i < dm_timer_count; i++) {
559 struct omap_dm_timer *timer;
560
561 timer = &dm_timers[i];
562 592
563 if (!timer->enabled) 593 list_for_each_entry(timer, &omap_timer_list, node) {
594 if (!timer->reserved)
564 continue; 595 continue;
565 596
566 if (omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG) & 597 if (omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG) &
@@ -572,69 +603,147 @@ int omap_dm_timers_active(void)
572} 603}
573EXPORT_SYMBOL_GPL(omap_dm_timers_active); 604EXPORT_SYMBOL_GPL(omap_dm_timers_active);
574 605
575static int __init omap_dm_timer_init(void) 606/**
607 * omap_dm_timer_probe - probe function called for every registered device
608 * @pdev: pointer to current timer platform device
609 *
610 * Called by driver framework at the end of device registration for all
611 * timer devices.
612 */
613static int __devinit omap_dm_timer_probe(struct platform_device *pdev)
576{ 614{
615 int ret;
616 unsigned long flags;
577 struct omap_dm_timer *timer; 617 struct omap_dm_timer *timer;
578 int i, map_size = SZ_8K; /* Module 4KB + L4 4KB except on omap1 */ 618 struct resource *mem, *irq, *ioarea;
619 struct dmtimer_platform_data *pdata = pdev->dev.platform_data;
579 620
580 if (!(cpu_is_omap16xx() || cpu_class_is_omap2())) 621 if (!pdata) {
622 dev_err(&pdev->dev, "%s: no platform data.\n", __func__);
581 return -ENODEV; 623 return -ENODEV;
624 }
582 625
583 spin_lock_init(&dm_timer_lock); 626 irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
584 627 if (unlikely(!irq)) {
585 if (cpu_class_is_omap1()) { 628 dev_err(&pdev->dev, "%s: no IRQ resource.\n", __func__);
586 dm_timers = omap1_dm_timers; 629 return -ENODEV;
587 dm_timer_count = omap1_dm_timer_count;
588 map_size = SZ_2K;
589 } else if (cpu_is_omap24xx()) {
590 dm_timers = omap2_dm_timers;
591 dm_timer_count = omap2_dm_timer_count;
592 dm_source_names = omap2_dm_source_names;
593 dm_source_clocks = omap2_dm_source_clocks;
594 } else if (cpu_is_omap34xx()) {
595 dm_timers = omap3_dm_timers;
596 dm_timer_count = omap3_dm_timer_count;
597 dm_source_names = omap3_dm_source_names;
598 dm_source_clocks = omap3_dm_source_clocks;
599 } else if (cpu_is_omap44xx()) {
600 dm_timers = omap4_dm_timers;
601 dm_timer_count = omap4_dm_timer_count;
602 dm_source_names = omap4_dm_source_names;
603 dm_source_clocks = omap4_dm_source_clocks;
604 } 630 }
605 631
606 if (cpu_class_is_omap2()) 632 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
607 for (i = 0; dm_source_names[i] != NULL; i++) 633 if (unlikely(!mem)) {
608 dm_source_clocks[i] = clk_get(NULL, dm_source_names[i]); 634 dev_err(&pdev->dev, "%s: no memory resource.\n", __func__);
635 return -ENODEV;
636 }
609 637
610 if (cpu_is_omap243x()) 638 ioarea = request_mem_region(mem->start, resource_size(mem),
611 dm_timers[0].phys_base = 0x49018000; 639 pdev->name);
640 if (!ioarea) {
641 dev_err(&pdev->dev, "%s: region already claimed.\n", __func__);
642 return -EBUSY;
643 }
612 644
613 for (i = 0; i < dm_timer_count; i++) { 645 timer = kzalloc(sizeof(struct omap_dm_timer), GFP_KERNEL);
614 timer = &dm_timers[i]; 646 if (!timer) {
647 dev_err(&pdev->dev, "%s: no memory for omap_dm_timer.\n",
648 __func__);
649 ret = -ENOMEM;
650 goto err_free_ioregion;
651 }
615 652
616 /* Static mapping, never released */ 653 timer->io_base = ioremap(mem->start, resource_size(mem));
617 timer->io_base = ioremap(timer->phys_base, map_size); 654 if (!timer->io_base) {
618 BUG_ON(!timer->io_base); 655 dev_err(&pdev->dev, "%s: ioremap failed.\n", __func__);
656 ret = -ENOMEM;
657 goto err_free_mem;
658 }
619 659
620#ifdef CONFIG_ARCH_OMAP2PLUS 660 timer->id = pdev->id;
621 if (cpu_class_is_omap2()) { 661 timer->irq = irq->start;
622 char clk_name[16]; 662 timer->reserved = pdata->reserved;
623 sprintf(clk_name, "gpt%d_ick", i + 1); 663 timer->pdev = pdev;
624 timer->iclk = clk_get(NULL, clk_name); 664 timer->loses_context = pdata->loses_context;
625 sprintf(clk_name, "gpt%d_fck", i + 1); 665 timer->get_context_loss_count = pdata->get_context_loss_count;
626 timer->fclk = clk_get(NULL, clk_name); 666
627 } 667 /* Skip pm_runtime_enable for OMAP1 */
668 if (!pdata->needs_manual_reset) {
669 pm_runtime_enable(&pdev->dev);
670 pm_runtime_irq_safe(&pdev->dev);
671 }
628 672
629 /* One or two timers may be set up early for sys_timer */ 673 if (!timer->reserved) {
630 if (sys_timer_reserved & (1 << i)) { 674 pm_runtime_get_sync(&pdev->dev);
631 timer->reserved = 1; 675 __omap_dm_timer_init_regs(timer);
632 timer->posted = 1; 676 pm_runtime_put(&pdev->dev);
633 }
634#endif
635 } 677 }
636 678
679 /* add the timer element to the list */
680 spin_lock_irqsave(&dm_timer_lock, flags);
681 list_add_tail(&timer->node, &omap_timer_list);
682 spin_unlock_irqrestore(&dm_timer_lock, flags);
683
684 dev_dbg(&pdev->dev, "Device Probed.\n");
685
637 return 0; 686 return 0;
687
688err_free_mem:
689 kfree(timer);
690
691err_free_ioregion:
692 release_mem_region(mem->start, resource_size(mem));
693
694 return ret;
638} 695}
639 696
640arch_initcall(omap_dm_timer_init); 697/**
698 * omap_dm_timer_remove - cleanup a registered timer device
699 * @pdev: pointer to current timer platform device
700 *
701 * Called by driver framework whenever a timer device is unregistered.
702 * In addition to freeing platform resources it also deletes the timer
703 * entry from the local list.
704 */
705static int __devexit omap_dm_timer_remove(struct platform_device *pdev)
706{
707 struct omap_dm_timer *timer;
708 unsigned long flags;
709 int ret = -EINVAL;
710
711 spin_lock_irqsave(&dm_timer_lock, flags);
712 list_for_each_entry(timer, &omap_timer_list, node)
713 if (timer->pdev->id == pdev->id) {
714 list_del(&timer->node);
715 kfree(timer);
716 ret = 0;
717 break;
718 }
719 spin_unlock_irqrestore(&dm_timer_lock, flags);
720
721 return ret;
722}
723
724static struct platform_driver omap_dm_timer_driver = {
725 .probe = omap_dm_timer_probe,
726 .remove = __devexit_p(omap_dm_timer_remove),
727 .driver = {
728 .name = "omap_timer",
729 },
730};
731
732static int __init omap_dm_timer_driver_init(void)
733{
734 return platform_driver_register(&omap_dm_timer_driver);
735}
736
737static void __exit omap_dm_timer_driver_exit(void)
738{
739 platform_driver_unregister(&omap_dm_timer_driver);
740}
741
742early_platform_init("earlytimer", &omap_dm_timer_driver);
743module_init(omap_dm_timer_driver_init);
744module_exit(omap_dm_timer_driver_exit);
745
746MODULE_DESCRIPTION("OMAP Dual-Mode Timer Driver");
747MODULE_LICENSE("GPL");
748MODULE_ALIAS("platform:" DRIVER_NAME);
749MODULE_AUTHOR("Texas Instruments Inc");
diff --git a/arch/arm/plat-omap/include/plat/dmtimer.h b/arch/arm/plat-omap/include/plat/dmtimer.h
index eb5d16c60cd9..d11025e6e7a4 100644
--- a/arch/arm/plat-omap/include/plat/dmtimer.h
+++ b/arch/arm/plat-omap/include/plat/dmtimer.h
@@ -1,5 +1,5 @@
1/* 1/*
2 * arch/arm/plat-omap/include/mach/dmtimer.h 2 * arch/arm/plat-omap/include/plat/dmtimer.h
3 * 3 *
4 * OMAP Dual-Mode Timers 4 * OMAP Dual-Mode Timers
5 * 5 *
@@ -35,6 +35,7 @@
35#include <linux/clk.h> 35#include <linux/clk.h>
36#include <linux/delay.h> 36#include <linux/delay.h>
37#include <linux/io.h> 37#include <linux/io.h>
38#include <linux/platform_device.h>
38 39
39#ifndef __ASM_ARCH_DMTIMER_H 40#ifndef __ASM_ARCH_DMTIMER_H
40#define __ASM_ARCH_DMTIMER_H 41#define __ASM_ARCH_DMTIMER_H
@@ -59,12 +60,56 @@
59 * in OMAP4 can be distinguished. 60 * in OMAP4 can be distinguished.
60 */ 61 */
61#define OMAP_TIMER_IP_VERSION_1 0x1 62#define OMAP_TIMER_IP_VERSION_1 0x1
63
64/* timer capabilities used in hwmod database */
65#define OMAP_TIMER_SECURE 0x80000000
66#define OMAP_TIMER_ALWON 0x40000000
67#define OMAP_TIMER_HAS_PWM 0x20000000
68
69struct omap_timer_capability_dev_attr {
70 u32 timer_capability;
71};
72
62struct omap_dm_timer; 73struct omap_dm_timer;
63struct clk; 74struct clk;
64 75
76struct timer_regs {
77 u32 tidr;
78 u32 tiocp_cfg;
79 u32 tistat;
80 u32 tisr;
81 u32 tier;
82 u32 twer;
83 u32 tclr;
84 u32 tcrr;
85 u32 tldr;
86 u32 ttrg;
87 u32 twps;
88 u32 tmar;
89 u32 tcar1;
90 u32 tsicr;
91 u32 tcar2;
92 u32 tpir;
93 u32 tnir;
94 u32 tcvr;
95 u32 tocr;
96 u32 towr;
97};
98
99struct dmtimer_platform_data {
100 int (*set_timer_src)(struct platform_device *pdev, int source);
101 int timer_ip_version;
102 u32 needs_manual_reset:1;
103 bool reserved;
104
105 bool loses_context;
106
107 u32 (*get_context_loss_count)(struct device *dev);
108};
109
65struct omap_dm_timer *omap_dm_timer_request(void); 110struct omap_dm_timer *omap_dm_timer_request(void);
66struct omap_dm_timer *omap_dm_timer_request_specific(int timer_id); 111struct omap_dm_timer *omap_dm_timer_request_specific(int timer_id);
67void omap_dm_timer_free(struct omap_dm_timer *timer); 112int omap_dm_timer_free(struct omap_dm_timer *timer);
68void omap_dm_timer_enable(struct omap_dm_timer *timer); 113void omap_dm_timer_enable(struct omap_dm_timer *timer);
69void omap_dm_timer_disable(struct omap_dm_timer *timer); 114void omap_dm_timer_disable(struct omap_dm_timer *timer);
70 115
@@ -73,23 +118,23 @@ int omap_dm_timer_get_irq(struct omap_dm_timer *timer);
73u32 omap_dm_timer_modify_idlect_mask(u32 inputmask); 118u32 omap_dm_timer_modify_idlect_mask(u32 inputmask);
74struct clk *omap_dm_timer_get_fclk(struct omap_dm_timer *timer); 119struct clk *omap_dm_timer_get_fclk(struct omap_dm_timer *timer);
75 120
76void omap_dm_timer_trigger(struct omap_dm_timer *timer); 121int omap_dm_timer_trigger(struct omap_dm_timer *timer);
77void omap_dm_timer_start(struct omap_dm_timer *timer); 122int omap_dm_timer_start(struct omap_dm_timer *timer);
78void omap_dm_timer_stop(struct omap_dm_timer *timer); 123int omap_dm_timer_stop(struct omap_dm_timer *timer);
79 124
80int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source); 125int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source);
81void omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload, unsigned int value); 126int omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload, unsigned int value);
82void omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int autoreload, unsigned int value); 127int omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int autoreload, unsigned int value);
83void omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable, unsigned int match); 128int omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable, unsigned int match);
84void omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on, int toggle, int trigger); 129int omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on, int toggle, int trigger);
85void omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int prescaler); 130int omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int prescaler);
86 131
87void omap_dm_timer_set_int_enable(struct omap_dm_timer *timer, unsigned int value); 132int omap_dm_timer_set_int_enable(struct omap_dm_timer *timer, unsigned int value);
88 133
89unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer); 134unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer);
90void omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value); 135int omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value);
91unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer); 136unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer);
92void omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int value); 137int omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int value);
93 138
94int omap_dm_timers_active(void); 139int omap_dm_timers_active(void);
95 140
@@ -98,12 +143,30 @@ int omap_dm_timers_active(void);
98 * used by dmtimer.c and sys_timer related code. 143 * used by dmtimer.c and sys_timer related code.
99 */ 144 */
100 145
101/* register offsets */ 146/*
102#define _OMAP_TIMER_ID_OFFSET 0x00 147 * The interrupt registers are different between v1 and v2 ip.
103#define _OMAP_TIMER_OCP_CFG_OFFSET 0x10 148 * These registers are offsets from timer->iobase.
104#define _OMAP_TIMER_SYS_STAT_OFFSET 0x14 149 */
105#define _OMAP_TIMER_STAT_OFFSET 0x18 150#define OMAP_TIMER_ID_OFFSET 0x00
106#define _OMAP_TIMER_INT_EN_OFFSET 0x1c 151#define OMAP_TIMER_OCP_CFG_OFFSET 0x10
152
153#define OMAP_TIMER_V1_SYS_STAT_OFFSET 0x14
154#define OMAP_TIMER_V1_STAT_OFFSET 0x18
155#define OMAP_TIMER_V1_INT_EN_OFFSET 0x1c
156
157#define OMAP_TIMER_V2_IRQSTATUS_RAW 0x24
158#define OMAP_TIMER_V2_IRQSTATUS 0x28
159#define OMAP_TIMER_V2_IRQENABLE_SET 0x2c
160#define OMAP_TIMER_V2_IRQENABLE_CLR 0x30
161
162/*
163 * The functional registers have a different base on v1 and v2 ip.
164 * These registers are offsets from timer->func_base. The func_base
165 * is samae as io_base for v1 and io_base + 0x14 for v2 ip.
166 *
167 */
168#define OMAP_TIMER_V2_FUNC_OFFSET 0x14
169
107#define _OMAP_TIMER_WAKEUP_EN_OFFSET 0x20 170#define _OMAP_TIMER_WAKEUP_EN_OFFSET 0x20
108#define _OMAP_TIMER_CTRL_OFFSET 0x24 171#define _OMAP_TIMER_CTRL_OFFSET 0x24
109#define OMAP_TIMER_CTRL_GPOCFG (1 << 14) 172#define OMAP_TIMER_CTRL_GPOCFG (1 << 14)
@@ -147,21 +210,6 @@ int omap_dm_timers_active(void);
147/* register offsets with the write pending bit encoded */ 210/* register offsets with the write pending bit encoded */
148#define WPSHIFT 16 211#define WPSHIFT 16
149 212
150#define OMAP_TIMER_ID_REG (_OMAP_TIMER_ID_OFFSET \
151 | (WP_NONE << WPSHIFT))
152
153#define OMAP_TIMER_OCP_CFG_REG (_OMAP_TIMER_OCP_CFG_OFFSET \
154 | (WP_NONE << WPSHIFT))
155
156#define OMAP_TIMER_SYS_STAT_REG (_OMAP_TIMER_SYS_STAT_OFFSET \
157 | (WP_NONE << WPSHIFT))
158
159#define OMAP_TIMER_STAT_REG (_OMAP_TIMER_STAT_OFFSET \
160 | (WP_NONE << WPSHIFT))
161
162#define OMAP_TIMER_INT_EN_REG (_OMAP_TIMER_INT_EN_OFFSET \
163 | (WP_NONE << WPSHIFT))
164
165#define OMAP_TIMER_WAKEUP_EN_REG (_OMAP_TIMER_WAKEUP_EN_OFFSET \ 213#define OMAP_TIMER_WAKEUP_EN_REG (_OMAP_TIMER_WAKEUP_EN_OFFSET \
166 | (WP_NONE << WPSHIFT)) 214 | (WP_NONE << WPSHIFT))
167 215
@@ -209,49 +257,88 @@ int omap_dm_timers_active(void);
209 257
210struct omap_dm_timer { 258struct omap_dm_timer {
211 unsigned long phys_base; 259 unsigned long phys_base;
260 int id;
212 int irq; 261 int irq;
213#ifdef CONFIG_ARCH_OMAP2PLUS
214 struct clk *iclk, *fclk; 262 struct clk *iclk, *fclk;
215#endif 263
216 void __iomem *io_base; 264 void __iomem *io_base;
265 void __iomem *sys_stat; /* TISTAT timer status */
266 void __iomem *irq_stat; /* TISR/IRQSTATUS interrupt status */
267 void __iomem *irq_ena; /* irq enable */
268 void __iomem *irq_dis; /* irq disable, only on v2 ip */
269 void __iomem *pend; /* write pending */
270 void __iomem *func_base; /* function register base */
271
217 unsigned long rate; 272 unsigned long rate;
218 unsigned reserved:1; 273 unsigned reserved:1;
219 unsigned enabled:1;
220 unsigned posted:1; 274 unsigned posted:1;
275 struct timer_regs context;
276 bool loses_context;
277 int ctx_loss_count;
278 int revision;
279 struct platform_device *pdev;
280 struct list_head node;
281
282 u32 (*get_context_loss_count)(struct device *dev);
221}; 283};
222 284
223extern u32 sys_timer_reserved; 285int omap_dm_timer_prepare(struct omap_dm_timer *timer);
224void omap_dm_timer_prepare(struct omap_dm_timer *timer);
225 286
226static inline u32 __omap_dm_timer_read(void __iomem *base, u32 reg, 287static inline u32 __omap_dm_timer_read(struct omap_dm_timer *timer, u32 reg,
227 int posted) 288 int posted)
228{ 289{
229 if (posted) 290 if (posted)
230 while (__raw_readl(base + (OMAP_TIMER_WRITE_PEND_REG & 0xff)) 291 while (__raw_readl(timer->pend) & (reg >> WPSHIFT))
231 & (reg >> WPSHIFT))
232 cpu_relax(); 292 cpu_relax();
233 293
234 return __raw_readl(base + (reg & 0xff)); 294 return __raw_readl(timer->func_base + (reg & 0xff));
235} 295}
236 296
237static inline void __omap_dm_timer_write(void __iomem *base, u32 reg, u32 val, 297static inline void __omap_dm_timer_write(struct omap_dm_timer *timer,
238 int posted) 298 u32 reg, u32 val, int posted)
239{ 299{
240 if (posted) 300 if (posted)
241 while (__raw_readl(base + (OMAP_TIMER_WRITE_PEND_REG & 0xff)) 301 while (__raw_readl(timer->pend) & (reg >> WPSHIFT))
242 & (reg >> WPSHIFT))
243 cpu_relax(); 302 cpu_relax();
244 303
245 __raw_writel(val, base + (reg & 0xff)); 304 __raw_writel(val, timer->func_base + (reg & 0xff));
305}
306
307static inline void __omap_dm_timer_init_regs(struct omap_dm_timer *timer)
308{
309 u32 tidr;
310
311 /* Assume v1 ip if bits [31:16] are zero */
312 tidr = __raw_readl(timer->io_base);
313 if (!(tidr >> 16)) {
314 timer->revision = 1;
315 timer->sys_stat = timer->io_base +
316 OMAP_TIMER_V1_SYS_STAT_OFFSET;
317 timer->irq_stat = timer->io_base + OMAP_TIMER_V1_STAT_OFFSET;
318 timer->irq_ena = timer->io_base + OMAP_TIMER_V1_INT_EN_OFFSET;
319 timer->irq_dis = 0;
320 timer->pend = timer->io_base + _OMAP_TIMER_WRITE_PEND_OFFSET;
321 timer->func_base = timer->io_base;
322 } else {
323 timer->revision = 2;
324 timer->sys_stat = 0;
325 timer->irq_stat = timer->io_base + OMAP_TIMER_V2_IRQSTATUS;
326 timer->irq_ena = timer->io_base + OMAP_TIMER_V2_IRQENABLE_SET;
327 timer->irq_dis = timer->io_base + OMAP_TIMER_V2_IRQENABLE_CLR;
328 timer->pend = timer->io_base +
329 _OMAP_TIMER_WRITE_PEND_OFFSET +
330 OMAP_TIMER_V2_FUNC_OFFSET;
331 timer->func_base = timer->io_base + OMAP_TIMER_V2_FUNC_OFFSET;
332 }
246} 333}
247 334
248/* Assumes the source clock has been set by caller */ 335/* Assumes the source clock has been set by caller */
249static inline void __omap_dm_timer_reset(void __iomem *base, int autoidle, 336static inline void __omap_dm_timer_reset(struct omap_dm_timer *timer,
250 int wakeup) 337 int autoidle, int wakeup)
251{ 338{
252 u32 l; 339 u32 l;
253 340
254 l = __omap_dm_timer_read(base, OMAP_TIMER_OCP_CFG_REG, 0); 341 l = __raw_readl(timer->io_base + OMAP_TIMER_OCP_CFG_OFFSET);
255 l |= 0x02 << 3; /* Set to smart-idle mode */ 342 l |= 0x02 << 3; /* Set to smart-idle mode */
256 l |= 0x2 << 8; /* Set clock activity to perserve f-clock on idle */ 343 l |= 0x2 << 8; /* Set clock activity to perserve f-clock on idle */
257 344
@@ -261,10 +348,10 @@ static inline void __omap_dm_timer_reset(void __iomem *base, int autoidle,
261 if (wakeup) 348 if (wakeup)
262 l |= 1 << 2; 349 l |= 1 << 2;
263 350
264 __omap_dm_timer_write(base, OMAP_TIMER_OCP_CFG_REG, l, 0); 351 __raw_writel(l, timer->io_base + OMAP_TIMER_OCP_CFG_OFFSET);
265 352
266 /* Match hardware reset default of posted mode */ 353 /* Match hardware reset default of posted mode */
267 __omap_dm_timer_write(base, OMAP_TIMER_IF_CTRL_REG, 354 __omap_dm_timer_write(timer, OMAP_TIMER_IF_CTRL_REG,
268 OMAP_TIMER_CTRL_POSTED, 0); 355 OMAP_TIMER_CTRL_POSTED, 0);
269} 356}
270 357
@@ -286,18 +373,18 @@ static inline int __omap_dm_timer_set_source(struct clk *timer_fck,
286 return ret; 373 return ret;
287} 374}
288 375
289static inline void __omap_dm_timer_stop(void __iomem *base, int posted, 376static inline void __omap_dm_timer_stop(struct omap_dm_timer *timer,
290 unsigned long rate) 377 int posted, unsigned long rate)
291{ 378{
292 u32 l; 379 u32 l;
293 380
294 l = __omap_dm_timer_read(base, OMAP_TIMER_CTRL_REG, posted); 381 l = __omap_dm_timer_read(timer, OMAP_TIMER_CTRL_REG, posted);
295 if (l & OMAP_TIMER_CTRL_ST) { 382 if (l & OMAP_TIMER_CTRL_ST) {
296 l &= ~0x1; 383 l &= ~0x1;
297 __omap_dm_timer_write(base, OMAP_TIMER_CTRL_REG, l, posted); 384 __omap_dm_timer_write(timer, OMAP_TIMER_CTRL_REG, l, posted);
298#ifdef CONFIG_ARCH_OMAP2PLUS 385#ifdef CONFIG_ARCH_OMAP2PLUS
299 /* Readback to make sure write has completed */ 386 /* Readback to make sure write has completed */
300 __omap_dm_timer_read(base, OMAP_TIMER_CTRL_REG, posted); 387 __omap_dm_timer_read(timer, OMAP_TIMER_CTRL_REG, posted);
301 /* 388 /*
302 * Wait for functional clock period x 3.5 to make sure that 389 * Wait for functional clock period x 3.5 to make sure that
303 * timer is stopped 390 * timer is stopped
@@ -307,34 +394,34 @@ static inline void __omap_dm_timer_stop(void __iomem *base, int posted,
307 } 394 }
308 395
309 /* Ack possibly pending interrupt */ 396 /* Ack possibly pending interrupt */
310 __omap_dm_timer_write(base, OMAP_TIMER_STAT_REG, 397 __raw_writel(OMAP_TIMER_INT_OVERFLOW, timer->irq_stat);
311 OMAP_TIMER_INT_OVERFLOW, 0);
312} 398}
313 399
314static inline void __omap_dm_timer_load_start(void __iomem *base, u32 ctrl, 400static inline void __omap_dm_timer_load_start(struct omap_dm_timer *timer,
315 unsigned int load, int posted) 401 u32 ctrl, unsigned int load,
402 int posted)
316{ 403{
317 __omap_dm_timer_write(base, OMAP_TIMER_COUNTER_REG, load, posted); 404 __omap_dm_timer_write(timer, OMAP_TIMER_COUNTER_REG, load, posted);
318 __omap_dm_timer_write(base, OMAP_TIMER_CTRL_REG, ctrl, posted); 405 __omap_dm_timer_write(timer, OMAP_TIMER_CTRL_REG, ctrl, posted);
319} 406}
320 407
321static inline void __omap_dm_timer_int_enable(void __iomem *base, 408static inline void __omap_dm_timer_int_enable(struct omap_dm_timer *timer,
322 unsigned int value) 409 unsigned int value)
323{ 410{
324 __omap_dm_timer_write(base, OMAP_TIMER_INT_EN_REG, value, 0); 411 __raw_writel(value, timer->irq_ena);
325 __omap_dm_timer_write(base, OMAP_TIMER_WAKEUP_EN_REG, value, 0); 412 __omap_dm_timer_write(timer, OMAP_TIMER_WAKEUP_EN_REG, value, 0);
326} 413}
327 414
328static inline unsigned int __omap_dm_timer_read_counter(void __iomem *base, 415static inline unsigned int
329 int posted) 416__omap_dm_timer_read_counter(struct omap_dm_timer *timer, int posted)
330{ 417{
331 return __omap_dm_timer_read(base, OMAP_TIMER_COUNTER_REG, posted); 418 return __omap_dm_timer_read(timer, OMAP_TIMER_COUNTER_REG, posted);
332} 419}
333 420
334static inline void __omap_dm_timer_write_status(void __iomem *base, 421static inline void __omap_dm_timer_write_status(struct omap_dm_timer *timer,
335 unsigned int value) 422 unsigned int value)
336{ 423{
337 __omap_dm_timer_write(base, OMAP_TIMER_STAT_REG, value, 0); 424 __raw_writel(value, timer->irq_stat);
338} 425}
339 426
340#endif /* __ASM_ARCH_DMTIMER_H */ 427#endif /* __ASM_ARCH_DMTIMER_H */