diff options
35 files changed, 4917 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; | ||
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 4b9eec68fad6..78f9fd02c1b2 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig | |||
| @@ -329,6 +329,13 @@ config SPI_STMP3XXX | |||
| 329 | help | 329 | help |
| 330 | SPI driver for Freescale STMP37xx/378x SoC SSP interface | 330 | SPI driver for Freescale STMP37xx/378x SoC SSP interface |
| 331 | 331 | ||
| 332 | config SPI_TEGRA | ||
| 333 | tristate "Nvidia Tegra SPI controller" | ||
| 334 | depends on ARCH_TEGRA | ||
| 335 | select TEGRA_SYSTEM_DMA | ||
| 336 | help | ||
| 337 | SPI driver for NVidia Tegra SoCs | ||
| 338 | |||
| 332 | config SPI_TOPCLIFF_PCH | 339 | config SPI_TOPCLIFF_PCH |
| 333 | tristate "Topcliff PCH SPI Controller" | 340 | tristate "Topcliff PCH SPI Controller" |
| 334 | depends on PCI | 341 | depends on PCI |
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index 557aaadf56b2..8bc1a5abac1f 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile | |||
| @@ -39,6 +39,7 @@ obj-$(CONFIG_SPI_PPC4xx) += spi_ppc4xx.o | |||
| 39 | obj-$(CONFIG_SPI_S3C24XX_GPIO) += spi_s3c24xx_gpio.o | 39 | obj-$(CONFIG_SPI_S3C24XX_GPIO) += spi_s3c24xx_gpio.o |
| 40 | obj-$(CONFIG_SPI_S3C24XX) += spi_s3c24xx_hw.o | 40 | obj-$(CONFIG_SPI_S3C24XX) += spi_s3c24xx_hw.o |
| 41 | obj-$(CONFIG_SPI_S3C64XX) += spi_s3c64xx.o | 41 | obj-$(CONFIG_SPI_S3C64XX) += spi_s3c64xx.o |
| 42 | obj-$(CONFIG_SPI_TEGRA) += spi_tegra.o | ||
| 42 | obj-$(CONFIG_SPI_TOPCLIFF_PCH) += spi_topcliff_pch.o | 43 | obj-$(CONFIG_SPI_TOPCLIFF_PCH) += spi_topcliff_pch.o |
| 43 | obj-$(CONFIG_SPI_TXX9) += spi_txx9.o | 44 | obj-$(CONFIG_SPI_TXX9) += spi_txx9.o |
| 44 | obj-$(CONFIG_SPI_XILINX) += xilinx_spi.o | 45 | obj-$(CONFIG_SPI_XILINX) += xilinx_spi.o |
diff --git a/drivers/spi/spi_tegra.c b/drivers/spi/spi_tegra.c new file mode 100644 index 000000000000..bb7df02a5472 --- /dev/null +++ b/drivers/spi/spi_tegra.c | |||
| @@ -0,0 +1,618 @@ | |||
| 1 | /* | ||
| 2 | * Driver for Nvidia TEGRA spi controller. | ||
| 3 | * | ||
| 4 | * Copyright (C) 2010 Google, Inc. | ||
| 5 | * | ||
| 6 | * Author: | ||
| 7 | * Erik Gilling <konkers@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/init.h> | ||
| 22 | #include <linux/err.h> | ||
| 23 | #include <linux/platform_device.h> | ||
| 24 | #include <linux/io.h> | ||
| 25 | #include <linux/dma-mapping.h> | ||
| 26 | #include <linux/dmapool.h> | ||
| 27 | #include <linux/clk.h> | ||
| 28 | #include <linux/interrupt.h> | ||
| 29 | #include <linux/delay.h> | ||
| 30 | |||
| 31 | #include <linux/spi/spi.h> | ||
| 32 | |||
| 33 | #include <mach/dma.h> | ||
| 34 | |||
| 35 | #define SLINK_COMMAND 0x000 | ||
| 36 | #define SLINK_BIT_LENGTH(x) (((x) & 0x1f) << 0) | ||
| 37 | #define SLINK_WORD_SIZE(x) (((x) & 0x1f) << 5) | ||
| 38 | #define SLINK_BOTH_EN (1 << 10) | ||
| 39 | #define SLINK_CS_SW (1 << 11) | ||
| 40 | #define SLINK_CS_VALUE (1 << 12) | ||
| 41 | #define SLINK_CS_POLARITY (1 << 13) | ||
| 42 | #define SLINK_IDLE_SDA_DRIVE_LOW (0 << 16) | ||
| 43 | #define SLINK_IDLE_SDA_DRIVE_HIGH (1 << 16) | ||
| 44 | #define SLINK_IDLE_SDA_PULL_LOW (2 << 16) | ||
| 45 | #define SLINK_IDLE_SDA_PULL_HIGH (3 << 16) | ||
| 46 | #define SLINK_IDLE_SDA_MASK (3 << 16) | ||
| 47 | #define SLINK_CS_POLARITY1 (1 << 20) | ||
| 48 | #define SLINK_CK_SDA (1 << 21) | ||
| 49 | #define SLINK_CS_POLARITY2 (1 << 22) | ||
| 50 | #define SLINK_CS_POLARITY3 (1 << 23) | ||
| 51 | #define SLINK_IDLE_SCLK_DRIVE_LOW (0 << 24) | ||
| 52 | #define SLINK_IDLE_SCLK_DRIVE_HIGH (1 << 24) | ||
| 53 | #define SLINK_IDLE_SCLK_PULL_LOW (2 << 24) | ||
| 54 | #define SLINK_IDLE_SCLK_PULL_HIGH (3 << 24) | ||
| 55 | #define SLINK_IDLE_SCLK_MASK (3 << 24) | ||
| 56 | #define SLINK_M_S (1 << 28) | ||
| 57 | #define SLINK_WAIT (1 << 29) | ||
| 58 | #define SLINK_GO (1 << 30) | ||
| 59 | #define SLINK_ENB (1 << 31) | ||
| 60 | |||
| 61 | #define SLINK_COMMAND2 0x004 | ||
| 62 | #define SLINK_LSBFE (1 << 0) | ||
| 63 | #define SLINK_SSOE (1 << 1) | ||
| 64 | #define SLINK_SPIE (1 << 4) | ||
| 65 | #define SLINK_BIDIROE (1 << 6) | ||
| 66 | #define SLINK_MODFEN (1 << 7) | ||
| 67 | #define SLINK_INT_SIZE(x) (((x) & 0x1f) << 8) | ||
| 68 | #define SLINK_CS_ACTIVE_BETWEEN (1 << 17) | ||
| 69 | #define SLINK_SS_EN_CS(x) (((x) & 0x3) << 18) | ||
| 70 | #define SLINK_SS_SETUP(x) (((x) & 0x3) << 20) | ||
| 71 | #define SLINK_FIFO_REFILLS_0 (0 << 22) | ||
| 72 | #define SLINK_FIFO_REFILLS_1 (1 << 22) | ||
| 73 | #define SLINK_FIFO_REFILLS_2 (2 << 22) | ||
| 74 | #define SLINK_FIFO_REFILLS_3 (3 << 22) | ||
| 75 | #define SLINK_FIFO_REFILLS_MASK (3 << 22) | ||
| 76 | #define SLINK_WAIT_PACK_INT(x) (((x) & 0x7) << 26) | ||
| 77 | #define SLINK_SPC0 (1 << 29) | ||
| 78 | #define SLINK_TXEN (1 << 30) | ||
| 79 | #define SLINK_RXEN (1 << 31) | ||
| 80 | |||
| 81 | #define SLINK_STATUS 0x008 | ||
| 82 | #define SLINK_COUNT(val) (((val) >> 0) & 0x1f) | ||
| 83 | #define SLINK_WORD(val) (((val) >> 5) & 0x1f) | ||
| 84 | #define SLINK_BLK_CNT(val) (((val) >> 0) & 0xffff) | ||
| 85 | #define SLINK_MODF (1 << 16) | ||
| 86 | #define SLINK_RX_UNF (1 << 18) | ||
| 87 | #define SLINK_TX_OVF (1 << 19) | ||
| 88 | #define SLINK_TX_FULL (1 << 20) | ||
| 89 | #define SLINK_TX_EMPTY (1 << 21) | ||
| 90 | #define SLINK_RX_FULL (1 << 22) | ||
| 91 | #define SLINK_RX_EMPTY (1 << 23) | ||
| 92 | #define SLINK_TX_UNF (1 << 24) | ||
| 93 | #define SLINK_RX_OVF (1 << 25) | ||
| 94 | #define SLINK_TX_FLUSH (1 << 26) | ||
| 95 | #define SLINK_RX_FLUSH (1 << 27) | ||
| 96 | #define SLINK_SCLK (1 << 28) | ||
| 97 | #define SLINK_ERR (1 << 29) | ||
| 98 | #define SLINK_RDY (1 << 30) | ||
| 99 | #define SLINK_BSY (1 << 31) | ||
| 100 | |||
| 101 | #define SLINK_MAS_DATA 0x010 | ||
| 102 | #define SLINK_SLAVE_DATA 0x014 | ||
| 103 | |||
| 104 | #define SLINK_DMA_CTL 0x018 | ||
| 105 | #define SLINK_DMA_BLOCK_SIZE(x) (((x) & 0xffff) << 0) | ||
| 106 | #define SLINK_TX_TRIG_1 (0 << 16) | ||
| 107 | #define SLINK_TX_TRIG_4 (1 << 16) | ||
| 108 | #define SLINK_TX_TRIG_8 (2 << 16) | ||
| 109 | #define SLINK_TX_TRIG_16 (3 << 16) | ||
| 110 | #define SLINK_TX_TRIG_MASK (3 << 16) | ||
| 111 | #define SLINK_RX_TRIG_1 (0 << 18) | ||
| 112 | #define SLINK_RX_TRIG_4 (1 << 18) | ||
| 113 | #define SLINK_RX_TRIG_8 (2 << 18) | ||
| 114 | #define SLINK_RX_TRIG_16 (3 << 18) | ||
| 115 | #define SLINK_RX_TRIG_MASK (3 << 18) | ||
| 116 | #define SLINK_PACKED (1 << 20) | ||
| 117 | #define SLINK_PACK_SIZE_4 (0 << 21) | ||
| 118 | #define SLINK_PACK_SIZE_8 (1 << 21) | ||
| 119 | #define SLINK_PACK_SIZE_16 (2 << 21) | ||
| 120 | #define SLINK_PACK_SIZE_32 (3 << 21) | ||
| 121 | #define SLINK_PACK_SIZE_MASK (3 << 21) | ||
| 122 | #define SLINK_IE_TXC (1 << 26) | ||
| 123 | #define SLINK_IE_RXC (1 << 27) | ||
| 124 | #define SLINK_DMA_EN (1 << 31) | ||
| 125 | |||
| 126 | #define SLINK_STATUS2 0x01c | ||
| 127 | #define SLINK_TX_FIFO_EMPTY_COUNT(val) (((val) & 0x3f) >> 0) | ||
| 128 | #define SLINK_RX_FIFO_FULL_COUNT(val) (((val) & 0x3f) >> 16) | ||
| 129 | |||
| 130 | #define SLINK_TX_FIFO 0x100 | ||
| 131 | #define SLINK_RX_FIFO 0x180 | ||
| 132 | |||
| 133 | static const unsigned long spi_tegra_req_sels[] = { | ||
| 134 | TEGRA_DMA_REQ_SEL_SL2B1, | ||
| 135 | TEGRA_DMA_REQ_SEL_SL2B2, | ||
| 136 | TEGRA_DMA_REQ_SEL_SL2B3, | ||
| 137 | TEGRA_DMA_REQ_SEL_SL2B4, | ||
| 138 | }; | ||
| 139 | |||
| 140 | #define BB_LEN 32 | ||
| 141 | |||
| 142 | struct spi_tegra_data { | ||
| 143 | struct spi_master *master; | ||
| 144 | struct platform_device *pdev; | ||
| 145 | spinlock_t lock; | ||
| 146 | |||
| 147 | struct clk *clk; | ||
| 148 | void __iomem *base; | ||
| 149 | unsigned long phys; | ||
| 150 | |||
| 151 | u32 cur_speed; | ||
| 152 | |||
| 153 | struct list_head queue; | ||
| 154 | struct spi_transfer *cur; | ||
| 155 | unsigned cur_pos; | ||
| 156 | unsigned cur_len; | ||
| 157 | unsigned cur_bytes_per_word; | ||
| 158 | |||
| 159 | /* The tegra spi controller has a bug which causes the first word | ||
| 160 | * in PIO transactions to be garbage. Since packed DMA transactions | ||
| 161 | * require transfers to be 4 byte aligned we need a bounce buffer | ||
| 162 | * for the generic case. | ||
| 163 | */ | ||
| 164 | struct tegra_dma_req rx_dma_req; | ||
| 165 | struct tegra_dma_channel *rx_dma; | ||
| 166 | u32 *rx_bb; | ||
| 167 | dma_addr_t rx_bb_phys; | ||
| 168 | }; | ||
| 169 | |||
| 170 | |||
| 171 | static inline unsigned long spi_tegra_readl(struct spi_tegra_data *tspi, | ||
| 172 | unsigned long reg) | ||
| 173 | { | ||
| 174 | return readl(tspi->base + reg); | ||
| 175 | } | ||
| 176 | |||
| 177 | static inline void spi_tegra_writel(struct spi_tegra_data *tspi, | ||
| 178 | unsigned long val, | ||
| 179 | unsigned long reg) | ||
| 180 | { | ||
| 181 | writel(val, tspi->base + reg); | ||
| 182 | } | ||
| 183 | |||
| 184 | static void spi_tegra_go(struct spi_tegra_data *tspi) | ||
| 185 | { | ||
| 186 | unsigned long val; | ||
| 187 | |||
| 188 | wmb(); | ||
| 189 | |||
| 190 | val = spi_tegra_readl(tspi, SLINK_DMA_CTL); | ||
| 191 | val &= ~SLINK_DMA_BLOCK_SIZE(~0) & ~SLINK_DMA_EN; | ||
| 192 | val |= SLINK_DMA_BLOCK_SIZE(tspi->rx_dma_req.size / 4 - 1); | ||
| 193 | spi_tegra_writel(tspi, val, SLINK_DMA_CTL); | ||
| 194 | |||
| 195 | tegra_dma_enqueue_req(tspi->rx_dma, &tspi->rx_dma_req); | ||
| 196 | |||
| 197 | val |= SLINK_DMA_EN; | ||
| 198 | spi_tegra_writel(tspi, val, SLINK_DMA_CTL); | ||
| 199 | } | ||
| 200 | |||
| 201 | static unsigned spi_tegra_fill_tx_fifo(struct spi_tegra_data *tspi, | ||
| 202 | struct spi_transfer *t) | ||
| 203 | { | ||
| 204 | unsigned len = min(t->len - tspi->cur_pos, BB_LEN * | ||
| 205 | tspi->cur_bytes_per_word); | ||
| 206 | u8 *tx_buf = (u8 *)t->tx_buf + tspi->cur_pos; | ||
| 207 | int i, j; | ||
| 208 | unsigned long val; | ||
| 209 | |||
| 210 | val = spi_tegra_readl(tspi, SLINK_COMMAND); | ||
| 211 | val &= ~SLINK_WORD_SIZE(~0); | ||
| 212 | val |= SLINK_WORD_SIZE(len / tspi->cur_bytes_per_word - 1); | ||
| 213 | spi_tegra_writel(tspi, val, SLINK_COMMAND); | ||
| 214 | |||
| 215 | for (i = 0; i < len; i += tspi->cur_bytes_per_word) { | ||
| 216 | val = 0; | ||
| 217 | for (j = 0; j < tspi->cur_bytes_per_word; j++) | ||
| 218 | val |= tx_buf[i + j] << j * 8; | ||
| 219 | |||
| 220 | spi_tegra_writel(tspi, val, SLINK_TX_FIFO); | ||
| 221 | } | ||
| 222 | |||
| 223 | tspi->rx_dma_req.size = len / tspi->cur_bytes_per_word * 4; | ||
| 224 | |||
| 225 | return len; | ||
| 226 | } | ||
| 227 | |||
| 228 | static unsigned spi_tegra_drain_rx_fifo(struct spi_tegra_data *tspi, | ||
| 229 | struct spi_transfer *t) | ||
| 230 | { | ||
| 231 | unsigned len = tspi->cur_len; | ||
| 232 | u8 *rx_buf = (u8 *)t->rx_buf + tspi->cur_pos; | ||
| 233 | int i, j; | ||
| 234 | unsigned long val; | ||
| 235 | |||
| 236 | for (i = 0; i < len; i += tspi->cur_bytes_per_word) { | ||
| 237 | val = tspi->rx_bb[i / tspi->cur_bytes_per_word]; | ||
| 238 | for (j = 0; j < tspi->cur_bytes_per_word; j++) | ||
| 239 | rx_buf[i + j] = (val >> (j * 8)) & 0xff; | ||
| 240 | } | ||
| 241 | |||
| 242 | return len; | ||
| 243 | } | ||
| 244 | |||
| 245 | static void spi_tegra_start_transfer(struct spi_device *spi, | ||
| 246 | struct spi_transfer *t) | ||
| 247 | { | ||
| 248 | struct spi_tegra_data *tspi = spi_master_get_devdata(spi->master); | ||
| 249 | u32 speed; | ||
| 250 | u8 bits_per_word; | ||
| 251 | unsigned long val; | ||
| 252 | |||
| 253 | speed = t->speed_hz ? t->speed_hz : spi->max_speed_hz; | ||
| 254 | bits_per_word = t->bits_per_word ? t->bits_per_word : | ||
| 255 | spi->bits_per_word; | ||
| 256 | |||
| 257 | tspi->cur_bytes_per_word = (bits_per_word - 1) / 8 + 1; | ||
| 258 | |||
| 259 | if (speed != tspi->cur_speed) | ||
| 260 | clk_set_rate(tspi->clk, speed); | ||
| 261 | |||
| 262 | if (tspi->cur_speed == 0) | ||
| 263 | clk_enable(tspi->clk); | ||
| 264 | |||
| 265 | tspi->cur_speed = speed; | ||
| 266 | |||
| 267 | val = spi_tegra_readl(tspi, SLINK_COMMAND2); | ||
| 268 | val &= ~SLINK_SS_EN_CS(~0) | SLINK_RXEN | SLINK_TXEN; | ||
| 269 | if (t->rx_buf) | ||
| 270 | val |= SLINK_RXEN; | ||
| 271 | if (t->tx_buf) | ||
| 272 | val |= SLINK_TXEN; | ||
| 273 | val |= SLINK_SS_EN_CS(spi->chip_select); | ||
| 274 | val |= SLINK_SPIE; | ||
| 275 | spi_tegra_writel(tspi, val, SLINK_COMMAND2); | ||
| 276 | |||
| 277 | val = spi_tegra_readl(tspi, SLINK_COMMAND); | ||
| 278 | val &= ~SLINK_BIT_LENGTH(~0); | ||
| 279 | val |= SLINK_BIT_LENGTH(bits_per_word - 1); | ||
| 280 | |||
| 281 | /* FIXME: should probably control CS manually so that we can be sure | ||
| 282 | * it does not go low between transfer and to support delay_usecs | ||
| 283 | * correctly. | ||
| 284 | */ | ||
| 285 | val &= ~SLINK_IDLE_SCLK_MASK & ~SLINK_CK_SDA & ~SLINK_CS_SW; | ||
| 286 | |||
| 287 | if (spi->mode & SPI_CPHA) | ||
| 288 | val |= SLINK_CK_SDA; | ||
| 289 | |||
| 290 | if (spi->mode & SPI_CPOL) | ||
| 291 | val |= SLINK_IDLE_SCLK_DRIVE_HIGH; | ||
| 292 | else | ||
| 293 | val |= SLINK_IDLE_SCLK_DRIVE_LOW; | ||
| 294 | |||
| 295 | val |= SLINK_M_S; | ||
| 296 | |||
| 297 | spi_tegra_writel(tspi, val, SLINK_COMMAND); | ||
| 298 | |||
| 299 | spi_tegra_writel(tspi, SLINK_RX_FLUSH | SLINK_TX_FLUSH, SLINK_STATUS); | ||
| 300 | |||
| 301 | tspi->cur = t; | ||
| 302 | tspi->cur_pos = 0; | ||
| 303 | tspi->cur_len = spi_tegra_fill_tx_fifo(tspi, t); | ||
| 304 | |||
| 305 | spi_tegra_go(tspi); | ||
| 306 | } | ||
| 307 | |||
| 308 | static void spi_tegra_start_message(struct spi_device *spi, | ||
| 309 | struct spi_message *m) | ||
| 310 | { | ||
| 311 | struct spi_transfer *t; | ||
| 312 | |||
| 313 | m->actual_length = 0; | ||
| 314 | m->status = 0; | ||
| 315 | |||
| 316 | t = list_first_entry(&m->transfers, struct spi_transfer, transfer_list); | ||
| 317 | spi_tegra_start_transfer(spi, t); | ||
| 318 | } | ||
| 319 | |||
| 320 | static void tegra_spi_rx_dma_complete(struct tegra_dma_req *req) | ||
| 321 | { | ||
| 322 | struct spi_tegra_data *tspi = req->dev; | ||
| 323 | unsigned long flags; | ||
| 324 | struct spi_message *m; | ||
| 325 | struct spi_device *spi; | ||
| 326 | int timeout = 0; | ||
| 327 | unsigned long val; | ||
| 328 | |||
| 329 | /* the SPI controller may come back with both the BSY and RDY bits | ||
| 330 | * set. In this case we need to wait for the BSY bit to clear so | ||
| 331 | * that we are sure the DMA is finished. 1000 reads was empirically | ||
| 332 | * determined to be long enough. | ||
| 333 | */ | ||
| 334 | while (timeout++ < 1000) { | ||
| 335 | if (!(spi_tegra_readl(tspi, SLINK_STATUS) & SLINK_BSY)) | ||
| 336 | break; | ||
| 337 | } | ||
| 338 | |||
| 339 | spin_lock_irqsave(&tspi->lock, flags); | ||
| 340 | |||
| 341 | val = spi_tegra_readl(tspi, SLINK_STATUS); | ||
| 342 | val |= SLINK_RDY; | ||
| 343 | spi_tegra_writel(tspi, val, SLINK_STATUS); | ||
| 344 | |||
| 345 | m = list_first_entry(&tspi->queue, struct spi_message, queue); | ||
| 346 | |||
| 347 | if (timeout >= 1000) | ||
| 348 | m->status = -EIO; | ||
| 349 | |||
| 350 | spi = m->state; | ||
| 351 | |||
| 352 | tspi->cur_pos += spi_tegra_drain_rx_fifo(tspi, tspi->cur); | ||
| 353 | m->actual_length += tspi->cur_pos; | ||
| 354 | |||
| 355 | if (tspi->cur_pos < tspi->cur->len) { | ||
| 356 | tspi->cur_len = spi_tegra_fill_tx_fifo(tspi, tspi->cur); | ||
| 357 | spi_tegra_go(tspi); | ||
| 358 | } else if (!list_is_last(&tspi->cur->transfer_list, | ||
| 359 | &m->transfers)) { | ||
| 360 | tspi->cur = list_first_entry(&tspi->cur->transfer_list, | ||
| 361 | struct spi_transfer, | ||
| 362 | transfer_list); | ||
| 363 | spi_tegra_start_transfer(spi, tspi->cur); | ||
| 364 | } else { | ||
| 365 | list_del(&m->queue); | ||
| 366 | |||
| 367 | m->complete(m->context); | ||
| 368 | |||
| 369 | if (!list_empty(&tspi->queue)) { | ||
| 370 | m = list_first_entry(&tspi->queue, struct spi_message, | ||
| 371 | queue); | ||
| 372 | spi = m->state; | ||
| 373 | spi_tegra_start_message(spi, m); | ||
| 374 | } else { | ||
| 375 | clk_disable(tspi->clk); | ||
| 376 | tspi->cur_speed = 0; | ||
| 377 | } | ||
| 378 | } | ||
| 379 | |||
| 380 | spin_unlock_irqrestore(&tspi->lock, flags); | ||
| 381 | } | ||
| 382 | |||
| 383 | static int spi_tegra_setup(struct spi_device *spi) | ||
| 384 | { | ||
| 385 | struct spi_tegra_data *tspi = spi_master_get_devdata(spi->master); | ||
| 386 | unsigned long cs_bit; | ||
| 387 | unsigned long val; | ||
| 388 | unsigned long flags; | ||
| 389 | |||
| 390 | dev_dbg(&spi->dev, "setup %d bpw, %scpol, %scpha, %dHz\n", | ||
| 391 | spi->bits_per_word, | ||
| 392 | spi->mode & SPI_CPOL ? "" : "~", | ||
| 393 | spi->mode & SPI_CPHA ? "" : "~", | ||
| 394 | spi->max_speed_hz); | ||
| 395 | |||
| 396 | |||
| 397 | switch (spi->chip_select) { | ||
| 398 | case 0: | ||
| 399 | cs_bit = SLINK_CS_POLARITY; | ||
| 400 | break; | ||
| 401 | |||
| 402 | case 1: | ||
| 403 | cs_bit = SLINK_CS_POLARITY1; | ||
| 404 | break; | ||
| 405 | |||
| 406 | case 2: | ||
| 407 | cs_bit = SLINK_CS_POLARITY2; | ||
| 408 | break; | ||
| 409 | |||
| 410 | case 4: | ||
| 411 | cs_bit = SLINK_CS_POLARITY3; | ||
| 412 | break; | ||
| 413 | |||
| 414 | default: | ||
| 415 | return -EINVAL; | ||
| 416 | } | ||
| 417 | |||
| 418 | spin_lock_irqsave(&tspi->lock, flags); | ||
| 419 | |||
| 420 | val = spi_tegra_readl(tspi, SLINK_COMMAND); | ||
| 421 | if (spi->mode & SPI_CS_HIGH) | ||
| 422 | val |= cs_bit; | ||
| 423 | else | ||
| 424 | val &= ~cs_bit; | ||
| 425 | spi_tegra_writel(tspi, val, SLINK_COMMAND); | ||
| 426 | |||
| 427 | spin_unlock_irqrestore(&tspi->lock, flags); | ||
| 428 | |||
| 429 | return 0; | ||
| 430 | } | ||
| 431 | |||
| 432 | static int spi_tegra_transfer(struct spi_device *spi, struct spi_message *m) | ||
| 433 | { | ||
| 434 | struct spi_tegra_data *tspi = spi_master_get_devdata(spi->master); | ||
| 435 | struct spi_transfer *t; | ||
| 436 | unsigned long flags; | ||
| 437 | int was_empty; | ||
| 438 | |||
| 439 | if (list_empty(&m->transfers) || !m->complete) | ||
| 440 | return -EINVAL; | ||
| 441 | |||
| 442 | list_for_each_entry(t, &m->transfers, transfer_list) { | ||
| 443 | if (t->bits_per_word < 0 || t->bits_per_word > 32) | ||
| 444 | return -EINVAL; | ||
| 445 | |||
| 446 | if (t->len == 0) | ||
| 447 | return -EINVAL; | ||
| 448 | |||
| 449 | if (!t->rx_buf && !t->tx_buf) | ||
| 450 | return -EINVAL; | ||
| 451 | } | ||
| 452 | |||
| 453 | m->state = spi; | ||
| 454 | |||
| 455 | spin_lock_irqsave(&tspi->lock, flags); | ||
| 456 | was_empty = list_empty(&tspi->queue); | ||
| 457 | list_add_tail(&m->queue, &tspi->queue); | ||
| 458 | |||
| 459 | if (was_empty) | ||
| 460 | spi_tegra_start_message(spi, m); | ||
| 461 | |||
| 462 | spin_unlock_irqrestore(&tspi->lock, flags); | ||
| 463 | |||
| 464 | return 0; | ||
| 465 | } | ||
| 466 | |||
| 467 | static int __init spi_tegra_probe(struct platform_device *pdev) | ||
| 468 | { | ||
| 469 | struct spi_master *master; | ||
| 470 | struct spi_tegra_data *tspi; | ||
| 471 | struct resource *r; | ||
| 472 | int ret; | ||
| 473 | |||
| 474 | master = spi_alloc_master(&pdev->dev, sizeof *tspi); | ||
| 475 | if (master == NULL) { | ||
| 476 | dev_err(&pdev->dev, "master allocation failed\n"); | ||
| 477 | return -ENOMEM; | ||
| 478 | } | ||
| 479 | |||
| 480 | /* the spi->mode bits understood by this driver: */ | ||
| 481 | master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; | ||
| 482 | |||
| 483 | master->bus_num = pdev->id; | ||
| 484 | |||
| 485 | master->setup = spi_tegra_setup; | ||
| 486 | master->transfer = spi_tegra_transfer; | ||
| 487 | master->num_chipselect = 4; | ||
| 488 | |||
| 489 | dev_set_drvdata(&pdev->dev, master); | ||
| 490 | tspi = spi_master_get_devdata(master); | ||
| 491 | tspi->master = master; | ||
| 492 | tspi->pdev = pdev; | ||
| 493 | spin_lock_init(&tspi->lock); | ||
| 494 | |||
| 495 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 496 | if (r == NULL) { | ||
| 497 | ret = -ENODEV; | ||
| 498 | goto err0; | ||
| 499 | } | ||
| 500 | |||
| 501 | if (!request_mem_region(r->start, (r->end - r->start) + 1, | ||
| 502 | dev_name(&pdev->dev))) { | ||
| 503 | ret = -EBUSY; | ||
| 504 | goto err0; | ||
| 505 | } | ||
| 506 | |||
| 507 | tspi->phys = r->start; | ||
| 508 | tspi->base = ioremap(r->start, r->end - r->start + 1); | ||
| 509 | if (!tspi->base) { | ||
| 510 | dev_err(&pdev->dev, "can't ioremap iomem\n"); | ||
| 511 | ret = -ENOMEM; | ||
| 512 | goto err1; | ||
| 513 | } | ||
| 514 | |||
| 515 | tspi->clk = clk_get(&pdev->dev, NULL); | ||
| 516 | if (IS_ERR_OR_NULL(tspi->clk)) { | ||
| 517 | dev_err(&pdev->dev, "can not get clock\n"); | ||
| 518 | ret = PTR_ERR(tspi->clk); | ||
| 519 | goto err2; | ||
| 520 | } | ||
| 521 | |||
| 522 | INIT_LIST_HEAD(&tspi->queue); | ||
| 523 | |||
| 524 | tspi->rx_dma = tegra_dma_allocate_channel(TEGRA_DMA_MODE_ONESHOT); | ||
| 525 | if (!tspi->rx_dma) { | ||
| 526 | dev_err(&pdev->dev, "can not allocate rx dma channel\n"); | ||
| 527 | ret = -ENODEV; | ||
| 528 | goto err3; | ||
| 529 | } | ||
| 530 | |||
| 531 | tspi->rx_bb = dma_alloc_coherent(&pdev->dev, sizeof(u32) * BB_LEN, | ||
| 532 | &tspi->rx_bb_phys, GFP_KERNEL); | ||
| 533 | if (!tspi->rx_bb) { | ||
| 534 | dev_err(&pdev->dev, "can not allocate rx bounce buffer\n"); | ||
| 535 | ret = -ENOMEM; | ||
| 536 | goto err4; | ||
| 537 | } | ||
| 538 | |||
| 539 | tspi->rx_dma_req.complete = tegra_spi_rx_dma_complete; | ||
| 540 | tspi->rx_dma_req.to_memory = 1; | ||
| 541 | tspi->rx_dma_req.dest_addr = tspi->rx_bb_phys; | ||
| 542 | tspi->rx_dma_req.dest_bus_width = 32; | ||
| 543 | tspi->rx_dma_req.source_addr = tspi->phys + SLINK_RX_FIFO; | ||
| 544 | tspi->rx_dma_req.source_bus_width = 32; | ||
| 545 | tspi->rx_dma_req.source_wrap = 4; | ||
| 546 | tspi->rx_dma_req.req_sel = spi_tegra_req_sels[pdev->id]; | ||
| 547 | tspi->rx_dma_req.dev = tspi; | ||
| 548 | |||
| 549 | ret = spi_register_master(master); | ||
| 550 | |||
| 551 | if (ret < 0) | ||
| 552 | goto err5; | ||
| 553 | |||
| 554 | return ret; | ||
| 555 | |||
| 556 | err5: | ||
| 557 | dma_free_coherent(&pdev->dev, sizeof(u32) * BB_LEN, | ||
| 558 | tspi->rx_bb, tspi->rx_bb_phys); | ||
| 559 | err4: | ||
| 560 | tegra_dma_free_channel(tspi->rx_dma); | ||
| 561 | err3: | ||
| 562 | clk_put(tspi->clk); | ||
| 563 | err2: | ||
| 564 | iounmap(tspi->base); | ||
| 565 | err1: | ||
| 566 | release_mem_region(r->start, (r->end - r->start) + 1); | ||
| 567 | err0: | ||
| 568 | spi_master_put(master); | ||
| 569 | return ret; | ||
| 570 | } | ||
| 571 | |||
| 572 | static int __devexit spi_tegra_remove(struct platform_device *pdev) | ||
| 573 | { | ||
| 574 | struct spi_master *master; | ||
| 575 | struct spi_tegra_data *tspi; | ||
| 576 | struct resource *r; | ||
| 577 | |||
| 578 | master = dev_get_drvdata(&pdev->dev); | ||
| 579 | tspi = spi_master_get_devdata(master); | ||
| 580 | |||
| 581 | tegra_dma_free_channel(tspi->rx_dma); | ||
| 582 | |||
| 583 | dma_free_coherent(&pdev->dev, sizeof(u32) * BB_LEN, | ||
| 584 | tspi->rx_bb, tspi->rx_bb_phys); | ||
| 585 | |||
| 586 | clk_put(tspi->clk); | ||
| 587 | iounmap(tspi->base); | ||
| 588 | |||
| 589 | spi_master_put(master); | ||
| 590 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 591 | release_mem_region(r->start, (r->end - r->start) + 1); | ||
| 592 | |||
| 593 | return 0; | ||
| 594 | } | ||
| 595 | |||
| 596 | MODULE_ALIAS("platform:spi_tegra"); | ||
| 597 | |||
| 598 | static struct platform_driver spi_tegra_driver = { | ||
| 599 | .driver = { | ||
| 600 | .name = "spi_tegra", | ||
| 601 | .owner = THIS_MODULE, | ||
| 602 | }, | ||
| 603 | .remove = __devexit_p(spi_tegra_remove), | ||
| 604 | }; | ||
| 605 | |||
| 606 | static int __init spi_tegra_init(void) | ||
| 607 | { | ||
| 608 | return platform_driver_probe(&spi_tegra_driver, spi_tegra_probe); | ||
| 609 | } | ||
| 610 | module_init(spi_tegra_init); | ||
| 611 | |||
| 612 | static void __exit spi_tegra_exit(void) | ||
| 613 | { | ||
| 614 | platform_driver_unregister(&spi_tegra_driver); | ||
| 615 | } | ||
| 616 | module_exit(spi_tegra_exit); | ||
| 617 | |||
| 618 | MODULE_LICENSE("GPL"); | ||
