diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-11-01 23:18:05 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-11-01 23:18:05 -0400 |
commit | ac5761a650d22dd7dfad4d417463a0981d2da0a4 (patch) | |
tree | c01a46a889dde74fbbb05d3b2da22387bb4875c6 /arch/arm | |
parent | 25498e5b3df931a3d52a6e0642ae242e4ee19488 (diff) | |
parent | eed1e576507b52e03e549e0c9e0c747978122403 (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')
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 |
6 | obj-y := io.o id.o sram.o time.o irq.o mux.o flash.o serial.o devices.o dma.o | 6 | obj-y := io.o id.o sram.o time.o irq.o mux.o flash.o serial.o devices.o dma.o |
7 | obj-y += clock.o clock_data.o opp_data.o reset.o pm_bus.o | 7 | obj-y += clock.o clock_data.o opp_data.o reset.o pm_bus.o timer.o |
8 | 8 | ||
9 | obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o | 9 | obj-$(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 | |||
44 | static 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 | |||
58 | int __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 | |||
165 | err_free_pdata: | ||
166 | kfree(pdata); | ||
167 | |||
168 | err_free_pdev: | ||
169 | platform_device_unregister(pdev); | ||
170 | |||
171 | return ret; | ||
172 | } | ||
173 | arch_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 | ||
3368 | int __init omap4xxx_clk_init(void) | 3401 | int __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 */ | ||
273 | static struct omap_timer_capability_dev_attr capability_alwon_dev_attr = { | ||
274 | .timer_capability = OMAP_TIMER_ALWON, | ||
275 | }; | ||
276 | |||
277 | /* pwm timers dev attribute */ | ||
278 | static struct omap_timer_capability_dev_attr capability_pwm_dev_attr = { | ||
279 | .timer_capability = OMAP_TIMER_HAS_PWM, | ||
280 | }; | ||
281 | |||
272 | /* timer1 */ | 282 | /* timer1 */ |
273 | static struct omap_hwmod omap2420_timer1_hwmod; | 283 | static 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 */ | ||
347 | static struct omap_timer_capability_dev_attr capability_alwon_dev_attr = { | ||
348 | .timer_capability = OMAP_TIMER_ALWON, | ||
349 | }; | ||
350 | |||
351 | /* pwm timers dev attribute */ | ||
352 | static struct omap_timer_capability_dev_attr capability_pwm_dev_attr = { | ||
353 | .timer_capability = OMAP_TIMER_HAS_PWM, | ||
354 | }; | ||
355 | |||
346 | /* timer1 */ | 356 | /* timer1 */ |
347 | static struct omap_hwmod omap2430_timer1_hwmod; | 357 | static 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 */ | ||
568 | static struct omap_timer_capability_dev_attr capability_secure_dev_attr = { | ||
569 | .timer_capability = OMAP_TIMER_SECURE, | ||
570 | }; | ||
571 | |||
572 | /* always-on timers dev attribute */ | ||
573 | static struct omap_timer_capability_dev_attr capability_alwon_dev_attr = { | ||
574 | .timer_capability = OMAP_TIMER_ALWON, | ||
575 | }; | ||
576 | |||
577 | /* pwm timers dev attribute */ | ||
578 | static struct omap_timer_capability_dev_attr capability_pwm_dev_attr = { | ||
579 | .timer_capability = OMAP_TIMER_HAS_PWM, | ||
580 | }; | ||
581 | |||
567 | /* timer1 */ | 582 | /* timer1 */ |
568 | static struct omap_hwmod omap3xxx_timer1_hwmod; | 583 | static 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 */ | ||
4206 | static struct omap_timer_capability_dev_attr capability_alwon_dev_attr = { | ||
4207 | .timer_capability = OMAP_TIMER_ALWON, | ||
4208 | }; | ||
4209 | |||
4210 | /* pwm timers dev attribute */ | ||
4211 | static struct omap_timer_capability_dev_attr capability_pwm_dev_attr = { | ||
4212 | .timer_capability = OMAP_TIMER_HAS_PWM, | ||
4213 | }; | ||
4214 | |||
4204 | /* timer1 */ | 4215 | /* timer1 */ |
4205 | static struct omap_hwmod omap44xx_timer1_hwmod; | 4216 | static struct omap_hwmod omap44xx_timer1_hwmod; |
4206 | static struct omap_hwmod_irq_info omap44xx_timer1_irqs[] = { | 4217 | static 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 | ||
70 | u32 sys_timer_reserved; | 75 | static 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 = { | |||
93 | static int omap2_gp_timer_set_next_event(unsigned long cycles, | 98 | static 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; | |||
251 | static DEFINE_CLOCK_DATA(cd); | 257 | static DEFINE_CLOCK_DATA(cd); |
252 | static cycle_t clocksource_read_cycles(struct clocksource *cs) | 258 | static 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 | ||
257 | static struct clocksource clocksource_gpt = { | 263 | static 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 | } |
342 | OMAP_SYS_TIMER(4) | 348 | OMAP_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 | */ | ||
356 | static 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 | |||
411 | struct 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 | */ | ||
431 | static 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 | */ | ||
501 | static 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 | } | ||
513 | arch_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 | ||
5 | obj-y := clock.o cpu.o devices.o devices-common.o \ | 5 | obj-y := clock.o cpu.o devices.o devices-common.o \ |
6 | id.o usb.o | 6 | id.o usb.o timer.o |
7 | obj-$(CONFIG_CACHE_L2X0) += cache-l2x0.o | 7 | obj-$(CONFIG_CACHE_L2X0) += cache-l2x0.o |
8 | obj-$(CONFIG_UX500_SOC_DB5500) += cpu-db5500.o dma-db5500.o | 8 | obj-$(CONFIG_UX500_SOC_DB5500) += cpu-db5500.o dma-db5500.o |
9 | obj-$(CONFIG_UX500_SOC_DB8500) += cpu-db8500.o devices-db8500.o | 9 | obj-$(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 | |||
54 | static 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 | |||
77 | struct 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 | |||
18 | static 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 | |||
59 | static void ux500_timer_reset(void) | ||
60 | { | ||
61 | nmdk_clkevt_reset(); | ||
62 | nmdk_clksrc_reset(); | ||
63 | } | ||
64 | |||
65 | struct 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 | ||
16 | config HAS_MTU | 16 | config 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 | ||
23 | config 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 | |||
24 | endif | 30 | endif |
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 */ |
11 | extern void __iomem *mtu_base; | 5 | extern void __iomem *mtu_base; |
12 | 6 | ||
13 | /* | 7 | void nmdk_clkevt_reset(void); |
14 | * The MTU device hosts four different counters, with 4 set of | 8 | void 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 | |||
70 | static bool clkevt_periodic; | ||
71 | static u32 clk_prescale; | ||
72 | static u32 nmdk_cycle; /* write-once */ | ||
25 | 73 | ||
26 | void __iomem *mtu_base; /* Assigned by machine code */ | 74 | void __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 */ |
103 | static 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 | |||
115 | void 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 | |||
53 | static void nmdk_clkevt_mode(enum clock_event_mode mode, | 133 | static 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 | ||
85 | static 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 | |||
92 | static struct clock_event_device nmdk_clkevt = { | 158 | static 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 | ||
185 | void 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 | |||
119 | void __init nmdk_timer_init(void) | 198 | void __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 | |||
44 | static int dm_timer_count; | ||
45 | |||
46 | #ifdef CONFIG_ARCH_OMAP1 | ||
47 | static 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 | |||
58 | static 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 | ||
66 | static 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 | |||
81 | static const char *omap2_dm_source_names[] __initdata = { | ||
82 | "sys_ck", | ||
83 | "func_32k_ck", | ||
84 | "alt_ck", | ||
85 | NULL | ||
86 | }; | ||
87 | |||
88 | static struct clk *omap2_dm_source_clocks[3]; | ||
89 | static 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 | ||
99 | static 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 | |||
114 | static const char *omap3_dm_source_names[] __initdata = { | ||
115 | "sys_ck", | ||
116 | "omap_32k_fck", | ||
117 | NULL | ||
118 | }; | ||
119 | |||
120 | static struct clk *omap3_dm_source_clocks[2]; | ||
121 | static 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 | ||
131 | static 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 | }; | ||
145 | static const char *omap4_dm_source_names[] __initdata = { | ||
146 | "sys_clkin_ck", | ||
147 | "sys_32k_ck", | ||
148 | NULL | ||
149 | }; | ||
150 | static struct clk *omap4_dm_source_clocks[2]; | ||
151 | static 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 | |||
160 | static struct omap_dm_timer *dm_timers; | ||
161 | static const char **dm_source_names; | ||
162 | static struct clk **dm_source_clocks; | ||
163 | 44 | ||
164 | static spinlock_t dm_timer_lock; | 45 | static LIST_HEAD(omap_timer_list); |
46 | static 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 | */ |
171 | static inline u32 omap_dm_timer_read_reg(struct omap_dm_timer *timer, u32 reg) | 57 | static 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 | */ |
182 | static void omap_dm_timer_write_reg(struct omap_dm_timer *timer, u32 reg, | 73 | static 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 | |||
80 | static 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 | ||
188 | static void omap_dm_timer_wait_for_reset(struct omap_dm_timer *timer) | 103 | static 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 | ||
202 | static void omap_dm_timer_reset(struct omap_dm_timer *timer) | 120 | static 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 | ||
226 | void omap_dm_timer_prepare(struct omap_dm_timer *timer) | 133 | int 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 | ||
232 | struct omap_dm_timer *omap_dm_timer_request(void) | 154 | struct 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 | ||
256 | struct omap_dm_timer *omap_dm_timer_request_specific(int id) | 186 | struct 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 | } |
278 | EXPORT_SYMBOL_GPL(omap_dm_timer_request_specific); | 215 | EXPORT_SYMBOL_GPL(omap_dm_timer_request_specific); |
279 | 216 | ||
280 | void omap_dm_timer_free(struct omap_dm_timer *timer) | 217 | int 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 | } |
289 | EXPORT_SYMBOL_GPL(omap_dm_timer_free); | 228 | EXPORT_SYMBOL_GPL(omap_dm_timer_free); |
290 | 229 | ||
291 | void omap_dm_timer_enable(struct omap_dm_timer *timer) | 230 | void 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 | } |
305 | EXPORT_SYMBOL_GPL(omap_dm_timer_enable); | 234 | EXPORT_SYMBOL_GPL(omap_dm_timer_enable); |
306 | 235 | ||
307 | void omap_dm_timer_disable(struct omap_dm_timer *timer) | 236 | void 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 | } |
321 | EXPORT_SYMBOL_GPL(omap_dm_timer_disable); | 240 | EXPORT_SYMBOL_GPL(omap_dm_timer_disable); |
322 | 241 | ||
323 | int omap_dm_timer_get_irq(struct omap_dm_timer *timer) | 242 | int 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 | } |
327 | EXPORT_SYMBOL_GPL(omap_dm_timer_get_irq); | 248 | EXPORT_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 | ||
362 | struct clk *omap_dm_timer_get_fclk(struct omap_dm_timer *timer) | 288 | struct 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 | } |
366 | EXPORT_SYMBOL_GPL(omap_dm_timer_get_fclk); | 294 | EXPORT_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 | ||
378 | void omap_dm_timer_trigger(struct omap_dm_timer *timer) | 306 | int 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 | } |
382 | EXPORT_SYMBOL_GPL(omap_dm_timer_trigger); | 316 | EXPORT_SYMBOL_GPL(omap_dm_timer_trigger); |
383 | 317 | ||
384 | void omap_dm_timer_start(struct omap_dm_timer *timer) | 318 | int 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 | } |
394 | EXPORT_SYMBOL_GPL(omap_dm_timer_start); | 344 | EXPORT_SYMBOL_GPL(omap_dm_timer_start); |
395 | 345 | ||
396 | void omap_dm_timer_stop(struct omap_dm_timer *timer) | 346 | int 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 | } |
406 | EXPORT_SYMBOL_GPL(omap_dm_timer_stop); | 361 | EXPORT_SYMBOL_GPL(omap_dm_timer_stop); |
407 | 362 | ||
408 | #ifdef CONFIG_ARCH_OMAP1 | ||
409 | |||
410 | int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source) | 363 | int 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; |
421 | EXPORT_SYMBOL_GPL(omap_dm_timer_set_source); | ||
422 | 370 | ||
423 | #else | 371 | pdata = timer->pdev->dev.platform_data; |
424 | 372 | ||
425 | int 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 | } |
433 | EXPORT_SYMBOL_GPL(omap_dm_timer_set_source); | 380 | EXPORT_SYMBOL_GPL(omap_dm_timer_set_source); |
434 | 381 | ||
435 | #endif | 382 | int omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload, |
436 | |||
437 | void 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 | } |
452 | EXPORT_SYMBOL_GPL(omap_dm_timer_set_load); | 406 | EXPORT_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 */ |
455 | void omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int autoreload, | 409 | int 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 | } |
471 | EXPORT_SYMBOL_GPL(omap_dm_timer_set_load_start); | 443 | EXPORT_SYMBOL_GPL(omap_dm_timer_set_load_start); |
472 | 444 | ||
473 | void omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable, | 445 | int 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 | } |
486 | EXPORT_SYMBOL_GPL(omap_dm_timer_set_match); | 468 | EXPORT_SYMBOL_GPL(omap_dm_timer_set_match); |
487 | 469 | ||
488 | void omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on, | 470 | int 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 | } |
503 | EXPORT_SYMBOL_GPL(omap_dm_timer_set_pwm); | 494 | EXPORT_SYMBOL_GPL(omap_dm_timer_set_pwm); |
504 | 495 | ||
505 | void omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int prescaler) | 496 | int 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 | } |
517 | EXPORT_SYMBOL_GPL(omap_dm_timer_set_prescaler); | 517 | EXPORT_SYMBOL_GPL(omap_dm_timer_set_prescaler); |
518 | 518 | ||
519 | void omap_dm_timer_set_int_enable(struct omap_dm_timer *timer, | 519 | int 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 | } |
524 | EXPORT_SYMBOL_GPL(omap_dm_timer_set_int_enable); | 534 | EXPORT_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 | } |
534 | EXPORT_SYMBOL_GPL(omap_dm_timer_read_status); | 549 | EXPORT_SYMBOL_GPL(omap_dm_timer_read_status); |
535 | 550 | ||
536 | void omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value) | 551 | int 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 | } |
540 | EXPORT_SYMBOL_GPL(omap_dm_timer_write_status); | 561 | EXPORT_SYMBOL_GPL(omap_dm_timer_write_status); |
541 | 562 | ||
542 | unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer) | 563 | unsigned 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 | } |
546 | EXPORT_SYMBOL_GPL(omap_dm_timer_read_counter); | 572 | EXPORT_SYMBOL_GPL(omap_dm_timer_read_counter); |
547 | 573 | ||
548 | void omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int value) | 574 | int 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 | } |
552 | EXPORT_SYMBOL_GPL(omap_dm_timer_write_counter); | 587 | EXPORT_SYMBOL_GPL(omap_dm_timer_write_counter); |
553 | 588 | ||
554 | int omap_dm_timers_active(void) | 589 | int 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 | } |
573 | EXPORT_SYMBOL_GPL(omap_dm_timers_active); | 604 | EXPORT_SYMBOL_GPL(omap_dm_timers_active); |
574 | 605 | ||
575 | static 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 | */ | ||
613 | static 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 | |||
688 | err_free_mem: | ||
689 | kfree(timer); | ||
690 | |||
691 | err_free_ioregion: | ||
692 | release_mem_region(mem->start, resource_size(mem)); | ||
693 | |||
694 | return ret; | ||
638 | } | 695 | } |
639 | 696 | ||
640 | arch_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 | */ | ||
705 | static 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 | |||
724 | static 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 | |||
732 | static int __init omap_dm_timer_driver_init(void) | ||
733 | { | ||
734 | return platform_driver_register(&omap_dm_timer_driver); | ||
735 | } | ||
736 | |||
737 | static void __exit omap_dm_timer_driver_exit(void) | ||
738 | { | ||
739 | platform_driver_unregister(&omap_dm_timer_driver); | ||
740 | } | ||
741 | |||
742 | early_platform_init("earlytimer", &omap_dm_timer_driver); | ||
743 | module_init(omap_dm_timer_driver_init); | ||
744 | module_exit(omap_dm_timer_driver_exit); | ||
745 | |||
746 | MODULE_DESCRIPTION("OMAP Dual-Mode Timer Driver"); | ||
747 | MODULE_LICENSE("GPL"); | ||
748 | MODULE_ALIAS("platform:" DRIVER_NAME); | ||
749 | MODULE_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 | |||
69 | struct omap_timer_capability_dev_attr { | ||
70 | u32 timer_capability; | ||
71 | }; | ||
72 | |||
62 | struct omap_dm_timer; | 73 | struct omap_dm_timer; |
63 | struct clk; | 74 | struct clk; |
64 | 75 | ||
76 | struct 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 | |||
99 | struct 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 | |||
65 | struct omap_dm_timer *omap_dm_timer_request(void); | 110 | struct omap_dm_timer *omap_dm_timer_request(void); |
66 | struct omap_dm_timer *omap_dm_timer_request_specific(int timer_id); | 111 | struct omap_dm_timer *omap_dm_timer_request_specific(int timer_id); |
67 | void omap_dm_timer_free(struct omap_dm_timer *timer); | 112 | int omap_dm_timer_free(struct omap_dm_timer *timer); |
68 | void omap_dm_timer_enable(struct omap_dm_timer *timer); | 113 | void omap_dm_timer_enable(struct omap_dm_timer *timer); |
69 | void omap_dm_timer_disable(struct omap_dm_timer *timer); | 114 | void 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); | |||
73 | u32 omap_dm_timer_modify_idlect_mask(u32 inputmask); | 118 | u32 omap_dm_timer_modify_idlect_mask(u32 inputmask); |
74 | struct clk *omap_dm_timer_get_fclk(struct omap_dm_timer *timer); | 119 | struct clk *omap_dm_timer_get_fclk(struct omap_dm_timer *timer); |
75 | 120 | ||
76 | void omap_dm_timer_trigger(struct omap_dm_timer *timer); | 121 | int omap_dm_timer_trigger(struct omap_dm_timer *timer); |
77 | void omap_dm_timer_start(struct omap_dm_timer *timer); | 122 | int omap_dm_timer_start(struct omap_dm_timer *timer); |
78 | void omap_dm_timer_stop(struct omap_dm_timer *timer); | 123 | int omap_dm_timer_stop(struct omap_dm_timer *timer); |
79 | 124 | ||
80 | int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source); | 125 | int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source); |
81 | void omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload, unsigned int value); | 126 | int omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload, unsigned int value); |
82 | void omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int autoreload, unsigned int value); | 127 | int omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int autoreload, unsigned int value); |
83 | void omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable, unsigned int match); | 128 | int omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable, unsigned int match); |
84 | void omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on, int toggle, int trigger); | 129 | int omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on, int toggle, int trigger); |
85 | void omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int prescaler); | 130 | int omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int prescaler); |
86 | 131 | ||
87 | void omap_dm_timer_set_int_enable(struct omap_dm_timer *timer, unsigned int value); | 132 | int omap_dm_timer_set_int_enable(struct omap_dm_timer *timer, unsigned int value); |
88 | 133 | ||
89 | unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer); | 134 | unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer); |
90 | void omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value); | 135 | int omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value); |
91 | unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer); | 136 | unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer); |
92 | void omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int value); | 137 | int omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int value); |
93 | 138 | ||
94 | int omap_dm_timers_active(void); | 139 | int 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 | ||
210 | struct omap_dm_timer { | 258 | struct 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 | ||
223 | extern u32 sys_timer_reserved; | 285 | int omap_dm_timer_prepare(struct omap_dm_timer *timer); |
224 | void omap_dm_timer_prepare(struct omap_dm_timer *timer); | ||
225 | 286 | ||
226 | static inline u32 __omap_dm_timer_read(void __iomem *base, u32 reg, | 287 | static 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 | ||
237 | static inline void __omap_dm_timer_write(void __iomem *base, u32 reg, u32 val, | 297 | static 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 | |||
307 | static 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 */ |
249 | static inline void __omap_dm_timer_reset(void __iomem *base, int autoidle, | 336 | static 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 | ||
289 | static inline void __omap_dm_timer_stop(void __iomem *base, int posted, | 376 | static 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 | ||
314 | static inline void __omap_dm_timer_load_start(void __iomem *base, u32 ctrl, | 400 | static 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 | ||
321 | static inline void __omap_dm_timer_int_enable(void __iomem *base, | 408 | static 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 | ||
328 | static inline unsigned int __omap_dm_timer_read_counter(void __iomem *base, | 415 | static 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 | ||
334 | static inline void __omap_dm_timer_write_status(void __iomem *base, | 421 | static 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 */ |