diff options
Diffstat (limited to 'arch')
32 files changed, 4291 insertions, 629 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index f401b92a99f5..bf7273f3dc64 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig | |||
@@ -573,6 +573,7 @@ config ARCH_TEGRA | |||
573 | select HAVE_CLK | 573 | select HAVE_CLK |
574 | select COMMON_CLKDEV | 574 | select COMMON_CLKDEV |
575 | select ARCH_HAS_BARRIERS if CACHE_L2X0 | 575 | select ARCH_HAS_BARRIERS if CACHE_L2X0 |
576 | select ARCH_HAS_CPUFREQ | ||
576 | help | 577 | help |
577 | This enables support for NVIDIA Tegra based systems (Tegra APX, | 578 | This enables support for NVIDIA Tegra based systems (Tegra APX, |
578 | Tegra 6xx and Tegra 2 series). | 579 | Tegra 6xx and Tegra 2 series). |
diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig index a57713c1954a..acd9552f8ada 100644 --- a/arch/arm/mach-tegra/Kconfig +++ b/arch/arm/mach-tegra/Kconfig | |||
@@ -16,6 +16,10 @@ config ARCH_TEGRA_2x_SOC | |||
16 | 16 | ||
17 | endchoice | 17 | endchoice |
18 | 18 | ||
19 | config TEGRA_PCI | ||
20 | bool "PCI Express support" | ||
21 | select PCI | ||
22 | |||
19 | comment "Tegra board type" | 23 | comment "Tegra board type" |
20 | 24 | ||
21 | config MACH_HARMONY | 25 | config MACH_HARMONY |
@@ -47,4 +51,11 @@ config TEGRA_DEBUG_UARTE | |||
47 | 51 | ||
48 | endchoice | 52 | endchoice |
49 | 53 | ||
54 | config TEGRA_SYSTEM_DMA | ||
55 | bool "Enable system DMA driver for NVIDIA Tegra SoCs" | ||
56 | default y | ||
57 | help | ||
58 | Adds system DMA functionality for NVIDIA Tegra SoCs, used by | ||
59 | several Tegra device drivers | ||
60 | |||
50 | endif | 61 | endif |
diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile index 51e9370eed99..cdbc68e4c0ca 100644 --- a/arch/arm/mach-tegra/Makefile +++ b/arch/arm/mach-tegra/Makefile | |||
@@ -1,14 +1,21 @@ | |||
1 | obj-y += common.o | 1 | obj-y += common.o |
2 | obj-y += io.o | 2 | obj-y += io.o |
3 | obj-y += irq.o | 3 | obj-y += irq.o legacy_irq.o |
4 | obj-y += clock.o | 4 | obj-y += clock.o |
5 | obj-y += timer.o | 5 | obj-y += timer.o |
6 | obj-y += gpio.o | 6 | obj-y += gpio.o |
7 | obj-y += pinmux.o | 7 | obj-y += pinmux.o |
8 | obj-y += fuse.o | ||
8 | obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += clock.o | 9 | obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += clock.o |
9 | obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra2_clocks.o | 10 | obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra2_clocks.o |
11 | obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra2_dvfs.o | ||
12 | obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += pinmux-t2-tables.o | ||
10 | obj-$(CONFIG_SMP) += platsmp.o localtimer.o headsmp.o | 13 | obj-$(CONFIG_SMP) += platsmp.o localtimer.o headsmp.o |
11 | obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o | 14 | obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o |
15 | obj-$(CONFIG_TEGRA_SYSTEM_DMA) += dma.o | ||
16 | obj-$(CONFIG_CPU_FREQ) += cpu-tegra.o | ||
17 | obj-$(CONFIG_TEGRA_PCI) += pcie.o | ||
12 | 18 | ||
13 | obj-${CONFIG_MACH_HARMONY} += board-harmony.o | 19 | obj-${CONFIG_MACH_HARMONY} += board-harmony.o |
14 | obj-${CONFIG_MACH_HARMONY} += board-harmony-pinmux.o | 20 | obj-${CONFIG_MACH_HARMONY} += board-harmony-pinmux.o |
21 | obj-${CONFIG_MACH_HARMONY} += board-harmony-pcie.o | ||
diff --git a/arch/arm/mach-tegra/board-harmony-pcie.c b/arch/arm/mach-tegra/board-harmony-pcie.c new file mode 100644 index 000000000000..f7e7d4514b6a --- /dev/null +++ b/arch/arm/mach-tegra/board-harmony-pcie.c | |||
@@ -0,0 +1,57 @@ | |||
1 | /* | ||
2 | * arch/arm/mach-tegra/board-harmony-pcie.c | ||
3 | * | ||
4 | * Copyright (C) 2010 CompuLab, Ltd. | ||
5 | * Mike Rapoport <mike@compulab.co.il> | ||
6 | * | ||
7 | * This software is licensed under the terms of the GNU General Public | ||
8 | * License version 2, as published by the Free Software Foundation, and | ||
9 | * may be copied, distributed, and modified under those terms. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | */ | ||
17 | |||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/gpio.h> | ||
20 | #include <linux/err.h> | ||
21 | #include <linux/regulator/consumer.h> | ||
22 | |||
23 | #include <asm/mach-types.h> | ||
24 | |||
25 | #include <mach/pinmux.h> | ||
26 | #include "board.h" | ||
27 | |||
28 | #ifdef CONFIG_TEGRA_PCI | ||
29 | |||
30 | static int __init harmony_pcie_init(void) | ||
31 | { | ||
32 | int err; | ||
33 | |||
34 | if (!machine_is_harmony()) | ||
35 | return 0; | ||
36 | |||
37 | tegra_pinmux_set_tristate(TEGRA_PINGROUP_GPV, TEGRA_TRI_NORMAL); | ||
38 | tegra_pinmux_set_tristate(TEGRA_PINGROUP_SLXA, TEGRA_TRI_NORMAL); | ||
39 | tegra_pinmux_set_tristate(TEGRA_PINGROUP_SLXK, TEGRA_TRI_NORMAL); | ||
40 | |||
41 | err = tegra_pcie_init(true, true); | ||
42 | if (err) | ||
43 | goto err_pcie; | ||
44 | |||
45 | return 0; | ||
46 | |||
47 | err_pcie: | ||
48 | tegra_pinmux_set_tristate(TEGRA_PINGROUP_GPV, TEGRA_TRI_TRISTATE); | ||
49 | tegra_pinmux_set_tristate(TEGRA_PINGROUP_SLXA, TEGRA_TRI_TRISTATE); | ||
50 | tegra_pinmux_set_tristate(TEGRA_PINGROUP_SLXK, TEGRA_TRI_TRISTATE); | ||
51 | |||
52 | return err; | ||
53 | } | ||
54 | |||
55 | subsys_initcall(harmony_pcie_init); | ||
56 | |||
57 | #endif | ||
diff --git a/arch/arm/mach-tegra/board.h b/arch/arm/mach-tegra/board.h index 3d06354136f2..0de565ca37c5 100644 --- a/arch/arm/mach-tegra/board.h +++ b/arch/arm/mach-tegra/board.h | |||
@@ -27,6 +27,7 @@ void __init tegra_common_init(void); | |||
27 | void __init tegra_map_common_io(void); | 27 | void __init tegra_map_common_io(void); |
28 | void __init tegra_init_irq(void); | 28 | void __init tegra_init_irq(void); |
29 | void __init tegra_init_clock(void); | 29 | void __init tegra_init_clock(void); |
30 | int __init tegra_pcie_init(bool init_port0, bool init_port1); | ||
30 | 31 | ||
31 | extern struct sys_timer tegra_timer; | 32 | extern struct sys_timer tegra_timer; |
32 | #endif | 33 | #endif |
diff --git a/arch/arm/mach-tegra/clock.c b/arch/arm/mach-tegra/clock.c index 03ad578349b9..ae19f95585be 100644 --- a/arch/arm/mach-tegra/clock.c +++ b/arch/arm/mach-tegra/clock.c | |||
@@ -24,13 +24,80 @@ | |||
24 | #include <linux/debugfs.h> | 24 | #include <linux/debugfs.h> |
25 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
26 | #include <linux/seq_file.h> | 26 | #include <linux/seq_file.h> |
27 | #include <linux/regulator/consumer.h> | ||
27 | #include <asm/clkdev.h> | 28 | #include <asm/clkdev.h> |
28 | 29 | ||
29 | #include "clock.h" | 30 | #include "clock.h" |
31 | #include "board.h" | ||
32 | #include "fuse.h" | ||
30 | 33 | ||
31 | static LIST_HEAD(clocks); | 34 | static LIST_HEAD(clocks); |
32 | 35 | ||
33 | static DEFINE_SPINLOCK(clock_lock); | 36 | static DEFINE_SPINLOCK(clock_lock); |
37 | static DEFINE_MUTEX(dvfs_lock); | ||
38 | |||
39 | static int clk_is_dvfs(struct clk *c) | ||
40 | { | ||
41 | return (c->dvfs != NULL); | ||
42 | }; | ||
43 | |||
44 | static int dvfs_set_rate(struct dvfs *d, unsigned long rate) | ||
45 | { | ||
46 | struct dvfs_table *t; | ||
47 | |||
48 | if (d->table == NULL) | ||
49 | return -ENODEV; | ||
50 | |||
51 | for (t = d->table; t->rate != 0; t++) { | ||
52 | if (rate <= t->rate) { | ||
53 | if (!d->reg) | ||
54 | return 0; | ||
55 | |||
56 | return regulator_set_voltage(d->reg, | ||
57 | t->millivolts * 1000, | ||
58 | d->max_millivolts * 1000); | ||
59 | } | ||
60 | } | ||
61 | |||
62 | return -EINVAL; | ||
63 | } | ||
64 | |||
65 | static void dvfs_init(struct clk *c) | ||
66 | { | ||
67 | int process_id; | ||
68 | int i; | ||
69 | struct dvfs_table *table; | ||
70 | |||
71 | process_id = c->dvfs->cpu ? tegra_core_process_id() : | ||
72 | tegra_cpu_process_id(); | ||
73 | |||
74 | for (i = 0; i < c->dvfs->process_id_table_length; i++) | ||
75 | if (process_id == c->dvfs->process_id_table[i].process_id) | ||
76 | c->dvfs->table = c->dvfs->process_id_table[i].table; | ||
77 | |||
78 | if (c->dvfs->table == NULL) { | ||
79 | pr_err("Failed to find dvfs table for clock %s process %d\n", | ||
80 | c->name, process_id); | ||
81 | return; | ||
82 | } | ||
83 | |||
84 | c->dvfs->max_millivolts = 0; | ||
85 | for (table = c->dvfs->table; table->rate != 0; table++) | ||
86 | if (c->dvfs->max_millivolts < table->millivolts) | ||
87 | c->dvfs->max_millivolts = table->millivolts; | ||
88 | |||
89 | c->dvfs->reg = regulator_get(NULL, c->dvfs->reg_id); | ||
90 | |||
91 | if (IS_ERR(c->dvfs->reg)) { | ||
92 | pr_err("Failed to get regulator %s for clock %s\n", | ||
93 | c->dvfs->reg_id, c->name); | ||
94 | c->dvfs->reg = NULL; | ||
95 | return; | ||
96 | } | ||
97 | |||
98 | if (c->refcnt > 0) | ||
99 | dvfs_set_rate(c->dvfs, c->rate); | ||
100 | } | ||
34 | 101 | ||
35 | struct clk *tegra_get_clock_by_name(const char *name) | 102 | struct clk *tegra_get_clock_by_name(const char *name) |
36 | { | 103 | { |
@@ -48,14 +115,31 @@ struct clk *tegra_get_clock_by_name(const char *name) | |||
48 | return ret; | 115 | return ret; |
49 | } | 116 | } |
50 | 117 | ||
118 | static void clk_recalculate_rate(struct clk *c) | ||
119 | { | ||
120 | u64 rate; | ||
121 | |||
122 | if (!c->parent) | ||
123 | return; | ||
124 | |||
125 | rate = c->parent->rate; | ||
126 | |||
127 | if (c->mul != 0 && c->div != 0) { | ||
128 | rate = rate * c->mul; | ||
129 | do_div(rate, c->div); | ||
130 | } | ||
131 | |||
132 | if (rate > c->max_rate) | ||
133 | pr_warn("clocks: Set clock %s to rate %llu, max is %lu\n", | ||
134 | c->name, rate, c->max_rate); | ||
135 | |||
136 | c->rate = rate; | ||
137 | } | ||
138 | |||
51 | int clk_reparent(struct clk *c, struct clk *parent) | 139 | int clk_reparent(struct clk *c, struct clk *parent) |
52 | { | 140 | { |
53 | pr_debug("%s: %s\n", __func__, c->name); | 141 | pr_debug("%s: %s\n", __func__, c->name); |
54 | if (c->refcnt && c->parent) | ||
55 | clk_disable_locked(c->parent); | ||
56 | c->parent = parent; | 142 | c->parent = parent; |
57 | if (c->refcnt && c->parent) | ||
58 | clk_enable_locked(c->parent); | ||
59 | list_del(&c->sibling); | 143 | list_del(&c->sibling); |
60 | list_add_tail(&c->sibling, &parent->children); | 144 | list_add_tail(&c->sibling, &parent->children); |
61 | return 0; | 145 | return 0; |
@@ -67,8 +151,7 @@ static void propagate_rate(struct clk *c) | |||
67 | pr_debug("%s: %s\n", __func__, c->name); | 151 | pr_debug("%s: %s\n", __func__, c->name); |
68 | list_for_each_entry(clkp, &c->children, sibling) { | 152 | list_for_each_entry(clkp, &c->children, sibling) { |
69 | pr_debug(" %s\n", clkp->name); | 153 | pr_debug(" %s\n", clkp->name); |
70 | if (clkp->ops->recalculate_rate) | 154 | clk_recalculate_rate(clkp); |
71 | clkp->ops->recalculate_rate(clkp); | ||
72 | propagate_rate(clkp); | 155 | propagate_rate(clkp); |
73 | } | 156 | } |
74 | } | 157 | } |
@@ -77,6 +160,8 @@ void clk_init(struct clk *c) | |||
77 | { | 160 | { |
78 | unsigned long flags; | 161 | unsigned long flags; |
79 | 162 | ||
163 | pr_debug("%s: %s\n", __func__, c->name); | ||
164 | |||
80 | spin_lock_irqsave(&clock_lock, flags); | 165 | spin_lock_irqsave(&clock_lock, flags); |
81 | 166 | ||
82 | INIT_LIST_HEAD(&c->children); | 167 | INIT_LIST_HEAD(&c->children); |
@@ -85,6 +170,8 @@ void clk_init(struct clk *c) | |||
85 | if (c->ops && c->ops->init) | 170 | if (c->ops && c->ops->init) |
86 | c->ops->init(c); | 171 | c->ops->init(c); |
87 | 172 | ||
173 | clk_recalculate_rate(c); | ||
174 | |||
88 | list_add(&c->node, &clocks); | 175 | list_add(&c->node, &clocks); |
89 | 176 | ||
90 | if (c->parent) | 177 | if (c->parent) |
@@ -122,13 +209,38 @@ int clk_enable_locked(struct clk *c) | |||
122 | return 0; | 209 | return 0; |
123 | } | 210 | } |
124 | 211 | ||
212 | int clk_enable_cansleep(struct clk *c) | ||
213 | { | ||
214 | int ret; | ||
215 | unsigned long flags; | ||
216 | |||
217 | mutex_lock(&dvfs_lock); | ||
218 | |||
219 | if (clk_is_dvfs(c) && c->refcnt > 0) | ||
220 | dvfs_set_rate(c->dvfs, c->rate); | ||
221 | |||
222 | spin_lock_irqsave(&clock_lock, flags); | ||
223 | ret = clk_enable_locked(c); | ||
224 | spin_unlock_irqrestore(&clock_lock, flags); | ||
225 | |||
226 | mutex_unlock(&dvfs_lock); | ||
227 | |||
228 | return ret; | ||
229 | } | ||
230 | EXPORT_SYMBOL(clk_enable_cansleep); | ||
231 | |||
125 | int clk_enable(struct clk *c) | 232 | int clk_enable(struct clk *c) |
126 | { | 233 | { |
127 | int ret; | 234 | int ret; |
128 | unsigned long flags; | 235 | unsigned long flags; |
236 | |||
237 | if (clk_is_dvfs(c)) | ||
238 | BUG(); | ||
239 | |||
129 | spin_lock_irqsave(&clock_lock, flags); | 240 | spin_lock_irqsave(&clock_lock, flags); |
130 | ret = clk_enable_locked(c); | 241 | ret = clk_enable_locked(c); |
131 | spin_unlock_irqrestore(&clock_lock, flags); | 242 | spin_unlock_irqrestore(&clock_lock, flags); |
243 | |||
132 | return ret; | 244 | return ret; |
133 | } | 245 | } |
134 | EXPORT_SYMBOL(clk_enable); | 246 | EXPORT_SYMBOL(clk_enable); |
@@ -152,9 +264,30 @@ void clk_disable_locked(struct clk *c) | |||
152 | c->refcnt--; | 264 | c->refcnt--; |
153 | } | 265 | } |
154 | 266 | ||
267 | void clk_disable_cansleep(struct clk *c) | ||
268 | { | ||
269 | unsigned long flags; | ||
270 | |||
271 | mutex_lock(&dvfs_lock); | ||
272 | |||
273 | spin_lock_irqsave(&clock_lock, flags); | ||
274 | clk_disable_locked(c); | ||
275 | spin_unlock_irqrestore(&clock_lock, flags); | ||
276 | |||
277 | if (clk_is_dvfs(c) && c->refcnt == 0) | ||
278 | dvfs_set_rate(c->dvfs, c->rate); | ||
279 | |||
280 | mutex_unlock(&dvfs_lock); | ||
281 | } | ||
282 | EXPORT_SYMBOL(clk_disable_cansleep); | ||
283 | |||
155 | void clk_disable(struct clk *c) | 284 | void clk_disable(struct clk *c) |
156 | { | 285 | { |
157 | unsigned long flags; | 286 | unsigned long flags; |
287 | |||
288 | if (clk_is_dvfs(c)) | ||
289 | BUG(); | ||
290 | |||
158 | spin_lock_irqsave(&clock_lock, flags); | 291 | spin_lock_irqsave(&clock_lock, flags); |
159 | clk_disable_locked(c); | 292 | clk_disable_locked(c); |
160 | spin_unlock_irqrestore(&clock_lock, flags); | 293 | spin_unlock_irqrestore(&clock_lock, flags); |
@@ -175,6 +308,8 @@ int clk_set_parent_locked(struct clk *c, struct clk *parent) | |||
175 | if (ret) | 308 | if (ret) |
176 | return ret; | 309 | return ret; |
177 | 310 | ||
311 | clk_recalculate_rate(c); | ||
312 | |||
178 | propagate_rate(c); | 313 | propagate_rate(c); |
179 | 314 | ||
180 | return 0; | 315 | return 0; |
@@ -197,22 +332,69 @@ struct clk *clk_get_parent(struct clk *c) | |||
197 | } | 332 | } |
198 | EXPORT_SYMBOL(clk_get_parent); | 333 | EXPORT_SYMBOL(clk_get_parent); |
199 | 334 | ||
200 | int clk_set_rate(struct clk *c, unsigned long rate) | 335 | int clk_set_rate_locked(struct clk *c, unsigned long rate) |
336 | { | ||
337 | int ret; | ||
338 | |||
339 | if (rate > c->max_rate) | ||
340 | rate = c->max_rate; | ||
341 | |||
342 | if (!c->ops || !c->ops->set_rate) | ||
343 | return -ENOSYS; | ||
344 | |||
345 | ret = c->ops->set_rate(c, rate); | ||
346 | |||
347 | if (ret) | ||
348 | return ret; | ||
349 | |||
350 | clk_recalculate_rate(c); | ||
351 | |||
352 | propagate_rate(c); | ||
353 | |||
354 | return 0; | ||
355 | } | ||
356 | |||
357 | int clk_set_rate_cansleep(struct clk *c, unsigned long rate) | ||
201 | { | 358 | { |
202 | int ret = 0; | 359 | int ret = 0; |
203 | unsigned long flags; | 360 | unsigned long flags; |
204 | 361 | ||
362 | pr_debug("%s: %s\n", __func__, c->name); | ||
363 | |||
364 | mutex_lock(&dvfs_lock); | ||
365 | |||
366 | if (rate > c->rate) | ||
367 | ret = dvfs_set_rate(c->dvfs, rate); | ||
368 | if (ret) | ||
369 | goto out; | ||
370 | |||
205 | spin_lock_irqsave(&clock_lock, flags); | 371 | spin_lock_irqsave(&clock_lock, flags); |
372 | ret = clk_set_rate_locked(c, rate); | ||
373 | spin_unlock_irqrestore(&clock_lock, flags); | ||
206 | 374 | ||
207 | pr_debug("%s: %s\n", __func__, c->name); | 375 | if (ret) |
376 | goto out; | ||
208 | 377 | ||
209 | if (c->ops && c->ops->set_rate) | 378 | ret = dvfs_set_rate(c->dvfs, rate); |
210 | ret = c->ops->set_rate(c, rate); | ||
211 | else | ||
212 | ret = -ENOSYS; | ||
213 | 379 | ||
214 | propagate_rate(c); | 380 | out: |
381 | mutex_unlock(&dvfs_lock); | ||
382 | return ret; | ||
383 | } | ||
384 | EXPORT_SYMBOL(clk_set_rate_cansleep); | ||
385 | |||
386 | int clk_set_rate(struct clk *c, unsigned long rate) | ||
387 | { | ||
388 | int ret = 0; | ||
389 | unsigned long flags; | ||
390 | |||
391 | pr_debug("%s: %s\n", __func__, c->name); | ||
392 | |||
393 | if (clk_is_dvfs(c)) | ||
394 | BUG(); | ||
215 | 395 | ||
396 | spin_lock_irqsave(&clock_lock, flags); | ||
397 | ret = clk_set_rate_locked(c, rate); | ||
216 | spin_unlock_irqrestore(&clock_lock, flags); | 398 | spin_unlock_irqrestore(&clock_lock, flags); |
217 | 399 | ||
218 | return ret; | 400 | return ret; |
@@ -235,6 +417,20 @@ unsigned long clk_get_rate(struct clk *c) | |||
235 | } | 417 | } |
236 | EXPORT_SYMBOL(clk_get_rate); | 418 | EXPORT_SYMBOL(clk_get_rate); |
237 | 419 | ||
420 | long clk_round_rate(struct clk *c, unsigned long rate) | ||
421 | { | ||
422 | pr_debug("%s: %s\n", __func__, c->name); | ||
423 | |||
424 | if (!c->ops || !c->ops->round_rate) | ||
425 | return -ENOSYS; | ||
426 | |||
427 | if (rate > c->max_rate) | ||
428 | rate = c->max_rate; | ||
429 | |||
430 | return c->ops->round_rate(c, rate); | ||
431 | } | ||
432 | EXPORT_SYMBOL(clk_round_rate); | ||
433 | |||
238 | static int tegra_clk_init_one_from_table(struct tegra_clk_init_table *table) | 434 | static int tegra_clk_init_one_from_table(struct tegra_clk_init_table *table) |
239 | { | 435 | { |
240 | struct clk *c; | 436 | struct clk *c; |
@@ -308,13 +504,28 @@ void tegra_periph_reset_assert(struct clk *c) | |||
308 | } | 504 | } |
309 | EXPORT_SYMBOL(tegra_periph_reset_assert); | 505 | EXPORT_SYMBOL(tegra_periph_reset_assert); |
310 | 506 | ||
311 | int __init tegra_init_clock(void) | 507 | void __init tegra_init_clock(void) |
312 | { | 508 | { |
313 | tegra2_init_clocks(); | 509 | tegra2_init_clocks(); |
510 | } | ||
511 | |||
512 | int __init tegra_init_dvfs(void) | ||
513 | { | ||
514 | struct clk *c, *safe; | ||
515 | |||
516 | mutex_lock(&dvfs_lock); | ||
517 | |||
518 | list_for_each_entry_safe(c, safe, &clocks, node) | ||
519 | if (c->dvfs) | ||
520 | dvfs_init(c); | ||
521 | |||
522 | mutex_unlock(&dvfs_lock); | ||
314 | 523 | ||
315 | return 0; | 524 | return 0; |
316 | } | 525 | } |
317 | 526 | ||
527 | late_initcall(tegra_init_dvfs); | ||
528 | |||
318 | #ifdef CONFIG_DEBUG_FS | 529 | #ifdef CONFIG_DEBUG_FS |
319 | static struct dentry *clk_debugfs_root; | 530 | static struct dentry *clk_debugfs_root; |
320 | 531 | ||
@@ -324,7 +535,7 @@ static void clock_tree_show_one(struct seq_file *s, struct clk *c, int level) | |||
324 | struct clk *child; | 535 | struct clk *child; |
325 | struct clk *safe; | 536 | struct clk *safe; |
326 | const char *state = "uninit"; | 537 | const char *state = "uninit"; |
327 | char div[5] = {0}; | 538 | char div[8] = {0}; |
328 | 539 | ||
329 | if (c->state == ON) | 540 | if (c->state == ON) |
330 | state = "on"; | 541 | state = "on"; |
@@ -332,16 +543,26 @@ static void clock_tree_show_one(struct seq_file *s, struct clk *c, int level) | |||
332 | state = "off"; | 543 | state = "off"; |
333 | 544 | ||
334 | if (c->mul != 0 && c->div != 0) { | 545 | if (c->mul != 0 && c->div != 0) { |
335 | BUG_ON(c->mul > 2); | 546 | if (c->mul > c->div) { |
336 | if (c->mul > c->div) | 547 | int mul = c->mul / c->div; |
337 | snprintf(div, sizeof(div), "x%d", c->mul / c->div); | 548 | int mul2 = (c->mul * 10 / c->div) % 10; |
338 | else | 549 | int mul3 = (c->mul * 10) % c->div; |
550 | if (mul2 == 0 && mul3 == 0) | ||
551 | snprintf(div, sizeof(div), "x%d", mul); | ||
552 | else if (mul3 == 0) | ||
553 | snprintf(div, sizeof(div), "x%d.%d", mul, mul2); | ||
554 | else | ||
555 | snprintf(div, sizeof(div), "x%d.%d..", mul, mul2); | ||
556 | } else { | ||
339 | snprintf(div, sizeof(div), "%d%s", c->div / c->mul, | 557 | snprintf(div, sizeof(div), "%d%s", c->div / c->mul, |
340 | (c->div % c->mul) ? ".5" : ""); | 558 | (c->div % c->mul) ? ".5" : ""); |
559 | } | ||
341 | } | 560 | } |
342 | 561 | ||
343 | seq_printf(s, "%*s%-*s %-6s %-3d %-5s %-10lu\n", | 562 | seq_printf(s, "%*s%c%c%-*s %-6s %-3d %-8s %-10lu\n", |
344 | level * 3 + 1, c->set ? "" : "*", | 563 | level * 3 + 1, "", |
564 | c->rate > c->max_rate ? '!' : ' ', | ||
565 | !c->set ? '*' : ' ', | ||
345 | 30 - level * 3, c->name, | 566 | 30 - level * 3, c->name, |
346 | state, c->refcnt, div, c->rate); | 567 | state, c->refcnt, div, c->rate); |
347 | list_for_each_entry_safe(child, safe, &c->children, sibling) { | 568 | list_for_each_entry_safe(child, safe, &c->children, sibling) { |
@@ -353,8 +574,8 @@ static int clock_tree_show(struct seq_file *s, void *data) | |||
353 | { | 574 | { |
354 | struct clk *c; | 575 | struct clk *c; |
355 | unsigned long flags; | 576 | unsigned long flags; |
356 | seq_printf(s, " clock state ref div rate \n"); | 577 | seq_printf(s, " clock state ref div rate\n"); |
357 | seq_printf(s, "-----------------------------------------------------------\n"); | 578 | seq_printf(s, "--------------------------------------------------------------\n"); |
358 | spin_lock_irqsave(&clock_lock, flags); | 579 | spin_lock_irqsave(&clock_lock, flags); |
359 | list_for_each_entry(c, &clocks, node) | 580 | list_for_each_entry(c, &clocks, node) |
360 | if (c->parent == NULL) | 581 | if (c->parent == NULL) |
diff --git a/arch/arm/mach-tegra/clock.h b/arch/arm/mach-tegra/clock.h index af7c70e2a3ba..94fd859770f1 100644 --- a/arch/arm/mach-tegra/clock.h +++ b/arch/arm/mach-tegra/clock.h | |||
@@ -27,18 +27,43 @@ | |||
27 | #define DIV_U71 (1 << 1) | 27 | #define DIV_U71 (1 << 1) |
28 | #define DIV_U71_FIXED (1 << 2) | 28 | #define DIV_U71_FIXED (1 << 2) |
29 | #define DIV_2 (1 << 3) | 29 | #define DIV_2 (1 << 3) |
30 | #define PLL_FIXED (1 << 4) | 30 | #define DIV_U16 (1 << 4) |
31 | #define PLL_HAS_CPCON (1 << 5) | 31 | #define PLL_FIXED (1 << 5) |
32 | #define MUX (1 << 6) | 32 | #define PLL_HAS_CPCON (1 << 6) |
33 | #define PLLD (1 << 7) | 33 | #define MUX (1 << 7) |
34 | #define PERIPH_NO_RESET (1 << 8) | 34 | #define PLLD (1 << 8) |
35 | #define PERIPH_NO_ENB (1 << 9) | 35 | #define PERIPH_NO_RESET (1 << 9) |
36 | #define PERIPH_EMC_ENB (1 << 10) | 36 | #define PERIPH_NO_ENB (1 << 10) |
37 | #define PERIPH_MANUAL_RESET (1 << 11) | 37 | #define PERIPH_EMC_ENB (1 << 11) |
38 | #define PLL_ALT_MISC_REG (1 << 12) | 38 | #define PERIPH_MANUAL_RESET (1 << 12) |
39 | #define PLL_ALT_MISC_REG (1 << 13) | ||
40 | #define PLLU (1 << 14) | ||
39 | #define ENABLE_ON_INIT (1 << 28) | 41 | #define ENABLE_ON_INIT (1 << 28) |
40 | 42 | ||
41 | struct clk; | 43 | struct clk; |
44 | struct regulator; | ||
45 | |||
46 | struct dvfs_table { | ||
47 | unsigned long rate; | ||
48 | int millivolts; | ||
49 | }; | ||
50 | |||
51 | struct dvfs_process_id_table { | ||
52 | int process_id; | ||
53 | struct dvfs_table *table; | ||
54 | }; | ||
55 | |||
56 | |||
57 | struct dvfs { | ||
58 | struct regulator *reg; | ||
59 | struct dvfs_table *table; | ||
60 | int max_millivolts; | ||
61 | |||
62 | int process_id_table_length; | ||
63 | const char *reg_id; | ||
64 | bool cpu; | ||
65 | struct dvfs_process_id_table process_id_table[]; | ||
66 | }; | ||
42 | 67 | ||
43 | struct clk_mux_sel { | 68 | struct clk_mux_sel { |
44 | struct clk *input; | 69 | struct clk *input; |
@@ -58,12 +83,9 @@ struct clk_ops { | |||
58 | void (*init)(struct clk *); | 83 | void (*init)(struct clk *); |
59 | int (*enable)(struct clk *); | 84 | int (*enable)(struct clk *); |
60 | void (*disable)(struct clk *); | 85 | void (*disable)(struct clk *); |
61 | void (*recalc)(struct clk *); | ||
62 | int (*set_parent)(struct clk *, struct clk *); | 86 | int (*set_parent)(struct clk *, struct clk *); |
63 | int (*set_rate)(struct clk *, unsigned long); | 87 | int (*set_rate)(struct clk *, unsigned long); |
64 | unsigned long (*get_rate)(struct clk *); | ||
65 | long (*round_rate)(struct clk *, unsigned long); | 88 | long (*round_rate)(struct clk *, unsigned long); |
66 | unsigned long (*recalculate_rate)(struct clk *); | ||
67 | }; | 89 | }; |
68 | 90 | ||
69 | enum clk_state { | 91 | enum clk_state { |
@@ -85,6 +107,7 @@ struct clk { | |||
85 | struct clk *parent; | 107 | struct clk *parent; |
86 | struct clk_lookup lookup; | 108 | struct clk_lookup lookup; |
87 | unsigned long rate; | 109 | unsigned long rate; |
110 | unsigned long max_rate; | ||
88 | u32 flags; | 111 | u32 flags; |
89 | u32 refcnt; | 112 | u32 refcnt; |
90 | const char *name; | 113 | const char *name; |
@@ -103,10 +126,6 @@ struct clk { | |||
103 | unsigned long cf_max; | 126 | unsigned long cf_max; |
104 | unsigned long vco_min; | 127 | unsigned long vco_min; |
105 | unsigned long vco_max; | 128 | unsigned long vco_max; |
106 | u32 m; | ||
107 | u32 n; | ||
108 | u32 p; | ||
109 | u32 cpcon; | ||
110 | const struct clk_pll_table *pll_table; | 129 | const struct clk_pll_table *pll_table; |
111 | 130 | ||
112 | /* DIV */ | 131 | /* DIV */ |
@@ -117,6 +136,12 @@ struct clk { | |||
117 | const struct clk_mux_sel *inputs; | 136 | const struct clk_mux_sel *inputs; |
118 | u32 sel; | 137 | u32 sel; |
119 | u32 reg_mask; | 138 | u32 reg_mask; |
139 | |||
140 | /* Virtual cpu clock */ | ||
141 | struct clk *main; | ||
142 | struct clk *backup; | ||
143 | |||
144 | struct dvfs *dvfs; | ||
120 | }; | 145 | }; |
121 | 146 | ||
122 | 147 | ||
@@ -141,6 +166,7 @@ unsigned long clk_measure_input_freq(void); | |||
141 | void clk_disable_locked(struct clk *c); | 166 | void clk_disable_locked(struct clk *c); |
142 | int clk_enable_locked(struct clk *c); | 167 | int clk_enable_locked(struct clk *c); |
143 | int clk_set_parent_locked(struct clk *c, struct clk *parent); | 168 | int clk_set_parent_locked(struct clk *c, struct clk *parent); |
169 | int clk_set_rate_locked(struct clk *c, unsigned long rate); | ||
144 | int clk_reparent(struct clk *c, struct clk *parent); | 170 | int clk_reparent(struct clk *c, struct clk *parent); |
145 | void tegra_clk_init_from_table(struct tegra_clk_init_table *table); | 171 | void tegra_clk_init_from_table(struct tegra_clk_init_table *table); |
146 | 172 | ||
diff --git a/arch/arm/mach-tegra/common.c b/arch/arm/mach-tegra/common.c index 039a514b61ef..7c91e2b9d643 100644 --- a/arch/arm/mach-tegra/common.c +++ b/arch/arm/mach-tegra/common.c | |||
@@ -19,13 +19,17 @@ | |||
19 | 19 | ||
20 | #include <linux/init.h> | 20 | #include <linux/init.h> |
21 | #include <linux/io.h> | 21 | #include <linux/io.h> |
22 | #include <linux/clk.h> | ||
23 | #include <linux/delay.h> | ||
22 | 24 | ||
23 | #include <asm/hardware/cache-l2x0.h> | 25 | #include <asm/hardware/cache-l2x0.h> |
24 | 26 | ||
25 | #include <mach/iomap.h> | 27 | #include <mach/iomap.h> |
28 | #include <mach/dma.h> | ||
26 | 29 | ||
27 | #include "board.h" | 30 | #include "board.h" |
28 | #include "clock.h" | 31 | #include "clock.h" |
32 | #include "fuse.h" | ||
29 | 33 | ||
30 | static __initdata struct tegra_clk_init_table common_clk_init_table[] = { | 34 | static __initdata struct tegra_clk_init_table common_clk_init_table[] = { |
31 | /* name parent rate enabled */ | 35 | /* name parent rate enabled */ |
@@ -35,8 +39,8 @@ static __initdata struct tegra_clk_init_table common_clk_init_table[] = { | |||
35 | { "pll_p_out2", "pll_p", 48000000, true }, | 39 | { "pll_p_out2", "pll_p", 48000000, true }, |
36 | { "pll_p_out3", "pll_p", 72000000, true }, | 40 | { "pll_p_out3", "pll_p", 72000000, true }, |
37 | { "pll_p_out4", "pll_p", 108000000, true }, | 41 | { "pll_p_out4", "pll_p", 108000000, true }, |
38 | { "sys", "pll_p_out4", 108000000, true }, | 42 | { "sclk", "pll_p_out4", 108000000, true }, |
39 | { "hclk", "sys", 108000000, true }, | 43 | { "hclk", "sclk", 108000000, true }, |
40 | { "pclk", "hclk", 54000000, true }, | 44 | { "pclk", "hclk", 54000000, true }, |
41 | { NULL, NULL, 0, 0}, | 45 | { NULL, NULL, 0, 0}, |
42 | }; | 46 | }; |
@@ -51,11 +55,16 @@ void __init tegra_init_cache(void) | |||
51 | 55 | ||
52 | l2x0_init(p, 0x6C080001, 0x8200c3fe); | 56 | l2x0_init(p, 0x6C080001, 0x8200c3fe); |
53 | #endif | 57 | #endif |
58 | |||
54 | } | 59 | } |
55 | 60 | ||
56 | void __init tegra_common_init(void) | 61 | void __init tegra_common_init(void) |
57 | { | 62 | { |
63 | tegra_init_fuse(); | ||
58 | tegra_init_clock(); | 64 | tegra_init_clock(); |
59 | tegra_clk_init_from_table(common_clk_init_table); | 65 | tegra_clk_init_from_table(common_clk_init_table); |
60 | tegra_init_cache(); | 66 | tegra_init_cache(); |
67 | #ifdef CONFIG_TEGRA_SYSTEM_DMA | ||
68 | tegra_dma_init(); | ||
69 | #endif | ||
61 | } | 70 | } |
diff --git a/arch/arm/mach-tegra/cpu-tegra.c b/arch/arm/mach-tegra/cpu-tegra.c new file mode 100644 index 000000000000..fea5719c7072 --- /dev/null +++ b/arch/arm/mach-tegra/cpu-tegra.c | |||
@@ -0,0 +1,185 @@ | |||
1 | /* | ||
2 | * arch/arm/mach-tegra/cpu-tegra.c | ||
3 | * | ||
4 | * Copyright (C) 2010 Google, Inc. | ||
5 | * | ||
6 | * Author: | ||
7 | * Colin Cross <ccross@google.com> | ||
8 | * Based on arch/arm/plat-omap/cpu-omap.c, (C) 2005 Nokia Corporation | ||
9 | * | ||
10 | * This software is licensed under the terms of the GNU General Public | ||
11 | * License version 2, as published by the Free Software Foundation, and | ||
12 | * may be copied, distributed, and modified under those terms. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | */ | ||
20 | |||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/module.h> | ||
23 | #include <linux/types.h> | ||
24 | #include <linux/sched.h> | ||
25 | #include <linux/cpufreq.h> | ||
26 | #include <linux/delay.h> | ||
27 | #include <linux/init.h> | ||
28 | #include <linux/err.h> | ||
29 | #include <linux/clk.h> | ||
30 | #include <linux/io.h> | ||
31 | |||
32 | #include <asm/system.h> | ||
33 | |||
34 | #include <mach/hardware.h> | ||
35 | #include <mach/clk.h> | ||
36 | |||
37 | /* Frequency table index must be sequential starting at 0 */ | ||
38 | static struct cpufreq_frequency_table freq_table[] = { | ||
39 | { 0, 312000 }, | ||
40 | { 1, 456000 }, | ||
41 | { 2, 608000 }, | ||
42 | { 3, 760000 }, | ||
43 | { 4, 816000 }, | ||
44 | { 5, 912000 }, | ||
45 | { 6, 1000000 }, | ||
46 | { 7, CPUFREQ_TABLE_END }, | ||
47 | }; | ||
48 | |||
49 | #define NUM_CPUS 2 | ||
50 | |||
51 | static struct clk *cpu_clk; | ||
52 | |||
53 | static unsigned long target_cpu_speed[NUM_CPUS]; | ||
54 | |||
55 | int tegra_verify_speed(struct cpufreq_policy *policy) | ||
56 | { | ||
57 | return cpufreq_frequency_table_verify(policy, freq_table); | ||
58 | } | ||
59 | |||
60 | unsigned int tegra_getspeed(unsigned int cpu) | ||
61 | { | ||
62 | unsigned long rate; | ||
63 | |||
64 | if (cpu >= NUM_CPUS) | ||
65 | return 0; | ||
66 | |||
67 | rate = clk_get_rate(cpu_clk) / 1000; | ||
68 | return rate; | ||
69 | } | ||
70 | |||
71 | static int tegra_update_cpu_speed(void) | ||
72 | { | ||
73 | int i; | ||
74 | unsigned long rate = 0; | ||
75 | int ret = 0; | ||
76 | struct cpufreq_freqs freqs; | ||
77 | |||
78 | for_each_online_cpu(i) | ||
79 | rate = max(rate, target_cpu_speed[i]); | ||
80 | |||
81 | freqs.old = tegra_getspeed(0); | ||
82 | freqs.new = rate; | ||
83 | |||
84 | if (freqs.old == freqs.new) | ||
85 | return ret; | ||
86 | |||
87 | for_each_online_cpu(freqs.cpu) | ||
88 | cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); | ||
89 | |||
90 | #ifdef CONFIG_CPU_FREQ_DEBUG | ||
91 | printk(KERN_DEBUG "cpufreq-tegra: transition: %u --> %u\n", | ||
92 | freqs.old, freqs.new); | ||
93 | #endif | ||
94 | |||
95 | ret = clk_set_rate_cansleep(cpu_clk, freqs.new * 1000); | ||
96 | if (ret) { | ||
97 | pr_err("cpu-tegra: Failed to set cpu frequency to %d kHz\n", | ||
98 | freqs.new); | ||
99 | return ret; | ||
100 | } | ||
101 | |||
102 | for_each_online_cpu(freqs.cpu) | ||
103 | cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); | ||
104 | |||
105 | return 0; | ||
106 | } | ||
107 | |||
108 | static int tegra_target(struct cpufreq_policy *policy, | ||
109 | unsigned int target_freq, | ||
110 | unsigned int relation) | ||
111 | { | ||
112 | int idx; | ||
113 | unsigned int freq; | ||
114 | |||
115 | cpufreq_frequency_table_target(policy, freq_table, target_freq, | ||
116 | relation, &idx); | ||
117 | |||
118 | freq = freq_table[idx].frequency; | ||
119 | |||
120 | target_cpu_speed[policy->cpu] = freq; | ||
121 | |||
122 | return tegra_update_cpu_speed(); | ||
123 | } | ||
124 | |||
125 | static int tegra_cpu_init(struct cpufreq_policy *policy) | ||
126 | { | ||
127 | if (policy->cpu >= NUM_CPUS) | ||
128 | return -EINVAL; | ||
129 | |||
130 | cpu_clk = clk_get_sys(NULL, "cpu"); | ||
131 | if (IS_ERR(cpu_clk)) | ||
132 | return PTR_ERR(cpu_clk); | ||
133 | |||
134 | cpufreq_frequency_table_cpuinfo(policy, freq_table); | ||
135 | cpufreq_frequency_table_get_attr(freq_table, policy->cpu); | ||
136 | policy->cur = tegra_getspeed(policy->cpu); | ||
137 | target_cpu_speed[policy->cpu] = policy->cur; | ||
138 | |||
139 | /* FIXME: what's the actual transition time? */ | ||
140 | policy->cpuinfo.transition_latency = 300 * 1000; | ||
141 | |||
142 | policy->shared_type = CPUFREQ_SHARED_TYPE_ALL; | ||
143 | cpumask_copy(policy->related_cpus, cpu_possible_mask); | ||
144 | |||
145 | return 0; | ||
146 | } | ||
147 | |||
148 | static int tegra_cpu_exit(struct cpufreq_policy *policy) | ||
149 | { | ||
150 | cpufreq_frequency_table_cpuinfo(policy, freq_table); | ||
151 | clk_put(cpu_clk); | ||
152 | return 0; | ||
153 | } | ||
154 | |||
155 | static struct freq_attr *tegra_cpufreq_attr[] = { | ||
156 | &cpufreq_freq_attr_scaling_available_freqs, | ||
157 | NULL, | ||
158 | }; | ||
159 | |||
160 | static struct cpufreq_driver tegra_cpufreq_driver = { | ||
161 | .verify = tegra_verify_speed, | ||
162 | .target = tegra_target, | ||
163 | .get = tegra_getspeed, | ||
164 | .init = tegra_cpu_init, | ||
165 | .exit = tegra_cpu_exit, | ||
166 | .name = "tegra", | ||
167 | .attr = tegra_cpufreq_attr, | ||
168 | }; | ||
169 | |||
170 | static int __init tegra_cpufreq_init(void) | ||
171 | { | ||
172 | return cpufreq_register_driver(&tegra_cpufreq_driver); | ||
173 | } | ||
174 | |||
175 | static void __exit tegra_cpufreq_exit(void) | ||
176 | { | ||
177 | cpufreq_unregister_driver(&tegra_cpufreq_driver); | ||
178 | } | ||
179 | |||
180 | |||
181 | MODULE_AUTHOR("Colin Cross <ccross@android.com>"); | ||
182 | MODULE_DESCRIPTION("cpufreq driver for Nvidia Tegra2"); | ||
183 | MODULE_LICENSE("GPL"); | ||
184 | module_init(tegra_cpufreq_init); | ||
185 | module_exit(tegra_cpufreq_exit); | ||
diff --git a/arch/arm/mach-tegra/dma.c b/arch/arm/mach-tegra/dma.c new file mode 100644 index 000000000000..edda6ec5e925 --- /dev/null +++ b/arch/arm/mach-tegra/dma.c | |||
@@ -0,0 +1,752 @@ | |||
1 | /* | ||
2 | * arch/arm/mach-tegra/dma.c | ||
3 | * | ||
4 | * System DMA driver for NVIDIA Tegra SoCs | ||
5 | * | ||
6 | * Copyright (c) 2008-2009, NVIDIA Corporation. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
14 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
15 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
16 | * more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License along | ||
19 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
20 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
21 | */ | ||
22 | |||
23 | #include <linux/io.h> | ||
24 | #include <linux/interrupt.h> | ||
25 | #include <linux/module.h> | ||
26 | #include <linux/spinlock.h> | ||
27 | #include <linux/err.h> | ||
28 | #include <linux/irq.h> | ||
29 | #include <linux/delay.h> | ||
30 | #include <mach/dma.h> | ||
31 | #include <mach/irqs.h> | ||
32 | #include <mach/iomap.h> | ||
33 | |||
34 | #define APB_DMA_GEN 0x000 | ||
35 | #define GEN_ENABLE (1<<31) | ||
36 | |||
37 | #define APB_DMA_CNTRL 0x010 | ||
38 | |||
39 | #define APB_DMA_IRQ_MASK 0x01c | ||
40 | |||
41 | #define APB_DMA_IRQ_MASK_SET 0x020 | ||
42 | |||
43 | #define APB_DMA_CHAN_CSR 0x000 | ||
44 | #define CSR_ENB (1<<31) | ||
45 | #define CSR_IE_EOC (1<<30) | ||
46 | #define CSR_HOLD (1<<29) | ||
47 | #define CSR_DIR (1<<28) | ||
48 | #define CSR_ONCE (1<<27) | ||
49 | #define CSR_FLOW (1<<21) | ||
50 | #define CSR_REQ_SEL_SHIFT 16 | ||
51 | #define CSR_REQ_SEL_MASK (0x1F<<CSR_REQ_SEL_SHIFT) | ||
52 | #define CSR_REQ_SEL_INVALID (31<<CSR_REQ_SEL_SHIFT) | ||
53 | #define CSR_WCOUNT_SHIFT 2 | ||
54 | #define CSR_WCOUNT_MASK 0xFFFC | ||
55 | |||
56 | #define APB_DMA_CHAN_STA 0x004 | ||
57 | #define STA_BUSY (1<<31) | ||
58 | #define STA_ISE_EOC (1<<30) | ||
59 | #define STA_HALT (1<<29) | ||
60 | #define STA_PING_PONG (1<<28) | ||
61 | #define STA_COUNT_SHIFT 2 | ||
62 | #define STA_COUNT_MASK 0xFFFC | ||
63 | |||
64 | #define APB_DMA_CHAN_AHB_PTR 0x010 | ||
65 | |||
66 | #define APB_DMA_CHAN_AHB_SEQ 0x014 | ||
67 | #define AHB_SEQ_INTR_ENB (1<<31) | ||
68 | #define AHB_SEQ_BUS_WIDTH_SHIFT 28 | ||
69 | #define AHB_SEQ_BUS_WIDTH_MASK (0x7<<AHB_SEQ_BUS_WIDTH_SHIFT) | ||
70 | #define AHB_SEQ_BUS_WIDTH_8 (0<<AHB_SEQ_BUS_WIDTH_SHIFT) | ||
71 | #define AHB_SEQ_BUS_WIDTH_16 (1<<AHB_SEQ_BUS_WIDTH_SHIFT) | ||
72 | #define AHB_SEQ_BUS_WIDTH_32 (2<<AHB_SEQ_BUS_WIDTH_SHIFT) | ||
73 | #define AHB_SEQ_BUS_WIDTH_64 (3<<AHB_SEQ_BUS_WIDTH_SHIFT) | ||
74 | #define AHB_SEQ_BUS_WIDTH_128 (4<<AHB_SEQ_BUS_WIDTH_SHIFT) | ||
75 | #define AHB_SEQ_DATA_SWAP (1<<27) | ||
76 | #define AHB_SEQ_BURST_MASK (0x7<<24) | ||
77 | #define AHB_SEQ_BURST_1 (4<<24) | ||
78 | #define AHB_SEQ_BURST_4 (5<<24) | ||
79 | #define AHB_SEQ_BURST_8 (6<<24) | ||
80 | #define AHB_SEQ_DBL_BUF (1<<19) | ||
81 | #define AHB_SEQ_WRAP_SHIFT 16 | ||
82 | #define AHB_SEQ_WRAP_MASK (0x7<<AHB_SEQ_WRAP_SHIFT) | ||
83 | |||
84 | #define APB_DMA_CHAN_APB_PTR 0x018 | ||
85 | |||
86 | #define APB_DMA_CHAN_APB_SEQ 0x01c | ||
87 | #define APB_SEQ_BUS_WIDTH_SHIFT 28 | ||
88 | #define APB_SEQ_BUS_WIDTH_MASK (0x7<<APB_SEQ_BUS_WIDTH_SHIFT) | ||
89 | #define APB_SEQ_BUS_WIDTH_8 (0<<APB_SEQ_BUS_WIDTH_SHIFT) | ||
90 | #define APB_SEQ_BUS_WIDTH_16 (1<<APB_SEQ_BUS_WIDTH_SHIFT) | ||
91 | #define APB_SEQ_BUS_WIDTH_32 (2<<APB_SEQ_BUS_WIDTH_SHIFT) | ||
92 | #define APB_SEQ_BUS_WIDTH_64 (3<<APB_SEQ_BUS_WIDTH_SHIFT) | ||
93 | #define APB_SEQ_BUS_WIDTH_128 (4<<APB_SEQ_BUS_WIDTH_SHIFT) | ||
94 | #define APB_SEQ_DATA_SWAP (1<<27) | ||
95 | #define APB_SEQ_WRAP_SHIFT 16 | ||
96 | #define APB_SEQ_WRAP_MASK (0x7<<APB_SEQ_WRAP_SHIFT) | ||
97 | |||
98 | #define TEGRA_SYSTEM_DMA_CH_NR 16 | ||
99 | #define TEGRA_SYSTEM_DMA_AVP_CH_NUM 4 | ||
100 | #define TEGRA_SYSTEM_DMA_CH_MIN 0 | ||
101 | #define TEGRA_SYSTEM_DMA_CH_MAX \ | ||
102 | (TEGRA_SYSTEM_DMA_CH_NR - TEGRA_SYSTEM_DMA_AVP_CH_NUM - 1) | ||
103 | |||
104 | #define NV_DMA_MAX_TRASFER_SIZE 0x10000 | ||
105 | |||
106 | const unsigned int ahb_addr_wrap_table[8] = { | ||
107 | 0, 32, 64, 128, 256, 512, 1024, 2048 | ||
108 | }; | ||
109 | |||
110 | const unsigned int apb_addr_wrap_table[8] = {0, 1, 2, 4, 8, 16, 32, 64}; | ||
111 | |||
112 | const unsigned int bus_width_table[5] = {8, 16, 32, 64, 128}; | ||
113 | |||
114 | #define TEGRA_DMA_NAME_SIZE 16 | ||
115 | struct tegra_dma_channel { | ||
116 | struct list_head list; | ||
117 | int id; | ||
118 | spinlock_t lock; | ||
119 | char name[TEGRA_DMA_NAME_SIZE]; | ||
120 | void __iomem *addr; | ||
121 | int mode; | ||
122 | int irq; | ||
123 | |||
124 | /* Register shadow */ | ||
125 | u32 csr; | ||
126 | u32 ahb_seq; | ||
127 | u32 ahb_ptr; | ||
128 | u32 apb_seq; | ||
129 | u32 apb_ptr; | ||
130 | }; | ||
131 | |||
132 | #define NV_DMA_MAX_CHANNELS 32 | ||
133 | |||
134 | static DECLARE_BITMAP(channel_usage, NV_DMA_MAX_CHANNELS); | ||
135 | static struct tegra_dma_channel dma_channels[NV_DMA_MAX_CHANNELS]; | ||
136 | |||
137 | static void tegra_dma_update_hw(struct tegra_dma_channel *ch, | ||
138 | struct tegra_dma_req *req); | ||
139 | static void tegra_dma_update_hw_partial(struct tegra_dma_channel *ch, | ||
140 | struct tegra_dma_req *req); | ||
141 | static void tegra_dma_init_hw(struct tegra_dma_channel *ch); | ||
142 | static void tegra_dma_stop(struct tegra_dma_channel *ch); | ||
143 | |||
144 | void tegra_dma_flush(struct tegra_dma_channel *ch) | ||
145 | { | ||
146 | } | ||
147 | EXPORT_SYMBOL(tegra_dma_flush); | ||
148 | |||
149 | void tegra_dma_dequeue(struct tegra_dma_channel *ch) | ||
150 | { | ||
151 | struct tegra_dma_req *req; | ||
152 | |||
153 | req = list_entry(ch->list.next, typeof(*req), node); | ||
154 | |||
155 | tegra_dma_dequeue_req(ch, req); | ||
156 | return; | ||
157 | } | ||
158 | |||
159 | void tegra_dma_stop(struct tegra_dma_channel *ch) | ||
160 | { | ||
161 | unsigned int csr; | ||
162 | unsigned int status; | ||
163 | |||
164 | csr = ch->csr; | ||
165 | csr &= ~CSR_IE_EOC; | ||
166 | writel(csr, ch->addr + APB_DMA_CHAN_CSR); | ||
167 | |||
168 | csr &= ~CSR_ENB; | ||
169 | writel(csr, ch->addr + APB_DMA_CHAN_CSR); | ||
170 | |||
171 | status = readl(ch->addr + APB_DMA_CHAN_STA); | ||
172 | if (status & STA_ISE_EOC) | ||
173 | writel(status, ch->addr + APB_DMA_CHAN_STA); | ||
174 | } | ||
175 | |||
176 | int tegra_dma_cancel(struct tegra_dma_channel *ch) | ||
177 | { | ||
178 | unsigned int csr; | ||
179 | unsigned long irq_flags; | ||
180 | |||
181 | spin_lock_irqsave(&ch->lock, irq_flags); | ||
182 | while (!list_empty(&ch->list)) | ||
183 | list_del(ch->list.next); | ||
184 | |||
185 | csr = ch->csr; | ||
186 | csr &= ~CSR_REQ_SEL_MASK; | ||
187 | csr |= CSR_REQ_SEL_INVALID; | ||
188 | |||
189 | /* Set the enable as that is not shadowed */ | ||
190 | csr |= CSR_ENB; | ||
191 | writel(csr, ch->addr + APB_DMA_CHAN_CSR); | ||
192 | |||
193 | tegra_dma_stop(ch); | ||
194 | |||
195 | spin_unlock_irqrestore(&ch->lock, irq_flags); | ||
196 | return 0; | ||
197 | } | ||
198 | |||
199 | int tegra_dma_dequeue_req(struct tegra_dma_channel *ch, | ||
200 | struct tegra_dma_req *_req) | ||
201 | { | ||
202 | unsigned int csr; | ||
203 | unsigned int status; | ||
204 | struct tegra_dma_req *req = NULL; | ||
205 | int found = 0; | ||
206 | unsigned long irq_flags; | ||
207 | int to_transfer; | ||
208 | int req_transfer_count; | ||
209 | |||
210 | spin_lock_irqsave(&ch->lock, irq_flags); | ||
211 | list_for_each_entry(req, &ch->list, node) { | ||
212 | if (req == _req) { | ||
213 | list_del(&req->node); | ||
214 | found = 1; | ||
215 | break; | ||
216 | } | ||
217 | } | ||
218 | if (!found) { | ||
219 | spin_unlock_irqrestore(&ch->lock, irq_flags); | ||
220 | return 0; | ||
221 | } | ||
222 | |||
223 | /* STOP the DMA and get the transfer count. | ||
224 | * Getting the transfer count is tricky. | ||
225 | * - Change the source selector to invalid to stop the DMA from | ||
226 | * FIFO to memory. | ||
227 | * - Read the status register to know the number of pending | ||
228 | * bytes to be transfered. | ||
229 | * - Finally stop or program the DMA to the next buffer in the | ||
230 | * list. | ||
231 | */ | ||
232 | csr = ch->csr; | ||
233 | csr &= ~CSR_REQ_SEL_MASK; | ||
234 | csr |= CSR_REQ_SEL_INVALID; | ||
235 | |||
236 | /* Set the enable as that is not shadowed */ | ||
237 | csr |= CSR_ENB; | ||
238 | writel(csr, ch->addr + APB_DMA_CHAN_CSR); | ||
239 | |||
240 | /* Get the transfer count */ | ||
241 | status = readl(ch->addr + APB_DMA_CHAN_STA); | ||
242 | to_transfer = (status & STA_COUNT_MASK) >> STA_COUNT_SHIFT; | ||
243 | req_transfer_count = (ch->csr & CSR_WCOUNT_MASK) >> CSR_WCOUNT_SHIFT; | ||
244 | req_transfer_count += 1; | ||
245 | to_transfer += 1; | ||
246 | |||
247 | req->bytes_transferred = req_transfer_count; | ||
248 | |||
249 | if (status & STA_BUSY) | ||
250 | req->bytes_transferred -= to_transfer; | ||
251 | |||
252 | /* In continous transfer mode, DMA only tracks the count of the | ||
253 | * half DMA buffer. So, if the DMA already finished half the DMA | ||
254 | * then add the half buffer to the completed count. | ||
255 | * | ||
256 | * FIXME: There can be a race here. What if the req to | ||
257 | * dequue happens at the same time as the DMA just moved to | ||
258 | * the new buffer and SW didn't yet received the interrupt? | ||
259 | */ | ||
260 | if (ch->mode & TEGRA_DMA_MODE_CONTINOUS) | ||
261 | if (req->buffer_status == TEGRA_DMA_REQ_BUF_STATUS_HALF_FULL) | ||
262 | req->bytes_transferred += req_transfer_count; | ||
263 | |||
264 | req->bytes_transferred *= 4; | ||
265 | |||
266 | tegra_dma_stop(ch); | ||
267 | if (!list_empty(&ch->list)) { | ||
268 | /* if the list is not empty, queue the next request */ | ||
269 | struct tegra_dma_req *next_req; | ||
270 | next_req = list_entry(ch->list.next, | ||
271 | typeof(*next_req), node); | ||
272 | tegra_dma_update_hw(ch, next_req); | ||
273 | } | ||
274 | req->status = -TEGRA_DMA_REQ_ERROR_ABORTED; | ||
275 | |||
276 | spin_unlock_irqrestore(&ch->lock, irq_flags); | ||
277 | |||
278 | /* Callback should be called without any lock */ | ||
279 | req->complete(req); | ||
280 | return 0; | ||
281 | } | ||
282 | EXPORT_SYMBOL(tegra_dma_dequeue_req); | ||
283 | |||
284 | bool tegra_dma_is_empty(struct tegra_dma_channel *ch) | ||
285 | { | ||
286 | unsigned long irq_flags; | ||
287 | bool is_empty; | ||
288 | |||
289 | spin_lock_irqsave(&ch->lock, irq_flags); | ||
290 | if (list_empty(&ch->list)) | ||
291 | is_empty = true; | ||
292 | else | ||
293 | is_empty = false; | ||
294 | spin_unlock_irqrestore(&ch->lock, irq_flags); | ||
295 | return is_empty; | ||
296 | } | ||
297 | EXPORT_SYMBOL(tegra_dma_is_empty); | ||
298 | |||
299 | bool tegra_dma_is_req_inflight(struct tegra_dma_channel *ch, | ||
300 | struct tegra_dma_req *_req) | ||
301 | { | ||
302 | unsigned long irq_flags; | ||
303 | struct tegra_dma_req *req; | ||
304 | |||
305 | spin_lock_irqsave(&ch->lock, irq_flags); | ||
306 | list_for_each_entry(req, &ch->list, node) { | ||
307 | if (req == _req) { | ||
308 | spin_unlock_irqrestore(&ch->lock, irq_flags); | ||
309 | return true; | ||
310 | } | ||
311 | } | ||
312 | spin_unlock_irqrestore(&ch->lock, irq_flags); | ||
313 | return false; | ||
314 | } | ||
315 | EXPORT_SYMBOL(tegra_dma_is_req_inflight); | ||
316 | |||
317 | int tegra_dma_enqueue_req(struct tegra_dma_channel *ch, | ||
318 | struct tegra_dma_req *req) | ||
319 | { | ||
320 | unsigned long irq_flags; | ||
321 | int start_dma = 0; | ||
322 | |||
323 | if (req->size > NV_DMA_MAX_TRASFER_SIZE || | ||
324 | req->source_addr & 0x3 || req->dest_addr & 0x3) { | ||
325 | pr_err("Invalid DMA request for channel %d\n", ch->id); | ||
326 | return -EINVAL; | ||
327 | } | ||
328 | |||
329 | spin_lock_irqsave(&ch->lock, irq_flags); | ||
330 | |||
331 | req->bytes_transferred = 0; | ||
332 | req->status = 0; | ||
333 | req->buffer_status = 0; | ||
334 | if (list_empty(&ch->list)) | ||
335 | start_dma = 1; | ||
336 | |||
337 | list_add_tail(&req->node, &ch->list); | ||
338 | |||
339 | if (start_dma) | ||
340 | tegra_dma_update_hw(ch, req); | ||
341 | |||
342 | spin_unlock_irqrestore(&ch->lock, irq_flags); | ||
343 | |||
344 | return 0; | ||
345 | } | ||
346 | EXPORT_SYMBOL(tegra_dma_enqueue_req); | ||
347 | |||
348 | struct tegra_dma_channel *tegra_dma_allocate_channel(int mode) | ||
349 | { | ||
350 | int channel; | ||
351 | struct tegra_dma_channel *ch; | ||
352 | |||
353 | /* first channel is the shared channel */ | ||
354 | if (mode & TEGRA_DMA_SHARED) { | ||
355 | channel = TEGRA_SYSTEM_DMA_CH_MIN; | ||
356 | } else { | ||
357 | channel = find_first_zero_bit(channel_usage, | ||
358 | ARRAY_SIZE(dma_channels)); | ||
359 | if (channel >= ARRAY_SIZE(dma_channels)) | ||
360 | return NULL; | ||
361 | } | ||
362 | __set_bit(channel, channel_usage); | ||
363 | ch = &dma_channels[channel]; | ||
364 | ch->mode = mode; | ||
365 | return ch; | ||
366 | } | ||
367 | EXPORT_SYMBOL(tegra_dma_allocate_channel); | ||
368 | |||
369 | void tegra_dma_free_channel(struct tegra_dma_channel *ch) | ||
370 | { | ||
371 | if (ch->mode & TEGRA_DMA_SHARED) | ||
372 | return; | ||
373 | tegra_dma_cancel(ch); | ||
374 | __clear_bit(ch->id, channel_usage); | ||
375 | } | ||
376 | EXPORT_SYMBOL(tegra_dma_free_channel); | ||
377 | |||
378 | static void tegra_dma_update_hw_partial(struct tegra_dma_channel *ch, | ||
379 | struct tegra_dma_req *req) | ||
380 | { | ||
381 | if (req->to_memory) { | ||
382 | ch->apb_ptr = req->source_addr; | ||
383 | ch->ahb_ptr = req->dest_addr; | ||
384 | } else { | ||
385 | ch->apb_ptr = req->dest_addr; | ||
386 | ch->ahb_ptr = req->source_addr; | ||
387 | } | ||
388 | writel(ch->apb_ptr, ch->addr + APB_DMA_CHAN_APB_PTR); | ||
389 | writel(ch->ahb_ptr, ch->addr + APB_DMA_CHAN_AHB_PTR); | ||
390 | |||
391 | req->status = TEGRA_DMA_REQ_INFLIGHT; | ||
392 | return; | ||
393 | } | ||
394 | |||
395 | static void tegra_dma_update_hw(struct tegra_dma_channel *ch, | ||
396 | struct tegra_dma_req *req) | ||
397 | { | ||
398 | int ahb_addr_wrap; | ||
399 | int apb_addr_wrap; | ||
400 | int ahb_bus_width; | ||
401 | int apb_bus_width; | ||
402 | int index; | ||
403 | unsigned long csr; | ||
404 | |||
405 | |||
406 | ch->csr |= CSR_FLOW; | ||
407 | ch->csr &= ~CSR_REQ_SEL_MASK; | ||
408 | ch->csr |= req->req_sel << CSR_REQ_SEL_SHIFT; | ||
409 | ch->ahb_seq &= ~AHB_SEQ_BURST_MASK; | ||
410 | ch->ahb_seq |= AHB_SEQ_BURST_1; | ||
411 | |||
412 | /* One shot mode is always single buffered, | ||
413 | * continuous mode is always double buffered | ||
414 | * */ | ||
415 | if (ch->mode & TEGRA_DMA_MODE_ONESHOT) { | ||
416 | ch->csr |= CSR_ONCE; | ||
417 | ch->ahb_seq &= ~AHB_SEQ_DBL_BUF; | ||
418 | ch->csr &= ~CSR_WCOUNT_MASK; | ||
419 | ch->csr |= ((req->size>>2) - 1) << CSR_WCOUNT_SHIFT; | ||
420 | } else { | ||
421 | ch->csr &= ~CSR_ONCE; | ||
422 | ch->ahb_seq |= AHB_SEQ_DBL_BUF; | ||
423 | |||
424 | /* In double buffered mode, we set the size to half the | ||
425 | * requested size and interrupt when half the buffer | ||
426 | * is full */ | ||
427 | ch->csr &= ~CSR_WCOUNT_MASK; | ||
428 | ch->csr |= ((req->size>>3) - 1) << CSR_WCOUNT_SHIFT; | ||
429 | } | ||
430 | |||
431 | if (req->to_memory) { | ||
432 | ch->csr &= ~CSR_DIR; | ||
433 | ch->apb_ptr = req->source_addr; | ||
434 | ch->ahb_ptr = req->dest_addr; | ||
435 | |||
436 | apb_addr_wrap = req->source_wrap; | ||
437 | ahb_addr_wrap = req->dest_wrap; | ||
438 | apb_bus_width = req->source_bus_width; | ||
439 | ahb_bus_width = req->dest_bus_width; | ||
440 | |||
441 | } else { | ||
442 | ch->csr |= CSR_DIR; | ||
443 | ch->apb_ptr = req->dest_addr; | ||
444 | ch->ahb_ptr = req->source_addr; | ||
445 | |||
446 | apb_addr_wrap = req->dest_wrap; | ||
447 | ahb_addr_wrap = req->source_wrap; | ||
448 | apb_bus_width = req->dest_bus_width; | ||
449 | ahb_bus_width = req->source_bus_width; | ||
450 | } | ||
451 | |||
452 | apb_addr_wrap >>= 2; | ||
453 | ahb_addr_wrap >>= 2; | ||
454 | |||
455 | /* set address wrap for APB size */ | ||
456 | index = 0; | ||
457 | do { | ||
458 | if (apb_addr_wrap_table[index] == apb_addr_wrap) | ||
459 | break; | ||
460 | index++; | ||
461 | } while (index < ARRAY_SIZE(apb_addr_wrap_table)); | ||
462 | BUG_ON(index == ARRAY_SIZE(apb_addr_wrap_table)); | ||
463 | ch->apb_seq &= ~APB_SEQ_WRAP_MASK; | ||
464 | ch->apb_seq |= index << APB_SEQ_WRAP_SHIFT; | ||
465 | |||
466 | /* set address wrap for AHB size */ | ||
467 | index = 0; | ||
468 | do { | ||
469 | if (ahb_addr_wrap_table[index] == ahb_addr_wrap) | ||
470 | break; | ||
471 | index++; | ||
472 | } while (index < ARRAY_SIZE(ahb_addr_wrap_table)); | ||
473 | BUG_ON(index == ARRAY_SIZE(ahb_addr_wrap_table)); | ||
474 | ch->ahb_seq &= ~AHB_SEQ_WRAP_MASK; | ||
475 | ch->ahb_seq |= index << AHB_SEQ_WRAP_SHIFT; | ||
476 | |||
477 | for (index = 0; index < ARRAY_SIZE(bus_width_table); index++) { | ||
478 | if (bus_width_table[index] == ahb_bus_width) | ||
479 | break; | ||
480 | } | ||
481 | BUG_ON(index == ARRAY_SIZE(bus_width_table)); | ||
482 | ch->ahb_seq &= ~AHB_SEQ_BUS_WIDTH_MASK; | ||
483 | ch->ahb_seq |= index << AHB_SEQ_BUS_WIDTH_SHIFT; | ||
484 | |||
485 | for (index = 0; index < ARRAY_SIZE(bus_width_table); index++) { | ||
486 | if (bus_width_table[index] == apb_bus_width) | ||
487 | break; | ||
488 | } | ||
489 | BUG_ON(index == ARRAY_SIZE(bus_width_table)); | ||
490 | ch->apb_seq &= ~APB_SEQ_BUS_WIDTH_MASK; | ||
491 | ch->apb_seq |= index << APB_SEQ_BUS_WIDTH_SHIFT; | ||
492 | |||
493 | ch->csr |= CSR_IE_EOC; | ||
494 | |||
495 | /* update hw registers with the shadow */ | ||
496 | writel(ch->csr, ch->addr + APB_DMA_CHAN_CSR); | ||
497 | writel(ch->apb_seq, ch->addr + APB_DMA_CHAN_APB_SEQ); | ||
498 | writel(ch->apb_ptr, ch->addr + APB_DMA_CHAN_APB_PTR); | ||
499 | writel(ch->ahb_seq, ch->addr + APB_DMA_CHAN_AHB_SEQ); | ||
500 | writel(ch->ahb_ptr, ch->addr + APB_DMA_CHAN_AHB_PTR); | ||
501 | |||
502 | csr = ch->csr | CSR_ENB; | ||
503 | writel(csr, ch->addr + APB_DMA_CHAN_CSR); | ||
504 | |||
505 | req->status = TEGRA_DMA_REQ_INFLIGHT; | ||
506 | } | ||
507 | |||
508 | static void tegra_dma_init_hw(struct tegra_dma_channel *ch) | ||
509 | { | ||
510 | /* One shot with an interrupt to CPU after transfer */ | ||
511 | ch->csr = CSR_ONCE | CSR_IE_EOC; | ||
512 | ch->ahb_seq = AHB_SEQ_BUS_WIDTH_32 | AHB_SEQ_INTR_ENB; | ||
513 | ch->apb_seq = APB_SEQ_BUS_WIDTH_32 | 1 << APB_SEQ_WRAP_SHIFT; | ||
514 | } | ||
515 | |||
516 | static void handle_oneshot_dma(struct tegra_dma_channel *ch) | ||
517 | { | ||
518 | struct tegra_dma_req *req; | ||
519 | |||
520 | spin_lock(&ch->lock); | ||
521 | if (list_empty(&ch->list)) { | ||
522 | spin_unlock(&ch->lock); | ||
523 | return; | ||
524 | } | ||
525 | |||
526 | req = list_entry(ch->list.next, typeof(*req), node); | ||
527 | if (req) { | ||
528 | int bytes_transferred; | ||
529 | |||
530 | bytes_transferred = | ||
531 | (ch->csr & CSR_WCOUNT_MASK) >> CSR_WCOUNT_SHIFT; | ||
532 | bytes_transferred += 1; | ||
533 | bytes_transferred <<= 2; | ||
534 | |||
535 | list_del(&req->node); | ||
536 | req->bytes_transferred = bytes_transferred; | ||
537 | req->status = TEGRA_DMA_REQ_SUCCESS; | ||
538 | |||
539 | spin_unlock(&ch->lock); | ||
540 | /* Callback should be called without any lock */ | ||
541 | pr_debug("%s: transferred %d bytes\n", __func__, | ||
542 | req->bytes_transferred); | ||
543 | req->complete(req); | ||
544 | spin_lock(&ch->lock); | ||
545 | } | ||
546 | |||
547 | if (!list_empty(&ch->list)) { | ||
548 | req = list_entry(ch->list.next, typeof(*req), node); | ||
549 | /* the complete function we just called may have enqueued | ||
550 | another req, in which case dma has already started */ | ||
551 | if (req->status != TEGRA_DMA_REQ_INFLIGHT) | ||
552 | tegra_dma_update_hw(ch, req); | ||
553 | } | ||
554 | spin_unlock(&ch->lock); | ||
555 | } | ||
556 | |||
557 | static void handle_continuous_dma(struct tegra_dma_channel *ch) | ||
558 | { | ||
559 | struct tegra_dma_req *req; | ||
560 | |||
561 | spin_lock(&ch->lock); | ||
562 | if (list_empty(&ch->list)) { | ||
563 | spin_unlock(&ch->lock); | ||
564 | return; | ||
565 | } | ||
566 | |||
567 | req = list_entry(ch->list.next, typeof(*req), node); | ||
568 | if (req) { | ||
569 | if (req->buffer_status == TEGRA_DMA_REQ_BUF_STATUS_EMPTY) { | ||
570 | /* Load the next request into the hardware, if available | ||
571 | * */ | ||
572 | if (!list_is_last(&req->node, &ch->list)) { | ||
573 | struct tegra_dma_req *next_req; | ||
574 | |||
575 | next_req = list_entry(req->node.next, | ||
576 | typeof(*next_req), node); | ||
577 | tegra_dma_update_hw_partial(ch, next_req); | ||
578 | } | ||
579 | req->buffer_status = TEGRA_DMA_REQ_BUF_STATUS_HALF_FULL; | ||
580 | req->status = TEGRA_DMA_REQ_SUCCESS; | ||
581 | /* DMA lock is NOT held when callback is called */ | ||
582 | spin_unlock(&ch->lock); | ||
583 | if (likely(req->threshold)) | ||
584 | req->threshold(req); | ||
585 | return; | ||
586 | |||
587 | } else if (req->buffer_status == | ||
588 | TEGRA_DMA_REQ_BUF_STATUS_HALF_FULL) { | ||
589 | /* Callback when the buffer is completely full (i.e on | ||
590 | * the second interrupt */ | ||
591 | int bytes_transferred; | ||
592 | |||
593 | bytes_transferred = | ||
594 | (ch->csr & CSR_WCOUNT_MASK) >> CSR_WCOUNT_SHIFT; | ||
595 | bytes_transferred += 1; | ||
596 | bytes_transferred <<= 3; | ||
597 | |||
598 | req->buffer_status = TEGRA_DMA_REQ_BUF_STATUS_FULL; | ||
599 | req->bytes_transferred = bytes_transferred; | ||
600 | req->status = TEGRA_DMA_REQ_SUCCESS; | ||
601 | list_del(&req->node); | ||
602 | |||
603 | /* DMA lock is NOT held when callbak is called */ | ||
604 | spin_unlock(&ch->lock); | ||
605 | req->complete(req); | ||
606 | return; | ||
607 | |||
608 | } else { | ||
609 | BUG(); | ||
610 | } | ||
611 | } | ||
612 | spin_unlock(&ch->lock); | ||
613 | } | ||
614 | |||
615 | static irqreturn_t dma_isr(int irq, void *data) | ||
616 | { | ||
617 | struct tegra_dma_channel *ch = data; | ||
618 | unsigned long status; | ||
619 | |||
620 | status = readl(ch->addr + APB_DMA_CHAN_STA); | ||
621 | if (status & STA_ISE_EOC) | ||
622 | writel(status, ch->addr + APB_DMA_CHAN_STA); | ||
623 | else { | ||
624 | pr_warning("Got a spurious ISR for DMA channel %d\n", ch->id); | ||
625 | return IRQ_HANDLED; | ||
626 | } | ||
627 | return IRQ_WAKE_THREAD; | ||
628 | } | ||
629 | |||
630 | static irqreturn_t dma_thread_fn(int irq, void *data) | ||
631 | { | ||
632 | struct tegra_dma_channel *ch = data; | ||
633 | |||
634 | if (ch->mode & TEGRA_DMA_MODE_ONESHOT) | ||
635 | handle_oneshot_dma(ch); | ||
636 | else | ||
637 | handle_continuous_dma(ch); | ||
638 | |||
639 | |||
640 | return IRQ_HANDLED; | ||
641 | } | ||
642 | |||
643 | int __init tegra_dma_init(void) | ||
644 | { | ||
645 | int ret = 0; | ||
646 | int i; | ||
647 | unsigned int irq; | ||
648 | void __iomem *addr; | ||
649 | |||
650 | addr = IO_ADDRESS(TEGRA_APB_DMA_BASE); | ||
651 | writel(GEN_ENABLE, addr + APB_DMA_GEN); | ||
652 | writel(0, addr + APB_DMA_CNTRL); | ||
653 | writel(0xFFFFFFFFul >> (31 - TEGRA_SYSTEM_DMA_CH_MAX), | ||
654 | addr + APB_DMA_IRQ_MASK_SET); | ||
655 | |||
656 | memset(channel_usage, 0, sizeof(channel_usage)); | ||
657 | memset(dma_channels, 0, sizeof(dma_channels)); | ||
658 | |||
659 | /* Reserve all the channels we are not supposed to touch */ | ||
660 | for (i = 0; i < TEGRA_SYSTEM_DMA_CH_MIN; i++) | ||
661 | __set_bit(i, channel_usage); | ||
662 | |||
663 | for (i = TEGRA_SYSTEM_DMA_CH_MIN; i <= TEGRA_SYSTEM_DMA_CH_MAX; i++) { | ||
664 | struct tegra_dma_channel *ch = &dma_channels[i]; | ||
665 | |||
666 | __clear_bit(i, channel_usage); | ||
667 | |||
668 | ch->id = i; | ||
669 | snprintf(ch->name, TEGRA_DMA_NAME_SIZE, "dma_channel_%d", i); | ||
670 | |||
671 | ch->addr = IO_ADDRESS(TEGRA_APB_DMA_CH0_BASE + | ||
672 | TEGRA_APB_DMA_CH0_SIZE * i); | ||
673 | |||
674 | spin_lock_init(&ch->lock); | ||
675 | INIT_LIST_HEAD(&ch->list); | ||
676 | tegra_dma_init_hw(ch); | ||
677 | |||
678 | irq = INT_APB_DMA_CH0 + i; | ||
679 | ret = request_threaded_irq(irq, dma_isr, dma_thread_fn, 0, | ||
680 | dma_channels[i].name, ch); | ||
681 | if (ret) { | ||
682 | pr_err("Failed to register IRQ %d for DMA %d\n", | ||
683 | irq, i); | ||
684 | goto fail; | ||
685 | } | ||
686 | ch->irq = irq; | ||
687 | } | ||
688 | /* mark the shared channel allocated */ | ||
689 | __set_bit(TEGRA_SYSTEM_DMA_CH_MIN, channel_usage); | ||
690 | |||
691 | for (i = TEGRA_SYSTEM_DMA_CH_MAX+1; i < NV_DMA_MAX_CHANNELS; i++) | ||
692 | __set_bit(i, channel_usage); | ||
693 | |||
694 | return ret; | ||
695 | fail: | ||
696 | writel(0, addr + APB_DMA_GEN); | ||
697 | for (i = TEGRA_SYSTEM_DMA_CH_MIN; i <= TEGRA_SYSTEM_DMA_CH_MAX; i++) { | ||
698 | struct tegra_dma_channel *ch = &dma_channels[i]; | ||
699 | if (ch->irq) | ||
700 | free_irq(ch->irq, ch); | ||
701 | } | ||
702 | return ret; | ||
703 | } | ||
704 | |||
705 | #ifdef CONFIG_PM | ||
706 | static u32 apb_dma[5*TEGRA_SYSTEM_DMA_CH_NR + 3]; | ||
707 | |||
708 | void tegra_dma_suspend(void) | ||
709 | { | ||
710 | void __iomem *addr = IO_ADDRESS(TEGRA_APB_DMA_BASE); | ||
711 | u32 *ctx = apb_dma; | ||
712 | int i; | ||
713 | |||
714 | *ctx++ = readl(addr + APB_DMA_GEN); | ||
715 | *ctx++ = readl(addr + APB_DMA_CNTRL); | ||
716 | *ctx++ = readl(addr + APB_DMA_IRQ_MASK); | ||
717 | |||
718 | for (i = 0; i < TEGRA_SYSTEM_DMA_CH_NR; i++) { | ||
719 | addr = IO_ADDRESS(TEGRA_APB_DMA_CH0_BASE + | ||
720 | TEGRA_APB_DMA_CH0_SIZE * i); | ||
721 | |||
722 | *ctx++ = readl(addr + APB_DMA_CHAN_CSR); | ||
723 | *ctx++ = readl(addr + APB_DMA_CHAN_AHB_PTR); | ||
724 | *ctx++ = readl(addr + APB_DMA_CHAN_AHB_SEQ); | ||
725 | *ctx++ = readl(addr + APB_DMA_CHAN_APB_PTR); | ||
726 | *ctx++ = readl(addr + APB_DMA_CHAN_APB_SEQ); | ||
727 | } | ||
728 | } | ||
729 | |||
730 | void tegra_dma_resume(void) | ||
731 | { | ||
732 | void __iomem *addr = IO_ADDRESS(TEGRA_APB_DMA_BASE); | ||
733 | u32 *ctx = apb_dma; | ||
734 | int i; | ||
735 | |||
736 | writel(*ctx++, addr + APB_DMA_GEN); | ||
737 | writel(*ctx++, addr + APB_DMA_CNTRL); | ||
738 | writel(*ctx++, addr + APB_DMA_IRQ_MASK); | ||
739 | |||
740 | for (i = 0; i < TEGRA_SYSTEM_DMA_CH_NR; i++) { | ||
741 | addr = IO_ADDRESS(TEGRA_APB_DMA_CH0_BASE + | ||
742 | TEGRA_APB_DMA_CH0_SIZE * i); | ||
743 | |||
744 | writel(*ctx++, addr + APB_DMA_CHAN_CSR); | ||
745 | writel(*ctx++, addr + APB_DMA_CHAN_AHB_PTR); | ||
746 | writel(*ctx++, addr + APB_DMA_CHAN_AHB_SEQ); | ||
747 | writel(*ctx++, addr + APB_DMA_CHAN_APB_PTR); | ||
748 | writel(*ctx++, addr + APB_DMA_CHAN_APB_SEQ); | ||
749 | } | ||
750 | } | ||
751 | |||
752 | #endif | ||
diff --git a/arch/arm/mach-tegra/fuse.c b/arch/arm/mach-tegra/fuse.c new file mode 100644 index 000000000000..1fa26d9a1a68 --- /dev/null +++ b/arch/arm/mach-tegra/fuse.c | |||
@@ -0,0 +1,84 @@ | |||
1 | /* | ||
2 | * arch/arm/mach-tegra/fuse.c | ||
3 | * | ||
4 | * Copyright (C) 2010 Google, Inc. | ||
5 | * | ||
6 | * Author: | ||
7 | * Colin Cross <ccross@android.com> | ||
8 | * | ||
9 | * This software is licensed under the terms of the GNU General Public | ||
10 | * License version 2, as published by the Free Software Foundation, and | ||
11 | * may be copied, distributed, and modified under those terms. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | */ | ||
19 | |||
20 | #include <linux/kernel.h> | ||
21 | #include <linux/io.h> | ||
22 | |||
23 | #include <mach/iomap.h> | ||
24 | |||
25 | #include "fuse.h" | ||
26 | |||
27 | #define FUSE_UID_LOW 0x108 | ||
28 | #define FUSE_UID_HIGH 0x10c | ||
29 | #define FUSE_SKU_INFO 0x110 | ||
30 | #define FUSE_SPARE_BIT 0x200 | ||
31 | |||
32 | static inline u32 fuse_readl(unsigned long offset) | ||
33 | { | ||
34 | return readl(IO_TO_VIRT(TEGRA_FUSE_BASE + offset)); | ||
35 | } | ||
36 | |||
37 | static inline void fuse_writel(u32 value, unsigned long offset) | ||
38 | { | ||
39 | writel(value, IO_TO_VIRT(TEGRA_FUSE_BASE + offset)); | ||
40 | } | ||
41 | |||
42 | void tegra_init_fuse(void) | ||
43 | { | ||
44 | u32 reg = readl(IO_TO_VIRT(TEGRA_CLK_RESET_BASE + 0x48)); | ||
45 | reg |= 1 << 28; | ||
46 | writel(reg, IO_TO_VIRT(TEGRA_CLK_RESET_BASE + 0x48)); | ||
47 | |||
48 | pr_info("Tegra SKU: %d CPU Process: %d Core Process: %d\n", | ||
49 | tegra_sku_id(), tegra_cpu_process_id(), | ||
50 | tegra_core_process_id()); | ||
51 | } | ||
52 | |||
53 | unsigned long long tegra_chip_uid(void) | ||
54 | { | ||
55 | unsigned long long lo, hi; | ||
56 | |||
57 | lo = fuse_readl(FUSE_UID_LOW); | ||
58 | hi = fuse_readl(FUSE_UID_HIGH); | ||
59 | return (hi << 32ull) | lo; | ||
60 | } | ||
61 | |||
62 | int tegra_sku_id(void) | ||
63 | { | ||
64 | int sku_id; | ||
65 | u32 reg = fuse_readl(FUSE_SKU_INFO); | ||
66 | sku_id = reg & 0xFF; | ||
67 | return sku_id; | ||
68 | } | ||
69 | |||
70 | int tegra_cpu_process_id(void) | ||
71 | { | ||
72 | int cpu_process_id; | ||
73 | u32 reg = fuse_readl(FUSE_SPARE_BIT); | ||
74 | cpu_process_id = (reg >> 6) & 3; | ||
75 | return cpu_process_id; | ||
76 | } | ||
77 | |||
78 | int tegra_core_process_id(void) | ||
79 | { | ||
80 | int core_process_id; | ||
81 | u32 reg = fuse_readl(FUSE_SPARE_BIT); | ||
82 | core_process_id = (reg >> 12) & 3; | ||
83 | return core_process_id; | ||
84 | } | ||
diff --git a/arch/arm/mach-tegra/fuse.h b/arch/arm/mach-tegra/fuse.h new file mode 100644 index 000000000000..584b2e27dbda --- /dev/null +++ b/arch/arm/mach-tegra/fuse.h | |||
@@ -0,0 +1,24 @@ | |||
1 | /* | ||
2 | * arch/arm/mach-tegra/fuse.c | ||
3 | * | ||
4 | * Copyright (C) 2010 Google, Inc. | ||
5 | * | ||
6 | * Author: | ||
7 | * Colin Cross <ccross@android.com> | ||
8 | * | ||
9 | * This software is licensed under the terms of the GNU General Public | ||
10 | * License version 2, as published by the Free Software Foundation, and | ||
11 | * may be copied, distributed, and modified under those terms. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | */ | ||
19 | |||
20 | unsigned long long tegra_chip_uid(void); | ||
21 | int tegra_sku_id(void); | ||
22 | int tegra_cpu_process_id(void); | ||
23 | int tegra_core_process_id(void); | ||
24 | void tegra_init_fuse(void); | ||
diff --git a/arch/arm/mach-tegra/gpio.c b/arch/arm/mach-tegra/gpio.c index fe78fba25f3c..0775265e69f5 100644 --- a/arch/arm/mach-tegra/gpio.c +++ b/arch/arm/mach-tegra/gpio.c | |||
@@ -19,6 +19,7 @@ | |||
19 | 19 | ||
20 | #include <linux/init.h> | 20 | #include <linux/init.h> |
21 | #include <linux/irq.h> | 21 | #include <linux/irq.h> |
22 | #include <linux/interrupt.h> | ||
22 | 23 | ||
23 | #include <linux/io.h> | 24 | #include <linux/io.h> |
24 | #include <linux/gpio.h> | 25 | #include <linux/gpio.h> |
@@ -60,6 +61,13 @@ struct tegra_gpio_bank { | |||
60 | int bank; | 61 | int bank; |
61 | int irq; | 62 | int irq; |
62 | spinlock_t lvl_lock[4]; | 63 | spinlock_t lvl_lock[4]; |
64 | #ifdef CONFIG_PM | ||
65 | u32 cnf[4]; | ||
66 | u32 out[4]; | ||
67 | u32 oe[4]; | ||
68 | u32 int_enb[4]; | ||
69 | u32 int_lvl[4]; | ||
70 | #endif | ||
63 | }; | 71 | }; |
64 | 72 | ||
65 | 73 | ||
@@ -131,7 +139,7 @@ static struct gpio_chip tegra_gpio_chip = { | |||
131 | .direction_output = tegra_gpio_direction_output, | 139 | .direction_output = tegra_gpio_direction_output, |
132 | .set = tegra_gpio_set, | 140 | .set = tegra_gpio_set, |
133 | .base = 0, | 141 | .base = 0, |
134 | .ngpio = ARCH_NR_GPIOS, | 142 | .ngpio = TEGRA_NR_GPIOS, |
135 | }; | 143 | }; |
136 | 144 | ||
137 | static void tegra_gpio_irq_ack(unsigned int irq) | 145 | static void tegra_gpio_irq_ack(unsigned int irq) |
@@ -244,6 +252,76 @@ static void tegra_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) | |||
244 | 252 | ||
245 | } | 253 | } |
246 | 254 | ||
255 | #ifdef CONFIG_PM | ||
256 | void tegra_gpio_resume(void) | ||
257 | { | ||
258 | unsigned long flags; | ||
259 | int b, p, i; | ||
260 | |||
261 | local_irq_save(flags); | ||
262 | |||
263 | for (b = 0; b < ARRAY_SIZE(tegra_gpio_banks); b++) { | ||
264 | struct tegra_gpio_bank *bank = &tegra_gpio_banks[b]; | ||
265 | |||
266 | for (p = 0; p < ARRAY_SIZE(bank->oe); p++) { | ||
267 | unsigned int gpio = (b<<5) | (p<<3); | ||
268 | __raw_writel(bank->cnf[p], GPIO_CNF(gpio)); | ||
269 | __raw_writel(bank->out[p], GPIO_OUT(gpio)); | ||
270 | __raw_writel(bank->oe[p], GPIO_OE(gpio)); | ||
271 | __raw_writel(bank->int_lvl[p], GPIO_INT_LVL(gpio)); | ||
272 | __raw_writel(bank->int_enb[p], GPIO_INT_ENB(gpio)); | ||
273 | } | ||
274 | } | ||
275 | |||
276 | local_irq_restore(flags); | ||
277 | |||
278 | for (i = INT_GPIO_BASE; i < (INT_GPIO_BASE + TEGRA_NR_GPIOS); i++) { | ||
279 | struct irq_desc *desc = irq_to_desc(i); | ||
280 | if (!desc || (desc->status & IRQ_WAKEUP)) | ||
281 | continue; | ||
282 | enable_irq(i); | ||
283 | } | ||
284 | } | ||
285 | |||
286 | void tegra_gpio_suspend(void) | ||
287 | { | ||
288 | unsigned long flags; | ||
289 | int b, p, i; | ||
290 | |||
291 | for (i = INT_GPIO_BASE; i < (INT_GPIO_BASE + TEGRA_NR_GPIOS); i++) { | ||
292 | struct irq_desc *desc = irq_to_desc(i); | ||
293 | if (!desc) | ||
294 | continue; | ||
295 | if (desc->status & IRQ_WAKEUP) { | ||
296 | int gpio = i - INT_GPIO_BASE; | ||
297 | pr_debug("gpio %d.%d is wakeup\n", gpio/8, gpio&7); | ||
298 | continue; | ||
299 | } | ||
300 | disable_irq(i); | ||
301 | } | ||
302 | |||
303 | local_irq_save(flags); | ||
304 | for (b = 0; b < ARRAY_SIZE(tegra_gpio_banks); b++) { | ||
305 | struct tegra_gpio_bank *bank = &tegra_gpio_banks[b]; | ||
306 | |||
307 | for (p = 0; p < ARRAY_SIZE(bank->oe); p++) { | ||
308 | unsigned int gpio = (b<<5) | (p<<3); | ||
309 | bank->cnf[p] = __raw_readl(GPIO_CNF(gpio)); | ||
310 | bank->out[p] = __raw_readl(GPIO_OUT(gpio)); | ||
311 | bank->oe[p] = __raw_readl(GPIO_OE(gpio)); | ||
312 | bank->int_enb[p] = __raw_readl(GPIO_INT_ENB(gpio)); | ||
313 | bank->int_lvl[p] = __raw_readl(GPIO_INT_LVL(gpio)); | ||
314 | } | ||
315 | } | ||
316 | local_irq_restore(flags); | ||
317 | } | ||
318 | |||
319 | static int tegra_gpio_wake_enable(unsigned int irq, unsigned int enable) | ||
320 | { | ||
321 | struct tegra_gpio_bank *bank = get_irq_chip_data(irq); | ||
322 | return set_irq_wake(bank->irq, enable); | ||
323 | } | ||
324 | #endif | ||
247 | 325 | ||
248 | static struct irq_chip tegra_gpio_irq_chip = { | 326 | static struct irq_chip tegra_gpio_irq_chip = { |
249 | .name = "GPIO", | 327 | .name = "GPIO", |
@@ -251,6 +329,9 @@ static struct irq_chip tegra_gpio_irq_chip = { | |||
251 | .mask = tegra_gpio_irq_mask, | 329 | .mask = tegra_gpio_irq_mask, |
252 | .unmask = tegra_gpio_irq_unmask, | 330 | .unmask = tegra_gpio_irq_unmask, |
253 | .set_type = tegra_gpio_irq_set_type, | 331 | .set_type = tegra_gpio_irq_set_type, |
332 | #ifdef CONFIG_PM | ||
333 | .set_wake = tegra_gpio_wake_enable, | ||
334 | #endif | ||
254 | }; | 335 | }; |
255 | 336 | ||
256 | 337 | ||
@@ -274,7 +355,7 @@ static int __init tegra_gpio_init(void) | |||
274 | 355 | ||
275 | gpiochip_add(&tegra_gpio_chip); | 356 | gpiochip_add(&tegra_gpio_chip); |
276 | 357 | ||
277 | for (i = INT_GPIO_BASE; i < (INT_GPIO_BASE + ARCH_NR_GPIOS); i++) { | 358 | for (i = INT_GPIO_BASE; i < (INT_GPIO_BASE + TEGRA_NR_GPIOS); i++) { |
278 | bank = &tegra_gpio_banks[GPIO_BANK(irq_to_gpio(i))]; | 359 | bank = &tegra_gpio_banks[GPIO_BANK(irq_to_gpio(i))]; |
279 | 360 | ||
280 | lockdep_set_class(&irq_desc[i].lock, &gpio_lock_class); | 361 | lockdep_set_class(&irq_desc[i].lock, &gpio_lock_class); |
@@ -312,15 +393,16 @@ static int dbg_gpio_show(struct seq_file *s, void *unused) | |||
312 | for (i = 0; i < 7; i++) { | 393 | for (i = 0; i < 7; i++) { |
313 | for (j = 0; j < 4; j++) { | 394 | for (j = 0; j < 4; j++) { |
314 | int gpio = tegra_gpio_compose(i, j, 0); | 395 | int gpio = tegra_gpio_compose(i, j, 0); |
315 | seq_printf(s, "%d:%d %02x %02x %02x %02x %02x %02x %06x\n", | 396 | seq_printf(s, |
316 | i, j, | 397 | "%d:%d %02x %02x %02x %02x %02x %02x %06x\n", |
317 | __raw_readl(GPIO_CNF(gpio)), | 398 | i, j, |
318 | __raw_readl(GPIO_OE(gpio)), | 399 | __raw_readl(GPIO_CNF(gpio)), |
319 | __raw_readl(GPIO_OUT(gpio)), | 400 | __raw_readl(GPIO_OE(gpio)), |
320 | __raw_readl(GPIO_IN(gpio)), | 401 | __raw_readl(GPIO_OUT(gpio)), |
321 | __raw_readl(GPIO_INT_STA(gpio)), | 402 | __raw_readl(GPIO_IN(gpio)), |
322 | __raw_readl(GPIO_INT_ENB(gpio)), | 403 | __raw_readl(GPIO_INT_STA(gpio)), |
323 | __raw_readl(GPIO_INT_LVL(gpio))); | 404 | __raw_readl(GPIO_INT_ENB(gpio)), |
405 | __raw_readl(GPIO_INT_LVL(gpio))); | ||
324 | } | 406 | } |
325 | } | 407 | } |
326 | return 0; | 408 | return 0; |
diff --git a/arch/arm/mach-tegra/include/mach/clk.h b/arch/arm/mach-tegra/include/mach/clk.h index 2896f25ebfb5..d7723955dac7 100644 --- a/arch/arm/mach-tegra/include/mach/clk.h +++ b/arch/arm/mach-tegra/include/mach/clk.h | |||
@@ -23,4 +23,9 @@ | |||
23 | void tegra_periph_reset_deassert(struct clk *c); | 23 | void tegra_periph_reset_deassert(struct clk *c); |
24 | void tegra_periph_reset_assert(struct clk *c); | 24 | void tegra_periph_reset_assert(struct clk *c); |
25 | 25 | ||
26 | int clk_enable_cansleep(struct clk *clk); | ||
27 | void clk_disable_cansleep(struct clk *clk); | ||
28 | int clk_set_rate_cansleep(struct clk *clk, unsigned long rate); | ||
29 | int clk_set_parent_cansleep(struct clk *clk, struct clk *parent); | ||
30 | |||
26 | #endif | 31 | #endif |
diff --git a/arch/arm/mach-tegra/include/mach/dma.h b/arch/arm/mach-tegra/include/mach/dma.h new file mode 100644 index 000000000000..39011bd9a925 --- /dev/null +++ b/arch/arm/mach-tegra/include/mach/dma.h | |||
@@ -0,0 +1,155 @@ | |||
1 | /* | ||
2 | * arch/arm/mach-tegra/include/mach/dma.h | ||
3 | * | ||
4 | * Copyright (c) 2008-2009, NVIDIA Corporation. | ||
5 | * | ||
6 | * 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 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
14 | * more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License along | ||
17 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
19 | */ | ||
20 | |||
21 | #ifndef __MACH_TEGRA_DMA_H | ||
22 | #define __MACH_TEGRA_DMA_H | ||
23 | |||
24 | #include <linux/list.h> | ||
25 | |||
26 | #if defined(CONFIG_TEGRA_SYSTEM_DMA) | ||
27 | |||
28 | struct tegra_dma_req; | ||
29 | struct tegra_dma_channel; | ||
30 | |||
31 | #define TEGRA_DMA_REQ_SEL_CNTR 0 | ||
32 | #define TEGRA_DMA_REQ_SEL_I2S_2 1 | ||
33 | #define TEGRA_DMA_REQ_SEL_I2S_1 2 | ||
34 | #define TEGRA_DMA_REQ_SEL_SPD_I 3 | ||
35 | #define TEGRA_DMA_REQ_SEL_UI_I 4 | ||
36 | #define TEGRA_DMA_REQ_SEL_MIPI 5 | ||
37 | #define TEGRA_DMA_REQ_SEL_I2S2_2 6 | ||
38 | #define TEGRA_DMA_REQ_SEL_I2S2_1 7 | ||
39 | #define TEGRA_DMA_REQ_SEL_UARTA 8 | ||
40 | #define TEGRA_DMA_REQ_SEL_UARTB 9 | ||
41 | #define TEGRA_DMA_REQ_SEL_UARTC 10 | ||
42 | #define TEGRA_DMA_REQ_SEL_SPI 11 | ||
43 | #define TEGRA_DMA_REQ_SEL_AC97 12 | ||
44 | #define TEGRA_DMA_REQ_SEL_ACMODEM 13 | ||
45 | #define TEGRA_DMA_REQ_SEL_SL4B 14 | ||
46 | #define TEGRA_DMA_REQ_SEL_SL2B1 15 | ||
47 | #define TEGRA_DMA_REQ_SEL_SL2B2 16 | ||
48 | #define TEGRA_DMA_REQ_SEL_SL2B3 17 | ||
49 | #define TEGRA_DMA_REQ_SEL_SL2B4 18 | ||
50 | #define TEGRA_DMA_REQ_SEL_UARTD 19 | ||
51 | #define TEGRA_DMA_REQ_SEL_UARTE 20 | ||
52 | #define TEGRA_DMA_REQ_SEL_I2C 21 | ||
53 | #define TEGRA_DMA_REQ_SEL_I2C2 22 | ||
54 | #define TEGRA_DMA_REQ_SEL_I2C3 23 | ||
55 | #define TEGRA_DMA_REQ_SEL_DVC_I2C 24 | ||
56 | #define TEGRA_DMA_REQ_SEL_OWR 25 | ||
57 | #define TEGRA_DMA_REQ_SEL_INVALID 31 | ||
58 | |||
59 | enum tegra_dma_mode { | ||
60 | TEGRA_DMA_SHARED = 1, | ||
61 | TEGRA_DMA_MODE_CONTINOUS = 2, | ||
62 | TEGRA_DMA_MODE_ONESHOT = 4, | ||
63 | }; | ||
64 | |||
65 | enum tegra_dma_req_error { | ||
66 | TEGRA_DMA_REQ_SUCCESS = 0, | ||
67 | TEGRA_DMA_REQ_ERROR_ABORTED, | ||
68 | TEGRA_DMA_REQ_INFLIGHT, | ||
69 | }; | ||
70 | |||
71 | enum tegra_dma_req_buff_status { | ||
72 | TEGRA_DMA_REQ_BUF_STATUS_EMPTY = 0, | ||
73 | TEGRA_DMA_REQ_BUF_STATUS_HALF_FULL, | ||
74 | TEGRA_DMA_REQ_BUF_STATUS_FULL, | ||
75 | }; | ||
76 | |||
77 | struct tegra_dma_req { | ||
78 | struct list_head node; | ||
79 | unsigned int modid; | ||
80 | int instance; | ||
81 | |||
82 | /* Called when the req is complete and from the DMA ISR context. | ||
83 | * When this is called the req structure is no longer queued by | ||
84 | * the DMA channel. | ||
85 | * | ||
86 | * State of the DMA depends on the number of req it has. If there are | ||
87 | * no DMA requests queued up, then it will STOP the DMA. It there are | ||
88 | * more requests in the DMA, then it will queue the next request. | ||
89 | */ | ||
90 | void (*complete)(struct tegra_dma_req *req); | ||
91 | |||
92 | /* This is a called from the DMA ISR context when the DMA is still in | ||
93 | * progress and is actively filling same buffer. | ||
94 | * | ||
95 | * In case of continous mode receive, this threshold is 1/2 the buffer | ||
96 | * size. In other cases, this will not even be called as there is no | ||
97 | * hardware support for it. | ||
98 | * | ||
99 | * In the case of continous mode receive, if there is next req already | ||
100 | * queued, DMA programs the HW to use that req when this req is | ||
101 | * completed. If there is no "next req" queued, then DMA ISR doesn't do | ||
102 | * anything before calling this callback. | ||
103 | * | ||
104 | * This is mainly used by the cases, where the clients has queued | ||
105 | * only one req and want to get some sort of DMA threshold | ||
106 | * callback to program the next buffer. | ||
107 | * | ||
108 | */ | ||
109 | void (*threshold)(struct tegra_dma_req *req); | ||
110 | |||
111 | /* 1 to copy to memory. | ||
112 | * 0 to copy from the memory to device FIFO */ | ||
113 | int to_memory; | ||
114 | |||
115 | void *virt_addr; | ||
116 | |||
117 | unsigned long source_addr; | ||
118 | unsigned long dest_addr; | ||
119 | unsigned long dest_wrap; | ||
120 | unsigned long source_wrap; | ||
121 | unsigned long source_bus_width; | ||
122 | unsigned long dest_bus_width; | ||
123 | unsigned long req_sel; | ||
124 | unsigned int size; | ||
125 | |||
126 | /* Updated by the DMA driver on the conpletion of the request. */ | ||
127 | int bytes_transferred; | ||
128 | int status; | ||
129 | |||
130 | /* DMA completion tracking information */ | ||
131 | int buffer_status; | ||
132 | |||
133 | /* Client specific data */ | ||
134 | void *dev; | ||
135 | }; | ||
136 | |||
137 | int tegra_dma_enqueue_req(struct tegra_dma_channel *ch, | ||
138 | struct tegra_dma_req *req); | ||
139 | int tegra_dma_dequeue_req(struct tegra_dma_channel *ch, | ||
140 | struct tegra_dma_req *req); | ||
141 | void tegra_dma_dequeue(struct tegra_dma_channel *ch); | ||
142 | void tegra_dma_flush(struct tegra_dma_channel *ch); | ||
143 | |||
144 | bool tegra_dma_is_req_inflight(struct tegra_dma_channel *ch, | ||
145 | struct tegra_dma_req *req); | ||
146 | bool tegra_dma_is_empty(struct tegra_dma_channel *ch); | ||
147 | |||
148 | struct tegra_dma_channel *tegra_dma_allocate_channel(int mode); | ||
149 | void tegra_dma_free_channel(struct tegra_dma_channel *ch); | ||
150 | |||
151 | int __init tegra_dma_init(void); | ||
152 | |||
153 | #endif | ||
154 | |||
155 | #endif | ||
diff --git a/arch/arm/mach-tegra/include/mach/gpio.h b/arch/arm/mach-tegra/include/mach/gpio.h index 540e822e50f7..e31f486d69a2 100644 --- a/arch/arm/mach-tegra/include/mach/gpio.h +++ b/arch/arm/mach-tegra/include/mach/gpio.h | |||
@@ -22,7 +22,7 @@ | |||
22 | 22 | ||
23 | #include <mach/irqs.h> | 23 | #include <mach/irqs.h> |
24 | 24 | ||
25 | #define ARCH_NR_GPIOS INT_GPIO_NR | 25 | #define TEGRA_NR_GPIOS INT_GPIO_NR |
26 | 26 | ||
27 | #include <asm-generic/gpio.h> | 27 | #include <asm-generic/gpio.h> |
28 | 28 | ||
@@ -35,7 +35,7 @@ | |||
35 | 35 | ||
36 | static inline int gpio_to_irq(unsigned int gpio) | 36 | static inline int gpio_to_irq(unsigned int gpio) |
37 | { | 37 | { |
38 | if (gpio < ARCH_NR_GPIOS) | 38 | if (gpio < TEGRA_NR_GPIOS) |
39 | return INT_GPIO_BASE + gpio; | 39 | return INT_GPIO_BASE + gpio; |
40 | return -EINVAL; | 40 | return -EINVAL; |
41 | } | 41 | } |
diff --git a/arch/arm/mach-tegra/include/mach/hardware.h b/arch/arm/mach-tegra/include/mach/hardware.h index 6014edf60d93..56e43b3a5b97 100644 --- a/arch/arm/mach-tegra/include/mach/hardware.h +++ b/arch/arm/mach-tegra/include/mach/hardware.h | |||
@@ -21,4 +21,8 @@ | |||
21 | #ifndef __MACH_TEGRA_HARDWARE_H | 21 | #ifndef __MACH_TEGRA_HARDWARE_H |
22 | #define __MACH_TEGRA_HARDWARE_H | 22 | #define __MACH_TEGRA_HARDWARE_H |
23 | 23 | ||
24 | #define PCIBIOS_MIN_IO 0x1000 | ||
25 | #define PCIBIOS_MIN_MEM 0 | ||
26 | #define pcibios_assign_all_busses() 1 | ||
27 | |||
24 | #endif | 28 | #endif |
diff --git a/arch/arm/mach-tegra/include/mach/io.h b/arch/arm/mach-tegra/include/mach/io.h index 35edfc32ffc9..f0981b1ac59e 100644 --- a/arch/arm/mach-tegra/include/mach/io.h +++ b/arch/arm/mach-tegra/include/mach/io.h | |||
@@ -21,7 +21,7 @@ | |||
21 | #ifndef __MACH_TEGRA_IO_H | 21 | #ifndef __MACH_TEGRA_IO_H |
22 | #define __MACH_TEGRA_IO_H | 22 | #define __MACH_TEGRA_IO_H |
23 | 23 | ||
24 | #define IO_SPACE_LIMIT 0xffffffff | 24 | #define IO_SPACE_LIMIT 0xffff |
25 | 25 | ||
26 | /* On TEGRA, many peripherals are very closely packed in | 26 | /* On TEGRA, many peripherals are very closely packed in |
27 | * two 256MB io windows (that actually only use about 64KB | 27 | * two 256MB io windows (that actually only use about 64KB |
@@ -33,6 +33,10 @@ | |||
33 | * | 33 | * |
34 | */ | 34 | */ |
35 | 35 | ||
36 | #define IO_IRAM_PHYS 0x40000000 | ||
37 | #define IO_IRAM_VIRT 0xFE400000 | ||
38 | #define IO_IRAM_SIZE SZ_256K | ||
39 | |||
36 | #define IO_CPU_PHYS 0x50040000 | 40 | #define IO_CPU_PHYS 0x50040000 |
37 | #define IO_CPU_VIRT 0xFE000000 | 41 | #define IO_CPU_VIRT 0xFE000000 |
38 | #define IO_CPU_SIZE SZ_16K | 42 | #define IO_CPU_SIZE SZ_16K |
@@ -55,6 +59,8 @@ | |||
55 | IO_TO_VIRT_XLATE((n), IO_APB_PHYS, IO_APB_VIRT) : \ | 59 | IO_TO_VIRT_XLATE((n), IO_APB_PHYS, IO_APB_VIRT) : \ |
56 | IO_TO_VIRT_BETWEEN((n), IO_CPU_PHYS, IO_CPU_SIZE) ? \ | 60 | IO_TO_VIRT_BETWEEN((n), IO_CPU_PHYS, IO_CPU_SIZE) ? \ |
57 | IO_TO_VIRT_XLATE((n), IO_CPU_PHYS, IO_CPU_VIRT) : \ | 61 | IO_TO_VIRT_XLATE((n), IO_CPU_PHYS, IO_CPU_VIRT) : \ |
62 | IO_TO_VIRT_BETWEEN((n), IO_IRAM_PHYS, IO_IRAM_SIZE) ? \ | ||
63 | IO_TO_VIRT_XLATE((n), IO_IRAM_PHYS, IO_IRAM_VIRT) : \ | ||
58 | 0) | 64 | 0) |
59 | 65 | ||
60 | #ifndef __ASSEMBLER__ | 66 | #ifndef __ASSEMBLER__ |
@@ -67,10 +73,20 @@ void tegra_iounmap(volatile void __iomem *addr); | |||
67 | 73 | ||
68 | #define IO_ADDRESS(n) ((void __iomem *) IO_TO_VIRT(n)) | 74 | #define IO_ADDRESS(n) ((void __iomem *) IO_TO_VIRT(n)) |
69 | 75 | ||
76 | #ifdef CONFIG_TEGRA_PCI | ||
77 | extern void __iomem *tegra_pcie_io_base; | ||
78 | |||
79 | static inline void __iomem *__io(unsigned long addr) | ||
80 | { | ||
81 | return tegra_pcie_io_base + (addr & IO_SPACE_LIMIT); | ||
82 | } | ||
83 | #else | ||
70 | static inline void __iomem *__io(unsigned long addr) | 84 | static inline void __iomem *__io(unsigned long addr) |
71 | { | 85 | { |
72 | return (void __iomem *)addr; | 86 | return (void __iomem *)addr; |
73 | } | 87 | } |
88 | #endif | ||
89 | |||
74 | #define __io(a) __io(a) | 90 | #define __io(a) __io(a) |
75 | #define __mem_pci(a) (a) | 91 | #define __mem_pci(a) (a) |
76 | 92 | ||
diff --git a/arch/arm/mach-tegra/include/mach/iomap.h b/arch/arm/mach-tegra/include/mach/iomap.h index 1741f7dd7a9b..44a4f4bcf91f 100644 --- a/arch/arm/mach-tegra/include/mach/iomap.h +++ b/arch/arm/mach-tegra/include/mach/iomap.h | |||
@@ -23,9 +23,15 @@ | |||
23 | 23 | ||
24 | #include <asm/sizes.h> | 24 | #include <asm/sizes.h> |
25 | 25 | ||
26 | #define TEGRA_IRAM_BASE 0x40000000 | ||
27 | #define TEGRA_IRAM_SIZE SZ_256K | ||
28 | |||
26 | #define TEGRA_ARM_PERIF_BASE 0x50040000 | 29 | #define TEGRA_ARM_PERIF_BASE 0x50040000 |
27 | #define TEGRA_ARM_PERIF_SIZE SZ_8K | 30 | #define TEGRA_ARM_PERIF_SIZE SZ_8K |
28 | 31 | ||
32 | #define TEGRA_ARM_PL310_BASE 0x50043000 | ||
33 | #define TEGRA_ARM_PL310_SIZE SZ_4K | ||
34 | |||
29 | #define TEGRA_ARM_INT_DIST_BASE 0x50041000 | 35 | #define TEGRA_ARM_INT_DIST_BASE 0x50041000 |
30 | #define TEGRA_ARM_INT_DIST_SIZE SZ_4K | 36 | #define TEGRA_ARM_INT_DIST_SIZE SZ_4K |
31 | 37 | ||
@@ -68,7 +74,22 @@ | |||
68 | #define TEGRA_FLOW_CTRL_BASE 0x60007000 | 74 | #define TEGRA_FLOW_CTRL_BASE 0x60007000 |
69 | #define TEGRA_FLOW_CTRL_SIZE 20 | 75 | #define TEGRA_FLOW_CTRL_SIZE 20 |
70 | 76 | ||
71 | #define TEGRA_STATMON_BASE 0x6000C4000 | 77 | #define TEGRA_AHB_DMA_BASE 0x60008000 |
78 | #define TEGRA_AHB_DMA_SIZE SZ_4K | ||
79 | |||
80 | #define TEGRA_AHB_DMA_CH0_BASE 0x60009000 | ||
81 | #define TEGRA_AHB_DMA_CH0_SIZE 32 | ||
82 | |||
83 | #define TEGRA_APB_DMA_BASE 0x6000A000 | ||
84 | #define TEGRA_APB_DMA_SIZE SZ_4K | ||
85 | |||
86 | #define TEGRA_APB_DMA_CH0_BASE 0x6000B000 | ||
87 | #define TEGRA_APB_DMA_CH0_SIZE 32 | ||
88 | |||
89 | #define TEGRA_AHB_GIZMO_BASE 0x6000C004 | ||
90 | #define TEGRA_AHB_GIZMO_SIZE 0x10C | ||
91 | |||
92 | #define TEGRA_STATMON_BASE 0x6000C400 | ||
72 | #define TEGRA_STATMON_SIZE SZ_1K | 93 | #define TEGRA_STATMON_SIZE SZ_1K |
73 | 94 | ||
74 | #define TEGRA_GPIO_BASE 0x6000D000 | 95 | #define TEGRA_GPIO_BASE 0x6000D000 |
@@ -137,7 +158,7 @@ | |||
137 | #define TEGRA_I2C3_BASE 0x7000C500 | 158 | #define TEGRA_I2C3_BASE 0x7000C500 |
138 | #define TEGRA_I2C3_SIZE SZ_256 | 159 | #define TEGRA_I2C3_SIZE SZ_256 |
139 | 160 | ||
140 | #define TEGRA_OWR_BASE 0x7000D000 | 161 | #define TEGRA_OWR_BASE 0x7000C600 |
141 | #define TEGRA_OWR_SIZE 80 | 162 | #define TEGRA_OWR_SIZE 80 |
142 | 163 | ||
143 | #define TEGRA_DVC_BASE 0x7000D000 | 164 | #define TEGRA_DVC_BASE 0x7000D000 |
@@ -182,12 +203,12 @@ | |||
182 | #define TEGRA_USB_BASE 0xC5000000 | 203 | #define TEGRA_USB_BASE 0xC5000000 |
183 | #define TEGRA_USB_SIZE SZ_16K | 204 | #define TEGRA_USB_SIZE SZ_16K |
184 | 205 | ||
185 | #define TEGRA_USB1_BASE 0xC5004000 | 206 | #define TEGRA_USB2_BASE 0xC5004000 |
186 | #define TEGRA_USB1_SIZE SZ_16K | ||
187 | |||
188 | #define TEGRA_USB2_BASE 0xC5008000 | ||
189 | #define TEGRA_USB2_SIZE SZ_16K | 207 | #define TEGRA_USB2_SIZE SZ_16K |
190 | 208 | ||
209 | #define TEGRA_USB3_BASE 0xC5008000 | ||
210 | #define TEGRA_USB3_SIZE SZ_16K | ||
211 | |||
191 | #define TEGRA_SDMMC1_BASE 0xC8000000 | 212 | #define TEGRA_SDMMC1_BASE 0xC8000000 |
192 | #define TEGRA_SDMMC1_SIZE SZ_512 | 213 | #define TEGRA_SDMMC1_SIZE SZ_512 |
193 | 214 | ||
diff --git a/arch/arm/mach-tegra/include/mach/irqs.h b/arch/arm/mach-tegra/include/mach/irqs.h index 20f640edaa0d..71bbf3422953 100644 --- a/arch/arm/mach-tegra/include/mach/irqs.h +++ b/arch/arm/mach-tegra/include/mach/irqs.h | |||
@@ -25,6 +25,7 @@ | |||
25 | 25 | ||
26 | #define IRQ_LOCALTIMER 29 | 26 | #define IRQ_LOCALTIMER 29 |
27 | 27 | ||
28 | #ifdef CONFIG_ARCH_TEGRA_2x_SOC | ||
28 | /* Primary Interrupt Controller */ | 29 | /* Primary Interrupt Controller */ |
29 | #define INT_PRI_BASE (INT_GIC_BASE + 32) | 30 | #define INT_PRI_BASE (INT_GIC_BASE + 32) |
30 | #define INT_TMR1 (INT_PRI_BASE + 0) | 31 | #define INT_TMR1 (INT_PRI_BASE + 0) |
@@ -169,5 +170,6 @@ | |||
169 | #define INT_GPIO_NR (28 * 8) | 170 | #define INT_GPIO_NR (28 * 8) |
170 | 171 | ||
171 | #define NR_IRQS (INT_GPIO_BASE + INT_GPIO_NR) | 172 | #define NR_IRQS (INT_GPIO_BASE + INT_GPIO_NR) |
173 | #endif | ||
172 | 174 | ||
173 | #endif | 175 | #endif |
diff --git a/arch/arm/mach-tegra/include/mach/legacy_irq.h b/arch/arm/mach-tegra/include/mach/legacy_irq.h new file mode 100644 index 000000000000..db1eb3dd04c8 --- /dev/null +++ b/arch/arm/mach-tegra/include/mach/legacy_irq.h | |||
@@ -0,0 +1,31 @@ | |||
1 | /* | ||
2 | * arch/arm/mach-tegra/include/mach/legacy_irq.h | ||
3 | * | ||
4 | * Copyright (C) 2010 Google, Inc. | ||
5 | * Author: Colin Cross <ccross@android.com> | ||
6 | * | ||
7 | * This software is licensed under the terms of the GNU General Public | ||
8 | * License version 2, as published by the Free Software Foundation, and | ||
9 | * may be copied, distributed, and modified under those terms. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | */ | ||
17 | |||
18 | #ifndef _ARCH_ARM_MACH_TEGRA_LEGARY_IRQ_H | ||
19 | #define _ARCH_ARM_MACH_TEGRA_LEGARY_IRQ_H | ||
20 | |||
21 | void tegra_legacy_mask_irq(unsigned int irq); | ||
22 | void tegra_legacy_unmask_irq(unsigned int irq); | ||
23 | void tegra_legacy_select_fiq(unsigned int irq, bool fiq); | ||
24 | void tegra_legacy_force_irq_set(unsigned int irq); | ||
25 | void tegra_legacy_force_irq_clr(unsigned int irq); | ||
26 | int tegra_legacy_force_irq_status(unsigned int irq); | ||
27 | void tegra_legacy_select_fiq(unsigned int irq, bool fiq); | ||
28 | unsigned long tegra_legacy_vfiq(int nr); | ||
29 | unsigned long tegra_legacy_class(int nr); | ||
30 | |||
31 | #endif | ||
diff --git a/arch/arm/mach-tegra/include/mach/pinmux-t2.h b/arch/arm/mach-tegra/include/mach/pinmux-t2.h new file mode 100644 index 000000000000..e5b9d740f973 --- /dev/null +++ b/arch/arm/mach-tegra/include/mach/pinmux-t2.h | |||
@@ -0,0 +1,174 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/mach-tegra/include/mach/pinmux-t2.h | ||
3 | * | ||
4 | * Copyright (C) 2010 Google, Inc. | ||
5 | * | ||
6 | * This software is licensed under the terms of the GNU General Public | ||
7 | * License version 2, as published by the Free Software Foundation, and | ||
8 | * may be copied, distributed, and modified under those terms. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | */ | ||
16 | |||
17 | #ifndef __MACH_TEGRA_PINMUX_T2_H | ||
18 | #define __MACH_TEGRA_PINMUX_T2_H | ||
19 | |||
20 | enum tegra_pingroup { | ||
21 | TEGRA_PINGROUP_ATA = 0, | ||
22 | TEGRA_PINGROUP_ATB, | ||
23 | TEGRA_PINGROUP_ATC, | ||
24 | TEGRA_PINGROUP_ATD, | ||
25 | TEGRA_PINGROUP_ATE, | ||
26 | TEGRA_PINGROUP_CDEV1, | ||
27 | TEGRA_PINGROUP_CDEV2, | ||
28 | TEGRA_PINGROUP_CRTP, | ||
29 | TEGRA_PINGROUP_CSUS, | ||
30 | TEGRA_PINGROUP_DAP1, | ||
31 | TEGRA_PINGROUP_DAP2, | ||
32 | TEGRA_PINGROUP_DAP3, | ||
33 | TEGRA_PINGROUP_DAP4, | ||
34 | TEGRA_PINGROUP_DDC, | ||
35 | TEGRA_PINGROUP_DTA, | ||
36 | TEGRA_PINGROUP_DTB, | ||
37 | TEGRA_PINGROUP_DTC, | ||
38 | TEGRA_PINGROUP_DTD, | ||
39 | TEGRA_PINGROUP_DTE, | ||
40 | TEGRA_PINGROUP_DTF, | ||
41 | TEGRA_PINGROUP_GMA, | ||
42 | TEGRA_PINGROUP_GMB, | ||
43 | TEGRA_PINGROUP_GMC, | ||
44 | TEGRA_PINGROUP_GMD, | ||
45 | TEGRA_PINGROUP_GME, | ||
46 | TEGRA_PINGROUP_GPU, | ||
47 | TEGRA_PINGROUP_GPU7, | ||
48 | TEGRA_PINGROUP_GPV, | ||
49 | TEGRA_PINGROUP_HDINT, | ||
50 | TEGRA_PINGROUP_I2CP, | ||
51 | TEGRA_PINGROUP_IRRX, | ||
52 | TEGRA_PINGROUP_IRTX, | ||
53 | TEGRA_PINGROUP_KBCA, | ||
54 | TEGRA_PINGROUP_KBCB, | ||
55 | TEGRA_PINGROUP_KBCC, | ||
56 | TEGRA_PINGROUP_KBCD, | ||
57 | TEGRA_PINGROUP_KBCE, | ||
58 | TEGRA_PINGROUP_KBCF, | ||
59 | TEGRA_PINGROUP_LCSN, | ||
60 | TEGRA_PINGROUP_LD0, | ||
61 | TEGRA_PINGROUP_LD1, | ||
62 | TEGRA_PINGROUP_LD10, | ||
63 | TEGRA_PINGROUP_LD11, | ||
64 | TEGRA_PINGROUP_LD12, | ||
65 | TEGRA_PINGROUP_LD13, | ||
66 | TEGRA_PINGROUP_LD14, | ||
67 | TEGRA_PINGROUP_LD15, | ||
68 | TEGRA_PINGROUP_LD16, | ||
69 | TEGRA_PINGROUP_LD17, | ||
70 | TEGRA_PINGROUP_LD2, | ||
71 | TEGRA_PINGROUP_LD3, | ||
72 | TEGRA_PINGROUP_LD4, | ||
73 | TEGRA_PINGROUP_LD5, | ||
74 | TEGRA_PINGROUP_LD6, | ||
75 | TEGRA_PINGROUP_LD7, | ||
76 | TEGRA_PINGROUP_LD8, | ||
77 | TEGRA_PINGROUP_LD9, | ||
78 | TEGRA_PINGROUP_LDC, | ||
79 | TEGRA_PINGROUP_LDI, | ||
80 | TEGRA_PINGROUP_LHP0, | ||
81 | TEGRA_PINGROUP_LHP1, | ||
82 | TEGRA_PINGROUP_LHP2, | ||
83 | TEGRA_PINGROUP_LHS, | ||
84 | TEGRA_PINGROUP_LM0, | ||
85 | TEGRA_PINGROUP_LM1, | ||
86 | TEGRA_PINGROUP_LPP, | ||
87 | TEGRA_PINGROUP_LPW0, | ||
88 | TEGRA_PINGROUP_LPW1, | ||
89 | TEGRA_PINGROUP_LPW2, | ||
90 | TEGRA_PINGROUP_LSC0, | ||
91 | TEGRA_PINGROUP_LSC1, | ||
92 | TEGRA_PINGROUP_LSCK, | ||
93 | TEGRA_PINGROUP_LSDA, | ||
94 | TEGRA_PINGROUP_LSDI, | ||
95 | TEGRA_PINGROUP_LSPI, | ||
96 | TEGRA_PINGROUP_LVP0, | ||
97 | TEGRA_PINGROUP_LVP1, | ||
98 | TEGRA_PINGROUP_LVS, | ||
99 | TEGRA_PINGROUP_OWC, | ||
100 | TEGRA_PINGROUP_PMC, | ||
101 | TEGRA_PINGROUP_PTA, | ||
102 | TEGRA_PINGROUP_RM, | ||
103 | TEGRA_PINGROUP_SDB, | ||
104 | TEGRA_PINGROUP_SDC, | ||
105 | TEGRA_PINGROUP_SDD, | ||
106 | TEGRA_PINGROUP_SDIO1, | ||
107 | TEGRA_PINGROUP_SLXA, | ||
108 | TEGRA_PINGROUP_SLXC, | ||
109 | TEGRA_PINGROUP_SLXD, | ||
110 | TEGRA_PINGROUP_SLXK, | ||
111 | TEGRA_PINGROUP_SPDI, | ||
112 | TEGRA_PINGROUP_SPDO, | ||
113 | TEGRA_PINGROUP_SPIA, | ||
114 | TEGRA_PINGROUP_SPIB, | ||
115 | TEGRA_PINGROUP_SPIC, | ||
116 | TEGRA_PINGROUP_SPID, | ||
117 | TEGRA_PINGROUP_SPIE, | ||
118 | TEGRA_PINGROUP_SPIF, | ||
119 | TEGRA_PINGROUP_SPIG, | ||
120 | TEGRA_PINGROUP_SPIH, | ||
121 | TEGRA_PINGROUP_UAA, | ||
122 | TEGRA_PINGROUP_UAB, | ||
123 | TEGRA_PINGROUP_UAC, | ||
124 | TEGRA_PINGROUP_UAD, | ||
125 | TEGRA_PINGROUP_UCA, | ||
126 | TEGRA_PINGROUP_UCB, | ||
127 | TEGRA_PINGROUP_UDA, | ||
128 | /* these pin groups only have pullup and pull down control */ | ||
129 | TEGRA_PINGROUP_CK32, | ||
130 | TEGRA_PINGROUP_DDRC, | ||
131 | TEGRA_PINGROUP_PMCA, | ||
132 | TEGRA_PINGROUP_PMCB, | ||
133 | TEGRA_PINGROUP_PMCC, | ||
134 | TEGRA_PINGROUP_PMCD, | ||
135 | TEGRA_PINGROUP_PMCE, | ||
136 | TEGRA_PINGROUP_XM2C, | ||
137 | TEGRA_PINGROUP_XM2D, | ||
138 | TEGRA_MAX_PINGROUP, | ||
139 | }; | ||
140 | |||
141 | enum tegra_drive_pingroup { | ||
142 | TEGRA_DRIVE_PINGROUP_AO1 = 0, | ||
143 | TEGRA_DRIVE_PINGROUP_AO2, | ||
144 | TEGRA_DRIVE_PINGROUP_AT1, | ||
145 | TEGRA_DRIVE_PINGROUP_AT2, | ||
146 | TEGRA_DRIVE_PINGROUP_CDEV1, | ||
147 | TEGRA_DRIVE_PINGROUP_CDEV2, | ||
148 | TEGRA_DRIVE_PINGROUP_CSUS, | ||
149 | TEGRA_DRIVE_PINGROUP_DAP1, | ||
150 | TEGRA_DRIVE_PINGROUP_DAP2, | ||
151 | TEGRA_DRIVE_PINGROUP_DAP3, | ||
152 | TEGRA_DRIVE_PINGROUP_DAP4, | ||
153 | TEGRA_DRIVE_PINGROUP_DBG, | ||
154 | TEGRA_DRIVE_PINGROUP_LCD1, | ||
155 | TEGRA_DRIVE_PINGROUP_LCD2, | ||
156 | TEGRA_DRIVE_PINGROUP_SDMMC2, | ||
157 | TEGRA_DRIVE_PINGROUP_SDMMC3, | ||
158 | TEGRA_DRIVE_PINGROUP_SPI, | ||
159 | TEGRA_DRIVE_PINGROUP_UAA, | ||
160 | TEGRA_DRIVE_PINGROUP_UAB, | ||
161 | TEGRA_DRIVE_PINGROUP_UART2, | ||
162 | TEGRA_DRIVE_PINGROUP_UART3, | ||
163 | TEGRA_DRIVE_PINGROUP_VI1, | ||
164 | TEGRA_DRIVE_PINGROUP_VI2, | ||
165 | TEGRA_DRIVE_PINGROUP_XM2A, | ||
166 | TEGRA_DRIVE_PINGROUP_XM2C, | ||
167 | TEGRA_DRIVE_PINGROUP_XM2D, | ||
168 | TEGRA_DRIVE_PINGROUP_XM2CLK, | ||
169 | TEGRA_DRIVE_PINGROUP_MEMCOMP, | ||
170 | TEGRA_MAX_DRIVE_PINGROUP, | ||
171 | }; | ||
172 | |||
173 | #endif | ||
174 | |||
diff --git a/arch/arm/mach-tegra/include/mach/pinmux.h b/arch/arm/mach-tegra/include/mach/pinmux.h index 41c8ce5b7c27..defd8775defa 100644 --- a/arch/arm/mach-tegra/include/mach/pinmux.h +++ b/arch/arm/mach-tegra/include/mach/pinmux.h | |||
@@ -17,126 +17,11 @@ | |||
17 | #ifndef __MACH_TEGRA_PINMUX_H | 17 | #ifndef __MACH_TEGRA_PINMUX_H |
18 | #define __MACH_TEGRA_PINMUX_H | 18 | #define __MACH_TEGRA_PINMUX_H |
19 | 19 | ||
20 | enum tegra_pingroup { | 20 | #if defined(CONFIG_ARCH_TEGRA_2x_SOC) |
21 | TEGRA_PINGROUP_ATA = 0, | 21 | #include "pinmux-t2.h" |
22 | TEGRA_PINGROUP_ATB, | 22 | #else |
23 | TEGRA_PINGROUP_ATC, | 23 | #error "Undefined Tegra architecture" |
24 | TEGRA_PINGROUP_ATD, | 24 | #endif |
25 | TEGRA_PINGROUP_ATE, | ||
26 | TEGRA_PINGROUP_CDEV1, | ||
27 | TEGRA_PINGROUP_CDEV2, | ||
28 | TEGRA_PINGROUP_CRTP, | ||
29 | TEGRA_PINGROUP_CSUS, | ||
30 | TEGRA_PINGROUP_DAP1, | ||
31 | TEGRA_PINGROUP_DAP2, | ||
32 | TEGRA_PINGROUP_DAP3, | ||
33 | TEGRA_PINGROUP_DAP4, | ||
34 | TEGRA_PINGROUP_DDC, | ||
35 | TEGRA_PINGROUP_DTA, | ||
36 | TEGRA_PINGROUP_DTB, | ||
37 | TEGRA_PINGROUP_DTC, | ||
38 | TEGRA_PINGROUP_DTD, | ||
39 | TEGRA_PINGROUP_DTE, | ||
40 | TEGRA_PINGROUP_DTF, | ||
41 | TEGRA_PINGROUP_GMA, | ||
42 | TEGRA_PINGROUP_GMB, | ||
43 | TEGRA_PINGROUP_GMC, | ||
44 | TEGRA_PINGROUP_GMD, | ||
45 | TEGRA_PINGROUP_GME, | ||
46 | TEGRA_PINGROUP_GPU, | ||
47 | TEGRA_PINGROUP_GPU7, | ||
48 | TEGRA_PINGROUP_GPV, | ||
49 | TEGRA_PINGROUP_HDINT, | ||
50 | TEGRA_PINGROUP_I2CP, | ||
51 | TEGRA_PINGROUP_IRRX, | ||
52 | TEGRA_PINGROUP_IRTX, | ||
53 | TEGRA_PINGROUP_KBCA, | ||
54 | TEGRA_PINGROUP_KBCB, | ||
55 | TEGRA_PINGROUP_KBCC, | ||
56 | TEGRA_PINGROUP_KBCD, | ||
57 | TEGRA_PINGROUP_KBCE, | ||
58 | TEGRA_PINGROUP_KBCF, | ||
59 | TEGRA_PINGROUP_LCSN, | ||
60 | TEGRA_PINGROUP_LD0, | ||
61 | TEGRA_PINGROUP_LD1, | ||
62 | TEGRA_PINGROUP_LD10, | ||
63 | TEGRA_PINGROUP_LD11, | ||
64 | TEGRA_PINGROUP_LD12, | ||
65 | TEGRA_PINGROUP_LD13, | ||
66 | TEGRA_PINGROUP_LD14, | ||
67 | TEGRA_PINGROUP_LD15, | ||
68 | TEGRA_PINGROUP_LD16, | ||
69 | TEGRA_PINGROUP_LD17, | ||
70 | TEGRA_PINGROUP_LD2, | ||
71 | TEGRA_PINGROUP_LD3, | ||
72 | TEGRA_PINGROUP_LD4, | ||
73 | TEGRA_PINGROUP_LD5, | ||
74 | TEGRA_PINGROUP_LD6, | ||
75 | TEGRA_PINGROUP_LD7, | ||
76 | TEGRA_PINGROUP_LD8, | ||
77 | TEGRA_PINGROUP_LD9, | ||
78 | TEGRA_PINGROUP_LDC, | ||
79 | TEGRA_PINGROUP_LDI, | ||
80 | TEGRA_PINGROUP_LHP0, | ||
81 | TEGRA_PINGROUP_LHP1, | ||
82 | TEGRA_PINGROUP_LHP2, | ||
83 | TEGRA_PINGROUP_LHS, | ||
84 | TEGRA_PINGROUP_LM0, | ||
85 | TEGRA_PINGROUP_LM1, | ||
86 | TEGRA_PINGROUP_LPP, | ||
87 | TEGRA_PINGROUP_LPW0, | ||
88 | TEGRA_PINGROUP_LPW1, | ||
89 | TEGRA_PINGROUP_LPW2, | ||
90 | TEGRA_PINGROUP_LSC0, | ||
91 | TEGRA_PINGROUP_LSC1, | ||
92 | TEGRA_PINGROUP_LSCK, | ||
93 | TEGRA_PINGROUP_LSDA, | ||
94 | TEGRA_PINGROUP_LSDI, | ||
95 | TEGRA_PINGROUP_LSPI, | ||
96 | TEGRA_PINGROUP_LVP0, | ||
97 | TEGRA_PINGROUP_LVP1, | ||
98 | TEGRA_PINGROUP_LVS, | ||
99 | TEGRA_PINGROUP_OWC, | ||
100 | TEGRA_PINGROUP_PMC, | ||
101 | TEGRA_PINGROUP_PTA, | ||
102 | TEGRA_PINGROUP_RM, | ||
103 | TEGRA_PINGROUP_SDB, | ||
104 | TEGRA_PINGROUP_SDC, | ||
105 | TEGRA_PINGROUP_SDD, | ||
106 | TEGRA_PINGROUP_SDIO1, | ||
107 | TEGRA_PINGROUP_SLXA, | ||
108 | TEGRA_PINGROUP_SLXC, | ||
109 | TEGRA_PINGROUP_SLXD, | ||
110 | TEGRA_PINGROUP_SLXK, | ||
111 | TEGRA_PINGROUP_SPDI, | ||
112 | TEGRA_PINGROUP_SPDO, | ||
113 | TEGRA_PINGROUP_SPIA, | ||
114 | TEGRA_PINGROUP_SPIB, | ||
115 | TEGRA_PINGROUP_SPIC, | ||
116 | TEGRA_PINGROUP_SPID, | ||
117 | TEGRA_PINGROUP_SPIE, | ||
118 | TEGRA_PINGROUP_SPIF, | ||
119 | TEGRA_PINGROUP_SPIG, | ||
120 | TEGRA_PINGROUP_SPIH, | ||
121 | TEGRA_PINGROUP_UAA, | ||
122 | TEGRA_PINGROUP_UAB, | ||
123 | TEGRA_PINGROUP_UAC, | ||
124 | TEGRA_PINGROUP_UAD, | ||
125 | TEGRA_PINGROUP_UCA, | ||
126 | TEGRA_PINGROUP_UCB, | ||
127 | TEGRA_PINGROUP_UDA, | ||
128 | /* these pin groups only have pullup and pull down control */ | ||
129 | TEGRA_PINGROUP_CK32, | ||
130 | TEGRA_PINGROUP_DDRC, | ||
131 | TEGRA_PINGROUP_PMCA, | ||
132 | TEGRA_PINGROUP_PMCB, | ||
133 | TEGRA_PINGROUP_PMCC, | ||
134 | TEGRA_PINGROUP_PMCD, | ||
135 | TEGRA_PINGROUP_PMCE, | ||
136 | TEGRA_PINGROUP_XM2C, | ||
137 | TEGRA_PINGROUP_XM2D, | ||
138 | TEGRA_MAX_PINGROUP, | ||
139 | }; | ||
140 | 25 | ||
141 | enum tegra_mux_func { | 26 | enum tegra_mux_func { |
142 | TEGRA_MUX_RSVD = 0x8000, | 27 | TEGRA_MUX_RSVD = 0x8000, |
@@ -205,6 +90,7 @@ enum tegra_mux_func { | |||
205 | TEGRA_MUX_VI, | 90 | TEGRA_MUX_VI, |
206 | TEGRA_MUX_VI_SENSOR_CLK, | 91 | TEGRA_MUX_VI_SENSOR_CLK, |
207 | TEGRA_MUX_XIO, | 92 | TEGRA_MUX_XIO, |
93 | TEGRA_MUX_SAFE, | ||
208 | TEGRA_MAX_MUX, | 94 | TEGRA_MAX_MUX, |
209 | }; | 95 | }; |
210 | 96 | ||
@@ -219,6 +105,18 @@ enum tegra_tristate { | |||
219 | TEGRA_TRI_TRISTATE = 1, | 105 | TEGRA_TRI_TRISTATE = 1, |
220 | }; | 106 | }; |
221 | 107 | ||
108 | enum tegra_vddio { | ||
109 | TEGRA_VDDIO_BB = 0, | ||
110 | TEGRA_VDDIO_LCD, | ||
111 | TEGRA_VDDIO_VI, | ||
112 | TEGRA_VDDIO_UART, | ||
113 | TEGRA_VDDIO_DDR, | ||
114 | TEGRA_VDDIO_NAND, | ||
115 | TEGRA_VDDIO_SYS, | ||
116 | TEGRA_VDDIO_AUDIO, | ||
117 | TEGRA_VDDIO_SD, | ||
118 | }; | ||
119 | |||
222 | struct tegra_pingroup_config { | 120 | struct tegra_pingroup_config { |
223 | enum tegra_pingroup pingroup; | 121 | enum tegra_pingroup pingroup; |
224 | enum tegra_mux_func func; | 122 | enum tegra_mux_func func; |
@@ -270,38 +168,6 @@ enum tegra_pull_strength { | |||
270 | TEGRA_MAX_PULL, | 168 | TEGRA_MAX_PULL, |
271 | }; | 169 | }; |
272 | 170 | ||
273 | enum tegra_drive_pingroup { | ||
274 | TEGRA_DRIVE_PINGROUP_AO1 = 0, | ||
275 | TEGRA_DRIVE_PINGROUP_AO2, | ||
276 | TEGRA_DRIVE_PINGROUP_AT1, | ||
277 | TEGRA_DRIVE_PINGROUP_AT2, | ||
278 | TEGRA_DRIVE_PINGROUP_CDEV1, | ||
279 | TEGRA_DRIVE_PINGROUP_CDEV2, | ||
280 | TEGRA_DRIVE_PINGROUP_CSUS, | ||
281 | TEGRA_DRIVE_PINGROUP_DAP1, | ||
282 | TEGRA_DRIVE_PINGROUP_DAP2, | ||
283 | TEGRA_DRIVE_PINGROUP_DAP3, | ||
284 | TEGRA_DRIVE_PINGROUP_DAP4, | ||
285 | TEGRA_DRIVE_PINGROUP_DBG, | ||
286 | TEGRA_DRIVE_PINGROUP_LCD1, | ||
287 | TEGRA_DRIVE_PINGROUP_LCD2, | ||
288 | TEGRA_DRIVE_PINGROUP_SDMMC2, | ||
289 | TEGRA_DRIVE_PINGROUP_SDMMC3, | ||
290 | TEGRA_DRIVE_PINGROUP_SPI, | ||
291 | TEGRA_DRIVE_PINGROUP_UAA, | ||
292 | TEGRA_DRIVE_PINGROUP_UAB, | ||
293 | TEGRA_DRIVE_PINGROUP_UART2, | ||
294 | TEGRA_DRIVE_PINGROUP_UART3, | ||
295 | TEGRA_DRIVE_PINGROUP_VI1, | ||
296 | TEGRA_DRIVE_PINGROUP_VI2, | ||
297 | TEGRA_DRIVE_PINGROUP_XM2A, | ||
298 | TEGRA_DRIVE_PINGROUP_XM2C, | ||
299 | TEGRA_DRIVE_PINGROUP_XM2D, | ||
300 | TEGRA_DRIVE_PINGROUP_XM2CLK, | ||
301 | TEGRA_DRIVE_PINGROUP_MEMCOMP, | ||
302 | TEGRA_MAX_DRIVE_PINGROUP, | ||
303 | }; | ||
304 | |||
305 | enum tegra_drive { | 171 | enum tegra_drive { |
306 | TEGRA_DRIVE_DIV_8 = 0, | 172 | TEGRA_DRIVE_DIV_8 = 0, |
307 | TEGRA_DRIVE_DIV_4, | 173 | TEGRA_DRIVE_DIV_4, |
@@ -331,18 +197,44 @@ struct tegra_drive_pingroup_config { | |||
331 | enum tegra_slew slew_falling; | 197 | enum tegra_slew slew_falling; |
332 | }; | 198 | }; |
333 | 199 | ||
334 | int tegra_pinmux_set_func(enum tegra_pingroup pg, enum tegra_mux_func func); | 200 | struct tegra_drive_pingroup_desc { |
335 | int tegra_pinmux_set_tristate(enum tegra_pingroup pg, enum tegra_tristate tristate); | 201 | const char *name; |
336 | int tegra_pinmux_set_pullupdown(enum tegra_pingroup pg, enum tegra_pullupdown pupd); | 202 | s16 reg; |
203 | }; | ||
204 | |||
205 | struct tegra_pingroup_desc { | ||
206 | const char *name; | ||
207 | int funcs[4]; | ||
208 | int func_safe; | ||
209 | int vddio; | ||
210 | s16 tri_reg; /* offset into the TRISTATE_REG_* register bank */ | ||
211 | s16 mux_reg; /* offset into the PIN_MUX_CTL_* register bank */ | ||
212 | s16 pupd_reg; /* offset into the PULL_UPDOWN_REG_* register bank */ | ||
213 | s8 tri_bit; /* offset into the TRISTATE_REG_* register bit */ | ||
214 | s8 mux_bit; /* offset into the PIN_MUX_CTL_* register bit */ | ||
215 | s8 pupd_bit; /* offset into the PULL_UPDOWN_REG_* register bit */ | ||
216 | }; | ||
217 | |||
218 | extern const struct tegra_pingroup_desc tegra_soc_pingroups[]; | ||
219 | extern const struct tegra_drive_pingroup_desc tegra_soc_drive_pingroups[]; | ||
337 | 220 | ||
338 | void tegra_pinmux_config_pingroup(enum tegra_pingroup pingroup, | 221 | int tegra_pinmux_set_tristate(enum tegra_pingroup pg, |
339 | enum tegra_mux_func func, enum tegra_pullupdown pupd, | ||
340 | enum tegra_tristate tristate); | 222 | enum tegra_tristate tristate); |
223 | int tegra_pinmux_set_pullupdown(enum tegra_pingroup pg, | ||
224 | enum tegra_pullupdown pupd); | ||
341 | 225 | ||
342 | void tegra_pinmux_config_table(struct tegra_pingroup_config *config, int len); | 226 | void tegra_pinmux_config_table(const struct tegra_pingroup_config *config, |
227 | int len); | ||
343 | 228 | ||
344 | void tegra_drive_pinmux_config_table(struct tegra_drive_pingroup_config *config, | 229 | void tegra_drive_pinmux_config_table(struct tegra_drive_pingroup_config *config, |
345 | int len); | 230 | int len); |
346 | 231 | void tegra_pinmux_set_safe_pinmux_table(const struct tegra_pingroup_config *config, | |
232 | int len); | ||
233 | void tegra_pinmux_config_pinmux_table(const struct tegra_pingroup_config *config, | ||
234 | int len); | ||
235 | void tegra_pinmux_config_tristate_table(const struct tegra_pingroup_config *config, | ||
236 | int len, enum tegra_tristate tristate); | ||
237 | void tegra_pinmux_config_pullupdown_table(const struct tegra_pingroup_config *config, | ||
238 | int len, enum tegra_pullupdown pupd); | ||
347 | #endif | 239 | #endif |
348 | 240 | ||
diff --git a/arch/arm/mach-tegra/io.c b/arch/arm/mach-tegra/io.c index 9fe2c5c683d4..31848a9592f8 100644 --- a/arch/arm/mach-tegra/io.c +++ b/arch/arm/mach-tegra/io.c | |||
@@ -49,6 +49,12 @@ static struct map_desc tegra_io_desc[] __initdata = { | |||
49 | .length = IO_CPU_SIZE, | 49 | .length = IO_CPU_SIZE, |
50 | .type = MT_DEVICE, | 50 | .type = MT_DEVICE, |
51 | }, | 51 | }, |
52 | { | ||
53 | .virtual = IO_IRAM_VIRT, | ||
54 | .pfn = __phys_to_pfn(IO_IRAM_PHYS), | ||
55 | .length = IO_IRAM_SIZE, | ||
56 | .type = MT_DEVICE, | ||
57 | }, | ||
52 | }; | 58 | }; |
53 | 59 | ||
54 | void __init tegra_map_common_io(void) | 60 | void __init tegra_map_common_io(void) |
diff --git a/arch/arm/mach-tegra/irq.c b/arch/arm/mach-tegra/irq.c index 1fdbe708d43d..50a8dfb9a0cf 100644 --- a/arch/arm/mach-tegra/irq.c +++ b/arch/arm/mach-tegra/irq.c | |||
@@ -4,6 +4,8 @@ | |||
4 | * Author: | 4 | * Author: |
5 | * Colin Cross <ccross@google.com> | 5 | * Colin Cross <ccross@google.com> |
6 | * | 6 | * |
7 | * Copyright (C) 2010, NVIDIA Corporation | ||
8 | * | ||
7 | * This software is licensed under the terms of the GNU General Public | 9 | * This software is licensed under the terms of the GNU General Public |
8 | * License version 2, as published by the Free Software Foundation, and | 10 | * License version 2, as published by the Free Software Foundation, and |
9 | * may be copied, distributed, and modified under those terms. | 11 | * may be copied, distributed, and modified under those terms. |
@@ -27,8 +29,143 @@ | |||
27 | 29 | ||
28 | #include "board.h" | 30 | #include "board.h" |
29 | 31 | ||
32 | #define INT_SYS_NR (INT_GPIO_BASE - INT_PRI_BASE) | ||
33 | #define INT_SYS_SZ (INT_SEC_BASE - INT_PRI_BASE) | ||
34 | #define PPI_NR ((INT_SYS_NR+INT_SYS_SZ-1)/INT_SYS_SZ) | ||
35 | |||
36 | #define APBDMA_IRQ_STA_CPU 0x14 | ||
37 | #define APBDMA_IRQ_MASK_SET 0x20 | ||
38 | #define APBDMA_IRQ_MASK_CLR 0x24 | ||
39 | |||
40 | #define ICTLR_CPU_IER 0x20 | ||
41 | #define ICTLR_CPU_IER_SET 0x24 | ||
42 | #define ICTLR_CPU_IER_CLR 0x28 | ||
43 | #define ICTLR_CPU_IEP_CLASS 0x2c | ||
44 | #define ICTLR_COP_IER 0x30 | ||
45 | #define ICTLR_COP_IER_SET 0x34 | ||
46 | #define ICTLR_COP_IER_CLR 0x38 | ||
47 | #define ICTLR_COP_IEP_CLASS 0x3c | ||
48 | |||
49 | static void (*gic_mask_irq)(unsigned int irq); | ||
50 | static void (*gic_unmask_irq)(unsigned int irq); | ||
51 | |||
52 | #define irq_to_ictlr(irq) (((irq)-32) >> 5) | ||
53 | static void __iomem *tegra_ictlr_base = IO_ADDRESS(TEGRA_PRIMARY_ICTLR_BASE); | ||
54 | #define ictlr_to_virt(ictlr) (tegra_ictlr_base + (ictlr)*0x100) | ||
55 | |||
56 | static void tegra_mask(unsigned int irq) | ||
57 | { | ||
58 | void __iomem *addr = ictlr_to_virt(irq_to_ictlr(irq)); | ||
59 | gic_mask_irq(irq); | ||
60 | writel(1<<(irq&31), addr+ICTLR_CPU_IER_CLR); | ||
61 | } | ||
62 | |||
63 | static void tegra_unmask(unsigned int irq) | ||
64 | { | ||
65 | void __iomem *addr = ictlr_to_virt(irq_to_ictlr(irq)); | ||
66 | gic_unmask_irq(irq); | ||
67 | writel(1<<(irq&31), addr+ICTLR_CPU_IER_SET); | ||
68 | } | ||
69 | |||
70 | #ifdef CONFIG_PM | ||
71 | |||
72 | static int tegra_set_wake(unsigned int irq, unsigned int on) | ||
73 | { | ||
74 | return 0; | ||
75 | } | ||
76 | #endif | ||
77 | |||
78 | static struct irq_chip tegra_irq = { | ||
79 | .name = "PPI", | ||
80 | .mask = tegra_mask, | ||
81 | .unmask = tegra_unmask, | ||
82 | #ifdef CONFIG_PM | ||
83 | .set_wake = tegra_set_wake, | ||
84 | #endif | ||
85 | }; | ||
86 | |||
30 | void __init tegra_init_irq(void) | 87 | void __init tegra_init_irq(void) |
31 | { | 88 | { |
89 | struct irq_chip *gic; | ||
90 | unsigned int i; | ||
91 | |||
92 | for (i = 0; i < PPI_NR; i++) { | ||
93 | writel(~0, ictlr_to_virt(i) + ICTLR_CPU_IER_CLR); | ||
94 | writel(0, ictlr_to_virt(i) + ICTLR_CPU_IEP_CLASS); | ||
95 | } | ||
96 | |||
32 | gic_dist_init(0, IO_ADDRESS(TEGRA_ARM_INT_DIST_BASE), 29); | 97 | gic_dist_init(0, IO_ADDRESS(TEGRA_ARM_INT_DIST_BASE), 29); |
33 | gic_cpu_init(0, IO_ADDRESS(TEGRA_ARM_PERIF_BASE + 0x100)); | 98 | gic_cpu_init(0, IO_ADDRESS(TEGRA_ARM_PERIF_BASE + 0x100)); |
99 | |||
100 | gic = get_irq_chip(29); | ||
101 | gic_unmask_irq = gic->unmask; | ||
102 | gic_mask_irq = gic->mask; | ||
103 | tegra_irq.ack = gic->ack; | ||
104 | #ifdef CONFIG_SMP | ||
105 | tegra_irq.set_affinity = gic->set_affinity; | ||
106 | #endif | ||
107 | |||
108 | for (i = INT_PRI_BASE; i < INT_GPIO_BASE; i++) { | ||
109 | set_irq_chip(i, &tegra_irq); | ||
110 | set_irq_handler(i, handle_level_irq); | ||
111 | set_irq_flags(i, IRQF_VALID); | ||
112 | } | ||
113 | } | ||
114 | |||
115 | #ifdef CONFIG_PM | ||
116 | static u32 cop_ier[PPI_NR]; | ||
117 | static u32 cpu_ier[PPI_NR]; | ||
118 | static u32 cpu_iep[PPI_NR]; | ||
119 | |||
120 | void tegra_irq_suspend(void) | ||
121 | { | ||
122 | unsigned long flags; | ||
123 | int i; | ||
124 | |||
125 | for (i = INT_PRI_BASE; i < INT_GPIO_BASE; i++) { | ||
126 | struct irq_desc *desc = irq_to_desc(i); | ||
127 | if (!desc) | ||
128 | continue; | ||
129 | if (desc->status & IRQ_WAKEUP) { | ||
130 | pr_debug("irq %d is wakeup\n", i); | ||
131 | continue; | ||
132 | } | ||
133 | disable_irq(i); | ||
134 | } | ||
135 | |||
136 | local_irq_save(flags); | ||
137 | for (i = 0; i < PPI_NR; i++) { | ||
138 | void __iomem *ictlr = ictlr_to_virt(i); | ||
139 | cpu_ier[i] = readl(ictlr + ICTLR_CPU_IER); | ||
140 | cpu_iep[i] = readl(ictlr + ICTLR_CPU_IEP_CLASS); | ||
141 | cop_ier[i] = readl(ictlr + ICTLR_COP_IER); | ||
142 | writel(~0, ictlr + ICTLR_COP_IER_CLR); | ||
143 | } | ||
144 | local_irq_restore(flags); | ||
145 | } | ||
146 | |||
147 | void tegra_irq_resume(void) | ||
148 | { | ||
149 | unsigned long flags; | ||
150 | int i; | ||
151 | |||
152 | local_irq_save(flags); | ||
153 | for (i = 0; i < PPI_NR; i++) { | ||
154 | void __iomem *ictlr = ictlr_to_virt(i); | ||
155 | writel(cpu_iep[i], ictlr + ICTLR_CPU_IEP_CLASS); | ||
156 | writel(~0ul, ictlr + ICTLR_CPU_IER_CLR); | ||
157 | writel(cpu_ier[i], ictlr + ICTLR_CPU_IER_SET); | ||
158 | writel(0, ictlr + ICTLR_COP_IEP_CLASS); | ||
159 | writel(~0ul, ictlr + ICTLR_COP_IER_CLR); | ||
160 | writel(cop_ier[i], ictlr + ICTLR_COP_IER_SET); | ||
161 | } | ||
162 | local_irq_restore(flags); | ||
163 | |||
164 | for (i = INT_PRI_BASE; i < INT_GPIO_BASE; i++) { | ||
165 | struct irq_desc *desc = irq_to_desc(i); | ||
166 | if (!desc || (desc->status & IRQ_WAKEUP)) | ||
167 | continue; | ||
168 | enable_irq(i); | ||
169 | } | ||
34 | } | 170 | } |
171 | #endif | ||
diff --git a/arch/arm/mach-tegra/legacy_irq.c b/arch/arm/mach-tegra/legacy_irq.c new file mode 100644 index 000000000000..7cc8601c19ff --- /dev/null +++ b/arch/arm/mach-tegra/legacy_irq.c | |||
@@ -0,0 +1,114 @@ | |||
1 | /* | ||
2 | * arch/arm/mach-tegra/legacy_irq.c | ||
3 | * | ||
4 | * Copyright (C) 2010 Google, Inc. | ||
5 | * Author: Colin Cross <ccross@android.com> | ||
6 | * | ||
7 | * This software is licensed under the terms of the GNU General Public | ||
8 | * License version 2, as published by the Free Software Foundation, and | ||
9 | * may be copied, distributed, and modified under those terms. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | */ | ||
17 | |||
18 | #include <linux/io.h> | ||
19 | #include <linux/kernel.h> | ||
20 | #include <mach/iomap.h> | ||
21 | #include <mach/legacy_irq.h> | ||
22 | |||
23 | #define ICTLR_CPU_IER 0x20 | ||
24 | #define ICTLR_CPU_IER_SET 0x24 | ||
25 | #define ICTLR_CPU_IER_CLR 0x28 | ||
26 | #define ICTLR_CPU_IEP_CLASS 0x2C | ||
27 | #define ICTLR_CPU_IEP_VFIQ 0x08 | ||
28 | #define ICTLR_CPU_IEP_FIR 0x14 | ||
29 | #define ICTLR_CPU_IEP_FIR_SET 0x18 | ||
30 | #define ICTLR_CPU_IEP_FIR_CLR 0x1c | ||
31 | |||
32 | static void __iomem *ictlr_reg_base[] = { | ||
33 | IO_ADDRESS(TEGRA_PRIMARY_ICTLR_BASE), | ||
34 | IO_ADDRESS(TEGRA_SECONDARY_ICTLR_BASE), | ||
35 | IO_ADDRESS(TEGRA_TERTIARY_ICTLR_BASE), | ||
36 | IO_ADDRESS(TEGRA_QUATERNARY_ICTLR_BASE), | ||
37 | }; | ||
38 | |||
39 | /* When going into deep sleep, the CPU is powered down, taking the GIC with it | ||
40 | In order to wake, the wake interrupts need to be enabled in the legacy | ||
41 | interrupt controller. */ | ||
42 | void tegra_legacy_unmask_irq(unsigned int irq) | ||
43 | { | ||
44 | void __iomem *base; | ||
45 | pr_debug("%s: %d\n", __func__, irq); | ||
46 | |||
47 | irq -= 32; | ||
48 | base = ictlr_reg_base[irq>>5]; | ||
49 | writel(1 << (irq & 31), base + ICTLR_CPU_IER_SET); | ||
50 | } | ||
51 | |||
52 | void tegra_legacy_mask_irq(unsigned int irq) | ||
53 | { | ||
54 | void __iomem *base; | ||
55 | pr_debug("%s: %d\n", __func__, irq); | ||
56 | |||
57 | irq -= 32; | ||
58 | base = ictlr_reg_base[irq>>5]; | ||
59 | writel(1 << (irq & 31), base + ICTLR_CPU_IER_CLR); | ||
60 | } | ||
61 | |||
62 | void tegra_legacy_force_irq_set(unsigned int irq) | ||
63 | { | ||
64 | void __iomem *base; | ||
65 | pr_debug("%s: %d\n", __func__, irq); | ||
66 | |||
67 | irq -= 32; | ||
68 | base = ictlr_reg_base[irq>>5]; | ||
69 | writel(1 << (irq & 31), base + ICTLR_CPU_IEP_FIR_SET); | ||
70 | } | ||
71 | |||
72 | void tegra_legacy_force_irq_clr(unsigned int irq) | ||
73 | { | ||
74 | void __iomem *base; | ||
75 | pr_debug("%s: %d\n", __func__, irq); | ||
76 | |||
77 | irq -= 32; | ||
78 | base = ictlr_reg_base[irq>>5]; | ||
79 | writel(1 << (irq & 31), base + ICTLR_CPU_IEP_FIR_CLR); | ||
80 | } | ||
81 | |||
82 | int tegra_legacy_force_irq_status(unsigned int irq) | ||
83 | { | ||
84 | void __iomem *base; | ||
85 | pr_debug("%s: %d\n", __func__, irq); | ||
86 | |||
87 | irq -= 32; | ||
88 | base = ictlr_reg_base[irq>>5]; | ||
89 | return !!(readl(base + ICTLR_CPU_IEP_FIR) & (1 << (irq & 31))); | ||
90 | } | ||
91 | |||
92 | void tegra_legacy_select_fiq(unsigned int irq, bool fiq) | ||
93 | { | ||
94 | void __iomem *base; | ||
95 | pr_debug("%s: %d\n", __func__, irq); | ||
96 | |||
97 | irq -= 32; | ||
98 | base = ictlr_reg_base[irq>>5]; | ||
99 | writel(fiq << (irq & 31), base + ICTLR_CPU_IEP_CLASS); | ||
100 | } | ||
101 | |||
102 | unsigned long tegra_legacy_vfiq(int nr) | ||
103 | { | ||
104 | void __iomem *base; | ||
105 | base = ictlr_reg_base[nr]; | ||
106 | return readl(base + ICTLR_CPU_IEP_VFIQ); | ||
107 | } | ||
108 | |||
109 | unsigned long tegra_legacy_class(int nr) | ||
110 | { | ||
111 | void __iomem *base; | ||
112 | base = ictlr_reg_base[nr]; | ||
113 | return readl(base + ICTLR_CPU_IEP_CLASS); | ||
114 | } | ||
diff --git a/arch/arm/mach-tegra/pcie.c b/arch/arm/mach-tegra/pcie.c new file mode 100644 index 000000000000..53f5fa37014a --- /dev/null +++ b/arch/arm/mach-tegra/pcie.c | |||
@@ -0,0 +1,915 @@ | |||
1 | /* | ||
2 | * arch/arm/mach-tegra/pci.c | ||
3 | * | ||
4 | * PCIe host controller driver for TEGRA(2) SOCs | ||
5 | * | ||
6 | * Copyright (c) 2010, CompuLab, Ltd. | ||
7 | * Author: Mike Rapoport <mike@compulab.co.il> | ||
8 | * | ||
9 | * Based on NVIDIA PCIe driver | ||
10 | * Copyright (c) 2008-2009, NVIDIA Corporation. | ||
11 | * | ||
12 | * Bits taken from arch/arm/mach-dove/pcie.c | ||
13 | * | ||
14 | * This program is free software; you can redistribute it and/or modify | ||
15 | * it under the terms of the GNU General Public License as published by | ||
16 | * the Free Software Foundation; either version 2 of the License, or | ||
17 | * (at your option) any later version. | ||
18 | * | ||
19 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
20 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
21 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
22 | * more details. | ||
23 | * | ||
24 | * You should have received a copy of the GNU General Public License along | ||
25 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
26 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
27 | */ | ||
28 | |||
29 | #include <linux/kernel.h> | ||
30 | #include <linux/pci.h> | ||
31 | #include <linux/interrupt.h> | ||
32 | #include <linux/irq.h> | ||
33 | #include <linux/clk.h> | ||
34 | #include <linux/delay.h> | ||
35 | |||
36 | #include <asm/sizes.h> | ||
37 | #include <asm/mach/pci.h> | ||
38 | |||
39 | #include <mach/pinmux.h> | ||
40 | #include <mach/iomap.h> | ||
41 | #include <mach/clk.h> | ||
42 | |||
43 | /* register definitions */ | ||
44 | #define AFI_OFFSET 0x3800 | ||
45 | #define PADS_OFFSET 0x3000 | ||
46 | #define RP0_OFFSET 0x0000 | ||
47 | #define RP1_OFFSET 0x1000 | ||
48 | |||
49 | #define AFI_AXI_BAR0_SZ 0x00 | ||
50 | #define AFI_AXI_BAR1_SZ 0x04 | ||
51 | #define AFI_AXI_BAR2_SZ 0x08 | ||
52 | #define AFI_AXI_BAR3_SZ 0x0c | ||
53 | #define AFI_AXI_BAR4_SZ 0x10 | ||
54 | #define AFI_AXI_BAR5_SZ 0x14 | ||
55 | |||
56 | #define AFI_AXI_BAR0_START 0x18 | ||
57 | #define AFI_AXI_BAR1_START 0x1c | ||
58 | #define AFI_AXI_BAR2_START 0x20 | ||
59 | #define AFI_AXI_BAR3_START 0x24 | ||
60 | #define AFI_AXI_BAR4_START 0x28 | ||
61 | #define AFI_AXI_BAR5_START 0x2c | ||
62 | |||
63 | #define AFI_FPCI_BAR0 0x30 | ||
64 | #define AFI_FPCI_BAR1 0x34 | ||
65 | #define AFI_FPCI_BAR2 0x38 | ||
66 | #define AFI_FPCI_BAR3 0x3c | ||
67 | #define AFI_FPCI_BAR4 0x40 | ||
68 | #define AFI_FPCI_BAR5 0x44 | ||
69 | |||
70 | #define AFI_CACHE_BAR0_SZ 0x48 | ||
71 | #define AFI_CACHE_BAR0_ST 0x4c | ||
72 | #define AFI_CACHE_BAR1_SZ 0x50 | ||
73 | #define AFI_CACHE_BAR1_ST 0x54 | ||
74 | |||
75 | #define AFI_MSI_BAR_SZ 0x60 | ||
76 | #define AFI_MSI_FPCI_BAR_ST 0x64 | ||
77 | #define AFI_MSI_AXI_BAR_ST 0x68 | ||
78 | |||
79 | #define AFI_CONFIGURATION 0xac | ||
80 | #define AFI_CONFIGURATION_EN_FPCI (1 << 0) | ||
81 | |||
82 | #define AFI_FPCI_ERROR_MASKS 0xb0 | ||
83 | |||
84 | #define AFI_INTR_MASK 0xb4 | ||
85 | #define AFI_INTR_MASK_INT_MASK (1 << 0) | ||
86 | #define AFI_INTR_MASK_MSI_MASK (1 << 8) | ||
87 | |||
88 | #define AFI_INTR_CODE 0xb8 | ||
89 | #define AFI_INTR_CODE_MASK 0xf | ||
90 | #define AFI_INTR_MASTER_ABORT 4 | ||
91 | #define AFI_INTR_LEGACY 6 | ||
92 | |||
93 | #define AFI_INTR_SIGNATURE 0xbc | ||
94 | #define AFI_SM_INTR_ENABLE 0xc4 | ||
95 | |||
96 | #define AFI_AFI_INTR_ENABLE 0xc8 | ||
97 | #define AFI_INTR_EN_INI_SLVERR (1 << 0) | ||
98 | #define AFI_INTR_EN_INI_DECERR (1 << 1) | ||
99 | #define AFI_INTR_EN_TGT_SLVERR (1 << 2) | ||
100 | #define AFI_INTR_EN_TGT_DECERR (1 << 3) | ||
101 | #define AFI_INTR_EN_TGT_WRERR (1 << 4) | ||
102 | #define AFI_INTR_EN_DFPCI_DECERR (1 << 5) | ||
103 | #define AFI_INTR_EN_AXI_DECERR (1 << 6) | ||
104 | #define AFI_INTR_EN_FPCI_TIMEOUT (1 << 7) | ||
105 | |||
106 | #define AFI_PCIE_CONFIG 0x0f8 | ||
107 | #define AFI_PCIE_CONFIG_PCIEC0_DISABLE_DEVICE (1 << 1) | ||
108 | #define AFI_PCIE_CONFIG_PCIEC1_DISABLE_DEVICE (1 << 2) | ||
109 | #define AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_MASK (0xf << 20) | ||
110 | #define AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_SINGLE (0x0 << 20) | ||
111 | #define AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_DUAL (0x1 << 20) | ||
112 | |||
113 | #define AFI_FUSE 0x104 | ||
114 | #define AFI_FUSE_PCIE_T0_GEN2_DIS (1 << 2) | ||
115 | |||
116 | #define AFI_PEX0_CTRL 0x110 | ||
117 | #define AFI_PEX1_CTRL 0x118 | ||
118 | #define AFI_PEX_CTRL_RST (1 << 0) | ||
119 | #define AFI_PEX_CTRL_REFCLK_EN (1 << 3) | ||
120 | |||
121 | #define RP_VEND_XP 0x00000F00 | ||
122 | #define RP_VEND_XP_DL_UP (1 << 30) | ||
123 | |||
124 | #define RP_LINK_CONTROL_STATUS 0x00000090 | ||
125 | #define RP_LINK_CONTROL_STATUS_LINKSTAT_MASK 0x3fff0000 | ||
126 | |||
127 | #define PADS_CTL_SEL 0x0000009C | ||
128 | |||
129 | #define PADS_CTL 0x000000A0 | ||
130 | #define PADS_CTL_IDDQ_1L (1 << 0) | ||
131 | #define PADS_CTL_TX_DATA_EN_1L (1 << 6) | ||
132 | #define PADS_CTL_RX_DATA_EN_1L (1 << 10) | ||
133 | |||
134 | #define PADS_PLL_CTL 0x000000B8 | ||
135 | #define PADS_PLL_CTL_RST_B4SM (1 << 1) | ||
136 | #define PADS_PLL_CTL_LOCKDET (1 << 8) | ||
137 | #define PADS_PLL_CTL_REFCLK_MASK (0x3 << 16) | ||
138 | #define PADS_PLL_CTL_REFCLK_INTERNAL_CML (0 << 16) | ||
139 | #define PADS_PLL_CTL_REFCLK_INTERNAL_CMOS (1 << 16) | ||
140 | #define PADS_PLL_CTL_REFCLK_EXTERNAL (2 << 16) | ||
141 | #define PADS_PLL_CTL_TXCLKREF_MASK (0x1 << 20) | ||
142 | #define PADS_PLL_CTL_TXCLKREF_DIV10 (0 << 20) | ||
143 | #define PADS_PLL_CTL_TXCLKREF_DIV5 (1 << 20) | ||
144 | |||
145 | /* PMC access is required for PCIE xclk (un)clamping */ | ||
146 | #define PMC_SCRATCH42 0x144 | ||
147 | #define PMC_SCRATCH42_PCX_CLAMP (1 << 0) | ||
148 | |||
149 | static void __iomem *reg_pmc_base = IO_ADDRESS(TEGRA_PMC_BASE); | ||
150 | |||
151 | #define pmc_writel(value, reg) \ | ||
152 | __raw_writel(value, (u32)reg_pmc_base + (reg)) | ||
153 | #define pmc_readl(reg) \ | ||
154 | __raw_readl((u32)reg_pmc_base + (reg)) | ||
155 | |||
156 | /* | ||
157 | * Tegra2 defines 1GB in the AXI address map for PCIe. | ||
158 | * | ||
159 | * That address space is split into different regions, with sizes and | ||
160 | * offsets as follows: | ||
161 | * | ||
162 | * 0x80000000 - 0x80003fff - PCI controller registers | ||
163 | * 0x80004000 - 0x80103fff - PCI configuration space | ||
164 | * 0x80104000 - 0x80203fff - PCI extended configuration space | ||
165 | * 0x80203fff - 0x803fffff - unused | ||
166 | * 0x80400000 - 0x8040ffff - downstream IO | ||
167 | * 0x80410000 - 0x8fffffff - unused | ||
168 | * 0x90000000 - 0x9fffffff - non-prefetchable memory | ||
169 | * 0xa0000000 - 0xbfffffff - prefetchable memory | ||
170 | */ | ||
171 | #define TEGRA_PCIE_BASE 0x80000000 | ||
172 | |||
173 | #define PCIE_REGS_SZ SZ_16K | ||
174 | #define PCIE_CFG_OFF PCIE_REGS_SZ | ||
175 | #define PCIE_CFG_SZ SZ_1M | ||
176 | #define PCIE_EXT_CFG_OFF (PCIE_CFG_SZ + PCIE_CFG_OFF) | ||
177 | #define PCIE_EXT_CFG_SZ SZ_1M | ||
178 | #define PCIE_IOMAP_SZ (PCIE_REGS_SZ + PCIE_CFG_SZ + PCIE_EXT_CFG_SZ) | ||
179 | |||
180 | #define MMIO_BASE (TEGRA_PCIE_BASE + SZ_4M) | ||
181 | #define MMIO_SIZE SZ_64K | ||
182 | #define MEM_BASE_0 (TEGRA_PCIE_BASE + SZ_256M) | ||
183 | #define MEM_SIZE_0 SZ_128M | ||
184 | #define MEM_BASE_1 (MEM_BASE_0 + MEM_SIZE_0) | ||
185 | #define MEM_SIZE_1 SZ_128M | ||
186 | #define PREFETCH_MEM_BASE_0 (MEM_BASE_1 + MEM_SIZE_1) | ||
187 | #define PREFETCH_MEM_SIZE_0 SZ_128M | ||
188 | #define PREFETCH_MEM_BASE_1 (PREFETCH_MEM_BASE_0 + PREFETCH_MEM_SIZE_0) | ||
189 | #define PREFETCH_MEM_SIZE_1 SZ_128M | ||
190 | |||
191 | #define PCIE_CONF_BUS(b) ((b) << 16) | ||
192 | #define PCIE_CONF_DEV(d) ((d) << 11) | ||
193 | #define PCIE_CONF_FUNC(f) ((f) << 8) | ||
194 | #define PCIE_CONF_REG(r) \ | ||
195 | (((r) & ~0x3) | (((r) < 256) ? PCIE_CFG_OFF : PCIE_EXT_CFG_OFF)) | ||
196 | |||
197 | struct tegra_pcie_port { | ||
198 | int index; | ||
199 | u8 root_bus_nr; | ||
200 | void __iomem *base; | ||
201 | |||
202 | bool link_up; | ||
203 | |||
204 | char io_space_name[16]; | ||
205 | char mem_space_name[16]; | ||
206 | char prefetch_space_name[20]; | ||
207 | struct resource res[3]; | ||
208 | }; | ||
209 | |||
210 | struct tegra_pcie_info { | ||
211 | struct tegra_pcie_port port[2]; | ||
212 | int num_ports; | ||
213 | |||
214 | void __iomem *regs; | ||
215 | struct resource res_mmio; | ||
216 | |||
217 | struct clk *pex_clk; | ||
218 | struct clk *afi_clk; | ||
219 | struct clk *pcie_xclk; | ||
220 | struct clk *pll_e; | ||
221 | }; | ||
222 | |||
223 | static struct tegra_pcie_info tegra_pcie = { | ||
224 | .res_mmio = { | ||
225 | .name = "PCI IO", | ||
226 | .start = MMIO_BASE, | ||
227 | .end = MMIO_BASE + MMIO_SIZE - 1, | ||
228 | .flags = IORESOURCE_MEM, | ||
229 | }, | ||
230 | }; | ||
231 | |||
232 | void __iomem *tegra_pcie_io_base; | ||
233 | EXPORT_SYMBOL(tegra_pcie_io_base); | ||
234 | |||
235 | static inline void afi_writel(u32 value, unsigned long offset) | ||
236 | { | ||
237 | writel(value, offset + AFI_OFFSET + tegra_pcie.regs); | ||
238 | } | ||
239 | |||
240 | static inline u32 afi_readl(unsigned long offset) | ||
241 | { | ||
242 | return readl(offset + AFI_OFFSET + tegra_pcie.regs); | ||
243 | } | ||
244 | |||
245 | static inline void pads_writel(u32 value, unsigned long offset) | ||
246 | { | ||
247 | writel(value, offset + PADS_OFFSET + tegra_pcie.regs); | ||
248 | } | ||
249 | |||
250 | static inline u32 pads_readl(unsigned long offset) | ||
251 | { | ||
252 | return readl(offset + PADS_OFFSET + tegra_pcie.regs); | ||
253 | } | ||
254 | |||
255 | static struct tegra_pcie_port *bus_to_port(int bus) | ||
256 | { | ||
257 | int i; | ||
258 | |||
259 | for (i = tegra_pcie.num_ports - 1; i >= 0; i--) { | ||
260 | int rbus = tegra_pcie.port[i].root_bus_nr; | ||
261 | if (rbus != -1 && rbus == bus) | ||
262 | break; | ||
263 | } | ||
264 | |||
265 | return i >= 0 ? tegra_pcie.port + i : NULL; | ||
266 | } | ||
267 | |||
268 | static int tegra_pcie_read_conf(struct pci_bus *bus, unsigned int devfn, | ||
269 | int where, int size, u32 *val) | ||
270 | { | ||
271 | struct tegra_pcie_port *pp = bus_to_port(bus->number); | ||
272 | void __iomem *addr; | ||
273 | |||
274 | if (pp) { | ||
275 | if (devfn != 0) { | ||
276 | *val = 0xffffffff; | ||
277 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
278 | } | ||
279 | |||
280 | addr = pp->base + (where & ~0x3); | ||
281 | } else { | ||
282 | addr = tegra_pcie.regs + (PCIE_CONF_BUS(bus->number) + | ||
283 | PCIE_CONF_DEV(PCI_SLOT(devfn)) + | ||
284 | PCIE_CONF_FUNC(PCI_FUNC(devfn)) + | ||
285 | PCIE_CONF_REG(where)); | ||
286 | } | ||
287 | |||
288 | *val = readl(addr); | ||
289 | |||
290 | if (size == 1) | ||
291 | *val = (*val >> (8 * (where & 3))) & 0xff; | ||
292 | else if (size == 2) | ||
293 | *val = (*val >> (8 * (where & 3))) & 0xffff; | ||
294 | |||
295 | return PCIBIOS_SUCCESSFUL; | ||
296 | } | ||
297 | |||
298 | static int tegra_pcie_write_conf(struct pci_bus *bus, unsigned int devfn, | ||
299 | int where, int size, u32 val) | ||
300 | { | ||
301 | struct tegra_pcie_port *pp = bus_to_port(bus->number); | ||
302 | void __iomem *addr; | ||
303 | |||
304 | u32 mask; | ||
305 | u32 tmp; | ||
306 | |||
307 | if (pp) { | ||
308 | if (devfn != 0) | ||
309 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
310 | |||
311 | addr = pp->base + (where & ~0x3); | ||
312 | } else { | ||
313 | addr = tegra_pcie.regs + (PCIE_CONF_BUS(bus->number) + | ||
314 | PCIE_CONF_DEV(PCI_SLOT(devfn)) + | ||
315 | PCIE_CONF_FUNC(PCI_FUNC(devfn)) + | ||
316 | PCIE_CONF_REG(where)); | ||
317 | } | ||
318 | |||
319 | if (size == 4) { | ||
320 | writel(val, addr); | ||
321 | return PCIBIOS_SUCCESSFUL; | ||
322 | } | ||
323 | |||
324 | if (size == 2) | ||
325 | mask = ~(0xffff << ((where & 0x3) * 8)); | ||
326 | else if (size == 1) | ||
327 | mask = ~(0xff << ((where & 0x3) * 8)); | ||
328 | else | ||
329 | return PCIBIOS_BAD_REGISTER_NUMBER; | ||
330 | |||
331 | tmp = readl(addr) & mask; | ||
332 | tmp |= val << ((where & 0x3) * 8); | ||
333 | writel(tmp, addr); | ||
334 | |||
335 | return PCIBIOS_SUCCESSFUL; | ||
336 | } | ||
337 | |||
338 | static struct pci_ops tegra_pcie_ops = { | ||
339 | .read = tegra_pcie_read_conf, | ||
340 | .write = tegra_pcie_write_conf, | ||
341 | }; | ||
342 | |||
343 | static void __devinit tegra_pcie_fixup_bridge(struct pci_dev *dev) | ||
344 | { | ||
345 | u16 reg; | ||
346 | |||
347 | if ((dev->class >> 16) == PCI_BASE_CLASS_BRIDGE) { | ||
348 | pci_read_config_word(dev, PCI_COMMAND, ®); | ||
349 | reg |= (PCI_COMMAND_IO | PCI_COMMAND_MEMORY | | ||
350 | PCI_COMMAND_MASTER | PCI_COMMAND_SERR); | ||
351 | pci_write_config_word(dev, PCI_COMMAND, reg); | ||
352 | } | ||
353 | } | ||
354 | DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, tegra_pcie_fixup_bridge); | ||
355 | |||
356 | /* Tegra PCIE root complex wrongly reports device class */ | ||
357 | static void __devinit tegra_pcie_fixup_class(struct pci_dev *dev) | ||
358 | { | ||
359 | dev->class = PCI_CLASS_BRIDGE_PCI << 8; | ||
360 | } | ||
361 | DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_NVIDIA, 0x0bf0, tegra_pcie_fixup_class); | ||
362 | DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_NVIDIA, 0x0bf1, tegra_pcie_fixup_class); | ||
363 | |||
364 | /* Tegra PCIE requires relaxed ordering */ | ||
365 | static void __devinit tegra_pcie_relax_enable(struct pci_dev *dev) | ||
366 | { | ||
367 | u16 val16; | ||
368 | int pos = pci_find_capability(dev, PCI_CAP_ID_EXP); | ||
369 | |||
370 | if (pos <= 0) { | ||
371 | dev_err(&dev->dev, "skipping relaxed ordering fixup\n"); | ||
372 | return; | ||
373 | } | ||
374 | |||
375 | pci_read_config_word(dev, pos + PCI_EXP_DEVCTL, &val16); | ||
376 | val16 |= PCI_EXP_DEVCTL_RELAX_EN; | ||
377 | pci_write_config_word(dev, pos + PCI_EXP_DEVCTL, val16); | ||
378 | } | ||
379 | DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, tegra_pcie_relax_enable); | ||
380 | |||
381 | static int tegra_pcie_setup(int nr, struct pci_sys_data *sys) | ||
382 | { | ||
383 | struct tegra_pcie_port *pp; | ||
384 | |||
385 | if (nr >= tegra_pcie.num_ports) | ||
386 | return 0; | ||
387 | |||
388 | pp = tegra_pcie.port + nr; | ||
389 | pp->root_bus_nr = sys->busnr; | ||
390 | |||
391 | /* | ||
392 | * IORESOURCE_IO | ||
393 | */ | ||
394 | snprintf(pp->io_space_name, sizeof(pp->io_space_name), | ||
395 | "PCIe %d I/O", pp->index); | ||
396 | pp->io_space_name[sizeof(pp->io_space_name) - 1] = 0; | ||
397 | pp->res[0].name = pp->io_space_name; | ||
398 | if (pp->index == 0) { | ||
399 | pp->res[0].start = PCIBIOS_MIN_IO; | ||
400 | pp->res[0].end = pp->res[0].start + SZ_32K - 1; | ||
401 | } else { | ||
402 | pp->res[0].start = PCIBIOS_MIN_IO + SZ_32K; | ||
403 | pp->res[0].end = IO_SPACE_LIMIT; | ||
404 | } | ||
405 | pp->res[0].flags = IORESOURCE_IO; | ||
406 | if (request_resource(&ioport_resource, &pp->res[0])) | ||
407 | panic("Request PCIe IO resource failed\n"); | ||
408 | sys->resource[0] = &pp->res[0]; | ||
409 | |||
410 | /* | ||
411 | * IORESOURCE_MEM | ||
412 | */ | ||
413 | snprintf(pp->mem_space_name, sizeof(pp->mem_space_name), | ||
414 | "PCIe %d MEM", pp->index); | ||
415 | pp->mem_space_name[sizeof(pp->mem_space_name) - 1] = 0; | ||
416 | pp->res[1].name = pp->mem_space_name; | ||
417 | if (pp->index == 0) { | ||
418 | pp->res[1].start = MEM_BASE_0; | ||
419 | pp->res[1].end = pp->res[1].start + MEM_SIZE_0 - 1; | ||
420 | } else { | ||
421 | pp->res[1].start = MEM_BASE_1; | ||
422 | pp->res[1].end = pp->res[1].start + MEM_SIZE_1 - 1; | ||
423 | } | ||
424 | pp->res[1].flags = IORESOURCE_MEM; | ||
425 | if (request_resource(&iomem_resource, &pp->res[1])) | ||
426 | panic("Request PCIe Memory resource failed\n"); | ||
427 | sys->resource[1] = &pp->res[1]; | ||
428 | |||
429 | /* | ||
430 | * IORESOURCE_MEM | IORESOURCE_PREFETCH | ||
431 | */ | ||
432 | snprintf(pp->prefetch_space_name, sizeof(pp->prefetch_space_name), | ||
433 | "PCIe %d PREFETCH MEM", pp->index); | ||
434 | pp->prefetch_space_name[sizeof(pp->prefetch_space_name) - 1] = 0; | ||
435 | pp->res[2].name = pp->prefetch_space_name; | ||
436 | if (pp->index == 0) { | ||
437 | pp->res[2].start = PREFETCH_MEM_BASE_0; | ||
438 | pp->res[2].end = pp->res[2].start + PREFETCH_MEM_SIZE_0 - 1; | ||
439 | } else { | ||
440 | pp->res[2].start = PREFETCH_MEM_BASE_1; | ||
441 | pp->res[2].end = pp->res[2].start + PREFETCH_MEM_SIZE_1 - 1; | ||
442 | } | ||
443 | pp->res[2].flags = IORESOURCE_MEM | IORESOURCE_PREFETCH; | ||
444 | if (request_resource(&iomem_resource, &pp->res[2])) | ||
445 | panic("Request PCIe Prefetch Memory resource failed\n"); | ||
446 | sys->resource[2] = &pp->res[2]; | ||
447 | |||
448 | return 1; | ||
449 | } | ||
450 | |||
451 | static int tegra_pcie_map_irq(struct pci_dev *dev, u8 slot, u8 pin) | ||
452 | { | ||
453 | return INT_PCIE_INTR; | ||
454 | } | ||
455 | |||
456 | static struct pci_bus __init *tegra_pcie_scan_bus(int nr, | ||
457 | struct pci_sys_data *sys) | ||
458 | { | ||
459 | struct tegra_pcie_port *pp; | ||
460 | |||
461 | if (nr >= tegra_pcie.num_ports) | ||
462 | return 0; | ||
463 | |||
464 | pp = tegra_pcie.port + nr; | ||
465 | pp->root_bus_nr = sys->busnr; | ||
466 | |||
467 | return pci_scan_bus(sys->busnr, &tegra_pcie_ops, sys); | ||
468 | } | ||
469 | |||
470 | static struct hw_pci tegra_pcie_hw __initdata = { | ||
471 | .nr_controllers = 2, | ||
472 | .setup = tegra_pcie_setup, | ||
473 | .scan = tegra_pcie_scan_bus, | ||
474 | .swizzle = pci_std_swizzle, | ||
475 | .map_irq = tegra_pcie_map_irq, | ||
476 | }; | ||
477 | |||
478 | |||
479 | static irqreturn_t tegra_pcie_isr(int irq, void *arg) | ||
480 | { | ||
481 | const char *err_msg[] = { | ||
482 | "Unknown", | ||
483 | "AXI slave error", | ||
484 | "AXI decode error", | ||
485 | "Target abort", | ||
486 | "Master abort", | ||
487 | "Invalid write", | ||
488 | "Response decoding error", | ||
489 | "AXI response decoding error", | ||
490 | "Transcation timeout", | ||
491 | }; | ||
492 | |||
493 | u32 code, signature; | ||
494 | |||
495 | code = afi_readl(AFI_INTR_CODE) & AFI_INTR_CODE_MASK; | ||
496 | signature = afi_readl(AFI_INTR_SIGNATURE); | ||
497 | afi_writel(0, AFI_INTR_CODE); | ||
498 | |||
499 | if (code == AFI_INTR_LEGACY) | ||
500 | return IRQ_NONE; | ||
501 | |||
502 | if (code >= ARRAY_SIZE(err_msg)) | ||
503 | code = 0; | ||
504 | |||
505 | /* | ||
506 | * do not pollute kernel log with master abort reports since they | ||
507 | * happen a lot during enumeration | ||
508 | */ | ||
509 | if (code == AFI_INTR_MASTER_ABORT) | ||
510 | pr_debug("PCIE: %s, signature: %08x\n", err_msg[code], signature); | ||
511 | else | ||
512 | pr_err("PCIE: %s, signature: %08x\n", err_msg[code], signature); | ||
513 | |||
514 | return IRQ_HANDLED; | ||
515 | } | ||
516 | |||
517 | static void tegra_pcie_setup_translations(void) | ||
518 | { | ||
519 | u32 fpci_bar; | ||
520 | u32 size; | ||
521 | u32 axi_address; | ||
522 | |||
523 | /* Bar 0: config Bar */ | ||
524 | fpci_bar = ((u32)0xfdff << 16); | ||
525 | size = PCIE_CFG_SZ; | ||
526 | axi_address = TEGRA_PCIE_BASE + PCIE_CFG_OFF; | ||
527 | afi_writel(axi_address, AFI_AXI_BAR0_START); | ||
528 | afi_writel(size >> 12, AFI_AXI_BAR0_SZ); | ||
529 | afi_writel(fpci_bar, AFI_FPCI_BAR0); | ||
530 | |||
531 | /* Bar 1: extended config Bar */ | ||
532 | fpci_bar = ((u32)0xfe1 << 20); | ||
533 | size = PCIE_EXT_CFG_SZ; | ||
534 | axi_address = TEGRA_PCIE_BASE + PCIE_EXT_CFG_OFF; | ||
535 | afi_writel(axi_address, AFI_AXI_BAR1_START); | ||
536 | afi_writel(size >> 12, AFI_AXI_BAR1_SZ); | ||
537 | afi_writel(fpci_bar, AFI_FPCI_BAR1); | ||
538 | |||
539 | /* Bar 2: downstream IO bar */ | ||
540 | fpci_bar = ((__u32)0xfdfc << 16); | ||
541 | size = MMIO_SIZE; | ||
542 | axi_address = MMIO_BASE; | ||
543 | afi_writel(axi_address, AFI_AXI_BAR2_START); | ||
544 | afi_writel(size >> 12, AFI_AXI_BAR2_SZ); | ||
545 | afi_writel(fpci_bar, AFI_FPCI_BAR2); | ||
546 | |||
547 | /* Bar 3: prefetchable memory BAR */ | ||
548 | fpci_bar = (((PREFETCH_MEM_BASE_0 >> 12) & 0x0fffffff) << 4) | 0x1; | ||
549 | size = PREFETCH_MEM_SIZE_0 + PREFETCH_MEM_SIZE_1; | ||
550 | axi_address = PREFETCH_MEM_BASE_0; | ||
551 | afi_writel(axi_address, AFI_AXI_BAR3_START); | ||
552 | afi_writel(size >> 12, AFI_AXI_BAR3_SZ); | ||
553 | afi_writel(fpci_bar, AFI_FPCI_BAR3); | ||
554 | |||
555 | /* Bar 4: non prefetchable memory BAR */ | ||
556 | fpci_bar = (((MEM_BASE_0 >> 12) & 0x0FFFFFFF) << 4) | 0x1; | ||
557 | size = MEM_SIZE_0 + MEM_SIZE_1; | ||
558 | axi_address = MEM_BASE_0; | ||
559 | afi_writel(axi_address, AFI_AXI_BAR4_START); | ||
560 | afi_writel(size >> 12, AFI_AXI_BAR4_SZ); | ||
561 | afi_writel(fpci_bar, AFI_FPCI_BAR4); | ||
562 | |||
563 | /* Bar 5: NULL out the remaining BAR as it is not used */ | ||
564 | fpci_bar = 0; | ||
565 | size = 0; | ||
566 | axi_address = 0; | ||
567 | afi_writel(axi_address, AFI_AXI_BAR5_START); | ||
568 | afi_writel(size >> 12, AFI_AXI_BAR5_SZ); | ||
569 | afi_writel(fpci_bar, AFI_FPCI_BAR5); | ||
570 | |||
571 | /* map all upstream transactions as uncached */ | ||
572 | afi_writel(PHYS_OFFSET, AFI_CACHE_BAR0_ST); | ||
573 | afi_writel(0, AFI_CACHE_BAR0_SZ); | ||
574 | afi_writel(0, AFI_CACHE_BAR1_ST); | ||
575 | afi_writel(0, AFI_CACHE_BAR1_SZ); | ||
576 | |||
577 | /* No MSI */ | ||
578 | afi_writel(0, AFI_MSI_FPCI_BAR_ST); | ||
579 | afi_writel(0, AFI_MSI_BAR_SZ); | ||
580 | afi_writel(0, AFI_MSI_AXI_BAR_ST); | ||
581 | afi_writel(0, AFI_MSI_BAR_SZ); | ||
582 | } | ||
583 | |||
584 | static void tegra_pcie_enable_controller(void) | ||
585 | { | ||
586 | u32 val, reg; | ||
587 | int i; | ||
588 | |||
589 | /* Enable slot clock and pulse the reset signals */ | ||
590 | for (i = 0, reg = AFI_PEX0_CTRL; i < 2; i++, reg += 0x8) { | ||
591 | val = afi_readl(reg) | AFI_PEX_CTRL_REFCLK_EN; | ||
592 | afi_writel(val, reg); | ||
593 | val &= ~AFI_PEX_CTRL_RST; | ||
594 | afi_writel(val, reg); | ||
595 | |||
596 | val = afi_readl(reg) | AFI_PEX_CTRL_RST; | ||
597 | afi_writel(val, reg); | ||
598 | } | ||
599 | |||
600 | /* Enable dual controller and both ports */ | ||
601 | val = afi_readl(AFI_PCIE_CONFIG); | ||
602 | val &= ~(AFI_PCIE_CONFIG_PCIEC0_DISABLE_DEVICE | | ||
603 | AFI_PCIE_CONFIG_PCIEC1_DISABLE_DEVICE | | ||
604 | AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_MASK); | ||
605 | val |= AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_DUAL; | ||
606 | afi_writel(val, AFI_PCIE_CONFIG); | ||
607 | |||
608 | val = afi_readl(AFI_FUSE) & ~AFI_FUSE_PCIE_T0_GEN2_DIS; | ||
609 | afi_writel(val, AFI_FUSE); | ||
610 | |||
611 | /* Initialze internal PHY, enable up to 16 PCIE lanes */ | ||
612 | pads_writel(0x0, PADS_CTL_SEL); | ||
613 | |||
614 | /* override IDDQ to 1 on all 4 lanes */ | ||
615 | val = pads_readl(PADS_CTL) | PADS_CTL_IDDQ_1L; | ||
616 | pads_writel(val, PADS_CTL); | ||
617 | |||
618 | /* | ||
619 | * set up PHY PLL inputs select PLLE output as refclock, | ||
620 | * set TX ref sel to div10 (not div5) | ||
621 | */ | ||
622 | val = pads_readl(PADS_PLL_CTL); | ||
623 | val &= ~(PADS_PLL_CTL_REFCLK_MASK | PADS_PLL_CTL_TXCLKREF_MASK); | ||
624 | val |= (PADS_PLL_CTL_REFCLK_INTERNAL_CML | PADS_PLL_CTL_TXCLKREF_DIV10); | ||
625 | pads_writel(val, PADS_PLL_CTL); | ||
626 | |||
627 | /* take PLL out of reset */ | ||
628 | val = pads_readl(PADS_PLL_CTL) | PADS_PLL_CTL_RST_B4SM; | ||
629 | pads_writel(val, PADS_PLL_CTL); | ||
630 | |||
631 | /* | ||
632 | * Hack, set the clock voltage to the DEFAULT provided by hw folks. | ||
633 | * This doesn't exist in the documentation | ||
634 | */ | ||
635 | pads_writel(0xfa5cfa5c, 0xc8); | ||
636 | |||
637 | /* Wait for the PLL to lock */ | ||
638 | do { | ||
639 | val = pads_readl(PADS_PLL_CTL); | ||
640 | } while (!(val & PADS_PLL_CTL_LOCKDET)); | ||
641 | |||
642 | /* turn off IDDQ override */ | ||
643 | val = pads_readl(PADS_CTL) & ~PADS_CTL_IDDQ_1L; | ||
644 | pads_writel(val, PADS_CTL); | ||
645 | |||
646 | /* enable TX/RX data */ | ||
647 | val = pads_readl(PADS_CTL); | ||
648 | val |= (PADS_CTL_TX_DATA_EN_1L | PADS_CTL_RX_DATA_EN_1L); | ||
649 | pads_writel(val, PADS_CTL); | ||
650 | |||
651 | /* Take the PCIe interface module out of reset */ | ||
652 | tegra_periph_reset_deassert(tegra_pcie.pcie_xclk); | ||
653 | |||
654 | /* Finally enable PCIe */ | ||
655 | val = afi_readl(AFI_CONFIGURATION) | AFI_CONFIGURATION_EN_FPCI; | ||
656 | afi_writel(val, AFI_CONFIGURATION); | ||
657 | |||
658 | val = (AFI_INTR_EN_INI_SLVERR | AFI_INTR_EN_INI_DECERR | | ||
659 | AFI_INTR_EN_TGT_SLVERR | AFI_INTR_EN_TGT_DECERR | | ||
660 | AFI_INTR_EN_TGT_WRERR | AFI_INTR_EN_DFPCI_DECERR); | ||
661 | afi_writel(val, AFI_AFI_INTR_ENABLE); | ||
662 | afi_writel(0xffffffff, AFI_SM_INTR_ENABLE); | ||
663 | |||
664 | /* FIXME: No MSI for now, only INT */ | ||
665 | afi_writel(AFI_INTR_MASK_INT_MASK, AFI_INTR_MASK); | ||
666 | |||
667 | /* Disable all execptions */ | ||
668 | afi_writel(0, AFI_FPCI_ERROR_MASKS); | ||
669 | |||
670 | return; | ||
671 | } | ||
672 | |||
673 | static void tegra_pcie_xclk_clamp(bool clamp) | ||
674 | { | ||
675 | u32 reg; | ||
676 | |||
677 | reg = pmc_readl(PMC_SCRATCH42) & ~PMC_SCRATCH42_PCX_CLAMP; | ||
678 | |||
679 | if (clamp) | ||
680 | reg |= PMC_SCRATCH42_PCX_CLAMP; | ||
681 | |||
682 | pmc_writel(reg, PMC_SCRATCH42); | ||
683 | } | ||
684 | |||
685 | static int tegra_pcie_power_on(void) | ||
686 | { | ||
687 | tegra_pcie_xclk_clamp(true); | ||
688 | tegra_periph_reset_assert(tegra_pcie.pcie_xclk); | ||
689 | tegra_pcie_xclk_clamp(false); | ||
690 | |||
691 | clk_enable(tegra_pcie.afi_clk); | ||
692 | clk_enable(tegra_pcie.pex_clk); | ||
693 | return clk_enable(tegra_pcie.pll_e); | ||
694 | } | ||
695 | |||
696 | static void tegra_pcie_power_off(void) | ||
697 | { | ||
698 | tegra_periph_reset_assert(tegra_pcie.pcie_xclk); | ||
699 | tegra_periph_reset_assert(tegra_pcie.afi_clk); | ||
700 | tegra_periph_reset_assert(tegra_pcie.pex_clk); | ||
701 | |||
702 | tegra_pcie_xclk_clamp(true); | ||
703 | } | ||
704 | |||
705 | static int tegra_pcie_clocks_get(void) | ||
706 | { | ||
707 | int err; | ||
708 | |||
709 | tegra_pcie.pex_clk = clk_get(NULL, "pex"); | ||
710 | if (IS_ERR(tegra_pcie.pex_clk)) | ||
711 | return PTR_ERR(tegra_pcie.pex_clk); | ||
712 | |||
713 | tegra_pcie.afi_clk = clk_get(NULL, "afi"); | ||
714 | if (IS_ERR(tegra_pcie.afi_clk)) { | ||
715 | err = PTR_ERR(tegra_pcie.afi_clk); | ||
716 | goto err_afi_clk; | ||
717 | } | ||
718 | |||
719 | tegra_pcie.pcie_xclk = clk_get(NULL, "pcie_xclk"); | ||
720 | if (IS_ERR(tegra_pcie.pcie_xclk)) { | ||
721 | err = PTR_ERR(tegra_pcie.pcie_xclk); | ||
722 | goto err_pcie_xclk; | ||
723 | } | ||
724 | |||
725 | tegra_pcie.pll_e = clk_get_sys(NULL, "pll_e"); | ||
726 | if (IS_ERR(tegra_pcie.pll_e)) { | ||
727 | err = PTR_ERR(tegra_pcie.pll_e); | ||
728 | goto err_pll_e; | ||
729 | } | ||
730 | |||
731 | return 0; | ||
732 | |||
733 | err_pll_e: | ||
734 | clk_put(tegra_pcie.pcie_xclk); | ||
735 | err_pcie_xclk: | ||
736 | clk_put(tegra_pcie.afi_clk); | ||
737 | err_afi_clk: | ||
738 | clk_put(tegra_pcie.pex_clk); | ||
739 | |||
740 | return err; | ||
741 | } | ||
742 | |||
743 | static void tegra_pcie_clocks_put(void) | ||
744 | { | ||
745 | clk_put(tegra_pcie.pll_e); | ||
746 | clk_put(tegra_pcie.pcie_xclk); | ||
747 | clk_put(tegra_pcie.afi_clk); | ||
748 | clk_put(tegra_pcie.pex_clk); | ||
749 | } | ||
750 | |||
751 | static int __init tegra_pcie_get_resources(void) | ||
752 | { | ||
753 | struct resource *res_mmio = &tegra_pcie.res_mmio; | ||
754 | int err; | ||
755 | |||
756 | err = tegra_pcie_clocks_get(); | ||
757 | if (err) { | ||
758 | pr_err("PCIE: failed to get clocks: %d\n", err); | ||
759 | return err; | ||
760 | } | ||
761 | |||
762 | err = tegra_pcie_power_on(); | ||
763 | if (err) { | ||
764 | pr_err("PCIE: failed to power up: %d\n", err); | ||
765 | goto err_pwr_on; | ||
766 | } | ||
767 | |||
768 | tegra_pcie.regs = ioremap_nocache(TEGRA_PCIE_BASE, PCIE_IOMAP_SZ); | ||
769 | if (tegra_pcie.regs == NULL) { | ||
770 | pr_err("PCIE: Failed to map PCI/AFI registers\n"); | ||
771 | err = -ENOMEM; | ||
772 | goto err_map_reg; | ||
773 | } | ||
774 | |||
775 | err = request_resource(&iomem_resource, res_mmio); | ||
776 | if (err) { | ||
777 | pr_err("PCIE: Failed to request resources: %d\n", err); | ||
778 | goto err_req_io; | ||
779 | } | ||
780 | |||
781 | tegra_pcie_io_base = ioremap_nocache(res_mmio->start, | ||
782 | resource_size(res_mmio)); | ||
783 | if (tegra_pcie_io_base == NULL) { | ||
784 | pr_err("PCIE: Failed to map IO\n"); | ||
785 | err = -ENOMEM; | ||
786 | goto err_map_io; | ||
787 | } | ||
788 | |||
789 | err = request_irq(INT_PCIE_INTR, tegra_pcie_isr, | ||
790 | IRQF_SHARED, "PCIE", &tegra_pcie); | ||
791 | if (err) { | ||
792 | pr_err("PCIE: Failed to register IRQ: %d\n", err); | ||
793 | goto err_irq; | ||
794 | } | ||
795 | set_irq_flags(INT_PCIE_INTR, IRQF_VALID); | ||
796 | |||
797 | return 0; | ||
798 | |||
799 | err_irq: | ||
800 | iounmap(tegra_pcie_io_base); | ||
801 | err_map_io: | ||
802 | release_resource(&tegra_pcie.res_mmio); | ||
803 | err_req_io: | ||
804 | iounmap(tegra_pcie.regs); | ||
805 | err_map_reg: | ||
806 | tegra_pcie_power_off(); | ||
807 | err_pwr_on: | ||
808 | tegra_pcie_clocks_put(); | ||
809 | |||
810 | return err; | ||
811 | } | ||
812 | |||
813 | /* | ||
814 | * FIXME: If there are no PCIe cards attached, then calling this function | ||
815 | * can result in the increase of the bootup time as there are big timeout | ||
816 | * loops. | ||
817 | */ | ||
818 | #define TEGRA_PCIE_LINKUP_TIMEOUT 200 /* up to 1.2 seconds */ | ||
819 | static bool tegra_pcie_check_link(struct tegra_pcie_port *pp, int idx, | ||
820 | u32 reset_reg) | ||
821 | { | ||
822 | u32 reg; | ||
823 | int retries = 3; | ||
824 | int timeout; | ||
825 | |||
826 | do { | ||
827 | timeout = TEGRA_PCIE_LINKUP_TIMEOUT; | ||
828 | while (timeout) { | ||
829 | reg = readl(pp->base + RP_VEND_XP); | ||
830 | |||
831 | if (reg & RP_VEND_XP_DL_UP) | ||
832 | break; | ||
833 | |||
834 | mdelay(1); | ||
835 | timeout--; | ||
836 | } | ||
837 | |||
838 | if (!timeout) { | ||
839 | pr_err("PCIE: port %d: link down, retrying\n", idx); | ||
840 | goto retry; | ||
841 | } | ||
842 | |||
843 | timeout = TEGRA_PCIE_LINKUP_TIMEOUT; | ||
844 | while (timeout) { | ||
845 | reg = readl(pp->base + RP_LINK_CONTROL_STATUS); | ||
846 | |||
847 | if (reg & 0x20000000) | ||
848 | return true; | ||
849 | |||
850 | mdelay(1); | ||
851 | timeout--; | ||
852 | } | ||
853 | |||
854 | retry: | ||
855 | /* Pulse the PEX reset */ | ||
856 | reg = afi_readl(reset_reg) | AFI_PEX_CTRL_RST; | ||
857 | afi_writel(reg, reset_reg); | ||
858 | mdelay(1); | ||
859 | reg = afi_readl(reset_reg) & ~AFI_PEX_CTRL_RST; | ||
860 | afi_writel(reg, reset_reg); | ||
861 | |||
862 | retries--; | ||
863 | } while (retries); | ||
864 | |||
865 | return false; | ||
866 | } | ||
867 | |||
868 | static void __init tegra_pcie_add_port(int index, u32 offset, u32 reset_reg) | ||
869 | { | ||
870 | struct tegra_pcie_port *pp; | ||
871 | |||
872 | pp = tegra_pcie.port + tegra_pcie.num_ports; | ||
873 | |||
874 | pp->index = -1; | ||
875 | pp->base = tegra_pcie.regs + offset; | ||
876 | pp->link_up = tegra_pcie_check_link(pp, index, reset_reg); | ||
877 | |||
878 | if (!pp->link_up) { | ||
879 | pp->base = NULL; | ||
880 | printk(KERN_INFO "PCIE: port %d: link down, ignoring\n", index); | ||
881 | return; | ||
882 | } | ||
883 | |||
884 | tegra_pcie.num_ports++; | ||
885 | pp->index = index; | ||
886 | pp->root_bus_nr = -1; | ||
887 | memset(pp->res, 0, sizeof(pp->res)); | ||
888 | } | ||
889 | |||
890 | int __init tegra_pcie_init(bool init_port0, bool init_port1) | ||
891 | { | ||
892 | int err; | ||
893 | |||
894 | if (!(init_port0 || init_port1)) | ||
895 | return -ENODEV; | ||
896 | |||
897 | err = tegra_pcie_get_resources(); | ||
898 | if (err) | ||
899 | return err; | ||
900 | |||
901 | tegra_pcie_enable_controller(); | ||
902 | |||
903 | /* setup the AFI address translations */ | ||
904 | tegra_pcie_setup_translations(); | ||
905 | |||
906 | if (init_port0) | ||
907 | tegra_pcie_add_port(0, RP0_OFFSET, AFI_PEX0_CTRL); | ||
908 | |||
909 | if (init_port1) | ||
910 | tegra_pcie_add_port(1, RP1_OFFSET, AFI_PEX1_CTRL); | ||
911 | |||
912 | pci_common_init(&tegra_pcie_hw); | ||
913 | |||
914 | return 0; | ||
915 | } | ||
diff --git a/arch/arm/mach-tegra/pinmux-t2-tables.c b/arch/arm/mach-tegra/pinmux-t2-tables.c new file mode 100644 index 000000000000..a6ea34e782dc --- /dev/null +++ b/arch/arm/mach-tegra/pinmux-t2-tables.c | |||
@@ -0,0 +1,260 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/mach-tegra/pinmux-t2-tables.c | ||
3 | * | ||
4 | * Common pinmux configurations for Tegra 2 SoCs | ||
5 | * | ||
6 | * Copyright (C) 2010 NVIDIA Corporation | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
14 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
15 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
16 | * more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License along | ||
19 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
20 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
21 | */ | ||
22 | |||
23 | #include <linux/kernel.h> | ||
24 | #include <linux/errno.h> | ||
25 | #include <linux/spinlock.h> | ||
26 | #include <linux/io.h> | ||
27 | #include <linux/init.h> | ||
28 | #include <linux/string.h> | ||
29 | |||
30 | #include <mach/iomap.h> | ||
31 | #include <mach/pinmux.h> | ||
32 | |||
33 | #define DRIVE_PINGROUP(pg_name, r) \ | ||
34 | [TEGRA_DRIVE_PINGROUP_ ## pg_name] = { \ | ||
35 | .name = #pg_name, \ | ||
36 | .reg = r \ | ||
37 | } | ||
38 | |||
39 | const struct tegra_drive_pingroup_desc tegra_soc_drive_pingroups[TEGRA_MAX_DRIVE_PINGROUP] = { | ||
40 | DRIVE_PINGROUP(AO1, 0x868), | ||
41 | DRIVE_PINGROUP(AO2, 0x86c), | ||
42 | DRIVE_PINGROUP(AT1, 0x870), | ||
43 | DRIVE_PINGROUP(AT2, 0x874), | ||
44 | DRIVE_PINGROUP(CDEV1, 0x878), | ||
45 | DRIVE_PINGROUP(CDEV2, 0x87c), | ||
46 | DRIVE_PINGROUP(CSUS, 0x880), | ||
47 | DRIVE_PINGROUP(DAP1, 0x884), | ||
48 | DRIVE_PINGROUP(DAP2, 0x888), | ||
49 | DRIVE_PINGROUP(DAP3, 0x88c), | ||
50 | DRIVE_PINGROUP(DAP4, 0x890), | ||
51 | DRIVE_PINGROUP(DBG, 0x894), | ||
52 | DRIVE_PINGROUP(LCD1, 0x898), | ||
53 | DRIVE_PINGROUP(LCD2, 0x89c), | ||
54 | DRIVE_PINGROUP(SDMMC2, 0x8a0), | ||
55 | DRIVE_PINGROUP(SDMMC3, 0x8a4), | ||
56 | DRIVE_PINGROUP(SPI, 0x8a8), | ||
57 | DRIVE_PINGROUP(UAA, 0x8ac), | ||
58 | DRIVE_PINGROUP(UAB, 0x8b0), | ||
59 | DRIVE_PINGROUP(UART2, 0x8b4), | ||
60 | DRIVE_PINGROUP(UART3, 0x8b8), | ||
61 | DRIVE_PINGROUP(VI1, 0x8bc), | ||
62 | DRIVE_PINGROUP(VI2, 0x8c0), | ||
63 | DRIVE_PINGROUP(XM2A, 0x8c4), | ||
64 | DRIVE_PINGROUP(XM2C, 0x8c8), | ||
65 | DRIVE_PINGROUP(XM2D, 0x8cc), | ||
66 | DRIVE_PINGROUP(XM2CLK, 0x8d0), | ||
67 | DRIVE_PINGROUP(MEMCOMP, 0x8d4), | ||
68 | }; | ||
69 | |||
70 | #define PINGROUP(pg_name, vdd, f0, f1, f2, f3, f_safe, \ | ||
71 | tri_r, tri_b, mux_r, mux_b, pupd_r, pupd_b) \ | ||
72 | [TEGRA_PINGROUP_ ## pg_name] = { \ | ||
73 | .name = #pg_name, \ | ||
74 | .vddio = TEGRA_VDDIO_ ## vdd, \ | ||
75 | .funcs = { \ | ||
76 | TEGRA_MUX_ ## f0, \ | ||
77 | TEGRA_MUX_ ## f1, \ | ||
78 | TEGRA_MUX_ ## f2, \ | ||
79 | TEGRA_MUX_ ## f3, \ | ||
80 | }, \ | ||
81 | .func_safe = TEGRA_MUX_ ## f_safe, \ | ||
82 | .tri_reg = tri_r, \ | ||
83 | .tri_bit = tri_b, \ | ||
84 | .mux_reg = mux_r, \ | ||
85 | .mux_bit = mux_b, \ | ||
86 | .pupd_reg = pupd_r, \ | ||
87 | .pupd_bit = pupd_b, \ | ||
88 | } | ||
89 | |||
90 | const struct tegra_pingroup_desc tegra_soc_pingroups[TEGRA_MAX_PINGROUP] = { | ||
91 | PINGROUP(ATA, NAND, IDE, NAND, GMI, RSVD, IDE, 0x14, 0, 0x80, 24, 0xA0, 0), | ||
92 | PINGROUP(ATB, NAND, IDE, NAND, GMI, SDIO4, IDE, 0x14, 1, 0x80, 16, 0xA0, 2), | ||
93 | PINGROUP(ATC, NAND, IDE, NAND, GMI, SDIO4, IDE, 0x14, 2, 0x80, 22, 0xA0, 4), | ||
94 | PINGROUP(ATD, NAND, IDE, NAND, GMI, SDIO4, IDE, 0x14, 3, 0x80, 20, 0xA0, 6), | ||
95 | PINGROUP(ATE, NAND, IDE, NAND, GMI, RSVD, IDE, 0x18, 25, 0x80, 12, 0xA0, 8), | ||
96 | PINGROUP(CDEV1, AUDIO, OSC, PLLA_OUT, PLLM_OUT1, AUDIO_SYNC, OSC, 0x14, 4, 0x88, 2, 0xA8, 0), | ||
97 | PINGROUP(CDEV2, AUDIO, OSC, AHB_CLK, APB_CLK, PLLP_OUT4, OSC, 0x14, 5, 0x88, 4, 0xA8, 2), | ||
98 | PINGROUP(CRTP, LCD, CRT, RSVD, RSVD, RSVD, RSVD, 0x20, 14, 0x98, 20, 0xA4, 24), | ||
99 | PINGROUP(CSUS, VI, PLLC_OUT1, PLLP_OUT2, PLLP_OUT3, VI_SENSOR_CLK, PLLC_OUT1, 0x14, 6, 0x88, 6, 0xAC, 24), | ||
100 | PINGROUP(DAP1, AUDIO, DAP1, RSVD, GMI, SDIO2, DAP1, 0x14, 7, 0x88, 20, 0xA0, 10), | ||
101 | PINGROUP(DAP2, AUDIO, DAP2, TWC, RSVD, GMI, DAP2, 0x14, 8, 0x88, 22, 0xA0, 12), | ||
102 | PINGROUP(DAP3, BB, DAP3, RSVD, RSVD, RSVD, DAP3, 0x14, 9, 0x88, 24, 0xA0, 14), | ||
103 | PINGROUP(DAP4, UART, DAP4, RSVD, GMI, RSVD, DAP4, 0x14, 10, 0x88, 26, 0xA0, 16), | ||
104 | PINGROUP(DDC, LCD, I2C2, RSVD, RSVD, RSVD, RSVD4, 0x18, 31, 0x88, 0, 0xB0, 28), | ||
105 | PINGROUP(DTA, VI, RSVD, SDIO2, VI, RSVD, RSVD4, 0x14, 11, 0x84, 20, 0xA0, 18), | ||
106 | PINGROUP(DTB, VI, RSVD, RSVD, VI, SPI1, RSVD1, 0x14, 12, 0x84, 22, 0xA0, 20), | ||
107 | PINGROUP(DTC, VI, RSVD, RSVD, VI, RSVD, RSVD1, 0x14, 13, 0x84, 26, 0xA0, 22), | ||
108 | PINGROUP(DTD, VI, RSVD, SDIO2, VI, RSVD, RSVD1, 0x14, 14, 0x84, 28, 0xA0, 24), | ||
109 | PINGROUP(DTE, VI, RSVD, RSVD, VI, SPI1, RSVD1, 0x14, 15, 0x84, 30, 0xA0, 26), | ||
110 | PINGROUP(DTF, VI, I2C3, RSVD, VI, RSVD, RSVD4, 0x20, 12, 0x98, 30, 0xA0, 28), | ||
111 | PINGROUP(GMA, NAND, UARTE, SPI3, GMI, SDIO4, SPI3, 0x14, 28, 0x84, 0, 0xB0, 20), | ||
112 | PINGROUP(GMB, NAND, IDE, NAND, GMI, GMI_INT, GMI, 0x18, 29, 0x88, 28, 0xB0, 22), | ||
113 | PINGROUP(GMC, NAND, UARTD, SPI4, GMI, SFLASH, SPI4, 0x14, 29, 0x84, 2, 0xB0, 24), | ||
114 | PINGROUP(GMD, NAND, RSVD, NAND, GMI, SFLASH, GMI, 0x18, 30, 0x88, 30, 0xB0, 26), | ||
115 | PINGROUP(GME, NAND, RSVD, DAP5, GMI, SDIO4, GMI, 0x18, 0, 0x8C, 0, 0xA8, 24), | ||
116 | PINGROUP(GPU, UART, PWM, UARTA, GMI, RSVD, RSVD4, 0x14, 16, 0x8C, 4, 0xA4, 20), | ||
117 | PINGROUP(GPU7, SYS, RTCK, RSVD, RSVD, RSVD, RTCK, 0x20, 11, 0x98, 28, 0xA4, 6), | ||
118 | PINGROUP(GPV, SD, PCIE, RSVD, RSVD, RSVD, PCIE, 0x14, 17, 0x8C, 2, 0xA0, 30), | ||
119 | PINGROUP(HDINT, LCD, HDMI, RSVD, RSVD, RSVD, HDMI, 0x1C, 23, 0x84, 4, 0xAC, 22), | ||
120 | PINGROUP(I2CP, SYS, I2C, RSVD, RSVD, RSVD, RSVD4, 0x14, 18, 0x88, 8, 0xA4, 2), | ||
121 | PINGROUP(IRRX, UART, UARTA, UARTB, GMI, SPI4, UARTB, 0x14, 20, 0x88, 18, 0xA8, 22), | ||
122 | PINGROUP(IRTX, UART, UARTA, UARTB, GMI, SPI4, UARTB, 0x14, 19, 0x88, 16, 0xA8, 20), | ||
123 | PINGROUP(KBCA, SYS, KBC, NAND, SDIO2, EMC_TEST0_DLL, KBC, 0x14, 22, 0x88, 10, 0xA4, 8), | ||
124 | PINGROUP(KBCB, SYS, KBC, NAND, SDIO2, MIO, KBC, 0x14, 21, 0x88, 12, 0xA4, 10), | ||
125 | PINGROUP(KBCC, SYS, KBC, NAND, TRACE, EMC_TEST1_DLL, KBC, 0x18, 26, 0x88, 14, 0xA4, 12), | ||
126 | PINGROUP(KBCD, SYS, KBC, NAND, SDIO2, MIO, KBC, 0x20, 10, 0x98, 26, 0xA4, 14), | ||
127 | PINGROUP(KBCE, SYS, KBC, NAND, OWR, RSVD, KBC, 0x14, 26, 0x80, 28, 0xB0, 2), | ||
128 | PINGROUP(KBCF, SYS, KBC, NAND, TRACE, MIO, KBC, 0x14, 27, 0x80, 26, 0xB0, 0), | ||
129 | PINGROUP(LCSN, LCD, DISPLAYA, DISPLAYB, SPI3, RSVD, RSVD4, 0x1C, 31, 0x90, 12, 0xAC, 20), | ||
130 | PINGROUP(LD0, LCD, DISPLAYA, DISPLAYB, XIO, RSVD, RSVD4, 0x1C, 0, 0x94, 0, 0xAC, 12), | ||
131 | PINGROUP(LD1, LCD, DISPLAYA, DISPLAYB, XIO, RSVD, RSVD4, 0x1C, 1, 0x94, 2, 0xAC, 12), | ||
132 | PINGROUP(LD10, LCD, DISPLAYA, DISPLAYB, XIO, RSVD, RSVD4, 0x1C, 10, 0x94, 20, 0xAC, 12), | ||
133 | PINGROUP(LD11, LCD, DISPLAYA, DISPLAYB, XIO, RSVD, RSVD4, 0x1C, 11, 0x94, 22, 0xAC, 12), | ||
134 | PINGROUP(LD12, LCD, DISPLAYA, DISPLAYB, XIO, RSVD, RSVD4, 0x1C, 12, 0x94, 24, 0xAC, 12), | ||
135 | PINGROUP(LD13, LCD, DISPLAYA, DISPLAYB, XIO, RSVD, RSVD4, 0x1C, 13, 0x94, 26, 0xAC, 12), | ||
136 | PINGROUP(LD14, LCD, DISPLAYA, DISPLAYB, XIO, RSVD, RSVD4, 0x1C, 14, 0x94, 28, 0xAC, 12), | ||
137 | PINGROUP(LD15, LCD, DISPLAYA, DISPLAYB, XIO, RSVD, RSVD4, 0x1C, 15, 0x94, 30, 0xAC, 12), | ||
138 | PINGROUP(LD16, LCD, DISPLAYA, DISPLAYB, XIO, RSVD, RSVD4, 0x1C, 16, 0x98, 0, 0xAC, 12), | ||
139 | PINGROUP(LD17, LCD, DISPLAYA, DISPLAYB, RSVD, RSVD, RSVD4, 0x1C, 17, 0x98, 2, 0xAC, 12), | ||
140 | PINGROUP(LD2, LCD, DISPLAYA, DISPLAYB, XIO, RSVD, RSVD4, 0x1C, 2, 0x94, 4, 0xAC, 12), | ||
141 | PINGROUP(LD3, LCD, DISPLAYA, DISPLAYB, XIO, RSVD, RSVD4, 0x1C, 3, 0x94, 6, 0xAC, 12), | ||
142 | PINGROUP(LD4, LCD, DISPLAYA, DISPLAYB, XIO, RSVD, RSVD4, 0x1C, 4, 0x94, 8, 0xAC, 12), | ||
143 | PINGROUP(LD5, LCD, DISPLAYA, DISPLAYB, XIO, RSVD, RSVD4, 0x1C, 5, 0x94, 10, 0xAC, 12), | ||
144 | PINGROUP(LD6, LCD, DISPLAYA, DISPLAYB, XIO, RSVD, RSVD4, 0x1C, 6, 0x94, 12, 0xAC, 12), | ||
145 | PINGROUP(LD7, LCD, DISPLAYA, DISPLAYB, XIO, RSVD, RSVD4, 0x1C, 7, 0x94, 14, 0xAC, 12), | ||
146 | PINGROUP(LD8, LCD, DISPLAYA, DISPLAYB, XIO, RSVD, RSVD4, 0x1C, 8, 0x94, 16, 0xAC, 12), | ||
147 | PINGROUP(LD9, LCD, DISPLAYA, DISPLAYB, XIO, RSVD, RSVD4, 0x1C, 9, 0x94, 18, 0xAC, 12), | ||
148 | PINGROUP(LDC, LCD, DISPLAYA, DISPLAYB, RSVD, RSVD, RSVD4, 0x1C, 30, 0x90, 14, 0xAC, 20), | ||
149 | PINGROUP(LDI, LCD, DISPLAYA, DISPLAYB, RSVD, RSVD, RSVD4, 0x20, 6, 0x98, 16, 0xAC, 18), | ||
150 | PINGROUP(LHP0, LCD, DISPLAYA, DISPLAYB, RSVD, RSVD, RSVD4, 0x1C, 18, 0x98, 10, 0xAC, 16), | ||
151 | PINGROUP(LHP1, LCD, DISPLAYA, DISPLAYB, RSVD, RSVD, RSVD4, 0x1C, 19, 0x98, 4, 0xAC, 14), | ||
152 | PINGROUP(LHP2, LCD, DISPLAYA, DISPLAYB, RSVD, RSVD, RSVD4, 0x1C, 20, 0x98, 6, 0xAC, 14), | ||
153 | PINGROUP(LHS, LCD, DISPLAYA, DISPLAYB, XIO, RSVD, RSVD4, 0x20, 7, 0x90, 22, 0xAC, 22), | ||
154 | PINGROUP(LM0, LCD, DISPLAYA, DISPLAYB, SPI3, RSVD, RSVD4, 0x1C, 24, 0x90, 26, 0xAC, 22), | ||
155 | PINGROUP(LM1, LCD, DISPLAYA, DISPLAYB, RSVD, CRT, RSVD3, 0x1C, 25, 0x90, 28, 0xAC, 22), | ||
156 | PINGROUP(LPP, LCD, DISPLAYA, DISPLAYB, RSVD, RSVD, RSVD4, 0x20, 8, 0x98, 14, 0xAC, 18), | ||
157 | PINGROUP(LPW0, LCD, DISPLAYA, DISPLAYB, SPI3, HDMI, DISPLAYA, 0x20, 3, 0x90, 0, 0xAC, 20), | ||
158 | PINGROUP(LPW1, LCD, DISPLAYA, DISPLAYB, RSVD, RSVD, RSVD4, 0x20, 4, 0x90, 2, 0xAC, 20), | ||
159 | PINGROUP(LPW2, LCD, DISPLAYA, DISPLAYB, SPI3, HDMI, DISPLAYA, 0x20, 5, 0x90, 4, 0xAC, 20), | ||
160 | PINGROUP(LSC0, LCD, DISPLAYA, DISPLAYB, XIO, RSVD, RSVD4, 0x1C, 27, 0x90, 18, 0xAC, 22), | ||
161 | PINGROUP(LSC1, LCD, DISPLAYA, DISPLAYB, SPI3, HDMI, DISPLAYA, 0x1C, 28, 0x90, 20, 0xAC, 20), | ||
162 | PINGROUP(LSCK, LCD, DISPLAYA, DISPLAYB, SPI3, HDMI, DISPLAYA, 0x1C, 29, 0x90, 16, 0xAC, 20), | ||
163 | PINGROUP(LSDA, LCD, DISPLAYA, DISPLAYB, SPI3, HDMI, DISPLAYA, 0x20, 1, 0x90, 8, 0xAC, 20), | ||
164 | PINGROUP(LSDI, LCD, DISPLAYA, DISPLAYB, SPI3, RSVD, DISPLAYA, 0x20, 2, 0x90, 6, 0xAC, 20), | ||
165 | PINGROUP(LSPI, LCD, DISPLAYA, DISPLAYB, XIO, HDMI, DISPLAYA, 0x20, 0, 0x90, 10, 0xAC, 22), | ||
166 | PINGROUP(LVP0, LCD, DISPLAYA, DISPLAYB, RSVD, RSVD, RSVD4, 0x1C, 21, 0x90, 30, 0xAC, 22), | ||
167 | PINGROUP(LVP1, LCD, DISPLAYA, DISPLAYB, RSVD, RSVD, RSVD4, 0x1C, 22, 0x98, 8, 0xAC, 16), | ||
168 | PINGROUP(LVS, LCD, DISPLAYA, DISPLAYB, XIO, RSVD, RSVD4, 0x1C, 26, 0x90, 24, 0xAC, 22), | ||
169 | PINGROUP(OWC, SYS, OWR, RSVD, RSVD, RSVD, OWR, 0x14, 31, 0x84, 8, 0xB0, 30), | ||
170 | PINGROUP(PMC, SYS, PWR_ON, PWR_INTR, RSVD, RSVD, PWR_ON, 0x14, 23, 0x98, 18, -1, -1), | ||
171 | PINGROUP(PTA, NAND, I2C2, HDMI, GMI, RSVD, RSVD4, 0x14, 24, 0x98, 22, 0xA4, 4), | ||
172 | PINGROUP(RM, UART, I2C, RSVD, RSVD, RSVD, RSVD4, 0x14, 25, 0x80, 14, 0xA4, 0), | ||
173 | PINGROUP(SDB, SD, UARTA, PWM, SDIO3, SPI2, PWM, 0x20, 15, 0x8C, 10, -1, -1), | ||
174 | PINGROUP(SDC, SD, PWM, TWC, SDIO3, SPI3, TWC, 0x18, 1, 0x8C, 12, 0xAC, 28), | ||
175 | PINGROUP(SDD, SD, UARTA, PWM, SDIO3, SPI3, PWM, 0x18, 2, 0x8C, 14, 0xAC, 30), | ||
176 | PINGROUP(SDIO1, BB, SDIO1, RSVD, UARTE, UARTA, RSVD2, 0x14, 30, 0x80, 30, 0xB0, 18), | ||
177 | PINGROUP(SLXA, SD, PCIE, SPI4, SDIO3, SPI2, PCIE, 0x18, 3, 0x84, 6, 0xA4, 22), | ||
178 | PINGROUP(SLXC, SD, SPDIF, SPI4, SDIO3, SPI2, SPI4, 0x18, 5, 0x84, 10, 0xA4, 26), | ||
179 | PINGROUP(SLXD, SD, SPDIF, SPI4, SDIO3, SPI2, SPI4, 0x18, 6, 0x84, 12, 0xA4, 28), | ||
180 | PINGROUP(SLXK, SD, PCIE, SPI4, SDIO3, SPI2, PCIE, 0x18, 7, 0x84, 14, 0xA4, 30), | ||
181 | PINGROUP(SPDI, AUDIO, SPDIF, RSVD, I2C, SDIO2, RSVD2, 0x18, 8, 0x8C, 8, 0xA4, 16), | ||
182 | PINGROUP(SPDO, AUDIO, SPDIF, RSVD, I2C, SDIO2, RSVD2, 0x18, 9, 0x8C, 6, 0xA4, 18), | ||
183 | PINGROUP(SPIA, AUDIO, SPI1, SPI2, SPI3, GMI, GMI, 0x18, 10, 0x8C, 30, 0xA8, 4), | ||
184 | PINGROUP(SPIB, AUDIO, SPI1, SPI2, SPI3, GMI, GMI, 0x18, 11, 0x8C, 28, 0xA8, 6), | ||
185 | PINGROUP(SPIC, AUDIO, SPI1, SPI2, SPI3, GMI, GMI, 0x18, 12, 0x8C, 26, 0xA8, 8), | ||
186 | PINGROUP(SPID, AUDIO, SPI2, SPI1, SPI2_ALT, GMI, GMI, 0x18, 13, 0x8C, 24, 0xA8, 10), | ||
187 | PINGROUP(SPIE, AUDIO, SPI2, SPI1, SPI2_ALT, GMI, GMI, 0x18, 14, 0x8C, 22, 0xA8, 12), | ||
188 | PINGROUP(SPIF, AUDIO, SPI3, SPI1, SPI2, RSVD, RSVD4, 0x18, 15, 0x8C, 20, 0xA8, 14), | ||
189 | PINGROUP(SPIG, AUDIO, SPI3, SPI2, SPI2_ALT, I2C, SPI2_ALT, 0x18, 16, 0x8C, 18, 0xA8, 16), | ||
190 | PINGROUP(SPIH, AUDIO, SPI3, SPI2, SPI2_ALT, I2C, SPI2_ALT, 0x18, 17, 0x8C, 16, 0xA8, 18), | ||
191 | PINGROUP(UAA, BB, SPI3, MIPI_HS, UARTA, ULPI, MIPI_HS, 0x18, 18, 0x80, 0, 0xAC, 0), | ||
192 | PINGROUP(UAB, BB, SPI2, MIPI_HS, UARTA, ULPI, MIPI_HS, 0x18, 19, 0x80, 2, 0xAC, 2), | ||
193 | PINGROUP(UAC, BB, OWR, RSVD, RSVD, RSVD, RSVD4, 0x18, 20, 0x80, 4, 0xAC, 4), | ||
194 | PINGROUP(UAD, UART, IRDA, SPDIF, UARTA, SPI4, SPDIF, 0x18, 21, 0x80, 6, 0xAC, 6), | ||
195 | PINGROUP(UCA, UART, UARTC, RSVD, GMI, RSVD, RSVD4, 0x18, 22, 0x84, 16, 0xAC, 8), | ||
196 | PINGROUP(UCB, UART, UARTC, PWM, GMI, RSVD, RSVD4, 0x18, 23, 0x84, 18, 0xAC, 10), | ||
197 | PINGROUP(UDA, BB, SPI1, RSVD, UARTD, ULPI, RSVD2, 0x20, 13, 0x80, 8, 0xB0, 16), | ||
198 | /* these pin groups only have pullup and pull down control */ | ||
199 | PINGROUP(CK32, SYS, RSVD, RSVD, RSVD, RSVD, RSVD, -1, -1, -1, -1, 0xB0, 14), | ||
200 | PINGROUP(DDRC, DDR, RSVD, RSVD, RSVD, RSVD, RSVD, -1, -1, -1, -1, 0xAC, 26), | ||
201 | PINGROUP(PMCA, SYS, RSVD, RSVD, RSVD, RSVD, RSVD, -1, -1, -1, -1, 0xB0, 4), | ||
202 | PINGROUP(PMCB, SYS, RSVD, RSVD, RSVD, RSVD, RSVD, -1, -1, -1, -1, 0xB0, 6), | ||
203 | PINGROUP(PMCC, SYS, RSVD, RSVD, RSVD, RSVD, RSVD, -1, -1, -1, -1, 0xB0, 8), | ||
204 | PINGROUP(PMCD, SYS, RSVD, RSVD, RSVD, RSVD, RSVD, -1, -1, -1, -1, 0xB0, 10), | ||
205 | PINGROUP(PMCE, SYS, RSVD, RSVD, RSVD, RSVD, RSVD, -1, -1, -1, -1, 0xB0, 12), | ||
206 | PINGROUP(XM2C, DDR, RSVD, RSVD, RSVD, RSVD, RSVD, -1, -1, -1, -1, 0xA8, 30), | ||
207 | PINGROUP(XM2D, DDR, RSVD, RSVD, RSVD, RSVD, RSVD, -1, -1, -1, -1, 0xA8, 28), | ||
208 | }; | ||
209 | |||
210 | #ifdef CONFIG_PM | ||
211 | #define TRISTATE_REG_A 0x14 | ||
212 | #define TRISTATE_REG_NUM 4 | ||
213 | #define PIN_MUX_CTL_REG_A 0x80 | ||
214 | #define PIN_MUX_CTL_REG_NUM 8 | ||
215 | #define PULLUPDOWN_REG_A 0xa0 | ||
216 | #define PULLUPDOWN_REG_NUM 5 | ||
217 | |||
218 | static u32 pinmux_reg[TRISTATE_REG_NUM + PIN_MUX_CTL_REG_NUM + | ||
219 | PULLUPDOWN_REG_NUM]; | ||
220 | |||
221 | static inline unsigned long pg_readl(unsigned long offset) | ||
222 | { | ||
223 | return readl(IO_TO_VIRT(TEGRA_APB_MISC_BASE + offset)); | ||
224 | } | ||
225 | |||
226 | static inline void pg_writel(unsigned long value, unsigned long offset) | ||
227 | { | ||
228 | writel(value, IO_TO_VIRT(TEGRA_APB_MISC_BASE + offset)); | ||
229 | } | ||
230 | |||
231 | void tegra_pinmux_suspend(void) | ||
232 | { | ||
233 | unsigned int i; | ||
234 | u32 *ctx = pinmux_reg; | ||
235 | |||
236 | for (i = 0; i < TRISTATE_REG_NUM; i++) | ||
237 | *ctx++ = pg_readl(TRISTATE_REG_A + i*4); | ||
238 | |||
239 | for (i = 0; i < PIN_MUX_CTL_REG_NUM; i++) | ||
240 | *ctx++ = pg_readl(PIN_MUX_CTL_REG_A + i*4); | ||
241 | |||
242 | for (i = 0; i < PULLUPDOWN_REG_NUM; i++) | ||
243 | *ctx++ = pg_readl(PULLUPDOWN_REG_A + i*4); | ||
244 | } | ||
245 | |||
246 | void tegra_pinmux_resume(void) | ||
247 | { | ||
248 | unsigned int i; | ||
249 | u32 *ctx = pinmux_reg; | ||
250 | |||
251 | for (i = 0; i < PIN_MUX_CTL_REG_NUM; i++) | ||
252 | pg_writel(*ctx++, PIN_MUX_CTL_REG_A + i*4); | ||
253 | |||
254 | for (i = 0; i < PULLUPDOWN_REG_NUM; i++) | ||
255 | pg_writel(*ctx++, PULLUPDOWN_REG_A + i*4); | ||
256 | |||
257 | for (i = 0; i < TRISTATE_REG_NUM; i++) | ||
258 | pg_writel(*ctx++, TRISTATE_REG_A + i*4); | ||
259 | } | ||
260 | #endif | ||
diff --git a/arch/arm/mach-tegra/pinmux.c b/arch/arm/mach-tegra/pinmux.c index 13ae10237e84..f80d507671bc 100644 --- a/arch/arm/mach-tegra/pinmux.c +++ b/arch/arm/mach-tegra/pinmux.c | |||
@@ -14,7 +14,8 @@ | |||
14 | * | 14 | * |
15 | */ | 15 | */ |
16 | 16 | ||
17 | 17 | #include <linux/init.h> | |
18 | #include <linux/module.h> | ||
18 | #include <linux/kernel.h> | 19 | #include <linux/kernel.h> |
19 | #include <linux/errno.h> | 20 | #include <linux/errno.h> |
20 | #include <linux/spinlock.h> | 21 | #include <linux/spinlock.h> |
@@ -23,21 +24,6 @@ | |||
23 | #include <mach/iomap.h> | 24 | #include <mach/iomap.h> |
24 | #include <mach/pinmux.h> | 25 | #include <mach/pinmux.h> |
25 | 26 | ||
26 | |||
27 | #define TEGRA_TRI_STATE(x) (0x14 + (4 * (x))) | ||
28 | #define TEGRA_PP_MUX_CTL(x) (0x80 + (4 * (x))) | ||
29 | #define TEGRA_PP_PU_PD(x) (0xa0 + (4 * (x))) | ||
30 | |||
31 | #define REG_A 0 | ||
32 | #define REG_B 1 | ||
33 | #define REG_C 2 | ||
34 | #define REG_D 3 | ||
35 | #define REG_E 4 | ||
36 | #define REG_F 5 | ||
37 | #define REG_G 6 | ||
38 | |||
39 | #define REG_N -1 | ||
40 | |||
41 | #define HSM_EN(reg) (((reg) >> 2) & 0x1) | 27 | #define HSM_EN(reg) (((reg) >> 2) & 0x1) |
42 | #define SCHMT_EN(reg) (((reg) >> 3) & 0x1) | 28 | #define SCHMT_EN(reg) (((reg) >> 3) & 0x1) |
43 | #define LPMD(reg) (((reg) >> 4) & 0x3) | 29 | #define LPMD(reg) (((reg) >> 4) & 0x3) |
@@ -46,154 +32,8 @@ | |||
46 | #define SLWR(reg) (((reg) >> 28) & 0x3) | 32 | #define SLWR(reg) (((reg) >> 28) & 0x3) |
47 | #define SLWF(reg) (((reg) >> 30) & 0x3) | 33 | #define SLWF(reg) (((reg) >> 30) & 0x3) |
48 | 34 | ||
49 | struct tegra_pingroup_desc { | 35 | static const struct tegra_pingroup_desc *const pingroups = tegra_soc_pingroups; |
50 | const char *name; | 36 | static const struct tegra_drive_pingroup_desc *const drive_pingroups = tegra_soc_drive_pingroups; |
51 | int funcs[4]; | ||
52 | s8 tri_reg; /* offset into the TRISTATE_REG_* register bank */ | ||
53 | s8 tri_bit; /* offset into the TRISTATE_REG_* register bit */ | ||
54 | s8 mux_reg; /* offset into the PIN_MUX_CTL_* register bank */ | ||
55 | s8 mux_bit; /* offset into the PIN_MUX_CTL_* register bit */ | ||
56 | s8 pupd_reg; /* offset into the PULL_UPDOWN_REG_* register bank */ | ||
57 | s8 pupd_bit; /* offset into the PULL_UPDOWN_REG_* register bit */ | ||
58 | }; | ||
59 | |||
60 | #define PINGROUP(pg_name, f0, f1, f2, f3, \ | ||
61 | tri_r, tri_b, mux_r, mux_b, pupd_r, pupd_b) \ | ||
62 | [TEGRA_PINGROUP_ ## pg_name] = { \ | ||
63 | .name = #pg_name, \ | ||
64 | .funcs = { \ | ||
65 | TEGRA_MUX_ ## f0, \ | ||
66 | TEGRA_MUX_ ## f1, \ | ||
67 | TEGRA_MUX_ ## f2, \ | ||
68 | TEGRA_MUX_ ## f3, \ | ||
69 | }, \ | ||
70 | .tri_reg = REG_ ## tri_r, \ | ||
71 | .tri_bit = tri_b, \ | ||
72 | .mux_reg = REG_ ## mux_r, \ | ||
73 | .mux_bit = mux_b, \ | ||
74 | .pupd_reg = REG_ ## pupd_r, \ | ||
75 | .pupd_bit = pupd_b, \ | ||
76 | } | ||
77 | |||
78 | static const struct tegra_pingroup_desc pingroups[TEGRA_MAX_PINGROUP] = { | ||
79 | PINGROUP(ATA, IDE, NAND, GMI, RSVD, A, 0, A, 24, A, 0), | ||
80 | PINGROUP(ATB, IDE, NAND, GMI, SDIO4, A, 1, A, 16, A, 2), | ||
81 | PINGROUP(ATC, IDE, NAND, GMI, SDIO4, A, 2, A, 22, A, 4), | ||
82 | PINGROUP(ATD, IDE, NAND, GMI, SDIO4, A, 3, A, 20, A, 6), | ||
83 | PINGROUP(ATE, IDE, NAND, GMI, RSVD, B, 25, A, 12, A, 8), | ||
84 | PINGROUP(CDEV1, OSC, PLLA_OUT, PLLM_OUT1, AUDIO_SYNC, A, 4, C, 2, C, 0), | ||
85 | PINGROUP(CDEV2, OSC, AHB_CLK, APB_CLK, PLLP_OUT4, A, 5, C, 4, C, 2), | ||
86 | PINGROUP(CRTP, CRT, RSVD, RSVD, RSVD, D, 14, G, 20, B, 24), | ||
87 | PINGROUP(CSUS, PLLC_OUT1, PLLP_OUT2, PLLP_OUT3, VI_SENSOR_CLK, A, 6, C, 6, D, 24), | ||
88 | PINGROUP(DAP1, DAP1, RSVD, GMI, SDIO2, A, 7, C, 20, A, 10), | ||
89 | PINGROUP(DAP2, DAP2, TWC, RSVD, GMI, A, 8, C, 22, A, 12), | ||
90 | PINGROUP(DAP3, DAP3, RSVD, RSVD, RSVD, A, 9, C, 24, A, 14), | ||
91 | PINGROUP(DAP4, DAP4, RSVD, GMI, RSVD, A, 10, C, 26, A, 16), | ||
92 | PINGROUP(DDC, I2C2, RSVD, RSVD, RSVD, B, 31, C, 0, E, 28), | ||
93 | PINGROUP(DTA, RSVD, SDIO2, VI, RSVD, A, 11, B, 20, A, 18), | ||
94 | PINGROUP(DTB, RSVD, RSVD, VI, SPI1, A, 12, B, 22, A, 20), | ||
95 | PINGROUP(DTC, RSVD, RSVD, VI, RSVD, A, 13, B, 26, A, 22), | ||
96 | PINGROUP(DTD, RSVD, SDIO2, VI, RSVD, A, 14, B, 28, A, 24), | ||
97 | PINGROUP(DTE, RSVD, RSVD, VI, SPI1, A, 15, B, 30, A, 26), | ||
98 | PINGROUP(DTF, I2C3, RSVD, VI, RSVD, D, 12, G, 30, A, 28), | ||
99 | PINGROUP(GMA, UARTE, SPI3, GMI, SDIO4, A, 28, B, 0, E, 20), | ||
100 | PINGROUP(GMB, IDE, NAND, GMI, GMI_INT, B, 29, C, 28, E, 22), | ||
101 | PINGROUP(GMC, UARTD, SPI4, GMI, SFLASH, A, 29, B, 2, E, 24), | ||
102 | PINGROUP(GMD, RSVD, NAND, GMI, SFLASH, B, 30, C, 30, E, 26), | ||
103 | PINGROUP(GME, RSVD, DAP5, GMI, SDIO4, B, 0, D, 0, C, 24), | ||
104 | PINGROUP(GPU, PWM, UARTA, GMI, RSVD, A, 16, D, 4, B, 20), | ||
105 | PINGROUP(GPU7, RTCK, RSVD, RSVD, RSVD, D, 11, G, 28, B, 6), | ||
106 | PINGROUP(GPV, PCIE, RSVD, RSVD, RSVD, A, 17, D, 2, A, 30), | ||
107 | PINGROUP(HDINT, HDMI, RSVD, RSVD, RSVD, C, 23, B, 4, D, 22), | ||
108 | PINGROUP(I2CP, I2C, RSVD, RSVD, RSVD, A, 18, C, 8, B, 2), | ||
109 | PINGROUP(IRRX, UARTA, UARTB, GMI, SPI4, A, 20, C, 18, C, 22), | ||
110 | PINGROUP(IRTX, UARTA, UARTB, GMI, SPI4, A, 19, C, 16, C, 20), | ||
111 | PINGROUP(KBCA, KBC, NAND, SDIO2, EMC_TEST0_DLL, A, 22, C, 10, B, 8), | ||
112 | PINGROUP(KBCB, KBC, NAND, SDIO2, MIO, A, 21, C, 12, B, 10), | ||
113 | PINGROUP(KBCC, KBC, NAND, TRACE, EMC_TEST1_DLL, B, 26, C, 14, B, 12), | ||
114 | PINGROUP(KBCD, KBC, NAND, SDIO2, MIO, D, 10, G, 26, B, 14), | ||
115 | PINGROUP(KBCE, KBC, NAND, OWR, RSVD, A, 26, A, 28, E, 2), | ||
116 | PINGROUP(KBCF, KBC, NAND, TRACE, MIO, A, 27, A, 26, E, 0), | ||
117 | PINGROUP(LCSN, DISPLAYA, DISPLAYB, SPI3, RSVD, C, 31, E, 12, D, 20), | ||
118 | PINGROUP(LD0, DISPLAYA, DISPLAYB, XIO, RSVD, C, 0, F, 0, D, 12), | ||
119 | PINGROUP(LD1, DISPLAYA, DISPLAYB, XIO, RSVD, C, 1, F, 2, D, 12), | ||
120 | PINGROUP(LD10, DISPLAYA, DISPLAYB, XIO, RSVD, C, 10, F, 20, D, 12), | ||
121 | PINGROUP(LD11, DISPLAYA, DISPLAYB, XIO, RSVD, C, 11, F, 22, D, 12), | ||
122 | PINGROUP(LD12, DISPLAYA, DISPLAYB, XIO, RSVD, C, 12, F, 24, D, 12), | ||
123 | PINGROUP(LD13, DISPLAYA, DISPLAYB, XIO, RSVD, C, 13, F, 26, D, 12), | ||
124 | PINGROUP(LD14, DISPLAYA, DISPLAYB, XIO, RSVD, C, 14, F, 28, D, 12), | ||
125 | PINGROUP(LD15, DISPLAYA, DISPLAYB, XIO, RSVD, C, 15, F, 30, D, 12), | ||
126 | PINGROUP(LD16, DISPLAYA, DISPLAYB, XIO, RSVD, C, 16, G, 0, D, 12), | ||
127 | PINGROUP(LD17, DISPLAYA, DISPLAYB, RSVD, RSVD, C, 17, G, 2, D, 12), | ||
128 | PINGROUP(LD2, DISPLAYA, DISPLAYB, XIO, RSVD, C, 2, F, 4, D, 12), | ||
129 | PINGROUP(LD3, DISPLAYA, DISPLAYB, XIO, RSVD, C, 3, F, 6, D, 12), | ||
130 | PINGROUP(LD4, DISPLAYA, DISPLAYB, XIO, RSVD, C, 4, F, 8, D, 12), | ||
131 | PINGROUP(LD5, DISPLAYA, DISPLAYB, XIO, RSVD, C, 5, F, 10, D, 12), | ||
132 | PINGROUP(LD6, DISPLAYA, DISPLAYB, XIO, RSVD, C, 6, F, 12, D, 12), | ||
133 | PINGROUP(LD7, DISPLAYA, DISPLAYB, XIO, RSVD, C, 7, F, 14, D, 12), | ||
134 | PINGROUP(LD8, DISPLAYA, DISPLAYB, XIO, RSVD, C, 8, F, 16, D, 12), | ||
135 | PINGROUP(LD9, DISPLAYA, DISPLAYB, XIO, RSVD, C, 9, F, 18, D, 12), | ||
136 | PINGROUP(LDC, DISPLAYA, DISPLAYB, RSVD, RSVD, C, 30, E, 14, D, 20), | ||
137 | PINGROUP(LDI, DISPLAYA, DISPLAYB, RSVD, RSVD, D, 6, G, 16, D, 18), | ||
138 | PINGROUP(LHP0, DISPLAYA, DISPLAYB, RSVD, RSVD, C, 18, G, 10, D, 16), | ||
139 | PINGROUP(LHP1, DISPLAYA, DISPLAYB, RSVD, RSVD, C, 19, G, 4, D, 14), | ||
140 | PINGROUP(LHP2, DISPLAYA, DISPLAYB, RSVD, RSVD, C, 20, G, 6, D, 14), | ||
141 | PINGROUP(LHS, DISPLAYA, DISPLAYB, XIO, RSVD, D, 7, E, 22, D, 22), | ||
142 | PINGROUP(LM0, DISPLAYA, DISPLAYB, SPI3, RSVD, C, 24, E, 26, D, 22), | ||
143 | PINGROUP(LM1, DISPLAYA, DISPLAYB, RSVD, CRT, C, 25, E, 28, D, 22), | ||
144 | PINGROUP(LPP, DISPLAYA, DISPLAYB, RSVD, RSVD, D, 8, G, 14, D, 18), | ||
145 | PINGROUP(LPW0, DISPLAYA, DISPLAYB, SPI3, HDMI, D, 3, E, 0, D, 20), | ||
146 | PINGROUP(LPW1, DISPLAYA, DISPLAYB, RSVD, RSVD, D, 4, E, 2, D, 20), | ||
147 | PINGROUP(LPW2, DISPLAYA, DISPLAYB, SPI3, HDMI, D, 5, E, 4, D, 20), | ||
148 | PINGROUP(LSC0, DISPLAYA, DISPLAYB, XIO, RSVD, C, 27, E, 18, D, 22), | ||
149 | PINGROUP(LSC1, DISPLAYA, DISPLAYB, SPI3, HDMI, C, 28, E, 20, D, 20), | ||
150 | PINGROUP(LSCK, DISPLAYA, DISPLAYB, SPI3, HDMI, C, 29, E, 16, D, 20), | ||
151 | PINGROUP(LSDA, DISPLAYA, DISPLAYB, SPI3, HDMI, D, 1, E, 8, D, 20), | ||
152 | PINGROUP(LSDI, DISPLAYA, DISPLAYB, SPI3, RSVD, D, 2, E, 6, D, 20), | ||
153 | PINGROUP(LSPI, DISPLAYA, DISPLAYB, XIO, HDMI, D, 0, E, 10, D, 22), | ||
154 | PINGROUP(LVP0, DISPLAYA, DISPLAYB, RSVD, RSVD, C, 21, E, 30, D, 22), | ||
155 | PINGROUP(LVP1, DISPLAYA, DISPLAYB, RSVD, RSVD, C, 22, G, 8, D, 16), | ||
156 | PINGROUP(LVS, DISPLAYA, DISPLAYB, XIO, RSVD, C, 26, E, 24, D, 22), | ||
157 | PINGROUP(OWC, OWR, RSVD, RSVD, RSVD, A, 31, B, 8, E, 30), | ||
158 | PINGROUP(PMC, PWR_ON, PWR_INTR, RSVD, RSVD, A, 23, G, 18, N, -1), | ||
159 | PINGROUP(PTA, I2C2, HDMI, GMI, RSVD, A, 24, G, 22, B, 4), | ||
160 | PINGROUP(RM, I2C, RSVD, RSVD, RSVD, A, 25, A, 14, B, 0), | ||
161 | PINGROUP(SDB, UARTA, PWM, SDIO3, SPI2, D, 15, D, 10, N, -1), | ||
162 | PINGROUP(SDC, PWM, TWC, SDIO3, SPI3, B, 1, D, 12, D, 28), | ||
163 | PINGROUP(SDD, UARTA, PWM, SDIO3, SPI3, B, 2, D, 14, D, 30), | ||
164 | PINGROUP(SDIO1, SDIO1, RSVD, UARTE, UARTA, A, 30, A, 30, E, 18), | ||
165 | PINGROUP(SLXA, PCIE, SPI4, SDIO3, SPI2, B, 3, B, 6, B, 22), | ||
166 | PINGROUP(SLXC, SPDIF, SPI4, SDIO3, SPI2, B, 5, B, 10, B, 26), | ||
167 | PINGROUP(SLXD, SPDIF, SPI4, SDIO3, SPI2, B, 6, B, 12, B, 28), | ||
168 | PINGROUP(SLXK, PCIE, SPI4, SDIO3, SPI2, B, 7, B, 14, B, 30), | ||
169 | PINGROUP(SPDI, SPDIF, RSVD, I2C, SDIO2, B, 8, D, 8, B, 16), | ||
170 | PINGROUP(SPDO, SPDIF, RSVD, I2C, SDIO2, B, 9, D, 6, B, 18), | ||
171 | PINGROUP(SPIA, SPI1, SPI2, SPI3, GMI, B, 10, D, 30, C, 4), | ||
172 | PINGROUP(SPIB, SPI1, SPI2, SPI3, GMI, B, 11, D, 28, C, 6), | ||
173 | PINGROUP(SPIC, SPI1, SPI2, SPI3, GMI, B, 12, D, 26, C, 8), | ||
174 | PINGROUP(SPID, SPI2, SPI1, SPI2_ALT, GMI, B, 13, D, 24, C, 10), | ||
175 | PINGROUP(SPIE, SPI2, SPI1, SPI2_ALT, GMI, B, 14, D, 22, C, 12), | ||
176 | PINGROUP(SPIF, SPI3, SPI1, SPI2, RSVD, B, 15, D, 20, C, 14), | ||
177 | PINGROUP(SPIG, SPI3, SPI2, SPI2_ALT, I2C, B, 16, D, 18, C, 16), | ||
178 | PINGROUP(SPIH, SPI3, SPI2, SPI2_ALT, I2C, B, 17, D, 16, C, 18), | ||
179 | PINGROUP(UAA, SPI3, MIPI_HS, UARTA, ULPI, B, 18, A, 0, D, 0), | ||
180 | PINGROUP(UAB, SPI2, MIPI_HS, UARTA, ULPI, B, 19, A, 2, D, 2), | ||
181 | PINGROUP(UAC, OWR, RSVD, RSVD, RSVD, B, 20, A, 4, D, 4), | ||
182 | PINGROUP(UAD, IRDA, SPDIF, UARTA, SPI4, B, 21, A, 6, D, 6), | ||
183 | PINGROUP(UCA, UARTC, RSVD, GMI, RSVD, B, 22, B, 16, D, 8), | ||
184 | PINGROUP(UCB, UARTC, PWM, GMI, RSVD, B, 23, B, 18, D, 10), | ||
185 | PINGROUP(UDA, SPI1, RSVD, UARTD, ULPI, D, 13, A, 8, E, 16), | ||
186 | /* these pin groups only have pullup and pull down control */ | ||
187 | PINGROUP(CK32, RSVD, RSVD, RSVD, RSVD, N, -1, N, -1, E, 14), | ||
188 | PINGROUP(DDRC, RSVD, RSVD, RSVD, RSVD, N, -1, N, -1, D, 26), | ||
189 | PINGROUP(PMCA, RSVD, RSVD, RSVD, RSVD, N, -1, N, -1, E, 4), | ||
190 | PINGROUP(PMCB, RSVD, RSVD, RSVD, RSVD, N, -1, N, -1, E, 6), | ||
191 | PINGROUP(PMCC, RSVD, RSVD, RSVD, RSVD, N, -1, N, -1, E, 8), | ||
192 | PINGROUP(PMCD, RSVD, RSVD, RSVD, RSVD, N, -1, N, -1, E, 10), | ||
193 | PINGROUP(PMCE, RSVD, RSVD, RSVD, RSVD, N, -1, N, -1, E, 12), | ||
194 | PINGROUP(XM2C, RSVD, RSVD, RSVD, RSVD, N, -1, N, -1, C, 30), | ||
195 | PINGROUP(XM2D, RSVD, RSVD, RSVD, RSVD, N, -1, N, -1, C, 28), | ||
196 | }; | ||
197 | 37 | ||
198 | static char *tegra_mux_names[TEGRA_MAX_MUX] = { | 38 | static char *tegra_mux_names[TEGRA_MAX_MUX] = { |
199 | [TEGRA_MUX_AHB_CLK] = "AHB_CLK", | 39 | [TEGRA_MUX_AHB_CLK] = "AHB_CLK", |
@@ -256,48 +96,7 @@ static char *tegra_mux_names[TEGRA_MAX_MUX] = { | |||
256 | [TEGRA_MUX_VI] = "VI", | 96 | [TEGRA_MUX_VI] = "VI", |
257 | [TEGRA_MUX_VI_SENSOR_CLK] = "VI_SENSOR_CLK", | 97 | [TEGRA_MUX_VI_SENSOR_CLK] = "VI_SENSOR_CLK", |
258 | [TEGRA_MUX_XIO] = "XIO", | 98 | [TEGRA_MUX_XIO] = "XIO", |
259 | }; | 99 | [TEGRA_MUX_SAFE] = "<safe>", |
260 | |||
261 | struct tegra_drive_pingroup_desc { | ||
262 | const char *name; | ||
263 | s16 reg; | ||
264 | }; | ||
265 | |||
266 | #define DRIVE_PINGROUP(pg_name, r) \ | ||
267 | [TEGRA_DRIVE_PINGROUP_ ## pg_name] = { \ | ||
268 | .name = #pg_name, \ | ||
269 | .reg = r \ | ||
270 | } | ||
271 | |||
272 | static const struct tegra_drive_pingroup_desc drive_pingroups[TEGRA_MAX_PINGROUP] = { | ||
273 | DRIVE_PINGROUP(AO1, 0x868), | ||
274 | DRIVE_PINGROUP(AO2, 0x86c), | ||
275 | DRIVE_PINGROUP(AT1, 0x870), | ||
276 | DRIVE_PINGROUP(AT2, 0x874), | ||
277 | DRIVE_PINGROUP(CDEV1, 0x878), | ||
278 | DRIVE_PINGROUP(CDEV2, 0x87c), | ||
279 | DRIVE_PINGROUP(CSUS, 0x880), | ||
280 | DRIVE_PINGROUP(DAP1, 0x884), | ||
281 | DRIVE_PINGROUP(DAP2, 0x888), | ||
282 | DRIVE_PINGROUP(DAP3, 0x88c), | ||
283 | DRIVE_PINGROUP(DAP4, 0x890), | ||
284 | DRIVE_PINGROUP(DBG, 0x894), | ||
285 | DRIVE_PINGROUP(LCD1, 0x898), | ||
286 | DRIVE_PINGROUP(LCD2, 0x89c), | ||
287 | DRIVE_PINGROUP(SDMMC2, 0x8a0), | ||
288 | DRIVE_PINGROUP(SDMMC3, 0x8a4), | ||
289 | DRIVE_PINGROUP(SPI, 0x8a8), | ||
290 | DRIVE_PINGROUP(UAA, 0x8ac), | ||
291 | DRIVE_PINGROUP(UAB, 0x8b0), | ||
292 | DRIVE_PINGROUP(UART2, 0x8b4), | ||
293 | DRIVE_PINGROUP(UART3, 0x8b8), | ||
294 | DRIVE_PINGROUP(VI1, 0x8bc), | ||
295 | DRIVE_PINGROUP(VI2, 0x8c0), | ||
296 | DRIVE_PINGROUP(XM2A, 0x8c4), | ||
297 | DRIVE_PINGROUP(XM2C, 0x8c8), | ||
298 | DRIVE_PINGROUP(XM2D, 0x8cc), | ||
299 | DRIVE_PINGROUP(XM2CLK, 0x8d0), | ||
300 | DRIVE_PINGROUP(MEMCOMP, 0x8d4), | ||
301 | }; | 100 | }; |
302 | 101 | ||
303 | static const char *tegra_drive_names[TEGRA_MAX_DRIVE] = { | 102 | static const char *tegra_drive_names[TEGRA_MAX_DRIVE] = { |
@@ -381,22 +180,27 @@ static inline void pg_writel(unsigned long value, unsigned long offset) | |||
381 | writel(value, IO_TO_VIRT(TEGRA_APB_MISC_BASE + offset)); | 180 | writel(value, IO_TO_VIRT(TEGRA_APB_MISC_BASE + offset)); |
382 | } | 181 | } |
383 | 182 | ||
384 | int tegra_pinmux_set_func(enum tegra_pingroup pg, enum tegra_mux_func func) | 183 | static int tegra_pinmux_set_func(const struct tegra_pingroup_config *config) |
385 | { | 184 | { |
386 | int mux = -1; | 185 | int mux = -1; |
387 | int i; | 186 | int i; |
388 | unsigned long reg; | 187 | unsigned long reg; |
389 | unsigned long flags; | 188 | unsigned long flags; |
189 | enum tegra_pingroup pg = config->pingroup; | ||
190 | enum tegra_mux_func func = config->func; | ||
390 | 191 | ||
391 | if (pg < 0 || pg >= TEGRA_MAX_PINGROUP) | 192 | if (pg < 0 || pg >= TEGRA_MAX_PINGROUP) |
392 | return -ERANGE; | 193 | return -ERANGE; |
393 | 194 | ||
394 | if (pingroups[pg].mux_reg == REG_N) | 195 | if (pingroups[pg].mux_reg < 0) |
395 | return -EINVAL; | 196 | return -EINVAL; |
396 | 197 | ||
397 | if (func < 0) | 198 | if (func < 0) |
398 | return -ERANGE; | 199 | return -ERANGE; |
399 | 200 | ||
201 | if (func == TEGRA_MUX_SAFE) | ||
202 | func = pingroups[pg].func_safe; | ||
203 | |||
400 | if (func & TEGRA_MUX_RSVD) { | 204 | if (func & TEGRA_MUX_RSVD) { |
401 | mux = func & 0x3; | 205 | mux = func & 0x3; |
402 | } else { | 206 | } else { |
@@ -413,10 +217,10 @@ int tegra_pinmux_set_func(enum tegra_pingroup pg, enum tegra_mux_func func) | |||
413 | 217 | ||
414 | spin_lock_irqsave(&mux_lock, flags); | 218 | spin_lock_irqsave(&mux_lock, flags); |
415 | 219 | ||
416 | reg = pg_readl(TEGRA_PP_MUX_CTL(pingroups[pg].mux_reg)); | 220 | reg = pg_readl(pingroups[pg].mux_reg); |
417 | reg &= ~(0x3 << pingroups[pg].mux_bit); | 221 | reg &= ~(0x3 << pingroups[pg].mux_bit); |
418 | reg |= mux << pingroups[pg].mux_bit; | 222 | reg |= mux << pingroups[pg].mux_bit; |
419 | pg_writel(reg, TEGRA_PP_MUX_CTL(pingroups[pg].mux_reg)); | 223 | pg_writel(reg, pingroups[pg].mux_reg); |
420 | 224 | ||
421 | spin_unlock_irqrestore(&mux_lock, flags); | 225 | spin_unlock_irqrestore(&mux_lock, flags); |
422 | 226 | ||
@@ -432,16 +236,16 @@ int tegra_pinmux_set_tristate(enum tegra_pingroup pg, | |||
432 | if (pg < 0 || pg >= TEGRA_MAX_PINGROUP) | 236 | if (pg < 0 || pg >= TEGRA_MAX_PINGROUP) |
433 | return -ERANGE; | 237 | return -ERANGE; |
434 | 238 | ||
435 | if (pingroups[pg].tri_reg == REG_N) | 239 | if (pingroups[pg].tri_reg < 0) |
436 | return -EINVAL; | 240 | return -EINVAL; |
437 | 241 | ||
438 | spin_lock_irqsave(&mux_lock, flags); | 242 | spin_lock_irqsave(&mux_lock, flags); |
439 | 243 | ||
440 | reg = pg_readl(TEGRA_TRI_STATE(pingroups[pg].tri_reg)); | 244 | reg = pg_readl(pingroups[pg].tri_reg); |
441 | reg &= ~(0x1 << pingroups[pg].tri_bit); | 245 | reg &= ~(0x1 << pingroups[pg].tri_bit); |
442 | if (tristate) | 246 | if (tristate) |
443 | reg |= 1 << pingroups[pg].tri_bit; | 247 | reg |= 1 << pingroups[pg].tri_bit; |
444 | pg_writel(reg, TEGRA_TRI_STATE(pingroups[pg].tri_reg)); | 248 | pg_writel(reg, pingroups[pg].tri_reg); |
445 | 249 | ||
446 | spin_unlock_irqrestore(&mux_lock, flags); | 250 | spin_unlock_irqrestore(&mux_lock, flags); |
447 | 251 | ||
@@ -457,7 +261,7 @@ int tegra_pinmux_set_pullupdown(enum tegra_pingroup pg, | |||
457 | if (pg < 0 || pg >= TEGRA_MAX_PINGROUP) | 261 | if (pg < 0 || pg >= TEGRA_MAX_PINGROUP) |
458 | return -ERANGE; | 262 | return -ERANGE; |
459 | 263 | ||
460 | if (pingroups[pg].pupd_reg == REG_N) | 264 | if (pingroups[pg].pupd_reg < 0) |
461 | return -EINVAL; | 265 | return -EINVAL; |
462 | 266 | ||
463 | if (pupd != TEGRA_PUPD_NORMAL && | 267 | if (pupd != TEGRA_PUPD_NORMAL && |
@@ -468,38 +272,39 @@ int tegra_pinmux_set_pullupdown(enum tegra_pingroup pg, | |||
468 | 272 | ||
469 | spin_lock_irqsave(&mux_lock, flags); | 273 | spin_lock_irqsave(&mux_lock, flags); |
470 | 274 | ||
471 | reg = pg_readl(TEGRA_PP_PU_PD(pingroups[pg].pupd_reg)); | 275 | reg = pg_readl(pingroups[pg].pupd_reg); |
472 | reg &= ~(0x3 << pingroups[pg].pupd_bit); | 276 | reg &= ~(0x3 << pingroups[pg].pupd_bit); |
473 | reg |= pupd << pingroups[pg].pupd_bit; | 277 | reg |= pupd << pingroups[pg].pupd_bit; |
474 | pg_writel(reg, TEGRA_PP_PU_PD(pingroups[pg].pupd_reg)); | 278 | pg_writel(reg, pingroups[pg].pupd_reg); |
475 | 279 | ||
476 | spin_unlock_irqrestore(&mux_lock, flags); | 280 | spin_unlock_irqrestore(&mux_lock, flags); |
477 | 281 | ||
478 | return 0; | 282 | return 0; |
479 | } | 283 | } |
480 | 284 | ||
481 | void tegra_pinmux_config_pingroup(enum tegra_pingroup pingroup, | 285 | static void tegra_pinmux_config_pingroup(const struct tegra_pingroup_config *config) |
482 | enum tegra_mux_func func, | ||
483 | enum tegra_pullupdown pupd, | ||
484 | enum tegra_tristate tristate) | ||
485 | { | 286 | { |
287 | enum tegra_pingroup pingroup = config->pingroup; | ||
288 | enum tegra_mux_func func = config->func; | ||
289 | enum tegra_pullupdown pupd = config->pupd; | ||
290 | enum tegra_tristate tristate = config->tristate; | ||
486 | int err; | 291 | int err; |
487 | 292 | ||
488 | if (pingroups[pingroup].mux_reg != REG_N) { | 293 | if (pingroups[pingroup].mux_reg >= 0) { |
489 | err = tegra_pinmux_set_func(pingroup, func); | 294 | err = tegra_pinmux_set_func(config); |
490 | if (err < 0) | 295 | if (err < 0) |
491 | pr_err("pinmux: can't set pingroup %s func to %s: %d\n", | 296 | pr_err("pinmux: can't set pingroup %s func to %s: %d\n", |
492 | pingroup_name(pingroup), func_name(func), err); | 297 | pingroup_name(pingroup), func_name(func), err); |
493 | } | 298 | } |
494 | 299 | ||
495 | if (pingroups[pingroup].pupd_reg != REG_N) { | 300 | if (pingroups[pingroup].pupd_reg >= 0) { |
496 | err = tegra_pinmux_set_pullupdown(pingroup, pupd); | 301 | err = tegra_pinmux_set_pullupdown(pingroup, pupd); |
497 | if (err < 0) | 302 | if (err < 0) |
498 | pr_err("pinmux: can't set pingroup %s pullupdown to %s: %d\n", | 303 | pr_err("pinmux: can't set pingroup %s pullupdown to %s: %d\n", |
499 | pingroup_name(pingroup), pupd_name(pupd), err); | 304 | pingroup_name(pingroup), pupd_name(pupd), err); |
500 | } | 305 | } |
501 | 306 | ||
502 | if (pingroups[pingroup].tri_reg != REG_N) { | 307 | if (pingroups[pingroup].tri_reg >= 0) { |
503 | err = tegra_pinmux_set_tristate(pingroup, tristate); | 308 | err = tegra_pinmux_set_tristate(pingroup, tristate); |
504 | if (err < 0) | 309 | if (err < 0) |
505 | pr_err("pinmux: can't set pingroup %s tristate to %s: %d\n", | 310 | pr_err("pinmux: can't set pingroup %s tristate to %s: %d\n", |
@@ -507,17 +312,12 @@ void tegra_pinmux_config_pingroup(enum tegra_pingroup pingroup, | |||
507 | } | 312 | } |
508 | } | 313 | } |
509 | 314 | ||
510 | 315 | void tegra_pinmux_config_table(const struct tegra_pingroup_config *config, int len) | |
511 | |||
512 | void tegra_pinmux_config_table(struct tegra_pingroup_config *config, int len) | ||
513 | { | 316 | { |
514 | int i; | 317 | int i; |
515 | 318 | ||
516 | for (i = 0; i < len; i++) | 319 | for (i = 0; i < len; i++) |
517 | tegra_pinmux_config_pingroup(config[i].pingroup, | 320 | tegra_pinmux_config_pingroup(&config[i]); |
518 | config[i].func, | ||
519 | config[i].pupd, | ||
520 | config[i].tristate); | ||
521 | } | 321 | } |
522 | 322 | ||
523 | static const char *drive_pinmux_name(enum tegra_drive_pingroup pg) | 323 | static const char *drive_pinmux_name(enum tegra_drive_pingroup pg) |
@@ -784,6 +584,86 @@ void tegra_drive_pinmux_config_table(struct tegra_drive_pingroup_config *config, | |||
784 | config[i].slew_falling); | 584 | config[i].slew_falling); |
785 | } | 585 | } |
786 | 586 | ||
587 | void tegra_pinmux_set_safe_pinmux_table(const struct tegra_pingroup_config *config, | ||
588 | int len) | ||
589 | { | ||
590 | int i; | ||
591 | struct tegra_pingroup_config c; | ||
592 | |||
593 | for (i = 0; i < len; i++) { | ||
594 | int err; | ||
595 | c = config[i]; | ||
596 | if (c.pingroup < 0 || c.pingroup >= TEGRA_MAX_PINGROUP) { | ||
597 | WARN_ON(1); | ||
598 | continue; | ||
599 | } | ||
600 | c.func = pingroups[c.pingroup].func_safe; | ||
601 | err = tegra_pinmux_set_func(&c); | ||
602 | if (err < 0) | ||
603 | pr_err("%s: tegra_pinmux_set_func returned %d setting " | ||
604 | "%s to %s\n", __func__, err, | ||
605 | pingroup_name(c.pingroup), func_name(c.func)); | ||
606 | } | ||
607 | } | ||
608 | |||
609 | void tegra_pinmux_config_pinmux_table(const struct tegra_pingroup_config *config, | ||
610 | int len) | ||
611 | { | ||
612 | int i; | ||
613 | |||
614 | for (i = 0; i < len; i++) { | ||
615 | int err; | ||
616 | if (config[i].pingroup < 0 || | ||
617 | config[i].pingroup >= TEGRA_MAX_PINGROUP) { | ||
618 | WARN_ON(1); | ||
619 | continue; | ||
620 | } | ||
621 | err = tegra_pinmux_set_func(&config[i]); | ||
622 | if (err < 0) | ||
623 | pr_err("%s: tegra_pinmux_set_func returned %d setting " | ||
624 | "%s to %s\n", __func__, err, | ||
625 | pingroup_name(config[i].pingroup), | ||
626 | func_name(config[i].func)); | ||
627 | } | ||
628 | } | ||
629 | |||
630 | void tegra_pinmux_config_tristate_table(const struct tegra_pingroup_config *config, | ||
631 | int len, enum tegra_tristate tristate) | ||
632 | { | ||
633 | int i; | ||
634 | int err; | ||
635 | enum tegra_pingroup pingroup; | ||
636 | |||
637 | for (i = 0; i < len; i++) { | ||
638 | pingroup = config[i].pingroup; | ||
639 | if (pingroups[pingroup].tri_reg >= 0) { | ||
640 | err = tegra_pinmux_set_tristate(pingroup, tristate); | ||
641 | if (err < 0) | ||
642 | pr_err("pinmux: can't set pingroup %s tristate" | ||
643 | " to %s: %d\n", pingroup_name(pingroup), | ||
644 | tri_name(tristate), err); | ||
645 | } | ||
646 | } | ||
647 | } | ||
648 | |||
649 | void tegra_pinmux_config_pullupdown_table(const struct tegra_pingroup_config *config, | ||
650 | int len, enum tegra_pullupdown pupd) | ||
651 | { | ||
652 | int i; | ||
653 | int err; | ||
654 | enum tegra_pingroup pingroup; | ||
655 | |||
656 | for (i = 0; i < len; i++) { | ||
657 | pingroup = config[i].pingroup; | ||
658 | if (pingroups[pingroup].pupd_reg >= 0) { | ||
659 | err = tegra_pinmux_set_pullupdown(pingroup, pupd); | ||
660 | if (err < 0) | ||
661 | pr_err("pinmux: can't set pingroup %s pullupdown" | ||
662 | " to %s: %d\n", pingroup_name(pingroup), | ||
663 | pupd_name(pupd), err); | ||
664 | } | ||
665 | } | ||
666 | } | ||
787 | 667 | ||
788 | #ifdef CONFIG_DEBUG_FS | 668 | #ifdef CONFIG_DEBUG_FS |
789 | 669 | ||
@@ -812,11 +692,11 @@ static int dbg_pinmux_show(struct seq_file *s, void *unused) | |||
812 | len = strlen(pingroups[i].name); | 692 | len = strlen(pingroups[i].name); |
813 | dbg_pad_field(s, 5 - len); | 693 | dbg_pad_field(s, 5 - len); |
814 | 694 | ||
815 | if (pingroups[i].mux_reg == REG_N) { | 695 | if (pingroups[i].mux_reg < 0) { |
816 | seq_printf(s, "TEGRA_MUX_NONE"); | 696 | seq_printf(s, "TEGRA_MUX_NONE"); |
817 | len = strlen("NONE"); | 697 | len = strlen("NONE"); |
818 | } else { | 698 | } else { |
819 | mux = (pg_readl(TEGRA_PP_MUX_CTL(pingroups[i].mux_reg)) >> | 699 | mux = (pg_readl(pingroups[i].mux_reg) >> |
820 | pingroups[i].mux_bit) & 0x3; | 700 | pingroups[i].mux_bit) & 0x3; |
821 | if (pingroups[i].funcs[mux] == TEGRA_MUX_RSVD) { | 701 | if (pingroups[i].funcs[mux] == TEGRA_MUX_RSVD) { |
822 | seq_printf(s, "TEGRA_MUX_RSVD%1lu", mux+1); | 702 | seq_printf(s, "TEGRA_MUX_RSVD%1lu", mux+1); |
@@ -829,21 +709,21 @@ static int dbg_pinmux_show(struct seq_file *s, void *unused) | |||
829 | } | 709 | } |
830 | dbg_pad_field(s, 13-len); | 710 | dbg_pad_field(s, 13-len); |
831 | 711 | ||
832 | if (pingroups[i].mux_reg == REG_N) { | 712 | if (pingroups[i].pupd_reg < 0) { |
833 | seq_printf(s, "TEGRA_PUPD_NORMAL"); | 713 | seq_printf(s, "TEGRA_PUPD_NORMAL"); |
834 | len = strlen("NORMAL"); | 714 | len = strlen("NORMAL"); |
835 | } else { | 715 | } else { |
836 | pupd = (pg_readl(TEGRA_PP_PU_PD(pingroups[i].pupd_reg)) >> | 716 | pupd = (pg_readl(pingroups[i].pupd_reg) >> |
837 | pingroups[i].pupd_bit) & 0x3; | 717 | pingroups[i].pupd_bit) & 0x3; |
838 | seq_printf(s, "TEGRA_PUPD_%s", pupd_name(pupd)); | 718 | seq_printf(s, "TEGRA_PUPD_%s", pupd_name(pupd)); |
839 | len = strlen(pupd_name(pupd)); | 719 | len = strlen(pupd_name(pupd)); |
840 | } | 720 | } |
841 | dbg_pad_field(s, 9 - len); | 721 | dbg_pad_field(s, 9 - len); |
842 | 722 | ||
843 | if (pingroups[i].tri_reg == REG_N) { | 723 | if (pingroups[i].tri_reg < 0) { |
844 | seq_printf(s, "TEGRA_TRI_NORMAL"); | 724 | seq_printf(s, "TEGRA_TRI_NORMAL"); |
845 | } else { | 725 | } else { |
846 | tri = (pg_readl(TEGRA_TRI_STATE(pingroups[i].tri_reg)) >> | 726 | tri = (pg_readl(pingroups[i].tri_reg) >> |
847 | pingroups[i].tri_bit) & 0x1; | 727 | pingroups[i].tri_bit) & 0x1; |
848 | 728 | ||
849 | seq_printf(s, "TEGRA_TRI_%s", tri_name(tri)); | 729 | seq_printf(s, "TEGRA_TRI_%s", tri_name(tri)); |
diff --git a/arch/arm/mach-tegra/tegra2_clocks.c b/arch/arm/mach-tegra/tegra2_clocks.c index 426163231fff..ae3b308e22a4 100644 --- a/arch/arm/mach-tegra/tegra2_clocks.c +++ b/arch/arm/mach-tegra/tegra2_clocks.c | |||
@@ -30,14 +30,21 @@ | |||
30 | #include <mach/iomap.h> | 30 | #include <mach/iomap.h> |
31 | 31 | ||
32 | #include "clock.h" | 32 | #include "clock.h" |
33 | #include "fuse.h" | ||
34 | #include "tegra2_dvfs.h" | ||
33 | 35 | ||
34 | #define RST_DEVICES 0x004 | 36 | #define RST_DEVICES 0x004 |
35 | #define RST_DEVICES_SET 0x300 | 37 | #define RST_DEVICES_SET 0x300 |
36 | #define RST_DEVICES_CLR 0x304 | 38 | #define RST_DEVICES_CLR 0x304 |
39 | #define RST_DEVICES_NUM 3 | ||
37 | 40 | ||
38 | #define CLK_OUT_ENB 0x010 | 41 | #define CLK_OUT_ENB 0x010 |
39 | #define CLK_OUT_ENB_SET 0x320 | 42 | #define CLK_OUT_ENB_SET 0x320 |
40 | #define CLK_OUT_ENB_CLR 0x324 | 43 | #define CLK_OUT_ENB_CLR 0x324 |
44 | #define CLK_OUT_ENB_NUM 3 | ||
45 | |||
46 | #define CLK_MASK_ARM 0x44 | ||
47 | #define MISC_CLK_ENB 0x48 | ||
41 | 48 | ||
42 | #define OSC_CTRL 0x50 | 49 | #define OSC_CTRL 0x50 |
43 | #define OSC_CTRL_OSC_FREQ_MASK (3<<30) | 50 | #define OSC_CTRL_OSC_FREQ_MASK (3<<30) |
@@ -45,6 +52,7 @@ | |||
45 | #define OSC_CTRL_OSC_FREQ_19_2MHZ (1<<30) | 52 | #define OSC_CTRL_OSC_FREQ_19_2MHZ (1<<30) |
46 | #define OSC_CTRL_OSC_FREQ_12MHZ (2<<30) | 53 | #define OSC_CTRL_OSC_FREQ_12MHZ (2<<30) |
47 | #define OSC_CTRL_OSC_FREQ_26MHZ (3<<30) | 54 | #define OSC_CTRL_OSC_FREQ_26MHZ (3<<30) |
55 | #define OSC_CTRL_MASK 0x3f2 | ||
48 | 56 | ||
49 | #define OSC_FREQ_DET 0x58 | 57 | #define OSC_FREQ_DET 0x58 |
50 | #define OSC_FREQ_DET_TRIG (1<<31) | 58 | #define OSC_FREQ_DET_TRIG (1<<31) |
@@ -53,10 +61,17 @@ | |||
53 | #define OSC_FREQ_DET_BUSY (1<<31) | 61 | #define OSC_FREQ_DET_BUSY (1<<31) |
54 | #define OSC_FREQ_DET_CNT_MASK 0xFFFF | 62 | #define OSC_FREQ_DET_CNT_MASK 0xFFFF |
55 | 63 | ||
64 | #define PERIPH_CLK_SOURCE_I2S1 0x100 | ||
65 | #define PERIPH_CLK_SOURCE_EMC 0x19c | ||
66 | #define PERIPH_CLK_SOURCE_OSC 0x1fc | ||
67 | #define PERIPH_CLK_SOURCE_NUM \ | ||
68 | ((PERIPH_CLK_SOURCE_OSC - PERIPH_CLK_SOURCE_I2S1) / 4) | ||
69 | |||
56 | #define PERIPH_CLK_SOURCE_MASK (3<<30) | 70 | #define PERIPH_CLK_SOURCE_MASK (3<<30) |
57 | #define PERIPH_CLK_SOURCE_SHIFT 30 | 71 | #define PERIPH_CLK_SOURCE_SHIFT 30 |
58 | #define PERIPH_CLK_SOURCE_ENABLE (1<<28) | 72 | #define PERIPH_CLK_SOURCE_ENABLE (1<<28) |
59 | #define PERIPH_CLK_SOURCE_DIV_MASK 0xFF | 73 | #define PERIPH_CLK_SOURCE_DIVU71_MASK 0xFF |
74 | #define PERIPH_CLK_SOURCE_DIVU16_MASK 0xFFFF | ||
60 | #define PERIPH_CLK_SOURCE_DIV_SHIFT 0 | 75 | #define PERIPH_CLK_SOURCE_DIV_SHIFT 0 |
61 | 76 | ||
62 | #define PLL_BASE 0x0 | 77 | #define PLL_BASE 0x0 |
@@ -79,8 +94,9 @@ | |||
79 | #define PLL_OUT_RESET_DISABLE (1<<0) | 94 | #define PLL_OUT_RESET_DISABLE (1<<0) |
80 | 95 | ||
81 | #define PLL_MISC(c) (((c)->flags & PLL_ALT_MISC_REG) ? 0x4 : 0xc) | 96 | #define PLL_MISC(c) (((c)->flags & PLL_ALT_MISC_REG) ? 0x4 : 0xc) |
97 | #define PLL_MISC_LOCK_ENABLE(c) (((c)->flags & PLLU) ? (1<<22) : (1<<18)) | ||
98 | |||
82 | #define PLL_MISC_DCCON_SHIFT 20 | 99 | #define PLL_MISC_DCCON_SHIFT 20 |
83 | #define PLL_MISC_LOCK_ENABLE (1<<18) | ||
84 | #define PLL_MISC_CPCON_SHIFT 8 | 100 | #define PLL_MISC_CPCON_SHIFT 8 |
85 | #define PLL_MISC_CPCON_MASK (0xF<<PLL_MISC_CPCON_SHIFT) | 101 | #define PLL_MISC_CPCON_MASK (0xF<<PLL_MISC_CPCON_SHIFT) |
86 | #define PLL_MISC_LFCON_SHIFT 4 | 102 | #define PLL_MISC_LFCON_SHIFT 4 |
@@ -88,10 +104,14 @@ | |||
88 | #define PLL_MISC_VCOCON_SHIFT 0 | 104 | #define PLL_MISC_VCOCON_SHIFT 0 |
89 | #define PLL_MISC_VCOCON_MASK (0xF<<PLL_MISC_VCOCON_SHIFT) | 105 | #define PLL_MISC_VCOCON_MASK (0xF<<PLL_MISC_VCOCON_SHIFT) |
90 | 106 | ||
107 | #define PLLU_BASE_POST_DIV (1<<20) | ||
108 | |||
91 | #define PLLD_MISC_CLKENABLE (1<<30) | 109 | #define PLLD_MISC_CLKENABLE (1<<30) |
92 | #define PLLD_MISC_DIV_RST (1<<23) | 110 | #define PLLD_MISC_DIV_RST (1<<23) |
93 | #define PLLD_MISC_DCCON_SHIFT 12 | 111 | #define PLLD_MISC_DCCON_SHIFT 12 |
94 | 112 | ||
113 | #define PLLE_MISC_READY (1 << 15) | ||
114 | |||
95 | #define PERIPH_CLK_TO_ENB_REG(c) ((c->clk_num / 32) * 4) | 115 | #define PERIPH_CLK_TO_ENB_REG(c) ((c->clk_num / 32) * 4) |
96 | #define PERIPH_CLK_TO_ENB_SET_REG(c) ((c->clk_num / 32) * 8) | 116 | #define PERIPH_CLK_TO_ENB_SET_REG(c) ((c->clk_num / 32) * 8) |
97 | #define PERIPH_CLK_TO_ENB_BIT(c) (1 << (c->clk_num % 32)) | 117 | #define PERIPH_CLK_TO_ENB_BIT(c) (1 << (c->clk_num % 32)) |
@@ -143,30 +163,37 @@ unsigned long clk_measure_input_freq(void) | |||
143 | } | 163 | } |
144 | } | 164 | } |
145 | 165 | ||
146 | static int clk_div71_get_divider(struct clk *c, unsigned long rate) | 166 | static int clk_div71_get_divider(unsigned long parent_rate, unsigned long rate) |
147 | { | 167 | { |
148 | unsigned long divider_u71; | 168 | s64 divider_u71 = parent_rate * 2; |
169 | divider_u71 += rate - 1; | ||
170 | do_div(divider_u71, rate); | ||
149 | 171 | ||
150 | divider_u71 = DIV_ROUND_UP(c->rate * 2, rate); | 172 | if (divider_u71 - 2 < 0) |
173 | return 0; | ||
151 | 174 | ||
152 | if (divider_u71 - 2 > 255 || divider_u71 - 2 < 0) | 175 | if (divider_u71 - 2 > 255) |
153 | return -EINVAL; | 176 | return -EINVAL; |
154 | 177 | ||
155 | return divider_u71 - 2; | 178 | return divider_u71 - 2; |
156 | } | 179 | } |
157 | 180 | ||
158 | static unsigned long tegra2_clk_recalculate_rate(struct clk *c) | 181 | static int clk_div16_get_divider(unsigned long parent_rate, unsigned long rate) |
159 | { | 182 | { |
160 | unsigned long rate; | 183 | s64 divider_u16; |
161 | rate = c->parent->rate; | ||
162 | 184 | ||
163 | if (c->mul != 0 && c->div != 0) | 185 | divider_u16 = parent_rate; |
164 | c->rate = rate * c->mul / c->div; | 186 | divider_u16 += rate - 1; |
165 | else | 187 | do_div(divider_u16, rate); |
166 | c->rate = rate; | 188 | |
167 | return c->rate; | 189 | if (divider_u16 - 1 < 0) |
168 | } | 190 | return 0; |
169 | 191 | ||
192 | if (divider_u16 - 1 > 255) | ||
193 | return -EINVAL; | ||
194 | |||
195 | return divider_u16 - 1; | ||
196 | } | ||
170 | 197 | ||
171 | /* clk_m functions */ | 198 | /* clk_m functions */ |
172 | static unsigned long tegra2_clk_m_autodetect_rate(struct clk *c) | 199 | static unsigned long tegra2_clk_m_autodetect_rate(struct clk *c) |
@@ -244,7 +271,6 @@ static void tegra2_super_clk_init(struct clk *c) | |||
244 | } | 271 | } |
245 | BUG_ON(sel->input == NULL); | 272 | BUG_ON(sel->input == NULL); |
246 | c->parent = sel->input; | 273 | c->parent = sel->input; |
247 | tegra2_clk_recalculate_rate(c); | ||
248 | } | 274 | } |
249 | 275 | ||
250 | static int tegra2_super_clk_enable(struct clk *c) | 276 | static int tegra2_super_clk_enable(struct clk *c) |
@@ -266,6 +292,7 @@ static int tegra2_super_clk_set_parent(struct clk *c, struct clk *p) | |||
266 | u32 val; | 292 | u32 val; |
267 | const struct clk_mux_sel *sel; | 293 | const struct clk_mux_sel *sel; |
268 | int shift; | 294 | int shift; |
295 | |||
269 | val = clk_readl(c->reg + SUPER_CLK_MUX);; | 296 | val = clk_readl(c->reg + SUPER_CLK_MUX);; |
270 | BUG_ON(((val & SUPER_STATE_MASK) != SUPER_STATE_RUN) && | 297 | BUG_ON(((val & SUPER_STATE_MASK) != SUPER_STATE_RUN) && |
271 | ((val & SUPER_STATE_MASK) != SUPER_STATE_IDLE)); | 298 | ((val & SUPER_STATE_MASK) != SUPER_STATE_IDLE)); |
@@ -273,11 +300,18 @@ static int tegra2_super_clk_set_parent(struct clk *c, struct clk *p) | |||
273 | SUPER_IDLE_SOURCE_SHIFT : SUPER_RUN_SOURCE_SHIFT; | 300 | SUPER_IDLE_SOURCE_SHIFT : SUPER_RUN_SOURCE_SHIFT; |
274 | for (sel = c->inputs; sel->input != NULL; sel++) { | 301 | for (sel = c->inputs; sel->input != NULL; sel++) { |
275 | if (sel->input == p) { | 302 | if (sel->input == p) { |
276 | clk_reparent(c, p); | ||
277 | val &= ~(SUPER_SOURCE_MASK << shift); | 303 | val &= ~(SUPER_SOURCE_MASK << shift); |
278 | val |= sel->value << shift; | 304 | val |= sel->value << shift; |
305 | |||
306 | if (c->refcnt) | ||
307 | clk_enable_locked(p); | ||
308 | |||
279 | clk_writel(val, c->reg); | 309 | clk_writel(val, c->reg); |
280 | c->rate = c->parent->rate; | 310 | |
311 | if (c->refcnt && c->parent) | ||
312 | clk_disable_locked(c->parent); | ||
313 | |||
314 | clk_reparent(c, p); | ||
281 | return 0; | 315 | return 0; |
282 | } | 316 | } |
283 | } | 317 | } |
@@ -289,7 +323,61 @@ static struct clk_ops tegra_super_ops = { | |||
289 | .enable = tegra2_super_clk_enable, | 323 | .enable = tegra2_super_clk_enable, |
290 | .disable = tegra2_super_clk_disable, | 324 | .disable = tegra2_super_clk_disable, |
291 | .set_parent = tegra2_super_clk_set_parent, | 325 | .set_parent = tegra2_super_clk_set_parent, |
292 | .recalculate_rate = tegra2_clk_recalculate_rate, | 326 | }; |
327 | |||
328 | /* virtual cpu clock functions */ | ||
329 | /* some clocks can not be stopped (cpu, memory bus) while the SoC is running. | ||
330 | To change the frequency of these clocks, the parent pll may need to be | ||
331 | reprogrammed, so the clock must be moved off the pll, the pll reprogrammed, | ||
332 | and then the clock moved back to the pll. To hide this sequence, a virtual | ||
333 | clock handles it. | ||
334 | */ | ||
335 | static void tegra2_cpu_clk_init(struct clk *c) | ||
336 | { | ||
337 | } | ||
338 | |||
339 | static int tegra2_cpu_clk_enable(struct clk *c) | ||
340 | { | ||
341 | return 0; | ||
342 | } | ||
343 | |||
344 | static void tegra2_cpu_clk_disable(struct clk *c) | ||
345 | { | ||
346 | pr_debug("%s on clock %s\n", __func__, c->name); | ||
347 | |||
348 | /* oops - don't disable the CPU clock! */ | ||
349 | BUG(); | ||
350 | } | ||
351 | |||
352 | static int tegra2_cpu_clk_set_rate(struct clk *c, unsigned long rate) | ||
353 | { | ||
354 | int ret; | ||
355 | ret = clk_set_parent_locked(c->parent, c->backup); | ||
356 | if (ret) { | ||
357 | pr_err("Failed to switch cpu to clock %s\n", c->backup->name); | ||
358 | return ret; | ||
359 | } | ||
360 | |||
361 | ret = clk_set_rate_locked(c->main, rate); | ||
362 | if (ret) { | ||
363 | pr_err("Failed to change cpu pll to %lu\n", rate); | ||
364 | return ret; | ||
365 | } | ||
366 | |||
367 | ret = clk_set_parent_locked(c->parent, c->main); | ||
368 | if (ret) { | ||
369 | pr_err("Failed to switch cpu to clock %s\n", c->main->name); | ||
370 | return ret; | ||
371 | } | ||
372 | |||
373 | return 0; | ||
374 | } | ||
375 | |||
376 | static struct clk_ops tegra_cpu_ops = { | ||
377 | .init = tegra2_cpu_clk_init, | ||
378 | .enable = tegra2_cpu_clk_enable, | ||
379 | .disable = tegra2_cpu_clk_disable, | ||
380 | .set_rate = tegra2_cpu_clk_set_rate, | ||
293 | }; | 381 | }; |
294 | 382 | ||
295 | /* bus clock functions */ | 383 | /* bus clock functions */ |
@@ -299,7 +387,6 @@ static void tegra2_bus_clk_init(struct clk *c) | |||
299 | c->state = ((val >> c->reg_shift) & BUS_CLK_DISABLE) ? OFF : ON; | 387 | c->state = ((val >> c->reg_shift) & BUS_CLK_DISABLE) ? OFF : ON; |
300 | c->div = ((val >> c->reg_shift) & BUS_CLK_DIV_MASK) + 1; | 388 | c->div = ((val >> c->reg_shift) & BUS_CLK_DIV_MASK) + 1; |
301 | c->mul = 1; | 389 | c->mul = 1; |
302 | tegra2_clk_recalculate_rate(c); | ||
303 | } | 390 | } |
304 | 391 | ||
305 | static int tegra2_bus_clk_enable(struct clk *c) | 392 | static int tegra2_bus_clk_enable(struct clk *c) |
@@ -340,27 +427,15 @@ static struct clk_ops tegra_bus_ops = { | |||
340 | .enable = tegra2_bus_clk_enable, | 427 | .enable = tegra2_bus_clk_enable, |
341 | .disable = tegra2_bus_clk_disable, | 428 | .disable = tegra2_bus_clk_disable, |
342 | .set_rate = tegra2_bus_clk_set_rate, | 429 | .set_rate = tegra2_bus_clk_set_rate, |
343 | .recalculate_rate = tegra2_clk_recalculate_rate, | ||
344 | }; | 430 | }; |
345 | 431 | ||
346 | /* PLL Functions */ | 432 | /* PLL Functions */ |
347 | static unsigned long tegra2_pll_clk_recalculate_rate(struct clk *c) | ||
348 | { | ||
349 | u64 rate; | ||
350 | rate = c->parent->rate; | ||
351 | rate *= c->n; | ||
352 | do_div(rate, c->m); | ||
353 | if (c->p == 2) | ||
354 | rate >>= 1; | ||
355 | c->rate = rate; | ||
356 | return c->rate; | ||
357 | } | ||
358 | |||
359 | static int tegra2_pll_clk_wait_for_lock(struct clk *c) | 433 | static int tegra2_pll_clk_wait_for_lock(struct clk *c) |
360 | { | 434 | { |
361 | ktime_t before; | 435 | ktime_t before; |
362 | 436 | ||
363 | before = ktime_get(); | 437 | before = ktime_get(); |
438 | |||
364 | while (!(clk_readl(c->reg + PLL_BASE) & PLL_BASE_LOCK)) { | 439 | while (!(clk_readl(c->reg + PLL_BASE) & PLL_BASE_LOCK)) { |
365 | if (ktime_us_delta(ktime_get(), before) > 5000) { | 440 | if (ktime_us_delta(ktime_get(), before) > 5000) { |
366 | pr_err("Timed out waiting for lock bit on pll %s", | 441 | pr_err("Timed out waiting for lock bit on pll %s", |
@@ -380,24 +455,19 @@ static void tegra2_pll_clk_init(struct clk *c) | |||
380 | 455 | ||
381 | if (c->flags & PLL_FIXED && !(val & PLL_BASE_OVERRIDE)) { | 456 | if (c->flags & PLL_FIXED && !(val & PLL_BASE_OVERRIDE)) { |
382 | pr_warning("Clock %s has unknown fixed frequency\n", c->name); | 457 | pr_warning("Clock %s has unknown fixed frequency\n", c->name); |
383 | c->n = 1; | 458 | c->mul = 1; |
384 | c->m = 0; | 459 | c->div = 1; |
385 | c->p = 1; | ||
386 | } else if (val & PLL_BASE_BYPASS) { | 460 | } else if (val & PLL_BASE_BYPASS) { |
387 | c->n = 1; | 461 | c->mul = 1; |
388 | c->m = 1; | 462 | c->div = 1; |
389 | c->p = 1; | ||
390 | } else { | 463 | } else { |
391 | c->n = (val & PLL_BASE_DIVN_MASK) >> PLL_BASE_DIVN_SHIFT; | 464 | c->mul = (val & PLL_BASE_DIVN_MASK) >> PLL_BASE_DIVN_SHIFT; |
392 | c->m = (val & PLL_BASE_DIVM_MASK) >> PLL_BASE_DIVM_SHIFT; | 465 | c->div = (val & PLL_BASE_DIVM_MASK) >> PLL_BASE_DIVM_SHIFT; |
393 | c->p = (val & PLL_BASE_DIVP_MASK) ? 2 : 1; | 466 | if (c->flags & PLLU) |
467 | c->div *= (val & PLLU_BASE_POST_DIV) ? 1 : 2; | ||
468 | else | ||
469 | c->div *= (val & PLL_BASE_DIVP_MASK) ? 2 : 1; | ||
394 | } | 470 | } |
395 | |||
396 | val = clk_readl(c->reg + PLL_MISC(c)); | ||
397 | if (c->flags & PLL_HAS_CPCON) | ||
398 | c->cpcon = (val & PLL_MISC_CPCON_MASK) >> PLL_MISC_CPCON_SHIFT; | ||
399 | |||
400 | tegra2_pll_clk_recalculate_rate(c); | ||
401 | } | 471 | } |
402 | 472 | ||
403 | static int tegra2_pll_clk_enable(struct clk *c) | 473 | static int tegra2_pll_clk_enable(struct clk *c) |
@@ -411,7 +481,7 @@ static int tegra2_pll_clk_enable(struct clk *c) | |||
411 | clk_writel(val, c->reg + PLL_BASE); | 481 | clk_writel(val, c->reg + PLL_BASE); |
412 | 482 | ||
413 | val = clk_readl(c->reg + PLL_MISC(c)); | 483 | val = clk_readl(c->reg + PLL_MISC(c)); |
414 | val |= PLL_MISC_LOCK_ENABLE; | 484 | val |= PLL_MISC_LOCK_ENABLE(c); |
415 | clk_writel(val, c->reg + PLL_MISC(c)); | 485 | clk_writel(val, c->reg + PLL_MISC(c)); |
416 | 486 | ||
417 | tegra2_pll_clk_wait_for_lock(c); | 487 | tegra2_pll_clk_wait_for_lock(c); |
@@ -441,33 +511,36 @@ static int tegra2_pll_clk_set_rate(struct clk *c, unsigned long rate) | |||
441 | input_rate = c->parent->rate; | 511 | input_rate = c->parent->rate; |
442 | for (sel = c->pll_table; sel->input_rate != 0; sel++) { | 512 | for (sel = c->pll_table; sel->input_rate != 0; sel++) { |
443 | if (sel->input_rate == input_rate && sel->output_rate == rate) { | 513 | if (sel->input_rate == input_rate && sel->output_rate == rate) { |
444 | c->n = sel->n; | 514 | c->mul = sel->n; |
445 | c->m = sel->m; | 515 | c->div = sel->m * sel->p; |
446 | c->p = sel->p; | ||
447 | c->cpcon = sel->cpcon; | ||
448 | 516 | ||
449 | val = clk_readl(c->reg + PLL_BASE); | 517 | val = clk_readl(c->reg + PLL_BASE); |
450 | if (c->flags & PLL_FIXED) | 518 | if (c->flags & PLL_FIXED) |
451 | val |= PLL_BASE_OVERRIDE; | 519 | val |= PLL_BASE_OVERRIDE; |
452 | val &= ~(PLL_BASE_DIVP_MASK | PLL_BASE_DIVN_MASK | | 520 | val &= ~(PLL_BASE_DIVP_MASK | PLL_BASE_DIVN_MASK | |
453 | PLL_BASE_DIVM_MASK); | 521 | PLL_BASE_DIVM_MASK); |
454 | val |= (c->m << PLL_BASE_DIVM_SHIFT) | | 522 | val |= (sel->m << PLL_BASE_DIVM_SHIFT) | |
455 | (c->n << PLL_BASE_DIVN_SHIFT); | 523 | (sel->n << PLL_BASE_DIVN_SHIFT); |
456 | BUG_ON(c->p > 2); | 524 | BUG_ON(sel->p < 1 || sel->p > 2); |
457 | if (c->p == 2) | 525 | if (c->flags & PLLU) { |
458 | val |= 1 << PLL_BASE_DIVP_SHIFT; | 526 | if (sel->p == 1) |
527 | val |= PLLU_BASE_POST_DIV; | ||
528 | } else { | ||
529 | if (sel->p == 2) | ||
530 | val |= 1 << PLL_BASE_DIVP_SHIFT; | ||
531 | } | ||
459 | clk_writel(val, c->reg + PLL_BASE); | 532 | clk_writel(val, c->reg + PLL_BASE); |
460 | 533 | ||
461 | if (c->flags & PLL_HAS_CPCON) { | 534 | if (c->flags & PLL_HAS_CPCON) { |
462 | val = c->cpcon << PLL_MISC_CPCON_SHIFT; | 535 | val = clk_readl(c->reg + PLL_MISC(c)); |
463 | val |= PLL_MISC_LOCK_ENABLE; | 536 | val &= ~PLL_MISC_CPCON_MASK; |
537 | val |= sel->cpcon << PLL_MISC_CPCON_SHIFT; | ||
464 | clk_writel(val, c->reg + PLL_MISC(c)); | 538 | clk_writel(val, c->reg + PLL_MISC(c)); |
465 | } | 539 | } |
466 | 540 | ||
467 | if (c->state == ON) | 541 | if (c->state == ON) |
468 | tegra2_pll_clk_enable(c); | 542 | tegra2_pll_clk_enable(c); |
469 | 543 | ||
470 | c->rate = rate; | ||
471 | return 0; | 544 | return 0; |
472 | } | 545 | } |
473 | } | 546 | } |
@@ -479,7 +552,46 @@ static struct clk_ops tegra_pll_ops = { | |||
479 | .enable = tegra2_pll_clk_enable, | 552 | .enable = tegra2_pll_clk_enable, |
480 | .disable = tegra2_pll_clk_disable, | 553 | .disable = tegra2_pll_clk_disable, |
481 | .set_rate = tegra2_pll_clk_set_rate, | 554 | .set_rate = tegra2_pll_clk_set_rate, |
482 | .recalculate_rate = tegra2_pll_clk_recalculate_rate, | 555 | }; |
556 | |||
557 | static void tegra2_pllx_clk_init(struct clk *c) | ||
558 | { | ||
559 | tegra2_pll_clk_init(c); | ||
560 | |||
561 | if (tegra_sku_id() == 7) | ||
562 | c->max_rate = 750000000; | ||
563 | } | ||
564 | |||
565 | static struct clk_ops tegra_pllx_ops = { | ||
566 | .init = tegra2_pllx_clk_init, | ||
567 | .enable = tegra2_pll_clk_enable, | ||
568 | .disable = tegra2_pll_clk_disable, | ||
569 | .set_rate = tegra2_pll_clk_set_rate, | ||
570 | }; | ||
571 | |||
572 | static int tegra2_plle_clk_enable(struct clk *c) | ||
573 | { | ||
574 | u32 val; | ||
575 | |||
576 | pr_debug("%s on clock %s\n", __func__, c->name); | ||
577 | |||
578 | mdelay(1); | ||
579 | |||
580 | val = clk_readl(c->reg + PLL_BASE); | ||
581 | if (!(val & PLLE_MISC_READY)) | ||
582 | return -EBUSY; | ||
583 | |||
584 | val = clk_readl(c->reg + PLL_BASE); | ||
585 | val |= PLL_BASE_ENABLE | PLL_BASE_BYPASS; | ||
586 | clk_writel(val, c->reg + PLL_BASE); | ||
587 | |||
588 | return 0; | ||
589 | } | ||
590 | |||
591 | static struct clk_ops tegra_plle_ops = { | ||
592 | .init = tegra2_pll_clk_init, | ||
593 | .enable = tegra2_plle_clk_enable, | ||
594 | .set_rate = tegra2_pll_clk_set_rate, | ||
483 | }; | 595 | }; |
484 | 596 | ||
485 | /* Clock divider ops */ | 597 | /* Clock divider ops */ |
@@ -503,8 +615,6 @@ static void tegra2_pll_div_clk_init(struct clk *c) | |||
503 | c->div = 1; | 615 | c->div = 1; |
504 | c->mul = 1; | 616 | c->mul = 1; |
505 | } | 617 | } |
506 | |||
507 | tegra2_clk_recalculate_rate(c); | ||
508 | } | 618 | } |
509 | 619 | ||
510 | static int tegra2_pll_div_clk_enable(struct clk *c) | 620 | static int tegra2_pll_div_clk_enable(struct clk *c) |
@@ -565,7 +675,7 @@ static int tegra2_pll_div_clk_set_rate(struct clk *c, unsigned long rate) | |||
565 | int divider_u71; | 675 | int divider_u71; |
566 | pr_debug("%s: %s %lu\n", __func__, c->name, rate); | 676 | pr_debug("%s: %s %lu\n", __func__, c->name, rate); |
567 | if (c->flags & DIV_U71) { | 677 | if (c->flags & DIV_U71) { |
568 | divider_u71 = clk_div71_get_divider(c->parent, rate); | 678 | divider_u71 = clk_div71_get_divider(c->parent->rate, rate); |
569 | if (divider_u71 >= 0) { | 679 | if (divider_u71 >= 0) { |
570 | val = clk_readl(c->reg); | 680 | val = clk_readl(c->reg); |
571 | new_val = val >> c->reg_shift; | 681 | new_val = val >> c->reg_shift; |
@@ -580,25 +690,37 @@ static int tegra2_pll_div_clk_set_rate(struct clk *c, unsigned long rate) | |||
580 | clk_writel(val, c->reg); | 690 | clk_writel(val, c->reg); |
581 | c->div = divider_u71 + 2; | 691 | c->div = divider_u71 + 2; |
582 | c->mul = 2; | 692 | c->mul = 2; |
583 | tegra2_clk_recalculate_rate(c); | ||
584 | return 0; | 693 | return 0; |
585 | } | 694 | } |
586 | } else if (c->flags & DIV_2) { | 695 | } else if (c->flags & DIV_2) { |
587 | if (c->parent->rate == rate * 2) { | 696 | if (c->parent->rate == rate * 2) |
588 | c->rate = rate; | ||
589 | return 0; | 697 | return 0; |
590 | } | ||
591 | } | 698 | } |
592 | return -EINVAL; | 699 | return -EINVAL; |
593 | } | 700 | } |
594 | 701 | ||
702 | static long tegra2_pll_div_clk_round_rate(struct clk *c, unsigned long rate) | ||
703 | { | ||
704 | int divider; | ||
705 | pr_debug("%s: %s %lu\n", __func__, c->name, rate); | ||
706 | |||
707 | if (c->flags & DIV_U71) { | ||
708 | divider = clk_div71_get_divider(c->parent->rate, rate); | ||
709 | if (divider < 0) | ||
710 | return divider; | ||
711 | return c->parent->rate * 2 / (divider + 2); | ||
712 | } else if (c->flags & DIV_2) { | ||
713 | return c->parent->rate / 2; | ||
714 | } | ||
715 | return -EINVAL; | ||
716 | } | ||
595 | 717 | ||
596 | static struct clk_ops tegra_pll_div_ops = { | 718 | static struct clk_ops tegra_pll_div_ops = { |
597 | .init = tegra2_pll_div_clk_init, | 719 | .init = tegra2_pll_div_clk_init, |
598 | .enable = tegra2_pll_div_clk_enable, | 720 | .enable = tegra2_pll_div_clk_enable, |
599 | .disable = tegra2_pll_div_clk_disable, | 721 | .disable = tegra2_pll_div_clk_disable, |
600 | .set_rate = tegra2_pll_div_clk_set_rate, | 722 | .set_rate = tegra2_pll_div_clk_set_rate, |
601 | .recalculate_rate = tegra2_clk_recalculate_rate, | 723 | .round_rate = tegra2_pll_div_clk_round_rate, |
602 | }; | 724 | }; |
603 | 725 | ||
604 | /* Periph clk ops */ | 726 | /* Periph clk ops */ |
@@ -621,9 +743,13 @@ static void tegra2_periph_clk_init(struct clk *c) | |||
621 | } | 743 | } |
622 | 744 | ||
623 | if (c->flags & DIV_U71) { | 745 | if (c->flags & DIV_U71) { |
624 | u32 divu71 = val & PERIPH_CLK_SOURCE_DIV_MASK; | 746 | u32 divu71 = val & PERIPH_CLK_SOURCE_DIVU71_MASK; |
625 | c->div = divu71 + 2; | 747 | c->div = divu71 + 2; |
626 | c->mul = 2; | 748 | c->mul = 2; |
749 | } else if (c->flags & DIV_U16) { | ||
750 | u32 divu16 = val & PERIPH_CLK_SOURCE_DIVU16_MASK; | ||
751 | c->div = divu16 + 1; | ||
752 | c->mul = 1; | ||
627 | } else { | 753 | } else { |
628 | c->div = 1; | 754 | c->div = 1; |
629 | c->mul = 1; | 755 | c->mul = 1; |
@@ -637,7 +763,6 @@ static void tegra2_periph_clk_init(struct clk *c) | |||
637 | if (clk_readl(RST_DEVICES + PERIPH_CLK_TO_ENB_REG(c)) & | 763 | if (clk_readl(RST_DEVICES + PERIPH_CLK_TO_ENB_REG(c)) & |
638 | PERIPH_CLK_TO_ENB_BIT(c)) | 764 | PERIPH_CLK_TO_ENB_BIT(c)) |
639 | c->state = OFF; | 765 | c->state = OFF; |
640 | tegra2_clk_recalculate_rate(c); | ||
641 | } | 766 | } |
642 | 767 | ||
643 | static int tegra2_periph_clk_enable(struct clk *c) | 768 | static int tegra2_periph_clk_enable(struct clk *c) |
@@ -692,12 +817,19 @@ static int tegra2_periph_clk_set_parent(struct clk *c, struct clk *p) | |||
692 | pr_debug("%s: %s %s\n", __func__, c->name, p->name); | 817 | pr_debug("%s: %s %s\n", __func__, c->name, p->name); |
693 | for (sel = c->inputs; sel->input != NULL; sel++) { | 818 | for (sel = c->inputs; sel->input != NULL; sel++) { |
694 | if (sel->input == p) { | 819 | if (sel->input == p) { |
695 | clk_reparent(c, p); | ||
696 | val = clk_readl(c->reg); | 820 | val = clk_readl(c->reg); |
697 | val &= ~PERIPH_CLK_SOURCE_MASK; | 821 | val &= ~PERIPH_CLK_SOURCE_MASK; |
698 | val |= (sel->value) << PERIPH_CLK_SOURCE_SHIFT; | 822 | val |= (sel->value) << PERIPH_CLK_SOURCE_SHIFT; |
823 | |||
824 | if (c->refcnt) | ||
825 | clk_enable_locked(p); | ||
826 | |||
699 | clk_writel(val, c->reg); | 827 | clk_writel(val, c->reg); |
700 | c->rate = c->parent->rate; | 828 | |
829 | if (c->refcnt && c->parent) | ||
830 | clk_disable_locked(c->parent); | ||
831 | |||
832 | clk_reparent(c, p); | ||
701 | return 0; | 833 | return 0; |
702 | } | 834 | } |
703 | } | 835 | } |
@@ -708,20 +840,55 @@ static int tegra2_periph_clk_set_parent(struct clk *c, struct clk *p) | |||
708 | static int tegra2_periph_clk_set_rate(struct clk *c, unsigned long rate) | 840 | static int tegra2_periph_clk_set_rate(struct clk *c, unsigned long rate) |
709 | { | 841 | { |
710 | u32 val; | 842 | u32 val; |
711 | int divider_u71; | 843 | int divider; |
712 | pr_debug("%s: %lu\n", __func__, rate); | 844 | pr_debug("%s: %lu\n", __func__, rate); |
713 | if (c->flags & DIV_U71) { | 845 | if (c->flags & DIV_U71) { |
714 | divider_u71 = clk_div71_get_divider(c->parent, rate); | 846 | divider = clk_div71_get_divider(c->parent->rate, rate); |
715 | if (divider_u71 >= 0) { | 847 | if (divider >= 0) { |
716 | val = clk_readl(c->reg); | 848 | val = clk_readl(c->reg); |
717 | val &= ~PERIPH_CLK_SOURCE_DIV_MASK; | 849 | val &= ~PERIPH_CLK_SOURCE_DIVU71_MASK; |
718 | val |= divider_u71; | 850 | val |= divider; |
719 | clk_writel(val, c->reg); | 851 | clk_writel(val, c->reg); |
720 | c->div = divider_u71 + 2; | 852 | c->div = divider + 2; |
721 | c->mul = 2; | 853 | c->mul = 2; |
722 | tegra2_clk_recalculate_rate(c); | ||
723 | return 0; | 854 | return 0; |
724 | } | 855 | } |
856 | } else if (c->flags & DIV_U16) { | ||
857 | divider = clk_div16_get_divider(c->parent->rate, rate); | ||
858 | if (divider >= 0) { | ||
859 | val = clk_readl(c->reg); | ||
860 | val &= ~PERIPH_CLK_SOURCE_DIVU16_MASK; | ||
861 | val |= divider; | ||
862 | clk_writel(val, c->reg); | ||
863 | c->div = divider + 1; | ||
864 | c->mul = 1; | ||
865 | return 0; | ||
866 | } | ||
867 | } else if (c->parent->rate <= rate) { | ||
868 | c->div = 1; | ||
869 | c->mul = 1; | ||
870 | return 0; | ||
871 | } | ||
872 | return -EINVAL; | ||
873 | } | ||
874 | |||
875 | static long tegra2_periph_clk_round_rate(struct clk *c, | ||
876 | unsigned long rate) | ||
877 | { | ||
878 | int divider; | ||
879 | pr_debug("%s: %s %lu\n", __func__, c->name, rate); | ||
880 | |||
881 | if (c->flags & DIV_U71) { | ||
882 | divider = clk_div71_get_divider(c->parent->rate, rate); | ||
883 | if (divider < 0) | ||
884 | return divider; | ||
885 | |||
886 | return c->parent->rate * 2 / (divider + 2); | ||
887 | } else if (c->flags & DIV_U16) { | ||
888 | divider = clk_div16_get_divider(c->parent->rate, rate); | ||
889 | if (divider < 0) | ||
890 | return divider; | ||
891 | return c->parent->rate / (divider + 1); | ||
725 | } | 892 | } |
726 | return -EINVAL; | 893 | return -EINVAL; |
727 | } | 894 | } |
@@ -732,7 +899,7 @@ static struct clk_ops tegra_periph_clk_ops = { | |||
732 | .disable = &tegra2_periph_clk_disable, | 899 | .disable = &tegra2_periph_clk_disable, |
733 | .set_parent = &tegra2_periph_clk_set_parent, | 900 | .set_parent = &tegra2_periph_clk_set_parent, |
734 | .set_rate = &tegra2_periph_clk_set_rate, | 901 | .set_rate = &tegra2_periph_clk_set_rate, |
735 | .recalculate_rate = &tegra2_clk_recalculate_rate, | 902 | .round_rate = &tegra2_periph_clk_round_rate, |
736 | }; | 903 | }; |
737 | 904 | ||
738 | /* Clock doubler ops */ | 905 | /* Clock doubler ops */ |
@@ -744,21 +911,108 @@ static void tegra2_clk_double_init(struct clk *c) | |||
744 | if (!(clk_readl(CLK_OUT_ENB + PERIPH_CLK_TO_ENB_REG(c)) & | 911 | if (!(clk_readl(CLK_OUT_ENB + PERIPH_CLK_TO_ENB_REG(c)) & |
745 | PERIPH_CLK_TO_ENB_BIT(c))) | 912 | PERIPH_CLK_TO_ENB_BIT(c))) |
746 | c->state = OFF; | 913 | c->state = OFF; |
747 | tegra2_clk_recalculate_rate(c); | ||
748 | }; | 914 | }; |
749 | 915 | ||
916 | static int tegra2_clk_double_set_rate(struct clk *c, unsigned long rate) | ||
917 | { | ||
918 | if (rate != 2 * c->parent->rate) | ||
919 | return -EINVAL; | ||
920 | c->mul = 2; | ||
921 | c->div = 1; | ||
922 | return 0; | ||
923 | } | ||
924 | |||
750 | static struct clk_ops tegra_clk_double_ops = { | 925 | static struct clk_ops tegra_clk_double_ops = { |
751 | .init = &tegra2_clk_double_init, | 926 | .init = &tegra2_clk_double_init, |
752 | .enable = &tegra2_periph_clk_enable, | 927 | .enable = &tegra2_periph_clk_enable, |
753 | .disable = &tegra2_periph_clk_disable, | 928 | .disable = &tegra2_periph_clk_disable, |
754 | .recalculate_rate = &tegra2_clk_recalculate_rate, | 929 | .set_rate = &tegra2_clk_double_set_rate, |
930 | }; | ||
931 | |||
932 | static void tegra2_audio_sync_clk_init(struct clk *c) | ||
933 | { | ||
934 | int source; | ||
935 | const struct clk_mux_sel *sel; | ||
936 | u32 val = clk_readl(c->reg); | ||
937 | c->state = (val & (1<<4)) ? OFF : ON; | ||
938 | source = val & 0xf; | ||
939 | for (sel = c->inputs; sel->input != NULL; sel++) | ||
940 | if (sel->value == source) | ||
941 | break; | ||
942 | BUG_ON(sel->input == NULL); | ||
943 | c->parent = sel->input; | ||
944 | } | ||
945 | |||
946 | static int tegra2_audio_sync_clk_enable(struct clk *c) | ||
947 | { | ||
948 | clk_writel(0, c->reg); | ||
949 | return 0; | ||
950 | } | ||
951 | |||
952 | static void tegra2_audio_sync_clk_disable(struct clk *c) | ||
953 | { | ||
954 | clk_writel(1, c->reg); | ||
955 | } | ||
956 | |||
957 | static int tegra2_audio_sync_clk_set_parent(struct clk *c, struct clk *p) | ||
958 | { | ||
959 | u32 val; | ||
960 | const struct clk_mux_sel *sel; | ||
961 | for (sel = c->inputs; sel->input != NULL; sel++) { | ||
962 | if (sel->input == p) { | ||
963 | val = clk_readl(c->reg); | ||
964 | val &= ~0xf; | ||
965 | val |= sel->value; | ||
966 | |||
967 | if (c->refcnt) | ||
968 | clk_enable_locked(p); | ||
969 | |||
970 | clk_writel(val, c->reg); | ||
971 | |||
972 | if (c->refcnt && c->parent) | ||
973 | clk_disable_locked(c->parent); | ||
974 | |||
975 | clk_reparent(c, p); | ||
976 | return 0; | ||
977 | } | ||
978 | } | ||
979 | |||
980 | return -EINVAL; | ||
981 | } | ||
982 | |||
983 | static int tegra2_audio_sync_clk_set_rate(struct clk *c, unsigned long rate) | ||
984 | { | ||
985 | unsigned long parent_rate; | ||
986 | if (!c->parent) { | ||
987 | pr_err("%s: clock has no parent\n", __func__); | ||
988 | return -EINVAL; | ||
989 | } | ||
990 | parent_rate = c->parent->rate; | ||
991 | if (rate != parent_rate) { | ||
992 | pr_err("%s: %s/%ld differs from parent %s/%ld\n", | ||
993 | __func__, | ||
994 | c->name, rate, | ||
995 | c->parent->name, parent_rate); | ||
996 | return -EINVAL; | ||
997 | } | ||
998 | c->rate = parent_rate; | ||
999 | return 0; | ||
1000 | } | ||
1001 | |||
1002 | static struct clk_ops tegra_audio_sync_clk_ops = { | ||
1003 | .init = tegra2_audio_sync_clk_init, | ||
1004 | .enable = tegra2_audio_sync_clk_enable, | ||
1005 | .disable = tegra2_audio_sync_clk_disable, | ||
1006 | .set_rate = tegra2_audio_sync_clk_set_rate, | ||
1007 | .set_parent = tegra2_audio_sync_clk_set_parent, | ||
755 | }; | 1008 | }; |
756 | 1009 | ||
757 | /* Clock definitions */ | 1010 | /* Clock definitions */ |
758 | static struct clk tegra_clk_32k = { | 1011 | static struct clk tegra_clk_32k = { |
759 | .name = "clk_32k", | 1012 | .name = "clk_32k", |
760 | .rate = 32678, | 1013 | .rate = 32768, |
761 | .ops = NULL, | 1014 | .ops = NULL, |
1015 | .max_rate = 32768, | ||
762 | }; | 1016 | }; |
763 | 1017 | ||
764 | static struct clk_pll_table tegra_pll_s_table[] = { | 1018 | static struct clk_pll_table tegra_pll_s_table[] = { |
@@ -782,6 +1036,7 @@ static struct clk tegra_pll_s = { | |||
782 | .vco_min = 12000000, | 1036 | .vco_min = 12000000, |
783 | .vco_max = 26000000, | 1037 | .vco_max = 26000000, |
784 | .pll_table = tegra_pll_s_table, | 1038 | .pll_table = tegra_pll_s_table, |
1039 | .max_rate = 26000000, | ||
785 | }; | 1040 | }; |
786 | 1041 | ||
787 | static struct clk_mux_sel tegra_clk_m_sel[] = { | 1042 | static struct clk_mux_sel tegra_clk_m_sel[] = { |
@@ -797,6 +1052,7 @@ static struct clk tegra_clk_m = { | |||
797 | .reg = 0x1fc, | 1052 | .reg = 0x1fc, |
798 | .reg_mask = (1<<28), | 1053 | .reg_mask = (1<<28), |
799 | .reg_shift = 28, | 1054 | .reg_shift = 28, |
1055 | .max_rate = 26000000, | ||
800 | }; | 1056 | }; |
801 | 1057 | ||
802 | static struct clk_pll_table tegra_pll_c_table[] = { | 1058 | static struct clk_pll_table tegra_pll_c_table[] = { |
@@ -816,6 +1072,7 @@ static struct clk tegra_pll_c = { | |||
816 | .vco_min = 20000000, | 1072 | .vco_min = 20000000, |
817 | .vco_max = 1400000000, | 1073 | .vco_max = 1400000000, |
818 | .pll_table = tegra_pll_c_table, | 1074 | .pll_table = tegra_pll_c_table, |
1075 | .max_rate = 600000000, | ||
819 | }; | 1076 | }; |
820 | 1077 | ||
821 | static struct clk tegra_pll_c_out1 = { | 1078 | static struct clk tegra_pll_c_out1 = { |
@@ -825,9 +1082,18 @@ static struct clk tegra_pll_c_out1 = { | |||
825 | .parent = &tegra_pll_c, | 1082 | .parent = &tegra_pll_c, |
826 | .reg = 0x84, | 1083 | .reg = 0x84, |
827 | .reg_shift = 0, | 1084 | .reg_shift = 0, |
1085 | .max_rate = 600000000, | ||
828 | }; | 1086 | }; |
829 | 1087 | ||
830 | static struct clk_pll_table tegra_pll_m_table[] = { | 1088 | static struct clk_pll_table tegra_pll_m_table[] = { |
1089 | { 12000000, 666000000, 666, 12, 1, 8}, | ||
1090 | { 13000000, 666000000, 666, 13, 1, 8}, | ||
1091 | { 19200000, 666000000, 555, 16, 1, 8}, | ||
1092 | { 26000000, 666000000, 666, 26, 1, 8}, | ||
1093 | { 12000000, 600000000, 600, 12, 1, 8}, | ||
1094 | { 13000000, 600000000, 600, 13, 1, 8}, | ||
1095 | { 19200000, 600000000, 375, 12, 1, 6}, | ||
1096 | { 26000000, 600000000, 600, 26, 1, 8}, | ||
831 | { 0, 0, 0, 0, 0, 0 }, | 1097 | { 0, 0, 0, 0, 0, 0 }, |
832 | }; | 1098 | }; |
833 | 1099 | ||
@@ -844,6 +1110,7 @@ static struct clk tegra_pll_m = { | |||
844 | .vco_min = 20000000, | 1110 | .vco_min = 20000000, |
845 | .vco_max = 1200000000, | 1111 | .vco_max = 1200000000, |
846 | .pll_table = tegra_pll_m_table, | 1112 | .pll_table = tegra_pll_m_table, |
1113 | .max_rate = 800000000, | ||
847 | }; | 1114 | }; |
848 | 1115 | ||
849 | static struct clk tegra_pll_m_out1 = { | 1116 | static struct clk tegra_pll_m_out1 = { |
@@ -853,6 +1120,7 @@ static struct clk tegra_pll_m_out1 = { | |||
853 | .parent = &tegra_pll_m, | 1120 | .parent = &tegra_pll_m, |
854 | .reg = 0x94, | 1121 | .reg = 0x94, |
855 | .reg_shift = 0, | 1122 | .reg_shift = 0, |
1123 | .max_rate = 600000000, | ||
856 | }; | 1124 | }; |
857 | 1125 | ||
858 | static struct clk_pll_table tegra_pll_p_table[] = { | 1126 | static struct clk_pll_table tegra_pll_p_table[] = { |
@@ -880,6 +1148,7 @@ static struct clk tegra_pll_p = { | |||
880 | .vco_min = 20000000, | 1148 | .vco_min = 20000000, |
881 | .vco_max = 1400000000, | 1149 | .vco_max = 1400000000, |
882 | .pll_table = tegra_pll_p_table, | 1150 | .pll_table = tegra_pll_p_table, |
1151 | .max_rate = 432000000, | ||
883 | }; | 1152 | }; |
884 | 1153 | ||
885 | static struct clk tegra_pll_p_out1 = { | 1154 | static struct clk tegra_pll_p_out1 = { |
@@ -889,6 +1158,7 @@ static struct clk tegra_pll_p_out1 = { | |||
889 | .parent = &tegra_pll_p, | 1158 | .parent = &tegra_pll_p, |
890 | .reg = 0xa4, | 1159 | .reg = 0xa4, |
891 | .reg_shift = 0, | 1160 | .reg_shift = 0, |
1161 | .max_rate = 432000000, | ||
892 | }; | 1162 | }; |
893 | 1163 | ||
894 | static struct clk tegra_pll_p_out2 = { | 1164 | static struct clk tegra_pll_p_out2 = { |
@@ -898,6 +1168,7 @@ static struct clk tegra_pll_p_out2 = { | |||
898 | .parent = &tegra_pll_p, | 1168 | .parent = &tegra_pll_p, |
899 | .reg = 0xa4, | 1169 | .reg = 0xa4, |
900 | .reg_shift = 16, | 1170 | .reg_shift = 16, |
1171 | .max_rate = 432000000, | ||
901 | }; | 1172 | }; |
902 | 1173 | ||
903 | static struct clk tegra_pll_p_out3 = { | 1174 | static struct clk tegra_pll_p_out3 = { |
@@ -907,6 +1178,7 @@ static struct clk tegra_pll_p_out3 = { | |||
907 | .parent = &tegra_pll_p, | 1178 | .parent = &tegra_pll_p, |
908 | .reg = 0xa8, | 1179 | .reg = 0xa8, |
909 | .reg_shift = 0, | 1180 | .reg_shift = 0, |
1181 | .max_rate = 432000000, | ||
910 | }; | 1182 | }; |
911 | 1183 | ||
912 | static struct clk tegra_pll_p_out4 = { | 1184 | static struct clk tegra_pll_p_out4 = { |
@@ -916,6 +1188,7 @@ static struct clk tegra_pll_p_out4 = { | |||
916 | .parent = &tegra_pll_p, | 1188 | .parent = &tegra_pll_p, |
917 | .reg = 0xa8, | 1189 | .reg = 0xa8, |
918 | .reg_shift = 16, | 1190 | .reg_shift = 16, |
1191 | .max_rate = 432000000, | ||
919 | }; | 1192 | }; |
920 | 1193 | ||
921 | static struct clk_pll_table tegra_pll_a_table[] = { | 1194 | static struct clk_pll_table tegra_pll_a_table[] = { |
@@ -923,6 +1196,7 @@ static struct clk_pll_table tegra_pll_a_table[] = { | |||
923 | { 28800000, 73728000, 64, 25, 1, 1}, | 1196 | { 28800000, 73728000, 64, 25, 1, 1}, |
924 | { 28800000, 11289600, 49, 25, 1, 1}, | 1197 | { 28800000, 11289600, 49, 25, 1, 1}, |
925 | { 28800000, 12288000, 64, 25, 1, 1}, | 1198 | { 28800000, 12288000, 64, 25, 1, 1}, |
1199 | { 28800000, 24000000, 5, 6, 1, 1}, | ||
926 | { 0, 0, 0, 0, 0, 0 }, | 1200 | { 0, 0, 0, 0, 0, 0 }, |
927 | }; | 1201 | }; |
928 | 1202 | ||
@@ -939,6 +1213,7 @@ static struct clk tegra_pll_a = { | |||
939 | .vco_min = 20000000, | 1213 | .vco_min = 20000000, |
940 | .vco_max = 1400000000, | 1214 | .vco_max = 1400000000, |
941 | .pll_table = tegra_pll_a_table, | 1215 | .pll_table = tegra_pll_a_table, |
1216 | .max_rate = 56448000, | ||
942 | }; | 1217 | }; |
943 | 1218 | ||
944 | static struct clk tegra_pll_a_out0 = { | 1219 | static struct clk tegra_pll_a_out0 = { |
@@ -948,6 +1223,7 @@ static struct clk tegra_pll_a_out0 = { | |||
948 | .parent = &tegra_pll_a, | 1223 | .parent = &tegra_pll_a, |
949 | .reg = 0xb4, | 1224 | .reg = 0xb4, |
950 | .reg_shift = 0, | 1225 | .reg_shift = 0, |
1226 | .max_rate = 56448000, | ||
951 | }; | 1227 | }; |
952 | 1228 | ||
953 | static struct clk_pll_table tegra_pll_d_table[] = { | 1229 | static struct clk_pll_table tegra_pll_d_table[] = { |
@@ -971,6 +1247,7 @@ static struct clk tegra_pll_d = { | |||
971 | .vco_min = 40000000, | 1247 | .vco_min = 40000000, |
972 | .vco_max = 1000000000, | 1248 | .vco_max = 1000000000, |
973 | .pll_table = tegra_pll_d_table, | 1249 | .pll_table = tegra_pll_d_table, |
1250 | .max_rate = 1000000000, | ||
974 | }; | 1251 | }; |
975 | 1252 | ||
976 | static struct clk tegra_pll_d_out0 = { | 1253 | static struct clk tegra_pll_d_out0 = { |
@@ -978,19 +1255,20 @@ static struct clk tegra_pll_d_out0 = { | |||
978 | .ops = &tegra_pll_div_ops, | 1255 | .ops = &tegra_pll_div_ops, |
979 | .flags = DIV_2 | PLLD, | 1256 | .flags = DIV_2 | PLLD, |
980 | .parent = &tegra_pll_d, | 1257 | .parent = &tegra_pll_d, |
1258 | .max_rate = 500000000, | ||
981 | }; | 1259 | }; |
982 | 1260 | ||
983 | static struct clk_pll_table tegra_pll_u_table[] = { | 1261 | static struct clk_pll_table tegra_pll_u_table[] = { |
984 | { 12000000, 480000000, 960, 12, 1, 0}, | 1262 | { 12000000, 480000000, 960, 12, 2, 0}, |
985 | { 13000000, 480000000, 960, 13, 1, 0}, | 1263 | { 13000000, 480000000, 960, 13, 2, 0}, |
986 | { 19200000, 480000000, 200, 4, 1, 0}, | 1264 | { 19200000, 480000000, 200, 4, 2, 0}, |
987 | { 26000000, 480000000, 960, 26, 1, 0}, | 1265 | { 26000000, 480000000, 960, 26, 2, 0}, |
988 | { 0, 0, 0, 0, 0, 0 }, | 1266 | { 0, 0, 0, 0, 0, 0 }, |
989 | }; | 1267 | }; |
990 | 1268 | ||
991 | static struct clk tegra_pll_u = { | 1269 | static struct clk tegra_pll_u = { |
992 | .name = "pll_u", | 1270 | .name = "pll_u", |
993 | .flags = 0, | 1271 | .flags = PLLU, |
994 | .ops = &tegra_pll_ops, | 1272 | .ops = &tegra_pll_ops, |
995 | .reg = 0xc0, | 1273 | .reg = 0xc0, |
996 | .input_min = 2000000, | 1274 | .input_min = 2000000, |
@@ -1001,24 +1279,59 @@ static struct clk tegra_pll_u = { | |||
1001 | .vco_min = 480000000, | 1279 | .vco_min = 480000000, |
1002 | .vco_max = 960000000, | 1280 | .vco_max = 960000000, |
1003 | .pll_table = tegra_pll_u_table, | 1281 | .pll_table = tegra_pll_u_table, |
1282 | .max_rate = 480000000, | ||
1004 | }; | 1283 | }; |
1005 | 1284 | ||
1006 | static struct clk_pll_table tegra_pll_x_table[] = { | 1285 | static struct clk_pll_table tegra_pll_x_table[] = { |
1286 | /* 1 GHz */ | ||
1007 | { 12000000, 1000000000, 1000, 12, 1, 12}, | 1287 | { 12000000, 1000000000, 1000, 12, 1, 12}, |
1008 | { 13000000, 1000000000, 1000, 13, 1, 12}, | 1288 | { 13000000, 1000000000, 1000, 13, 1, 12}, |
1009 | { 19200000, 1000000000, 625, 12, 1, 8}, | 1289 | { 19200000, 1000000000, 625, 12, 1, 8}, |
1010 | { 26000000, 1000000000, 1000, 26, 1, 12}, | 1290 | { 26000000, 1000000000, 1000, 26, 1, 12}, |
1011 | { 12000000, 750000000, 750, 12, 1, 12}, | 1291 | |
1012 | { 13000000, 750000000, 750, 13, 1, 12}, | 1292 | /* 912 MHz */ |
1013 | { 19200000, 750000000, 625, 16, 1, 8}, | 1293 | { 12000000, 912000000, 912, 12, 1, 12}, |
1014 | { 26000000, 750000000, 750, 26, 1, 12}, | 1294 | { 13000000, 912000000, 912, 13, 1, 12}, |
1295 | { 19200000, 912000000, 760, 16, 1, 8}, | ||
1296 | { 26000000, 912000000, 912, 26, 1, 12}, | ||
1297 | |||
1298 | /* 816 MHz */ | ||
1299 | { 12000000, 816000000, 816, 12, 1, 12}, | ||
1300 | { 13000000, 816000000, 816, 13, 1, 12}, | ||
1301 | { 19200000, 816000000, 680, 16, 1, 8}, | ||
1302 | { 26000000, 816000000, 816, 26, 1, 12}, | ||
1303 | |||
1304 | /* 760 MHz */ | ||
1305 | { 12000000, 760000000, 760, 12, 1, 12}, | ||
1306 | { 13000000, 760000000, 760, 13, 1, 12}, | ||
1307 | { 19200000, 760000000, 950, 24, 1, 8}, | ||
1308 | { 26000000, 760000000, 760, 26, 1, 12}, | ||
1309 | |||
1310 | /* 608 MHz */ | ||
1311 | { 12000000, 608000000, 760, 12, 1, 12}, | ||
1312 | { 13000000, 608000000, 760, 13, 1, 12}, | ||
1313 | { 19200000, 608000000, 380, 12, 1, 8}, | ||
1314 | { 26000000, 608000000, 760, 26, 1, 12}, | ||
1315 | |||
1316 | /* 456 MHz */ | ||
1317 | { 12000000, 456000000, 456, 12, 1, 12}, | ||
1318 | { 13000000, 456000000, 456, 13, 1, 12}, | ||
1319 | { 19200000, 456000000, 380, 16, 1, 8}, | ||
1320 | { 26000000, 456000000, 456, 26, 1, 12}, | ||
1321 | |||
1322 | /* 312 MHz */ | ||
1323 | { 12000000, 312000000, 312, 12, 1, 12}, | ||
1324 | { 13000000, 312000000, 312, 13, 1, 12}, | ||
1325 | { 19200000, 312000000, 260, 16, 1, 8}, | ||
1326 | { 26000000, 312000000, 312, 26, 1, 12}, | ||
1327 | |||
1015 | { 0, 0, 0, 0, 0, 0 }, | 1328 | { 0, 0, 0, 0, 0, 0 }, |
1016 | }; | 1329 | }; |
1017 | 1330 | ||
1018 | static struct clk tegra_pll_x = { | 1331 | static struct clk tegra_pll_x = { |
1019 | .name = "pll_x", | 1332 | .name = "pll_x", |
1020 | .flags = PLL_HAS_CPCON | PLL_ALT_MISC_REG, | 1333 | .flags = PLL_HAS_CPCON | PLL_ALT_MISC_REG, |
1021 | .ops = &tegra_pll_ops, | 1334 | .ops = &tegra_pllx_ops, |
1022 | .reg = 0xe0, | 1335 | .reg = 0xe0, |
1023 | .input_min = 2000000, | 1336 | .input_min = 2000000, |
1024 | .input_max = 31000000, | 1337 | .input_max = 31000000, |
@@ -1028,6 +1341,24 @@ static struct clk tegra_pll_x = { | |||
1028 | .vco_min = 20000000, | 1341 | .vco_min = 20000000, |
1029 | .vco_max = 1200000000, | 1342 | .vco_max = 1200000000, |
1030 | .pll_table = tegra_pll_x_table, | 1343 | .pll_table = tegra_pll_x_table, |
1344 | .max_rate = 1000000000, | ||
1345 | }; | ||
1346 | |||
1347 | static struct clk_pll_table tegra_pll_e_table[] = { | ||
1348 | { 12000000, 100000000, 200, 24, 1, 0 }, | ||
1349 | { 0, 0, 0, 0, 0, 0 }, | ||
1350 | }; | ||
1351 | |||
1352 | static struct clk tegra_pll_e = { | ||
1353 | .name = "pll_e", | ||
1354 | .flags = PLL_ALT_MISC_REG, | ||
1355 | .ops = &tegra_plle_ops, | ||
1356 | .input_min = 12000000, | ||
1357 | .input_max = 12000000, | ||
1358 | .max_rate = 100000000, | ||
1359 | .parent = &tegra_clk_m, | ||
1360 | .reg = 0xe8, | ||
1361 | .pll_table = tegra_pll_e_table, | ||
1031 | }; | 1362 | }; |
1032 | 1363 | ||
1033 | static struct clk tegra_clk_d = { | 1364 | static struct clk tegra_clk_d = { |
@@ -1038,19 +1369,77 @@ static struct clk tegra_clk_d = { | |||
1038 | .reg = 0x34, | 1369 | .reg = 0x34, |
1039 | .reg_shift = 12, | 1370 | .reg_shift = 12, |
1040 | .parent = &tegra_clk_m, | 1371 | .parent = &tegra_clk_m, |
1372 | .max_rate = 52000000, | ||
1373 | }; | ||
1374 | |||
1375 | /* initialized before peripheral clocks */ | ||
1376 | static struct clk_mux_sel mux_audio_sync_clk[8+1]; | ||
1377 | static const struct audio_sources { | ||
1378 | const char *name; | ||
1379 | int value; | ||
1380 | } mux_audio_sync_clk_sources[] = { | ||
1381 | { .name = "spdif_in", .value = 0 }, | ||
1382 | { .name = "i2s1", .value = 1 }, | ||
1383 | { .name = "i2s2", .value = 2 }, | ||
1384 | { .name = "pll_a_out0", .value = 4 }, | ||
1385 | #if 0 /* FIXME: not implemented */ | ||
1386 | { .name = "ac97", .value = 3 }, | ||
1387 | { .name = "ext_audio_clk2", .value = 5 }, | ||
1388 | { .name = "ext_audio_clk1", .value = 6 }, | ||
1389 | { .name = "ext_vimclk", .value = 7 }, | ||
1390 | #endif | ||
1391 | { 0, 0 } | ||
1392 | }; | ||
1393 | |||
1394 | static struct clk tegra_clk_audio = { | ||
1395 | .name = "audio", | ||
1396 | .inputs = mux_audio_sync_clk, | ||
1397 | .reg = 0x38, | ||
1398 | .max_rate = 24000000, | ||
1399 | .ops = &tegra_audio_sync_clk_ops | ||
1041 | }; | 1400 | }; |
1042 | 1401 | ||
1043 | /* FIXME: need tegra_audio | ||
1044 | static struct clk tegra_clk_audio_2x = { | 1402 | static struct clk tegra_clk_audio_2x = { |
1045 | .name = "clk_d", | 1403 | .name = "audio_2x", |
1046 | .flags = PERIPH_NO_RESET, | 1404 | .flags = PERIPH_NO_RESET, |
1405 | .max_rate = 48000000, | ||
1047 | .ops = &tegra_clk_double_ops, | 1406 | .ops = &tegra_clk_double_ops, |
1048 | .clk_num = 89, | 1407 | .clk_num = 89, |
1049 | .reg = 0x34, | 1408 | .reg = 0x34, |
1050 | .reg_shift = 8, | 1409 | .reg_shift = 8, |
1051 | .parent = &tegra_audio, | 1410 | .parent = &tegra_clk_audio, |
1411 | }; | ||
1412 | |||
1413 | struct clk_lookup tegra_audio_clk_lookups[] = { | ||
1414 | { .con_id = "audio", .clk = &tegra_clk_audio }, | ||
1415 | { .con_id = "audio_2x", .clk = &tegra_clk_audio_2x } | ||
1416 | }; | ||
1417 | |||
1418 | /* This is called after peripheral clocks are initialized, as the | ||
1419 | * audio_sync clock depends on some of the peripheral clocks. | ||
1420 | */ | ||
1421 | |||
1422 | static void init_audio_sync_clock_mux(void) | ||
1423 | { | ||
1424 | int i; | ||
1425 | struct clk_mux_sel *sel = mux_audio_sync_clk; | ||
1426 | const struct audio_sources *src = mux_audio_sync_clk_sources; | ||
1427 | struct clk_lookup *lookup; | ||
1428 | |||
1429 | for (i = 0; src->name; i++, sel++, src++) { | ||
1430 | sel->input = tegra_get_clock_by_name(src->name); | ||
1431 | if (!sel->input) | ||
1432 | pr_err("%s: could not find clk %s\n", __func__, | ||
1433 | src->name); | ||
1434 | sel->value = src->value; | ||
1435 | } | ||
1436 | |||
1437 | lookup = tegra_audio_clk_lookups; | ||
1438 | for (i = 0; i < ARRAY_SIZE(tegra_audio_clk_lookups); i++, lookup++) { | ||
1439 | clk_init(lookup->clk); | ||
1440 | clkdev_add(lookup); | ||
1441 | } | ||
1052 | } | 1442 | } |
1053 | */ | ||
1054 | 1443 | ||
1055 | static struct clk_mux_sel mux_cclk[] = { | 1444 | static struct clk_mux_sel mux_cclk[] = { |
1056 | { .input = &tegra_clk_m, .value = 0}, | 1445 | { .input = &tegra_clk_m, .value = 0}, |
@@ -1077,27 +1466,40 @@ static struct clk_mux_sel mux_sclk[] = { | |||
1077 | { 0, 0}, | 1466 | { 0, 0}, |
1078 | }; | 1467 | }; |
1079 | 1468 | ||
1080 | static struct clk tegra_clk_cpu = { | 1469 | static struct clk tegra_clk_cclk = { |
1081 | .name = "cpu", | 1470 | .name = "cclk", |
1082 | .inputs = mux_cclk, | 1471 | .inputs = mux_cclk, |
1083 | .reg = 0x20, | 1472 | .reg = 0x20, |
1084 | .ops = &tegra_super_ops, | 1473 | .ops = &tegra_super_ops, |
1474 | .max_rate = 1000000000, | ||
1085 | }; | 1475 | }; |
1086 | 1476 | ||
1087 | static struct clk tegra_clk_sys = { | 1477 | static struct clk tegra_clk_sclk = { |
1088 | .name = "sys", | 1478 | .name = "sclk", |
1089 | .inputs = mux_sclk, | 1479 | .inputs = mux_sclk, |
1090 | .reg = 0x28, | 1480 | .reg = 0x28, |
1091 | .ops = &tegra_super_ops, | 1481 | .ops = &tegra_super_ops, |
1482 | .max_rate = 600000000, | ||
1483 | }; | ||
1484 | |||
1485 | static struct clk tegra_clk_virtual_cpu = { | ||
1486 | .name = "cpu", | ||
1487 | .parent = &tegra_clk_cclk, | ||
1488 | .main = &tegra_pll_x, | ||
1489 | .backup = &tegra_clk_m, | ||
1490 | .ops = &tegra_cpu_ops, | ||
1491 | .max_rate = 1000000000, | ||
1492 | .dvfs = &tegra_dvfs_virtual_cpu_dvfs, | ||
1092 | }; | 1493 | }; |
1093 | 1494 | ||
1094 | static struct clk tegra_clk_hclk = { | 1495 | static struct clk tegra_clk_hclk = { |
1095 | .name = "hclk", | 1496 | .name = "hclk", |
1096 | .flags = DIV_BUS, | 1497 | .flags = DIV_BUS, |
1097 | .parent = &tegra_clk_sys, | 1498 | .parent = &tegra_clk_sclk, |
1098 | .reg = 0x30, | 1499 | .reg = 0x30, |
1099 | .reg_shift = 4, | 1500 | .reg_shift = 4, |
1100 | .ops = &tegra_bus_ops, | 1501 | .ops = &tegra_bus_ops, |
1502 | .max_rate = 240000000, | ||
1101 | }; | 1503 | }; |
1102 | 1504 | ||
1103 | static struct clk tegra_clk_pclk = { | 1505 | static struct clk tegra_clk_pclk = { |
@@ -1107,6 +1509,7 @@ static struct clk tegra_clk_pclk = { | |||
1107 | .reg = 0x30, | 1509 | .reg = 0x30, |
1108 | .reg_shift = 0, | 1510 | .reg_shift = 0, |
1109 | .ops = &tegra_bus_ops, | 1511 | .ops = &tegra_bus_ops, |
1512 | .max_rate = 108000000, | ||
1110 | }; | 1513 | }; |
1111 | 1514 | ||
1112 | static struct clk_mux_sel mux_pllm_pllc_pllp_plla[] = { | 1515 | static struct clk_mux_sel mux_pllm_pllc_pllp_plla[] = { |
@@ -1133,10 +1536,9 @@ static struct clk_mux_sel mux_pllp_pllc_pllm_clkm[] = { | |||
1133 | { 0, 0}, | 1536 | { 0, 0}, |
1134 | }; | 1537 | }; |
1135 | 1538 | ||
1136 | static struct clk_mux_sel mux_plla_audio_pllp_clkm[] = { | 1539 | static struct clk_mux_sel mux_pllaout0_audio2x_pllp_clkm[] = { |
1137 | {.input = &tegra_pll_a, .value = 0}, | 1540 | {.input = &tegra_pll_a_out0, .value = 0}, |
1138 | /* FIXME: no mux defined for tegra_audio | 1541 | {.input = &tegra_clk_audio_2x, .value = 1}, |
1139 | {.input = &tegra_audio, .value = 1},*/ | ||
1140 | {.input = &tegra_pll_p, .value = 2}, | 1542 | {.input = &tegra_pll_p, .value = 2}, |
1141 | {.input = &tegra_clk_m, .value = 3}, | 1543 | {.input = &tegra_clk_m, .value = 3}, |
1142 | { 0, 0}, | 1544 | { 0, 0}, |
@@ -1153,8 +1555,7 @@ static struct clk_mux_sel mux_pllp_plld_pllc_clkm[] = { | |||
1153 | static struct clk_mux_sel mux_pllp_pllc_audio_clkm_clk32[] = { | 1555 | static struct clk_mux_sel mux_pllp_pllc_audio_clkm_clk32[] = { |
1154 | {.input = &tegra_pll_p, .value = 0}, | 1556 | {.input = &tegra_pll_p, .value = 0}, |
1155 | {.input = &tegra_pll_c, .value = 1}, | 1557 | {.input = &tegra_pll_c, .value = 1}, |
1156 | /* FIXME: no mux defined for tegra_audio | 1558 | {.input = &tegra_clk_audio, .value = 2}, |
1157 | {.input = &tegra_audio, .value = 2},*/ | ||
1158 | {.input = &tegra_clk_m, .value = 3}, | 1559 | {.input = &tegra_clk_m, .value = 3}, |
1159 | {.input = &tegra_clk_32k, .value = 4}, | 1560 | {.input = &tegra_clk_32k, .value = 4}, |
1160 | { 0, 0}, | 1561 | { 0, 0}, |
@@ -1187,7 +1588,7 @@ static struct clk_mux_sel mux_clk_32k[] = { | |||
1187 | { 0, 0}, | 1588 | { 0, 0}, |
1188 | }; | 1589 | }; |
1189 | 1590 | ||
1190 | #define PERIPH_CLK(_name, _dev, _con, _clk_num, _reg, _inputs, _flags) \ | 1591 | #define PERIPH_CLK(_name, _dev, _con, _clk_num, _reg, _max, _inputs, _flags) \ |
1191 | { \ | 1592 | { \ |
1192 | .name = _name, \ | 1593 | .name = _name, \ |
1193 | .lookup = { \ | 1594 | .lookup = { \ |
@@ -1199,72 +1600,79 @@ static struct clk_mux_sel mux_clk_32k[] = { | |||
1199 | .reg = _reg, \ | 1600 | .reg = _reg, \ |
1200 | .inputs = _inputs, \ | 1601 | .inputs = _inputs, \ |
1201 | .flags = _flags, \ | 1602 | .flags = _flags, \ |
1603 | .max_rate = _max, \ | ||
1202 | } | 1604 | } |
1203 | 1605 | ||
1204 | struct clk tegra_periph_clks[] = { | 1606 | struct clk tegra_periph_clks[] = { |
1205 | PERIPH_CLK("rtc", "rtc-tegra", NULL, 4, 0, mux_clk_32k, PERIPH_NO_RESET), | 1607 | PERIPH_CLK("rtc", "rtc-tegra", NULL, 4, 0, 32768, mux_clk_32k, PERIPH_NO_RESET), |
1206 | PERIPH_CLK("timer", "timer", NULL, 5, 0, mux_clk_m, 0), | 1608 | PERIPH_CLK("timer", "timer", NULL, 5, 0, 26000000, mux_clk_m, 0), |
1207 | PERIPH_CLK("i2s1", "i2s.0", NULL, 11, 0x100, mux_plla_audio_pllp_clkm, MUX | DIV_U71), | 1609 | PERIPH_CLK("i2s1", "i2s.0", NULL, 11, 0x100, 26000000, mux_pllaout0_audio2x_pllp_clkm, MUX | DIV_U71), |
1208 | PERIPH_CLK("i2s2", "i2s.1", NULL, 18, 0x104, mux_plla_audio_pllp_clkm, MUX | DIV_U71), | 1610 | PERIPH_CLK("i2s2", "i2s.1", NULL, 18, 0x104, 26000000, mux_pllaout0_audio2x_pllp_clkm, MUX | DIV_U71), |
1209 | /* FIXME: spdif has 2 clocks but 1 enable */ | 1611 | /* FIXME: spdif has 2 clocks but 1 enable */ |
1210 | PERIPH_CLK("spdif_out", "spdif_out", NULL, 10, 0x108, mux_plla_audio_pllp_clkm, MUX | DIV_U71), | 1612 | PERIPH_CLK("spdif_out", "spdif_out", NULL, 10, 0x108, 100000000, mux_pllaout0_audio2x_pllp_clkm, MUX | DIV_U71), |
1211 | PERIPH_CLK("spdif_in", "spdif_in", NULL, 10, 0x10c, mux_pllp_pllc_pllm, MUX | DIV_U71), | 1613 | PERIPH_CLK("spdif_in", "spdif_in", NULL, 10, 0x10c, 100000000, mux_pllp_pllc_pllm, MUX | DIV_U71), |
1212 | PERIPH_CLK("pwm", "pwm", NULL, 17, 0x110, mux_pllp_pllc_audio_clkm_clk32, MUX | DIV_U71), | 1614 | PERIPH_CLK("pwm", "pwm", NULL, 17, 0x110, 432000000, mux_pllp_pllc_audio_clkm_clk32, MUX | DIV_U71), |
1213 | PERIPH_CLK("spi", "spi", NULL, 43, 0x114, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | 1615 | PERIPH_CLK("spi", "spi", NULL, 43, 0x114, 40000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), |
1214 | PERIPH_CLK("xio", "xio", NULL, 45, 0x120, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | 1616 | PERIPH_CLK("xio", "xio", NULL, 45, 0x120, 150000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), |
1215 | PERIPH_CLK("twc", "twc", NULL, 16, 0x12c, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | 1617 | PERIPH_CLK("twc", "twc", NULL, 16, 0x12c, 150000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), |
1216 | PERIPH_CLK("sbc1", "spi_tegra.0", NULL, 41, 0x134, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | 1618 | PERIPH_CLK("sbc1", "spi_tegra.0", NULL, 41, 0x134, 160000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), |
1217 | PERIPH_CLK("sbc2", "spi_tegra.1", NULL, 44, 0x118, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | 1619 | PERIPH_CLK("sbc2", "spi_tegra.1", NULL, 44, 0x118, 160000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), |
1218 | PERIPH_CLK("sbc3", "spi_tegra.2", NULL, 46, 0x11c, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | 1620 | PERIPH_CLK("sbc3", "spi_tegra.2", NULL, 46, 0x11c, 160000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), |
1219 | PERIPH_CLK("sbc4", "spi_tegra.3", NULL, 68, 0x1b4, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | 1621 | PERIPH_CLK("sbc4", "spi_tegra.3", NULL, 68, 0x1b4, 160000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), |
1220 | PERIPH_CLK("ide", "ide", NULL, 25, 0x144, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | 1622 | PERIPH_CLK("ide", "ide", NULL, 25, 0x144, 100000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), /* requires min voltage */ |
1221 | PERIPH_CLK("ndflash", "tegra_nand", NULL, 13, 0x160, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | 1623 | PERIPH_CLK("ndflash", "tegra_nand", NULL, 13, 0x160, 164000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), /* scales with voltage */ |
1222 | /* FIXME: vfir shares an enable with uartb */ | 1624 | /* FIXME: vfir shares an enable with uartb */ |
1223 | PERIPH_CLK("vfir", "vfir", NULL, 7, 0x168, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | 1625 | PERIPH_CLK("vfir", "vfir", NULL, 7, 0x168, 72000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), |
1224 | PERIPH_CLK("sdmmc1", "sdhci-tegra.0", NULL, 14, 0x150, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | 1626 | PERIPH_CLK("sdmmc1", "sdhci-tegra.0", NULL, 14, 0x150, 52000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), /* scales with voltage */ |
1225 | PERIPH_CLK("sdmmc2", "sdhci-tegra.1", NULL, 9, 0x154, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | 1627 | PERIPH_CLK("sdmmc2", "sdhci-tegra.1", NULL, 9, 0x154, 52000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), /* scales with voltage */ |
1226 | PERIPH_CLK("sdmmc3", "sdhci-tegra.2", NULL, 69, 0x1bc, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | 1628 | PERIPH_CLK("sdmmc3", "sdhci-tegra.2", NULL, 69, 0x1bc, 52000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), /* scales with voltage */ |
1227 | PERIPH_CLK("sdmmc4", "sdhci-tegra.3", NULL, 15, 0x160, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | 1629 | PERIPH_CLK("sdmmc4", "sdhci-tegra.3", NULL, 15, 0x160, 52000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), /* scales with voltage */ |
1228 | PERIPH_CLK("vde", "vde", NULL, 61, 0x1c8, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | 1630 | PERIPH_CLK("vde", "vde", NULL, 61, 0x1c8, 250000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), /* scales with voltage and process_id */ |
1229 | PERIPH_CLK("csite", "csite", NULL, 73, 0x1d4, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | 1631 | PERIPH_CLK("csite", "csite", NULL, 73, 0x1d4, 144000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), /* max rate ??? */ |
1230 | /* FIXME: what is la? */ | 1632 | /* FIXME: what is la? */ |
1231 | PERIPH_CLK("la", "la", NULL, 76, 0x1f8, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | 1633 | PERIPH_CLK("la", "la", NULL, 76, 0x1f8, 26000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), |
1232 | PERIPH_CLK("owr", "owr", NULL, 71, 0x1cc, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | 1634 | PERIPH_CLK("owr", "tegra_w1", NULL, 71, 0x1cc, 26000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), |
1233 | PERIPH_CLK("nor", "nor", NULL, 42, 0x1d0, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | 1635 | PERIPH_CLK("nor", "nor", NULL, 42, 0x1d0, 92000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), /* requires min voltage */ |
1234 | PERIPH_CLK("mipi", "mipi", NULL, 50, 0x174, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | 1636 | PERIPH_CLK("mipi", "mipi", NULL, 50, 0x174, 60000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), /* scales with voltage */ |
1235 | PERIPH_CLK("i2c1", "tegra-i2c.0", NULL, 12, 0x124, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | 1637 | PERIPH_CLK("i2c1", "tegra-i2c.0", NULL, 12, 0x124, 26000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U16), |
1236 | PERIPH_CLK("i2c2", "tegra-i2c.1", NULL, 54, 0x198, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | 1638 | PERIPH_CLK("i2c2", "tegra-i2c.1", NULL, 54, 0x198, 26000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U16), |
1237 | PERIPH_CLK("i2c3", "tegra-i2c.2", NULL, 67, 0x1b8, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | 1639 | PERIPH_CLK("i2c3", "tegra-i2c.2", NULL, 67, 0x1b8, 26000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U16), |
1238 | PERIPH_CLK("dvc", "tegra-i2c.3", NULL, 47, 0x128, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | 1640 | PERIPH_CLK("dvc", "tegra-i2c.3", NULL, 47, 0x128, 26000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U16), |
1239 | PERIPH_CLK("i2c1_i2c", "tegra-i2c.0", "i2c", 0, 0, mux_pllp_out3, 0), | 1641 | PERIPH_CLK("i2c1_i2c", "tegra-i2c.0", "i2c", 0, 0, 72000000, mux_pllp_out3, 0), |
1240 | PERIPH_CLK("i2c2_i2c", "tegra-i2c.1", "i2c", 0, 0, mux_pllp_out3, 0), | 1642 | PERIPH_CLK("i2c2_i2c", "tegra-i2c.1", "i2c", 0, 0, 72000000, mux_pllp_out3, 0), |
1241 | PERIPH_CLK("i2c3_i2c", "tegra-i2c.2", "i2c", 0, 0, mux_pllp_out3, 0), | 1643 | PERIPH_CLK("i2c3_i2c", "tegra-i2c.2", "i2c", 0, 0, 72000000, mux_pllp_out3, 0), |
1242 | PERIPH_CLK("dvc_i2c", "tegra-i2c.3", "i2c", 0, 0, mux_pllp_out3, 0), | 1644 | PERIPH_CLK("dvc_i2c", "tegra-i2c.3", "i2c", 0, 0, 72000000, mux_pllp_out3, 0), |
1243 | PERIPH_CLK("uarta", "uart.0", NULL, 6, 0x178, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | 1645 | PERIPH_CLK("uarta", "uart.0", NULL, 6, 0x178, 216000000, mux_pllp_pllc_pllm_clkm, MUX), |
1244 | PERIPH_CLK("uartb", "uart.1", NULL, 7, 0x17c, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | 1646 | PERIPH_CLK("uartb", "uart.1", NULL, 7, 0x17c, 216000000, mux_pllp_pllc_pllm_clkm, MUX), |
1245 | PERIPH_CLK("uartc", "uart.2", NULL, 55, 0x1a0, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | 1647 | PERIPH_CLK("uartc", "uart.2", NULL, 55, 0x1a0, 216000000, mux_pllp_pllc_pllm_clkm, MUX), |
1246 | PERIPH_CLK("uartd", "uart.3", NULL, 65, 0x1c0, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | 1648 | PERIPH_CLK("uartd", "uart.3", NULL, 65, 0x1c0, 216000000, mux_pllp_pllc_pllm_clkm, MUX), |
1247 | PERIPH_CLK("uarte", "uart.4", NULL, 66, 0x1c4, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | 1649 | PERIPH_CLK("uarte", "uart.4", NULL, 66, 0x1c4, 216000000, mux_pllp_pllc_pllm_clkm, MUX), |
1248 | PERIPH_CLK("3d", "3d", NULL, 24, 0x158, mux_pllm_pllc_pllp_plla, MUX | DIV_U71 | PERIPH_MANUAL_RESET), | 1650 | PERIPH_CLK("3d", "3d", NULL, 24, 0x158, 300000000, mux_pllm_pllc_pllp_plla, MUX | DIV_U71 | PERIPH_MANUAL_RESET), /* scales with voltage and process_id */ |
1249 | PERIPH_CLK("2d", "2d", NULL, 21, 0x15c, mux_pllm_pllc_pllp_plla, MUX | DIV_U71), | 1651 | PERIPH_CLK("2d", "2d", NULL, 21, 0x15c, 300000000, mux_pllm_pllc_pllp_plla, MUX | DIV_U71), /* scales with voltage and process_id */ |
1250 | /* FIXME: vi and vi_sensor share an enable */ | 1652 | /* FIXME: vi and vi_sensor share an enable */ |
1251 | PERIPH_CLK("vi", "vi", NULL, 20, 0x148, mux_pllm_pllc_pllp_plla, MUX | DIV_U71), | 1653 | PERIPH_CLK("vi", "vi", NULL, 20, 0x148, 150000000, mux_pllm_pllc_pllp_plla, MUX | DIV_U71), /* scales with voltage and process_id */ |
1252 | PERIPH_CLK("vi_sensor", "vi_sensor", NULL, 20, 0x1a8, mux_pllm_pllc_pllp_plla, MUX | DIV_U71), | 1654 | PERIPH_CLK("vi_sensor", "vi_sensor", NULL, 20, 0x1a8, 150000000, mux_pllm_pllc_pllp_plla, MUX | DIV_U71 | PERIPH_NO_RESET), /* scales with voltage and process_id */ |
1253 | PERIPH_CLK("epp", "epp", NULL, 19, 0x16c, mux_pllm_pllc_pllp_plla, MUX | DIV_U71), | 1655 | PERIPH_CLK("epp", "epp", NULL, 19, 0x16c, 300000000, mux_pllm_pllc_pllp_plla, MUX | DIV_U71), /* scales with voltage and process_id */ |
1254 | PERIPH_CLK("mpe", "mpe", NULL, 60, 0x170, mux_pllm_pllc_pllp_plla, MUX | DIV_U71), | 1656 | PERIPH_CLK("mpe", "mpe", NULL, 60, 0x170, 250000000, mux_pllm_pllc_pllp_plla, MUX | DIV_U71), /* scales with voltage and process_id */ |
1255 | PERIPH_CLK("host1x", "host1x", NULL, 28, 0x180, mux_pllm_pllc_pllp_plla, MUX | DIV_U71), | 1657 | PERIPH_CLK("host1x", "host1x", NULL, 28, 0x180, 166000000, mux_pllm_pllc_pllp_plla, MUX | DIV_U71), /* scales with voltage and process_id */ |
1256 | /* FIXME: cve and tvo share an enable */ | 1658 | /* FIXME: cve and tvo share an enable */ |
1257 | PERIPH_CLK("cve", "cve", NULL, 49, 0x140, mux_pllp_plld_pllc_clkm, MUX | DIV_U71), | 1659 | PERIPH_CLK("cve", "cve", NULL, 49, 0x140, 250000000, mux_pllp_plld_pllc_clkm, MUX | DIV_U71), /* requires min voltage */ |
1258 | PERIPH_CLK("tvo", "tvo", NULL, 49, 0x188, mux_pllp_plld_pllc_clkm, MUX | DIV_U71), | 1660 | PERIPH_CLK("tvo", "tvo", NULL, 49, 0x188, 250000000, mux_pllp_plld_pllc_clkm, MUX | DIV_U71), /* requires min voltage */ |
1259 | PERIPH_CLK("hdmi", "hdmi", NULL, 51, 0x18c, mux_pllp_plld_pllc_clkm, MUX | DIV_U71), | 1661 | PERIPH_CLK("hdmi", "hdmi", NULL, 51, 0x18c, 148500000, mux_pllp_plld_pllc_clkm, MUX | DIV_U71), /* requires min voltage */ |
1260 | PERIPH_CLK("tvdac", "tvdac", NULL, 53, 0x194, mux_pllp_plld_pllc_clkm, MUX | DIV_U71), | 1662 | PERIPH_CLK("tvdac", "tvdac", NULL, 53, 0x194, 250000000, mux_pllp_plld_pllc_clkm, MUX | DIV_U71), /* requires min voltage */ |
1261 | PERIPH_CLK("disp1", "tegrafb.0", NULL, 27, 0x138, mux_pllp_plld_pllc_clkm, MUX | DIV_U71), | 1663 | PERIPH_CLK("disp1", "tegrafb.0", NULL, 27, 0x138, 190000000, mux_pllp_plld_pllc_clkm, MUX | DIV_U71), /* scales with voltage and process_id */ |
1262 | PERIPH_CLK("disp2", "tegrafb.1", NULL, 26, 0x13c, mux_pllp_plld_pllc_clkm, MUX | DIV_U71), | 1664 | PERIPH_CLK("disp2", "tegrafb.1", NULL, 26, 0x13c, 190000000, mux_pllp_plld_pllc_clkm, MUX | DIV_U71), /* scales with voltage and process_id */ |
1263 | PERIPH_CLK("usbd", "fsl-tegra-udc", NULL, 22, 0, mux_clk_m, 0), | 1665 | PERIPH_CLK("usbd", "fsl-tegra-udc", NULL, 22, 0, 480000000, mux_clk_m, 0), /* requires min voltage */ |
1264 | PERIPH_CLK("usb2", "usb.1", NULL, 58, 0, mux_clk_m, 0), | 1666 | PERIPH_CLK("usb2", "tegra-ehci.1", NULL, 58, 0, 480000000, mux_clk_m, 0), /* requires min voltage */ |
1265 | PERIPH_CLK("usb3", "usb.2", NULL, 59, 0, mux_clk_m, 0), | 1667 | PERIPH_CLK("usb3", "tegra-ehci.2", NULL, 59, 0, 480000000, mux_clk_m, 0), /* requires min voltage */ |
1266 | PERIPH_CLK("emc", "emc", NULL, 57, 0x19c, mux_pllm_pllc_pllp_clkm, MUX | DIV_U71 | PERIPH_EMC_ENB), | 1668 | PERIPH_CLK("emc", "emc", NULL, 57, 0x19c, 800000000, mux_pllm_pllc_pllp_clkm, MUX | DIV_U71 | PERIPH_EMC_ENB), |
1267 | PERIPH_CLK("dsi", "dsi", NULL, 48, 0, mux_plld, 0), | 1669 | PERIPH_CLK("dsi", "dsi", NULL, 48, 0, 500000000, mux_plld, 0), /* scales with voltage */ |
1670 | PERIPH_CLK("csi", "csi", NULL, 52, 0, 72000000, mux_pllp_out3, 0), | ||
1671 | PERIPH_CLK("isp", "isp", NULL, 23, 0, 150000000, mux_clk_m, 0), /* same frequency as VI */ | ||
1672 | PERIPH_CLK("csus", "csus", NULL, 92, 0, 150000000, mux_clk_m, PERIPH_NO_RESET), | ||
1673 | PERIPH_CLK("pex", NULL, "pex", 70, 0, 26000000, mux_clk_m, PERIPH_MANUAL_RESET), | ||
1674 | PERIPH_CLK("afi", NULL, "afi", 72, 0, 26000000, mux_clk_m, PERIPH_MANUAL_RESET), | ||
1675 | PERIPH_CLK("pcie_xclk", NULL, "pcie_xclk", 74, 0, 26000000, mux_clk_m, PERIPH_MANUAL_RESET), | ||
1268 | }; | 1676 | }; |
1269 | 1677 | ||
1270 | #define CLK_DUPLICATE(_name, _dev, _con) \ | 1678 | #define CLK_DUPLICATE(_name, _dev, _con) \ |
@@ -1286,6 +1694,9 @@ struct clk_duplicate tegra_clk_duplicates[] = { | |||
1286 | CLK_DUPLICATE("uartc", "tegra_uart.2", NULL), | 1694 | CLK_DUPLICATE("uartc", "tegra_uart.2", NULL), |
1287 | CLK_DUPLICATE("uartd", "tegra_uart.3", NULL), | 1695 | CLK_DUPLICATE("uartd", "tegra_uart.3", NULL), |
1288 | CLK_DUPLICATE("uarte", "tegra_uart.4", NULL), | 1696 | CLK_DUPLICATE("uarte", "tegra_uart.4", NULL), |
1697 | CLK_DUPLICATE("host1x", "tegrafb.0", "host1x"), | ||
1698 | CLK_DUPLICATE("host1x", "tegrafb.1", "host1x"), | ||
1699 | CLK_DUPLICATE("usbd", "tegra-ehci.0", NULL), | ||
1289 | }; | 1700 | }; |
1290 | 1701 | ||
1291 | #define CLK(dev, con, ck) \ | 1702 | #define CLK(dev, con, ck) \ |
@@ -1315,11 +1726,13 @@ struct clk_lookup tegra_clk_lookups[] = { | |||
1315 | CLK(NULL, "pll_d_out0", &tegra_pll_d_out0), | 1726 | CLK(NULL, "pll_d_out0", &tegra_pll_d_out0), |
1316 | CLK(NULL, "pll_u", &tegra_pll_u), | 1727 | CLK(NULL, "pll_u", &tegra_pll_u), |
1317 | CLK(NULL, "pll_x", &tegra_pll_x), | 1728 | CLK(NULL, "pll_x", &tegra_pll_x), |
1318 | CLK(NULL, "cpu", &tegra_clk_cpu), | 1729 | CLK(NULL, "pll_e", &tegra_pll_e), |
1319 | CLK(NULL, "sys", &tegra_clk_sys), | 1730 | CLK(NULL, "cclk", &tegra_clk_cclk), |
1731 | CLK(NULL, "sclk", &tegra_clk_sclk), | ||
1320 | CLK(NULL, "hclk", &tegra_clk_hclk), | 1732 | CLK(NULL, "hclk", &tegra_clk_hclk), |
1321 | CLK(NULL, "pclk", &tegra_clk_pclk), | 1733 | CLK(NULL, "pclk", &tegra_clk_pclk), |
1322 | CLK(NULL, "clk_d", &tegra_clk_d), | 1734 | CLK(NULL, "clk_d", &tegra_clk_d), |
1735 | CLK(NULL, "cpu", &tegra_clk_virtual_cpu), | ||
1323 | }; | 1736 | }; |
1324 | 1737 | ||
1325 | void __init tegra2_init_clocks(void) | 1738 | void __init tegra2_init_clocks(void) |
@@ -1356,4 +1769,75 @@ void __init tegra2_init_clocks(void) | |||
1356 | cd->name); | 1769 | cd->name); |
1357 | } | 1770 | } |
1358 | } | 1771 | } |
1772 | |||
1773 | init_audio_sync_clock_mux(); | ||
1774 | } | ||
1775 | |||
1776 | #ifdef CONFIG_PM | ||
1777 | static u32 clk_rst_suspend[RST_DEVICES_NUM + CLK_OUT_ENB_NUM + | ||
1778 | PERIPH_CLK_SOURCE_NUM + 3]; | ||
1779 | |||
1780 | void tegra_clk_suspend(void) | ||
1781 | { | ||
1782 | unsigned long off, i; | ||
1783 | u32 *ctx = clk_rst_suspend; | ||
1784 | |||
1785 | *ctx++ = clk_readl(OSC_CTRL) & OSC_CTRL_MASK; | ||
1786 | |||
1787 | for (off = PERIPH_CLK_SOURCE_I2S1; off <= PERIPH_CLK_SOURCE_OSC; | ||
1788 | off += 4) { | ||
1789 | if (off == PERIPH_CLK_SOURCE_EMC) | ||
1790 | continue; | ||
1791 | *ctx++ = clk_readl(off); | ||
1792 | } | ||
1793 | |||
1794 | off = RST_DEVICES; | ||
1795 | for (i = 0; i < RST_DEVICES_NUM; i++, off += 4) | ||
1796 | *ctx++ = clk_readl(off); | ||
1797 | |||
1798 | off = CLK_OUT_ENB; | ||
1799 | for (i = 0; i < CLK_OUT_ENB_NUM; i++, off += 4) | ||
1800 | *ctx++ = clk_readl(off); | ||
1801 | |||
1802 | *ctx++ = clk_readl(MISC_CLK_ENB); | ||
1803 | *ctx++ = clk_readl(CLK_MASK_ARM); | ||
1804 | } | ||
1805 | |||
1806 | void tegra_clk_resume(void) | ||
1807 | { | ||
1808 | unsigned long off, i; | ||
1809 | const u32 *ctx = clk_rst_suspend; | ||
1810 | u32 val; | ||
1811 | |||
1812 | val = clk_readl(OSC_CTRL) & ~OSC_CTRL_MASK; | ||
1813 | val |= *ctx++; | ||
1814 | clk_writel(val, OSC_CTRL); | ||
1815 | |||
1816 | /* enable all clocks before configuring clock sources */ | ||
1817 | clk_writel(0xbffffff9ul, CLK_OUT_ENB); | ||
1818 | clk_writel(0xfefffff7ul, CLK_OUT_ENB + 4); | ||
1819 | clk_writel(0x77f01bfful, CLK_OUT_ENB + 8); | ||
1820 | wmb(); | ||
1821 | |||
1822 | for (off = PERIPH_CLK_SOURCE_I2S1; off <= PERIPH_CLK_SOURCE_OSC; | ||
1823 | off += 4) { | ||
1824 | if (off == PERIPH_CLK_SOURCE_EMC) | ||
1825 | continue; | ||
1826 | clk_writel(*ctx++, off); | ||
1827 | } | ||
1828 | wmb(); | ||
1829 | |||
1830 | off = RST_DEVICES; | ||
1831 | for (i = 0; i < RST_DEVICES_NUM; i++, off += 4) | ||
1832 | clk_writel(*ctx++, off); | ||
1833 | wmb(); | ||
1834 | |||
1835 | off = CLK_OUT_ENB; | ||
1836 | for (i = 0; i < CLK_OUT_ENB_NUM; i++, off += 4) | ||
1837 | clk_writel(*ctx++, off); | ||
1838 | wmb(); | ||
1839 | |||
1840 | clk_writel(*ctx++, MISC_CLK_ENB); | ||
1841 | clk_writel(*ctx++, CLK_MASK_ARM); | ||
1359 | } | 1842 | } |
1843 | #endif | ||
diff --git a/arch/arm/mach-tegra/tegra2_dvfs.c b/arch/arm/mach-tegra/tegra2_dvfs.c new file mode 100644 index 000000000000..5529c238dd77 --- /dev/null +++ b/arch/arm/mach-tegra/tegra2_dvfs.c | |||
@@ -0,0 +1,86 @@ | |||
1 | /* | ||
2 | * arch/arm/mach-tegra/tegra2_dvfs.c | ||
3 | * | ||
4 | * Copyright (C) 2010 Google, Inc. | ||
5 | * | ||
6 | * Author: | ||
7 | * Colin Cross <ccross@google.com> | ||
8 | * | ||
9 | * This software is licensed under the terms of the GNU General Public | ||
10 | * License version 2, as published by the Free Software Foundation, and | ||
11 | * may be copied, distributed, and modified under those terms. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | */ | ||
19 | |||
20 | #include <linux/kernel.h> | ||
21 | |||
22 | #include "clock.h" | ||
23 | #include "tegra2_dvfs.h" | ||
24 | |||
25 | static struct dvfs_table virtual_cpu_process_0[] = { | ||
26 | {314000000, 750}, | ||
27 | {456000000, 825}, | ||
28 | {608000000, 900}, | ||
29 | {760000000, 975}, | ||
30 | {817000000, 1000}, | ||
31 | {912000000, 1050}, | ||
32 | {1000000000, 1100}, | ||
33 | {0, 0}, | ||
34 | }; | ||
35 | |||
36 | static struct dvfs_table virtual_cpu_process_1[] = { | ||
37 | {314000000, 750}, | ||
38 | {456000000, 825}, | ||
39 | {618000000, 900}, | ||
40 | {770000000, 975}, | ||
41 | {827000000, 1000}, | ||
42 | {922000000, 1050}, | ||
43 | {1000000000, 1100}, | ||
44 | {0, 0}, | ||
45 | }; | ||
46 | |||
47 | static struct dvfs_table virtual_cpu_process_2[] = { | ||
48 | {494000000, 750}, | ||
49 | {675000000, 825}, | ||
50 | {817000000, 875}, | ||
51 | {922000000, 925}, | ||
52 | {1000000000, 975}, | ||
53 | {0, 0}, | ||
54 | }; | ||
55 | |||
56 | static struct dvfs_table virtual_cpu_process_3[] = { | ||
57 | {730000000, 750}, | ||
58 | {760000000, 775}, | ||
59 | {845000000, 800}, | ||
60 | {1000000000, 875}, | ||
61 | {0, 0}, | ||
62 | }; | ||
63 | |||
64 | struct dvfs tegra_dvfs_virtual_cpu_dvfs = { | ||
65 | .reg_id = "vdd_cpu", | ||
66 | .process_id_table = { | ||
67 | { | ||
68 | .process_id = 0, | ||
69 | .table = virtual_cpu_process_0, | ||
70 | }, | ||
71 | { | ||
72 | .process_id = 1, | ||
73 | .table = virtual_cpu_process_1, | ||
74 | }, | ||
75 | { | ||
76 | .process_id = 2, | ||
77 | .table = virtual_cpu_process_2, | ||
78 | }, | ||
79 | { | ||
80 | .process_id = 3, | ||
81 | .table = virtual_cpu_process_3, | ||
82 | }, | ||
83 | }, | ||
84 | .process_id_table_length = 4, | ||
85 | .cpu = 1, | ||
86 | }; | ||
diff --git a/arch/arm/mach-tegra/tegra2_dvfs.h b/arch/arm/mach-tegra/tegra2_dvfs.h new file mode 100644 index 000000000000..f8c1adba96a6 --- /dev/null +++ b/arch/arm/mach-tegra/tegra2_dvfs.h | |||
@@ -0,0 +1,20 @@ | |||
1 | /* | ||
2 | * arch/arm/mach-tegra/tegra2_dvfs.h | ||
3 | * | ||
4 | * Copyright (C) 2010 Google, Inc. | ||
5 | * | ||
6 | * Author: | ||
7 | * Colin Cross <ccross@google.com> | ||
8 | * | ||
9 | * This software is licensed under the terms of the GNU General Public | ||
10 | * License version 2, as published by the Free Software Foundation, and | ||
11 | * may be copied, distributed, and modified under those terms. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | */ | ||
19 | |||
20 | extern struct dvfs tegra_dvfs_virtual_cpu_dvfs; | ||