diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/Kconfig | 1 | ||||
-rw-r--r-- | arch/arm/mach-davinci/Kconfig | 12 | ||||
-rw-r--r-- | arch/arm/mach-davinci/board-evm.c | 2 | ||||
-rw-r--r-- | arch/arm/mach-davinci/clock.c | 385 | ||||
-rw-r--r-- | arch/arm/mach-davinci/clock.h | 87 | ||||
-rw-r--r-- | arch/arm/mach-davinci/include/mach/clkdev.h | 13 | ||||
-rw-r--r-- | arch/arm/mach-davinci/include/mach/clock.h | 1 | ||||
-rw-r--r-- | arch/arm/mach-davinci/include/mach/psc.h | 53 | ||||
-rw-r--r-- | arch/arm/mach-davinci/io.c | 1 | ||||
-rw-r--r-- | arch/arm/mach-davinci/psc.c | 81 |
10 files changed, 402 insertions, 234 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index bb57f35e7683..cfd99649ad85 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig | |||
@@ -586,6 +586,7 @@ config ARCH_DAVINCI | |||
586 | select HAVE_CLK | 586 | select HAVE_CLK |
587 | select ZONE_DMA | 587 | select ZONE_DMA |
588 | select HAVE_IDE | 588 | select HAVE_IDE |
589 | select COMMON_CLKDEV | ||
589 | help | 590 | help |
590 | Support for TI's DaVinci platform. | 591 | Support for TI's DaVinci platform. |
591 | 592 | ||
diff --git a/arch/arm/mach-davinci/Kconfig b/arch/arm/mach-davinci/Kconfig index bac988e7a4c3..af886734c73b 100644 --- a/arch/arm/mach-davinci/Kconfig +++ b/arch/arm/mach-davinci/Kconfig | |||
@@ -18,6 +18,18 @@ config MACH_DAVINCI_EVM | |||
18 | Configure this option to specify the whether the board used | 18 | Configure this option to specify the whether the board used |
19 | for development is a DaVinci EVM | 19 | for development is a DaVinci EVM |
20 | 20 | ||
21 | config DAVINCI_RESET_CLOCKS | ||
22 | bool "Reset unused clocks during boot" | ||
23 | depends on ARCH_DAVINCI | ||
24 | help | ||
25 | Say Y if you want to reset unused clocks during boot. | ||
26 | This option saves power, but assumes all drivers are | ||
27 | using the clock framework. Broken drivers that do not | ||
28 | yet use clock framework may not work with this option. | ||
29 | If you are booting from another operating system, you | ||
30 | probably do not want this option enabled until your | ||
31 | device drivers work properly. | ||
32 | |||
21 | endmenu | 33 | endmenu |
22 | 34 | ||
23 | endif | 35 | endif |
diff --git a/arch/arm/mach-davinci/board-evm.c b/arch/arm/mach-davinci/board-evm.c index 0b97a528902b..1b745c39d891 100644 --- a/arch/arm/mach-davinci/board-evm.c +++ b/arch/arm/mach-davinci/board-evm.c | |||
@@ -406,8 +406,6 @@ davinci_evm_map_io(void) | |||
406 | 406 | ||
407 | static __init void davinci_evm_init(void) | 407 | static __init void davinci_evm_init(void) |
408 | { | 408 | { |
409 | davinci_psc_init(); | ||
410 | |||
411 | #if defined(CONFIG_BLK_DEV_PALMCHIP_BK3710) || \ | 409 | #if defined(CONFIG_BLK_DEV_PALMCHIP_BK3710) || \ |
412 | defined(CONFIG_BLK_DEV_PALMCHIP_BK3710_MODULE) | 410 | defined(CONFIG_BLK_DEV_PALMCHIP_BK3710_MODULE) |
413 | #if defined(CONFIG_MTD_PHYSMAP) || \ | 411 | #if defined(CONFIG_MTD_PHYSMAP) || \ |
diff --git a/arch/arm/mach-davinci/clock.c b/arch/arm/mach-davinci/clock.c index abb92b7eca0c..f0baaa15a57e 100644 --- a/arch/arm/mach-davinci/clock.c +++ b/arch/arm/mach-davinci/clock.c | |||
@@ -1,7 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | * TI DaVinci clock config file | 2 | * Clock and PLL control for DaVinci devices |
3 | * | 3 | * |
4 | * Copyright (C) 2006 Texas Instruments. | 4 | * Copyright (C) 2006-2007 Texas Instruments. |
5 | * Copyright (C) 2008-2009 Deep Root Systems, LLC | ||
5 | * | 6 | * |
6 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
7 | * it under the terms of the GNU General Public License as published by | 8 | * it under the terms of the GNU General Public License as published by |
@@ -13,6 +14,7 @@ | |||
13 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
14 | #include <linux/init.h> | 15 | #include <linux/init.h> |
15 | #include <linux/errno.h> | 16 | #include <linux/errno.h> |
17 | #include <linux/clk.h> | ||
16 | #include <linux/err.h> | 18 | #include <linux/err.h> |
17 | #include <linux/mutex.h> | 19 | #include <linux/mutex.h> |
18 | #include <linux/platform_device.h> | 20 | #include <linux/platform_device.h> |
@@ -21,98 +23,50 @@ | |||
21 | #include <mach/hardware.h> | 23 | #include <mach/hardware.h> |
22 | 24 | ||
23 | #include <mach/psc.h> | 25 | #include <mach/psc.h> |
26 | #include <mach/cputype.h> | ||
24 | #include "clock.h" | 27 | #include "clock.h" |
25 | 28 | ||
26 | /* PLL/Reset register offsets */ | ||
27 | #define PLLM 0x110 | ||
28 | |||
29 | static LIST_HEAD(clocks); | 29 | static LIST_HEAD(clocks); |
30 | static DEFINE_MUTEX(clocks_mutex); | 30 | static DEFINE_MUTEX(clocks_mutex); |
31 | static DEFINE_SPINLOCK(clockfw_lock); | 31 | static DEFINE_SPINLOCK(clockfw_lock); |
32 | 32 | ||
33 | static unsigned int commonrate; | 33 | static unsigned psc_domain(struct clk *clk) |
34 | static unsigned int armrate; | ||
35 | static unsigned int fixedrate = 27000000; /* 27 MHZ */ | ||
36 | |||
37 | extern void davinci_psc_config(unsigned int domain, unsigned int id, char enable); | ||
38 | |||
39 | /* | ||
40 | * Returns a clock. Note that we first try to use device id on the bus | ||
41 | * and clock name. If this fails, we try to use clock name only. | ||
42 | */ | ||
43 | struct clk *clk_get(struct device *dev, const char *id) | ||
44 | { | 34 | { |
45 | struct clk *p, *clk = ERR_PTR(-ENOENT); | 35 | return (clk->flags & PSC_DSP) |
46 | int idno; | 36 | ? DAVINCI_GPSC_DSPDOMAIN |
47 | 37 | : DAVINCI_GPSC_ARMDOMAIN; | |
48 | if (dev == NULL || dev->bus != &platform_bus_type) | ||
49 | idno = -1; | ||
50 | else | ||
51 | idno = to_platform_device(dev)->id; | ||
52 | |||
53 | mutex_lock(&clocks_mutex); | ||
54 | |||
55 | list_for_each_entry(p, &clocks, node) { | ||
56 | if (p->id == idno && | ||
57 | strcmp(id, p->name) == 0 && try_module_get(p->owner)) { | ||
58 | clk = p; | ||
59 | goto found; | ||
60 | } | ||
61 | } | ||
62 | |||
63 | list_for_each_entry(p, &clocks, node) { | ||
64 | if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) { | ||
65 | clk = p; | ||
66 | break; | ||
67 | } | ||
68 | } | ||
69 | |||
70 | found: | ||
71 | mutex_unlock(&clocks_mutex); | ||
72 | |||
73 | return clk; | ||
74 | } | 38 | } |
75 | EXPORT_SYMBOL(clk_get); | ||
76 | 39 | ||
77 | void clk_put(struct clk *clk) | 40 | static void __clk_enable(struct clk *clk) |
78 | { | 41 | { |
79 | if (clk && !IS_ERR(clk)) | 42 | if (clk->parent) |
80 | module_put(clk->owner); | 43 | __clk_enable(clk->parent); |
81 | } | 44 | if (clk->usecount++ == 0 && (clk->flags & CLK_PSC)) |
82 | EXPORT_SYMBOL(clk_put); | 45 | davinci_psc_config(psc_domain(clk), clk->lpsc, 1); |
83 | |||
84 | static int __clk_enable(struct clk *clk) | ||
85 | { | ||
86 | if (clk->flags & ALWAYS_ENABLED) | ||
87 | return 0; | ||
88 | |||
89 | davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN, clk->lpsc, 1); | ||
90 | return 0; | ||
91 | } | 46 | } |
92 | 47 | ||
93 | static void __clk_disable(struct clk *clk) | 48 | static void __clk_disable(struct clk *clk) |
94 | { | 49 | { |
95 | if (clk->usecount) | 50 | if (WARN_ON(clk->usecount == 0)) |
96 | return; | 51 | return; |
97 | 52 | if (--clk->usecount == 0 && !(clk->flags & CLK_PLL)) | |
98 | davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN, clk->lpsc, 0); | 53 | davinci_psc_config(psc_domain(clk), clk->lpsc, 0); |
54 | if (clk->parent) | ||
55 | __clk_disable(clk->parent); | ||
99 | } | 56 | } |
100 | 57 | ||
101 | int clk_enable(struct clk *clk) | 58 | int clk_enable(struct clk *clk) |
102 | { | 59 | { |
103 | unsigned long flags; | 60 | unsigned long flags; |
104 | int ret = 0; | ||
105 | 61 | ||
106 | if (clk == NULL || IS_ERR(clk)) | 62 | if (clk == NULL || IS_ERR(clk)) |
107 | return -EINVAL; | 63 | return -EINVAL; |
108 | 64 | ||
109 | if (clk->usecount++ == 0) { | 65 | spin_lock_irqsave(&clockfw_lock, flags); |
110 | spin_lock_irqsave(&clockfw_lock, flags); | 66 | __clk_enable(clk); |
111 | ret = __clk_enable(clk); | 67 | spin_unlock_irqrestore(&clockfw_lock, flags); |
112 | spin_unlock_irqrestore(&clockfw_lock, flags); | ||
113 | } | ||
114 | 68 | ||
115 | return ret; | 69 | return 0; |
116 | } | 70 | } |
117 | EXPORT_SYMBOL(clk_enable); | 71 | EXPORT_SYMBOL(clk_enable); |
118 | 72 | ||
@@ -123,11 +77,9 @@ void clk_disable(struct clk *clk) | |||
123 | if (clk == NULL || IS_ERR(clk)) | 77 | if (clk == NULL || IS_ERR(clk)) |
124 | return; | 78 | return; |
125 | 79 | ||
126 | if (clk->usecount > 0 && !(--clk->usecount)) { | 80 | spin_lock_irqsave(&clockfw_lock, flags); |
127 | spin_lock_irqsave(&clockfw_lock, flags); | 81 | __clk_disable(clk); |
128 | __clk_disable(clk); | 82 | spin_unlock_irqrestore(&clockfw_lock, flags); |
129 | spin_unlock_irqrestore(&clockfw_lock, flags); | ||
130 | } | ||
131 | } | 83 | } |
132 | EXPORT_SYMBOL(clk_disable); | 84 | EXPORT_SYMBOL(clk_disable); |
133 | 85 | ||
@@ -136,7 +88,7 @@ unsigned long clk_get_rate(struct clk *clk) | |||
136 | if (clk == NULL || IS_ERR(clk)) | 88 | if (clk == NULL || IS_ERR(clk)) |
137 | return -EINVAL; | 89 | return -EINVAL; |
138 | 90 | ||
139 | return *(clk->rate); | 91 | return clk->rate; |
140 | } | 92 | } |
141 | EXPORT_SYMBOL(clk_get_rate); | 93 | EXPORT_SYMBOL(clk_get_rate); |
142 | 94 | ||
@@ -145,7 +97,7 @@ long clk_round_rate(struct clk *clk, unsigned long rate) | |||
145 | if (clk == NULL || IS_ERR(clk)) | 97 | if (clk == NULL || IS_ERR(clk)) |
146 | return -EINVAL; | 98 | return -EINVAL; |
147 | 99 | ||
148 | return *(clk->rate); | 100 | return clk->rate; |
149 | } | 101 | } |
150 | EXPORT_SYMBOL(clk_round_rate); | 102 | EXPORT_SYMBOL(clk_round_rate); |
151 | 103 | ||
@@ -164,10 +116,23 @@ int clk_register(struct clk *clk) | |||
164 | if (clk == NULL || IS_ERR(clk)) | 116 | if (clk == NULL || IS_ERR(clk)) |
165 | return -EINVAL; | 117 | return -EINVAL; |
166 | 118 | ||
119 | if (WARN(clk->parent && !clk->parent->rate, | ||
120 | "CLK: %s parent %s has no rate!\n", | ||
121 | clk->name, clk->parent->name)) | ||
122 | return -EINVAL; | ||
123 | |||
167 | mutex_lock(&clocks_mutex); | 124 | mutex_lock(&clocks_mutex); |
168 | list_add(&clk->node, &clocks); | 125 | list_add_tail(&clk->node, &clocks); |
169 | mutex_unlock(&clocks_mutex); | 126 | mutex_unlock(&clocks_mutex); |
170 | 127 | ||
128 | /* If rate is already set, use it */ | ||
129 | if (clk->rate) | ||
130 | return 0; | ||
131 | |||
132 | /* Otherwise, default to parent rate */ | ||
133 | if (clk->parent) | ||
134 | clk->rate = clk->parent->rate; | ||
135 | |||
171 | return 0; | 136 | return 0; |
172 | } | 137 | } |
173 | EXPORT_SYMBOL(clk_register); | 138 | EXPORT_SYMBOL(clk_register); |
@@ -183,84 +148,150 @@ void clk_unregister(struct clk *clk) | |||
183 | } | 148 | } |
184 | EXPORT_SYMBOL(clk_unregister); | 149 | EXPORT_SYMBOL(clk_unregister); |
185 | 150 | ||
186 | static struct clk davinci_clks[] = { | 151 | #ifdef CONFIG_DAVINCI_RESET_CLOCKS |
187 | { | 152 | /* |
188 | .name = "ARMCLK", | 153 | * Disable any unused clocks left on by the bootloader |
189 | .rate = &armrate, | 154 | */ |
190 | .lpsc = -1, | 155 | static int __init clk_disable_unused(void) |
191 | .flags = ALWAYS_ENABLED, | 156 | { |
192 | }, | 157 | struct clk *ck; |
193 | { | 158 | |
194 | .name = "UART", | 159 | spin_lock_irq(&clockfw_lock); |
195 | .rate = &fixedrate, | 160 | list_for_each_entry(ck, &clocks, node) { |
196 | .lpsc = DAVINCI_LPSC_UART0, | 161 | if (ck->usecount > 0) |
197 | }, | 162 | continue; |
198 | { | 163 | if (!(ck->flags & CLK_PSC)) |
199 | .name = "EMACCLK", | 164 | continue; |
200 | .rate = &commonrate, | 165 | |
201 | .lpsc = DAVINCI_LPSC_EMAC_WRAPPER, | 166 | /* ignore if in Disabled or SwRstDisable states */ |
202 | }, | 167 | if (!davinci_psc_is_clk_active(ck->lpsc)) |
203 | { | 168 | continue; |
204 | .name = "I2CCLK", | 169 | |
205 | .rate = &fixedrate, | 170 | pr_info("Clocks: disable unused %s\n", ck->name); |
206 | .lpsc = DAVINCI_LPSC_I2C, | 171 | davinci_psc_config(psc_domain(ck), ck->lpsc, 0); |
207 | }, | ||
208 | { | ||
209 | .name = "IDECLK", | ||
210 | .rate = &commonrate, | ||
211 | .lpsc = DAVINCI_LPSC_ATA, | ||
212 | }, | ||
213 | { | ||
214 | .name = "McBSPCLK", | ||
215 | .rate = &commonrate, | ||
216 | .lpsc = DAVINCI_LPSC_McBSP, | ||
217 | }, | ||
218 | { | ||
219 | .name = "MMCSDCLK", | ||
220 | .rate = &commonrate, | ||
221 | .lpsc = DAVINCI_LPSC_MMC_SD, | ||
222 | }, | ||
223 | { | ||
224 | .name = "SPICLK", | ||
225 | .rate = &commonrate, | ||
226 | .lpsc = DAVINCI_LPSC_SPI, | ||
227 | }, | ||
228 | { | ||
229 | .name = "gpio", | ||
230 | .rate = &commonrate, | ||
231 | .lpsc = DAVINCI_LPSC_GPIO, | ||
232 | }, | ||
233 | { | ||
234 | .name = "usb", | ||
235 | .rate = &commonrate, | ||
236 | .lpsc = DAVINCI_LPSC_USB, | ||
237 | }, | ||
238 | { | ||
239 | .name = "AEMIFCLK", | ||
240 | .rate = &commonrate, | ||
241 | .lpsc = DAVINCI_LPSC_AEMIF, | ||
242 | .usecount = 1, | ||
243 | } | 172 | } |
244 | }; | 173 | spin_unlock_irq(&clockfw_lock); |
174 | |||
175 | return 0; | ||
176 | } | ||
177 | late_initcall(clk_disable_unused); | ||
178 | #endif | ||
245 | 179 | ||
246 | int __init davinci_clk_init(void) | 180 | static void clk_sysclk_recalc(struct clk *clk) |
247 | { | 181 | { |
248 | struct clk *clkp; | 182 | u32 v, plldiv; |
249 | int count = 0; | 183 | struct pll_data *pll; |
250 | u32 pll_mult; | 184 | |
251 | 185 | /* If this is the PLL base clock, no more calculations needed */ | |
252 | pll_mult = davinci_readl(DAVINCI_PLL_CNTRL0_BASE + PLLM); | 186 | if (clk->pll_data) |
253 | commonrate = ((pll_mult + 1) * 27000000) / 6; | 187 | return; |
254 | armrate = ((pll_mult + 1) * 27000000) / 2; | 188 | |
255 | 189 | if (WARN_ON(!clk->parent)) | |
256 | for (clkp = davinci_clks; count < ARRAY_SIZE(davinci_clks); | 190 | return; |
257 | count++, clkp++) { | 191 | |
258 | clk_register(clkp); | 192 | clk->rate = clk->parent->rate; |
259 | 193 | ||
260 | /* Turn on clocks that have been enabled in the | 194 | /* Otherwise, the parent must be a PLL */ |
261 | * table above */ | 195 | if (WARN_ON(!clk->parent->pll_data)) |
262 | if (clkp->usecount) | 196 | return; |
263 | clk_enable(clkp); | 197 | |
198 | pll = clk->parent->pll_data; | ||
199 | |||
200 | /* If pre-PLL, source clock is before the multiplier and divider(s) */ | ||
201 | if (clk->flags & PRE_PLL) | ||
202 | clk->rate = pll->input_rate; | ||
203 | |||
204 | if (!clk->div_reg) | ||
205 | return; | ||
206 | |||
207 | v = __raw_readl(pll->base + clk->div_reg); | ||
208 | if (v & PLLDIV_EN) { | ||
209 | plldiv = (v & PLLDIV_RATIO_MASK) + 1; | ||
210 | if (plldiv) | ||
211 | clk->rate /= plldiv; | ||
212 | } | ||
213 | } | ||
214 | |||
215 | static void __init clk_pll_init(struct clk *clk) | ||
216 | { | ||
217 | u32 ctrl, mult = 1, prediv = 1, postdiv = 1; | ||
218 | u8 bypass; | ||
219 | struct pll_data *pll = clk->pll_data; | ||
220 | |||
221 | pll->base = IO_ADDRESS(pll->phys_base); | ||
222 | ctrl = __raw_readl(pll->base + PLLCTL); | ||
223 | clk->rate = pll->input_rate = clk->parent->rate; | ||
224 | |||
225 | if (ctrl & PLLCTL_PLLEN) { | ||
226 | bypass = 0; | ||
227 | mult = __raw_readl(pll->base + PLLM); | ||
228 | mult = (mult & PLLM_PLLM_MASK) + 1; | ||
229 | } else | ||
230 | bypass = 1; | ||
231 | |||
232 | if (pll->flags & PLL_HAS_PREDIV) { | ||
233 | prediv = __raw_readl(pll->base + PREDIV); | ||
234 | if (prediv & PLLDIV_EN) | ||
235 | prediv = (prediv & PLLDIV_RATIO_MASK) + 1; | ||
236 | else | ||
237 | prediv = 1; | ||
238 | } | ||
239 | |||
240 | /* pre-divider is fixed, but (some?) chips won't report that */ | ||
241 | if (cpu_is_davinci_dm355() && pll->num == 1) | ||
242 | prediv = 8; | ||
243 | |||
244 | if (pll->flags & PLL_HAS_POSTDIV) { | ||
245 | postdiv = __raw_readl(pll->base + POSTDIV); | ||
246 | if (postdiv & PLLDIV_EN) | ||
247 | postdiv = (postdiv & PLLDIV_RATIO_MASK) + 1; | ||
248 | else | ||
249 | postdiv = 1; | ||
250 | } | ||
251 | |||
252 | if (!bypass) { | ||
253 | clk->rate /= prediv; | ||
254 | clk->rate *= mult; | ||
255 | clk->rate /= postdiv; | ||
256 | } | ||
257 | |||
258 | pr_debug("PLL%d: input = %lu MHz [ ", | ||
259 | pll->num, clk->parent->rate / 1000000); | ||
260 | if (bypass) | ||
261 | pr_debug("bypass "); | ||
262 | if (prediv > 1) | ||
263 | pr_debug("/ %d ", prediv); | ||
264 | if (mult > 1) | ||
265 | pr_debug("* %d ", mult); | ||
266 | if (postdiv > 1) | ||
267 | pr_debug("/ %d ", postdiv); | ||
268 | pr_debug("] --> %lu MHz output.\n", clk->rate / 1000000); | ||
269 | } | ||
270 | |||
271 | int __init davinci_clk_init(struct davinci_clk *clocks) | ||
272 | { | ||
273 | struct davinci_clk *c; | ||
274 | struct clk *clk; | ||
275 | |||
276 | for (c = clocks; c->lk.clk; c++) { | ||
277 | clk = c->lk.clk; | ||
278 | |||
279 | if (clk->pll_data) | ||
280 | clk_pll_init(clk); | ||
281 | |||
282 | /* Calculate rates for PLL-derived clocks */ | ||
283 | else if (clk->flags & CLK_PLL) | ||
284 | clk_sysclk_recalc(clk); | ||
285 | |||
286 | if (clk->lpsc) | ||
287 | clk->flags |= CLK_PSC; | ||
288 | |||
289 | clkdev_add(&c->lk); | ||
290 | clk_register(clk); | ||
291 | |||
292 | /* Turn on clocks that Linux doesn't otherwise manage */ | ||
293 | if (clk->flags & ALWAYS_ENABLED) | ||
294 | clk_enable(clk); | ||
264 | } | 295 | } |
265 | 296 | ||
266 | return 0; | 297 | return 0; |
@@ -285,12 +316,52 @@ static void davinci_ck_stop(struct seq_file *m, void *v) | |||
285 | { | 316 | { |
286 | } | 317 | } |
287 | 318 | ||
288 | static int davinci_ck_show(struct seq_file *m, void *v) | 319 | #define CLKNAME_MAX 10 /* longest clock name */ |
320 | #define NEST_DELTA 2 | ||
321 | #define NEST_MAX 4 | ||
322 | |||
323 | static void | ||
324 | dump_clock(struct seq_file *s, unsigned nest, struct clk *parent) | ||
289 | { | 325 | { |
290 | struct clk *cp; | 326 | char *state; |
327 | char buf[CLKNAME_MAX + NEST_DELTA * NEST_MAX]; | ||
328 | struct clk *clk; | ||
329 | unsigned i; | ||
330 | |||
331 | if (parent->flags & CLK_PLL) | ||
332 | state = "pll"; | ||
333 | else if (parent->flags & CLK_PSC) | ||
334 | state = "psc"; | ||
335 | else | ||
336 | state = ""; | ||
337 | |||
338 | /* <nest spaces> name <pad to end> */ | ||
339 | memset(buf, ' ', sizeof(buf) - 1); | ||
340 | buf[sizeof(buf) - 1] = 0; | ||
341 | i = strlen(parent->name); | ||
342 | memcpy(buf + nest, parent->name, | ||
343 | min(i, (unsigned)(sizeof(buf) - 1 - nest))); | ||
344 | |||
345 | seq_printf(s, "%s users=%2d %-3s %9ld Hz\n", | ||
346 | buf, parent->usecount, state, clk_get_rate(parent)); | ||
347 | /* REVISIT show device associations too */ | ||
348 | |||
349 | /* cost is now small, but not linear... */ | ||
350 | list_for_each_entry(clk, &clocks, node) { | ||
351 | if (clk->parent == parent) | ||
352 | dump_clock(s, nest + NEST_DELTA, clk); | ||
353 | } | ||
354 | } | ||
291 | 355 | ||
292 | list_for_each_entry(cp, &clocks, node) | 356 | static int davinci_ck_show(struct seq_file *m, void *v) |
293 | seq_printf(m,"%s %d %d\n", cp->name, *(cp->rate), cp->usecount); | 357 | { |
358 | /* Show clock tree; we know the main oscillator is first. | ||
359 | * We trust nonzero usecounts equate to PSC enables... | ||
360 | */ | ||
361 | mutex_lock(&clocks_mutex); | ||
362 | if (!list_empty(&clocks)) | ||
363 | dump_clock(m, 0, list_first_entry(&clocks, struct clk, node)); | ||
364 | mutex_unlock(&clocks_mutex); | ||
294 | 365 | ||
295 | return 0; | 366 | return 0; |
296 | } | 367 | } |
@@ -321,4 +392,4 @@ static int __init davinci_ck_proc_init(void) | |||
321 | 392 | ||
322 | } | 393 | } |
323 | __initcall(davinci_ck_proc_init); | 394 | __initcall(davinci_ck_proc_init); |
324 | #endif /* CONFIG_DEBUG_PROC_FS */ | 395 | #endif /* CONFIG_DEBUG_PROC_FS */ |
diff --git a/arch/arm/mach-davinci/clock.h b/arch/arm/mach-davinci/clock.h index ed47079a52e4..35736ec202f8 100644 --- a/arch/arm/mach-davinci/clock.h +++ b/arch/arm/mach-davinci/clock.h | |||
@@ -1,7 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | * TI DaVinci clock definitions | 2 | * TI DaVinci clock definitions |
3 | * | 3 | * |
4 | * Copyright (C) 2006 Texas Instruments. | 4 | * Copyright (C) 2006-2007 Texas Instruments. |
5 | * Copyright (C) 2008-2009 Deep Root Systems, LLC | ||
5 | * | 6 | * |
6 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
7 | * it under the terms of the GNU General Public License version 2 as | 8 | * it under the terms of the GNU General Public License version 2 as |
@@ -11,23 +12,85 @@ | |||
11 | #ifndef __ARCH_ARM_DAVINCI_CLOCK_H | 12 | #ifndef __ARCH_ARM_DAVINCI_CLOCK_H |
12 | #define __ARCH_ARM_DAVINCI_CLOCK_H | 13 | #define __ARCH_ARM_DAVINCI_CLOCK_H |
13 | 14 | ||
15 | #include <linux/list.h> | ||
16 | #include <asm/clkdev.h> | ||
17 | |||
18 | #define DAVINCI_PLL1_BASE 0x01c40800 | ||
19 | #define DAVINCI_PLL2_BASE 0x01c40c00 | ||
20 | #define MAX_PLL 2 | ||
21 | |||
22 | /* PLL/Reset register offsets */ | ||
23 | #define PLLCTL 0x100 | ||
24 | #define PLLCTL_PLLEN BIT(0) | ||
25 | #define PLLCTL_CLKMODE BIT(8) | ||
26 | |||
27 | #define PLLM 0x110 | ||
28 | #define PLLM_PLLM_MASK 0xff | ||
29 | |||
30 | #define PREDIV 0x114 | ||
31 | #define PLLDIV1 0x118 | ||
32 | #define PLLDIV2 0x11c | ||
33 | #define PLLDIV3 0x120 | ||
34 | #define POSTDIV 0x128 | ||
35 | #define BPDIV 0x12c | ||
36 | #define PLLCMD 0x138 | ||
37 | #define PLLSTAT 0x13c | ||
38 | #define PLLALNCTL 0x140 | ||
39 | #define PLLDCHANGE 0x144 | ||
40 | #define PLLCKEN 0x148 | ||
41 | #define PLLCKSTAT 0x14c | ||
42 | #define PLLSYSTAT 0x150 | ||
43 | #define PLLDIV4 0x160 | ||
44 | #define PLLDIV5 0x164 | ||
45 | #define PLLDIV6 0x168 | ||
46 | #define PLLDIV7 0x16c | ||
47 | #define PLLDIV8 0x170 | ||
48 | #define PLLDIV9 0x174 | ||
49 | #define PLLDIV_EN BIT(15) | ||
50 | #define PLLDIV_RATIO_MASK 0x1f | ||
51 | |||
52 | struct pll_data { | ||
53 | u32 phys_base; | ||
54 | void __iomem *base; | ||
55 | u32 num; | ||
56 | u32 flags; | ||
57 | u32 input_rate; | ||
58 | }; | ||
59 | #define PLL_HAS_PREDIV 0x01 | ||
60 | #define PLL_HAS_POSTDIV 0x02 | ||
61 | |||
14 | struct clk { | 62 | struct clk { |
15 | struct list_head node; | 63 | struct list_head node; |
16 | struct module *owner; | 64 | struct module *owner; |
17 | const char *name; | 65 | const char *name; |
18 | unsigned int *rate; | 66 | unsigned long rate; |
19 | int id; | 67 | u8 usecount; |
20 | __s8 usecount; | 68 | u8 flags; |
21 | __u8 flags; | 69 | u8 lpsc; |
22 | __u8 lpsc; | 70 | struct clk *parent; |
71 | struct pll_data *pll_data; | ||
72 | u32 div_reg; | ||
23 | }; | 73 | }; |
24 | 74 | ||
25 | /* Clock flags */ | 75 | /* Clock flags */ |
26 | #define RATE_CKCTL 1 | 76 | #define ALWAYS_ENABLED BIT(1) |
27 | #define RATE_FIXED 2 | 77 | #define CLK_PSC BIT(2) |
28 | #define RATE_PROPAGATES 4 | 78 | #define PSC_DSP BIT(3) /* PSC uses DSP domain, not ARM */ |
29 | #define VIRTUAL_CLOCK 8 | 79 | #define CLK_PLL BIT(4) /* PLL-derived clock */ |
30 | #define ALWAYS_ENABLED 16 | 80 | #define PRE_PLL BIT(5) /* source is before PLL mult/div */ |
31 | #define ENABLE_REG_32BIT 32 | 81 | |
82 | struct davinci_clk { | ||
83 | struct clk_lookup lk; | ||
84 | }; | ||
85 | |||
86 | #define CLK(dev, con, ck) \ | ||
87 | { \ | ||
88 | .lk = { \ | ||
89 | .dev_id = dev, \ | ||
90 | .con_id = con, \ | ||
91 | .clk = ck, \ | ||
92 | }, \ | ||
93 | } | ||
32 | 94 | ||
95 | int davinci_clk_init(struct davinci_clk *clocks); | ||
33 | #endif | 96 | #endif |
diff --git a/arch/arm/mach-davinci/include/mach/clkdev.h b/arch/arm/mach-davinci/include/mach/clkdev.h new file mode 100644 index 000000000000..730c49d1ebd8 --- /dev/null +++ b/arch/arm/mach-davinci/include/mach/clkdev.h | |||
@@ -0,0 +1,13 @@ | |||
1 | #ifndef __MACH_CLKDEV_H | ||
2 | #define __MACH_CLKDEV_H | ||
3 | |||
4 | static inline int __clk_get(struct clk *clk) | ||
5 | { | ||
6 | return 1; | ||
7 | } | ||
8 | |||
9 | static inline void __clk_put(struct clk *clk) | ||
10 | { | ||
11 | } | ||
12 | |||
13 | #endif | ||
diff --git a/arch/arm/mach-davinci/include/mach/clock.h b/arch/arm/mach-davinci/include/mach/clock.h index 38bdd49bc181..a3b040219876 100644 --- a/arch/arm/mach-davinci/include/mach/clock.h +++ b/arch/arm/mach-davinci/include/mach/clock.h | |||
@@ -17,6 +17,5 @@ struct clk; | |||
17 | 17 | ||
18 | extern int clk_register(struct clk *clk); | 18 | extern int clk_register(struct clk *clk); |
19 | extern void clk_unregister(struct clk *clk); | 19 | extern void clk_unregister(struct clk *clk); |
20 | extern int davinci_clk_init(void); | ||
21 | 20 | ||
22 | #endif | 21 | #endif |
diff --git a/arch/arm/mach-davinci/include/mach/psc.h b/arch/arm/mach-davinci/include/mach/psc.h index 4977aa071e1e..55a90d419fac 100644 --- a/arch/arm/mach-davinci/include/mach/psc.h +++ b/arch/arm/mach-davinci/include/mach/psc.h | |||
@@ -38,8 +38,6 @@ | |||
38 | #define DAVINCI_LPSC_TPTC1 4 | 38 | #define DAVINCI_LPSC_TPTC1 4 |
39 | #define DAVINCI_LPSC_EMAC 5 | 39 | #define DAVINCI_LPSC_EMAC 5 |
40 | #define DAVINCI_LPSC_EMAC_WRAPPER 6 | 40 | #define DAVINCI_LPSC_EMAC_WRAPPER 6 |
41 | #define DAVINCI_LPSC_MDIO 7 | ||
42 | #define DAVINCI_LPSC_IEEE1394 8 | ||
43 | #define DAVINCI_LPSC_USB 9 | 41 | #define DAVINCI_LPSC_USB 9 |
44 | #define DAVINCI_LPSC_ATA 10 | 42 | #define DAVINCI_LPSC_ATA 10 |
45 | #define DAVINCI_LPSC_VLYNQ 11 | 43 | #define DAVINCI_LPSC_VLYNQ 11 |
@@ -47,7 +45,6 @@ | |||
47 | #define DAVINCI_LPSC_DDR_EMIF 13 | 45 | #define DAVINCI_LPSC_DDR_EMIF 13 |
48 | #define DAVINCI_LPSC_AEMIF 14 | 46 | #define DAVINCI_LPSC_AEMIF 14 |
49 | #define DAVINCI_LPSC_MMC_SD 15 | 47 | #define DAVINCI_LPSC_MMC_SD 15 |
50 | #define DAVINCI_LPSC_MEMSTICK 16 | ||
51 | #define DAVINCI_LPSC_McBSP 17 | 48 | #define DAVINCI_LPSC_McBSP 17 |
52 | #define DAVINCI_LPSC_I2C 18 | 49 | #define DAVINCI_LPSC_I2C 18 |
53 | #define DAVINCI_LPSC_UART0 19 | 50 | #define DAVINCI_LPSC_UART0 19 |
@@ -73,4 +70,54 @@ | |||
73 | #define DAVINCI_LPSC_GEM 39 | 70 | #define DAVINCI_LPSC_GEM 39 |
74 | #define DAVINCI_LPSC_IMCOP 40 | 71 | #define DAVINCI_LPSC_IMCOP 40 |
75 | 72 | ||
73 | #define DM355_LPSC_TIMER3 5 | ||
74 | #define DM355_LPSC_SPI1 6 | ||
75 | #define DM355_LPSC_MMC_SD1 7 | ||
76 | #define DM355_LPSC_McBSP1 8 | ||
77 | #define DM355_LPSC_PWM3 10 | ||
78 | #define DM355_LPSC_SPI2 11 | ||
79 | #define DM355_LPSC_RTO 12 | ||
80 | #define DM355_LPSC_VPSS_DAC 41 | ||
81 | |||
82 | /* | ||
83 | * LPSC Assignments | ||
84 | */ | ||
85 | #define DM646X_LPSC_ARM 0 | ||
86 | #define DM646X_LPSC_C64X_CPU 1 | ||
87 | #define DM646X_LPSC_HDVICP0 2 | ||
88 | #define DM646X_LPSC_HDVICP1 3 | ||
89 | #define DM646X_LPSC_TPCC 4 | ||
90 | #define DM646X_LPSC_TPTC0 5 | ||
91 | #define DM646X_LPSC_TPTC1 6 | ||
92 | #define DM646X_LPSC_TPTC2 7 | ||
93 | #define DM646X_LPSC_TPTC3 8 | ||
94 | #define DM646X_LPSC_PCI 13 | ||
95 | #define DM646X_LPSC_EMAC 14 | ||
96 | #define DM646X_LPSC_VDCE 15 | ||
97 | #define DM646X_LPSC_VPSSMSTR 16 | ||
98 | #define DM646X_LPSC_VPSSSLV 17 | ||
99 | #define DM646X_LPSC_TSIF0 18 | ||
100 | #define DM646X_LPSC_TSIF1 19 | ||
101 | #define DM646X_LPSC_DDR_EMIF 20 | ||
102 | #define DM646X_LPSC_AEMIF 21 | ||
103 | #define DM646X_LPSC_McASP0 22 | ||
104 | #define DM646X_LPSC_McASP1 23 | ||
105 | #define DM646X_LPSC_CRGEN0 24 | ||
106 | #define DM646X_LPSC_CRGEN1 25 | ||
107 | #define DM646X_LPSC_UART0 26 | ||
108 | #define DM646X_LPSC_UART1 27 | ||
109 | #define DM646X_LPSC_UART2 28 | ||
110 | #define DM646X_LPSC_PWM0 29 | ||
111 | #define DM646X_LPSC_PWM1 30 | ||
112 | #define DM646X_LPSC_I2C 31 | ||
113 | #define DM646X_LPSC_SPI 32 | ||
114 | #define DM646X_LPSC_GPIO 33 | ||
115 | #define DM646X_LPSC_TIMER0 34 | ||
116 | #define DM646X_LPSC_TIMER1 35 | ||
117 | #define DM646X_LPSC_ARM_INTC 45 | ||
118 | |||
119 | extern int davinci_psc_is_clk_active(unsigned int id); | ||
120 | extern void davinci_psc_config(unsigned int domain, unsigned int id, | ||
121 | char enable); | ||
122 | |||
76 | #endif /* __ASM_ARCH_PSC_H */ | 123 | #endif /* __ASM_ARCH_PSC_H */ |
diff --git a/arch/arm/mach-davinci/io.c b/arch/arm/mach-davinci/io.c index 299515f70b8b..71a7ae342b91 100644 --- a/arch/arm/mach-davinci/io.c +++ b/arch/arm/mach-davinci/io.c | |||
@@ -53,5 +53,4 @@ void __init davinci_map_common_io(void) | |||
53 | 53 | ||
54 | void __init davinci_init_common_hw(void) | 54 | void __init davinci_init_common_hw(void) |
55 | { | 55 | { |
56 | davinci_clk_init(); | ||
57 | } | 56 | } |
diff --git a/arch/arm/mach-davinci/psc.c b/arch/arm/mach-davinci/psc.c index 58754f066d5b..c5098831741f 100644 --- a/arch/arm/mach-davinci/psc.c +++ b/arch/arm/mach-davinci/psc.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/init.h> | 23 | #include <linux/init.h> |
24 | #include <linux/io.h> | 24 | #include <linux/io.h> |
25 | 25 | ||
26 | #include <mach/cputype.h> | ||
26 | #include <mach/hardware.h> | 27 | #include <mach/hardware.h> |
27 | #include <mach/psc.h> | 28 | #include <mach/psc.h> |
28 | #include <mach/mux.h> | 29 | #include <mach/mux.h> |
@@ -36,76 +37,57 @@ | |||
36 | #define MDSTAT 0x800 | 37 | #define MDSTAT 0x800 |
37 | #define MDCTL 0xA00 | 38 | #define MDCTL 0xA00 |
38 | 39 | ||
39 | /* System control register offsets */ | ||
40 | #define VDD3P3V_PWDN 0x48 | ||
41 | 40 | ||
42 | static void davinci_psc_mux(unsigned int id) | 41 | /* Return nonzero iff the domain's clock is active */ |
42 | int __init davinci_psc_is_clk_active(unsigned int id) | ||
43 | { | 43 | { |
44 | switch (id) { | 44 | void __iomem *psc_base = IO_ADDRESS(DAVINCI_PWR_SLEEP_CNTRL_BASE); |
45 | case DAVINCI_LPSC_ATA: | 45 | u32 mdstat = __raw_readl(psc_base + MDSTAT + 4 * id); |
46 | davinci_mux_peripheral(DAVINCI_MUX_HDIREN, 1); | 46 | |
47 | davinci_mux_peripheral(DAVINCI_MUX_ATAEN, 1); | 47 | /* if clocked, state can be "Enable" or "SyncReset" */ |
48 | break; | 48 | return mdstat & BIT(12); |
49 | case DAVINCI_LPSC_MMC_SD: | ||
50 | /* VDD power manupulations are done in U-Boot for CPMAC | ||
51 | * so applies to MMC as well | ||
52 | */ | ||
53 | /*Set up the pull regiter for MMC */ | ||
54 | davinci_writel(0, DAVINCI_SYSTEM_MODULE_BASE + VDD3P3V_PWDN); | ||
55 | davinci_mux_peripheral(DAVINCI_MUX_MSTK, 0); | ||
56 | break; | ||
57 | case DAVINCI_LPSC_I2C: | ||
58 | davinci_mux_peripheral(DAVINCI_MUX_I2C, 1); | ||
59 | break; | ||
60 | case DAVINCI_LPSC_McBSP: | ||
61 | davinci_mux_peripheral(DAVINCI_MUX_ASP, 1); | ||
62 | break; | ||
63 | default: | ||
64 | break; | ||
65 | } | ||
66 | } | 49 | } |
67 | 50 | ||
68 | /* Enable or disable a PSC domain */ | 51 | /* Enable or disable a PSC domain */ |
69 | void davinci_psc_config(unsigned int domain, unsigned int id, char enable) | 52 | void davinci_psc_config(unsigned int domain, unsigned int id, char enable) |
70 | { | 53 | { |
71 | u32 epcpr, ptcmd, ptstat, pdstat, pdctl1, mdstat, mdctl, mdstat_mask; | 54 | u32 epcpr, ptcmd, ptstat, pdstat, pdctl1, mdstat, mdctl, mdstat_mask; |
55 | void __iomem *psc_base = IO_ADDRESS(DAVINCI_PWR_SLEEP_CNTRL_BASE); | ||
72 | 56 | ||
73 | mdctl = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE + MDCTL + 4 * id); | 57 | mdctl = __raw_readl(psc_base + MDCTL + 4 * id); |
74 | if (enable) | 58 | if (enable) |
75 | mdctl |= 0x00000003; /* Enable Module */ | 59 | mdctl |= 0x00000003; /* Enable Module */ |
76 | else | 60 | else |
77 | mdctl &= 0xFFFFFFF2; /* Disable Module */ | 61 | mdctl &= 0xFFFFFFE2; /* Disable Module */ |
78 | davinci_writel(mdctl, DAVINCI_PWR_SLEEP_CNTRL_BASE + MDCTL + 4 * id); | 62 | __raw_writel(mdctl, psc_base + MDCTL + 4 * id); |
79 | 63 | ||
80 | pdstat = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE + PDSTAT); | 64 | pdstat = __raw_readl(psc_base + PDSTAT); |
81 | if ((pdstat & 0x00000001) == 0) { | 65 | if ((pdstat & 0x00000001) == 0) { |
82 | pdctl1 = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE + PDCTL1); | 66 | pdctl1 = __raw_readl(psc_base + PDCTL1); |
83 | pdctl1 |= 0x1; | 67 | pdctl1 |= 0x1; |
84 | davinci_writel(pdctl1, DAVINCI_PWR_SLEEP_CNTRL_BASE + PDCTL1); | 68 | __raw_writel(pdctl1, psc_base + PDCTL1); |
85 | 69 | ||
86 | ptcmd = 1 << domain; | 70 | ptcmd = 1 << domain; |
87 | davinci_writel(ptcmd, DAVINCI_PWR_SLEEP_CNTRL_BASE + PTCMD); | 71 | __raw_writel(ptcmd, psc_base + PTCMD); |
88 | 72 | ||
89 | do { | 73 | do { |
90 | epcpr = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE + | 74 | epcpr = __raw_readl(psc_base + EPCPR); |
91 | EPCPR); | ||
92 | } while ((((epcpr >> domain) & 1) == 0)); | 75 | } while ((((epcpr >> domain) & 1) == 0)); |
93 | 76 | ||
94 | pdctl1 = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE + PDCTL1); | 77 | pdctl1 = __raw_readl(psc_base + PDCTL1); |
95 | pdctl1 |= 0x100; | 78 | pdctl1 |= 0x100; |
96 | davinci_writel(pdctl1, DAVINCI_PWR_SLEEP_CNTRL_BASE + PDCTL1); | 79 | __raw_writel(pdctl1, psc_base + PDCTL1); |
97 | 80 | ||
98 | do { | 81 | do { |
99 | ptstat = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE + | 82 | ptstat = __raw_readl(psc_base + |
100 | PTSTAT); | 83 | PTSTAT); |
101 | } while (!(((ptstat >> domain) & 1) == 0)); | 84 | } while (!(((ptstat >> domain) & 1) == 0)); |
102 | } else { | 85 | } else { |
103 | ptcmd = 1 << domain; | 86 | ptcmd = 1 << domain; |
104 | davinci_writel(ptcmd, DAVINCI_PWR_SLEEP_CNTRL_BASE + PTCMD); | 87 | __raw_writel(ptcmd, psc_base + PTCMD); |
105 | 88 | ||
106 | do { | 89 | do { |
107 | ptstat = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE + | 90 | ptstat = __raw_readl(psc_base + PTSTAT); |
108 | PTSTAT); | ||
109 | } while (!(((ptstat >> domain) & 1) == 0)); | 91 | } while (!(((ptstat >> domain) & 1) == 0)); |
110 | } | 92 | } |
111 | 93 | ||
@@ -115,23 +97,6 @@ void davinci_psc_config(unsigned int domain, unsigned int id, char enable) | |||
115 | mdstat_mask = 0x2; | 97 | mdstat_mask = 0x2; |
116 | 98 | ||
117 | do { | 99 | do { |
118 | mdstat = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE + | 100 | mdstat = __raw_readl(psc_base + MDSTAT + 4 * id); |
119 | MDSTAT + 4 * id); | ||
120 | } while (!((mdstat & 0x0000001F) == mdstat_mask)); | 101 | } while (!((mdstat & 0x0000001F) == mdstat_mask)); |
121 | |||
122 | if (enable) | ||
123 | davinci_psc_mux(id); | ||
124 | } | ||
125 | |||
126 | void __init davinci_psc_init(void) | ||
127 | { | ||
128 | davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_VPSSMSTR, 1); | ||
129 | davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_VPSSSLV, 1); | ||
130 | davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_TPCC, 1); | ||
131 | davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_TPTC0, 1); | ||
132 | davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_TPTC1, 1); | ||
133 | davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_GPIO, 1); | ||
134 | |||
135 | /* Turn on WatchDog timer LPSC. Needed for RESET to work */ | ||
136 | davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_TIMER2, 1); | ||
137 | } | 102 | } |