aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2013-04-09 11:07:36 -0400
committerArnd Bergmann <arnd@arndb.de>2013-04-09 11:07:36 -0400
commit1194b152cd4eff475652785ce366b20afe82dfcf (patch)
tree78da3848410f05949714b2e475d4cf92b463fb31
parent86feb64f5bfe75da74f4a2faf18b5e57be9cde5e (diff)
parent38be85de698ef3f2755ee0eabf520530757860aa (diff)
Merge branch 'tegra/soc' into next/drivers
This is a dependency for the tegra/clk branch. Signed-off-by: Arnd Bergmann <arnd@arndb.de> Conflicts: drivers/clocksource/tegra20_timer.c
-rw-r--r--Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.txt67
-rw-r--r--arch/arm/Kconfig1
-rw-r--r--arch/arm/boot/dts/tegra114-dalmore.dts13
-rw-r--r--arch/arm/boot/dts/tegra114-pluto.dts13
-rw-r--r--arch/arm/boot/dts/tegra114.dtsi4
-rw-r--r--arch/arm/boot/dts/tegra20-colibri-512.dtsi15
-rw-r--r--arch/arm/boot/dts/tegra20-harmony.dts17
-rw-r--r--arch/arm/boot/dts/tegra20-paz00.dts15
-rw-r--r--arch/arm/boot/dts/tegra20-seaboard.dts15
-rw-r--r--arch/arm/boot/dts/tegra20-tamonten.dtsi15
-rw-r--r--arch/arm/boot/dts/tegra20-trimslice.dts15
-rw-r--r--arch/arm/boot/dts/tegra20-ventana.dts15
-rw-r--r--arch/arm/boot/dts/tegra20-whistler.dts14
-rw-r--r--arch/arm/boot/dts/tegra20.dtsi4
-rw-r--r--arch/arm/boot/dts/tegra30-beaver.dts15
-rw-r--r--arch/arm/boot/dts/tegra30-cardhu.dtsi15
-rw-r--r--arch/arm/boot/dts/tegra30.dtsi6
-rw-r--r--arch/arm/mach-tegra/Makefile5
-rw-r--r--arch/arm/mach-tegra/board-dt-tegra114.c46
-rw-r--r--arch/arm/mach-tegra/board-dt-tegra30.c60
-rw-r--r--arch/arm/mach-tegra/board-harmony-pcie.c7
-rw-r--r--arch/arm/mach-tegra/board.h4
-rw-r--r--arch/arm/mach-tegra/common.c31
-rw-r--r--arch/arm/mach-tegra/cpuidle-tegra20.c6
-rw-r--r--arch/arm/mach-tegra/cpuidle-tegra30.c10
-rw-r--r--arch/arm/mach-tegra/fuse.c4
-rw-r--r--arch/arm/mach-tegra/fuse.h7
-rw-r--r--arch/arm/mach-tegra/headsmp.S3
-rw-r--r--arch/arm/mach-tegra/hotplug.c23
-rw-r--r--arch/arm/mach-tegra/irq.c96
-rw-r--r--arch/arm/mach-tegra/irq.h6
-rw-r--r--arch/arm/mach-tegra/platsmp.c119
-rw-r--r--arch/arm/mach-tegra/pm.c150
-rw-r--r--arch/arm/mach-tegra/pm.h17
-rw-r--r--arch/arm/mach-tegra/pmc.c310
-rw-r--r--arch/arm/mach-tegra/pmc.h18
-rw-r--r--arch/arm/mach-tegra/reset-handler.S48
-rw-r--r--arch/arm/mach-tegra/sleep.h10
-rw-r--r--arch/arm/mach-tegra/tegra.c (renamed from arch/arm/mach-tegra/board-dt-tegra20.c)45
-rw-r--r--arch/arm/mach-tegra/tegra114_speedo.c104
-rw-r--r--drivers/clk/tegra/clk-tegra20.c36
-rw-r--r--drivers/clocksource/tegra20_timer.c4
-rw-r--r--drivers/gpio/gpio-tegra.c21
43 files changed, 1044 insertions, 405 deletions
diff --git a/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.txt b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.txt
index b5846e21cc2e..1608a54e90e1 100644
--- a/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.txt
+++ b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.txt
@@ -1,19 +1,84 @@
1NVIDIA Tegra Power Management Controller (PMC) 1NVIDIA Tegra Power Management Controller (PMC)
2 2
3Properties: 3The PMC block interacts with an external Power Management Unit. The PMC
4mostly controls the entry and exit of the system from different sleep
5modes. It provides power-gating controllers for SoC and CPU power-islands.
6
7Required properties:
4- name : Should be pmc 8- name : Should be pmc
5- compatible : Should contain "nvidia,tegra<chip>-pmc". 9- compatible : Should contain "nvidia,tegra<chip>-pmc".
6- reg : Offset and length of the register set for the device 10- reg : Offset and length of the register set for the device
11- clocks : Must contain an entry for each entry in clock-names.
12- clock-names : Must include the following entries:
13 "pclk" (The Tegra clock of that name),
14 "clk32k_in" (The 32KHz clock input to Tegra).
15
16Optional properties:
7- nvidia,invert-interrupt : If present, inverts the PMU interrupt signal. 17- nvidia,invert-interrupt : If present, inverts the PMU interrupt signal.
8 The PMU is an external Power Management Unit, whose interrupt output 18 The PMU is an external Power Management Unit, whose interrupt output
9 signal is fed into the PMC. This signal is optionally inverted, and then 19 signal is fed into the PMC. This signal is optionally inverted, and then
10 fed into the ARM GIC. The PMC is not involved in the detection or 20 fed into the ARM GIC. The PMC is not involved in the detection or
11 handling of this interrupt signal, merely its inversion. 21 handling of this interrupt signal, merely its inversion.
22- nvidia,suspend-mode : The suspend mode that the platform should use.
23 Valid values are 0, 1 and 2:
24 0 (LP0): CPU + Core voltage off and DRAM in self-refresh
25 1 (LP1): CPU voltage off and DRAM in self-refresh
26 2 (LP2): CPU voltage off
27- nvidia,core-power-req-active-high : Boolean, core power request active-high
28- nvidia,sys-clock-req-active-high : Boolean, system clock request active-high
29- nvidia,combined-power-req : Boolean, combined power request for CPU & Core
30- nvidia,cpu-pwr-good-en : Boolean, CPU power good signal (from PMIC to PMC)
31 is enabled.
32
33Required properties when nvidia,suspend-mode is specified:
34- nvidia,cpu-pwr-good-time : CPU power good time in uS.
35- nvidia,cpu-pwr-off-time : CPU power off time in uS.
36- nvidia,core-pwr-good-time : <Oscillator-stable-time Power-stable-time>
37 Core power good time in uS.
38- nvidia,core-pwr-off-time : Core power off time in uS.
39
40Required properties when nvidia,suspend-mode=<0>:
41- nvidia,lp0-vec : <start length> Starting address and length of LP0 vector
42 The LP0 vector contains the warm boot code that is executed by AVP when
43 resuming from the LP0 state. The AVP (Audio-Video Processor) is an ARM7
44 processor and always being the first boot processor when chip is power on
45 or resume from deep sleep mode. When the system is resumed from the deep
46 sleep mode, the warm boot code will restore some PLLs, clocks and then
47 bring up CPU0 for resuming the system.
12 48
13Example: 49Example:
14 50
51/ SoC dts including file
15pmc@7000f400 { 52pmc@7000f400 {
16 compatible = "nvidia,tegra20-pmc"; 53 compatible = "nvidia,tegra20-pmc";
17 reg = <0x7000e400 0x400>; 54 reg = <0x7000e400 0x400>;
55 clocks = <&tegra_car 110>, <&clk32k_in>;
56 clock-names = "pclk", "clk32k_in";
18 nvidia,invert-interrupt; 57 nvidia,invert-interrupt;
58 nvidia,suspend-mode = <1>;
59 nvidia,cpu-pwr-good-time = <2000>;
60 nvidia,cpu-pwr-off-time = <100>;
61 nvidia,core-pwr-good-time = <3845 3845>;
62 nvidia,core-pwr-off-time = <458>;
63 nvidia,core-power-req-active-high;
64 nvidia,sys-clock-req-active-high;
65 nvidia,lp0-vec = <0xbdffd000 0x2000>;
66};
67
68/ Tegra board dts file
69{
70 ...
71 clocks {
72 compatible = "simple-bus";
73 #address-cells = <1>;
74 #size-cells = <0>;
75
76 clk32k_in: clock {
77 compatible = "fixed-clock";
78 reg=<0>;
79 #clock-cells = <0>;
80 clock-frequency = <32768>;
81 };
82 };
83 ...
19}; 84};
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index eb91022b90ba..ada582b15cf2 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -673,6 +673,7 @@ config ARCH_TEGRA
673 select HAVE_CLK 673 select HAVE_CLK
674 select HAVE_SMP 674 select HAVE_SMP
675 select MIGHT_HAVE_CACHE_L2X0 675 select MIGHT_HAVE_CACHE_L2X0
676 select SOC_BUS
676 select SPARSE_IRQ 677 select SPARSE_IRQ
677 select USE_OF 678 select USE_OF
678 help 679 help
diff --git a/arch/arm/boot/dts/tegra114-dalmore.dts b/arch/arm/boot/dts/tegra114-dalmore.dts
index a30aca62658a..6ebc1b704190 100644
--- a/arch/arm/boot/dts/tegra114-dalmore.dts
+++ b/arch/arm/boot/dts/tegra114-dalmore.dts
@@ -18,4 +18,17 @@
18 pmc { 18 pmc {
19 nvidia,invert-interrupt; 19 nvidia,invert-interrupt;
20 }; 20 };
21
22 clocks {
23 compatible = "simple-bus";
24 #address-cells = <1>;
25 #size-cells = <0>;
26
27 clk32k_in: clock {
28 compatible = "fixed-clock";
29 reg=<0>;
30 #clock-cells = <0>;
31 clock-frequency = <32768>;
32 };
33 };
21}; 34};
diff --git a/arch/arm/boot/dts/tegra114-pluto.dts b/arch/arm/boot/dts/tegra114-pluto.dts
index 9bea8f57aa47..5deb8692b350 100644
--- a/arch/arm/boot/dts/tegra114-pluto.dts
+++ b/arch/arm/boot/dts/tegra114-pluto.dts
@@ -18,4 +18,17 @@
18 pmc { 18 pmc {
19 nvidia,invert-interrupt; 19 nvidia,invert-interrupt;
20 }; 20 };
21
22 clocks {
23 compatible = "simple-bus";
24 #address-cells = <1>;
25 #size-cells = <0>;
26
27 clk32k_in: clock {
28 compatible = "fixed-clock";
29 reg=<0>;
30 #clock-cells = <0>;
31 clock-frequency = <32768>;
32 };
33 };
21}; 34};
diff --git a/arch/arm/boot/dts/tegra114.dtsi b/arch/arm/boot/dts/tegra114.dtsi
index 1dfaf2874c57..c0b527d15fda 100644
--- a/arch/arm/boot/dts/tegra114.dtsi
+++ b/arch/arm/boot/dts/tegra114.dtsi
@@ -99,8 +99,10 @@
99 }; 99 };
100 100
101 pmc { 101 pmc {
102 compatible = "nvidia,tegra114-pmc", "nvidia,tegra30-pmc"; 102 compatible = "nvidia,tegra114-pmc";
103 reg = <0x7000e400 0x400>; 103 reg = <0x7000e400 0x400>;
104 clocks = <&tegra_car 261>, <&clk32k_in>;
105 clock-names = "pclk", "clk32k_in";
104 }; 106 };
105 107
106 iommu { 108 iommu {
diff --git a/arch/arm/boot/dts/tegra20-colibri-512.dtsi b/arch/arm/boot/dts/tegra20-colibri-512.dtsi
index 444162090042..4e3afdef28a8 100644
--- a/arch/arm/boot/dts/tegra20-colibri-512.dtsi
+++ b/arch/arm/boot/dts/tegra20-colibri-512.dtsi
@@ -444,7 +444,20 @@
444 }; 444 };
445 445
446 sdhci@c8000600 { 446 sdhci@c8000600 {
447 cd-gpios = <&gpio 23 0>; /* gpio PC7 */ 447 cd-gpios = <&gpio 23 1>; /* gpio PC7 */
448 };
449
450 clocks {
451 compatible = "simple-bus";
452 #address-cells = <1>;
453 #size-cells = <0>;
454
455 clk32k_in: clock {
456 compatible = "fixed-clock";
457 reg=<0>;
458 #clock-cells = <0>;
459 clock-frequency = <32768>;
460 };
448 }; 461 };
449 462
450 sound { 463 sound {
diff --git a/arch/arm/boot/dts/tegra20-harmony.dts b/arch/arm/boot/dts/tegra20-harmony.dts
index 61d027f03617..ae9d5a20834e 100644
--- a/arch/arm/boot/dts/tegra20-harmony.dts
+++ b/arch/arm/boot/dts/tegra20-harmony.dts
@@ -437,7 +437,7 @@
437 437
438 sdhci@c8000200 { 438 sdhci@c8000200 {
439 status = "okay"; 439 status = "okay";
440 cd-gpios = <&gpio 69 0>; /* gpio PI5 */ 440 cd-gpios = <&gpio 69 1>; /* gpio PI5 */
441 wp-gpios = <&gpio 57 0>; /* gpio PH1 */ 441 wp-gpios = <&gpio 57 0>; /* gpio PH1 */
442 power-gpios = <&gpio 155 0>; /* gpio PT3 */ 442 power-gpios = <&gpio 155 0>; /* gpio PT3 */
443 bus-width = <4>; 443 bus-width = <4>;
@@ -445,12 +445,25 @@
445 445
446 sdhci@c8000600 { 446 sdhci@c8000600 {
447 status = "okay"; 447 status = "okay";
448 cd-gpios = <&gpio 58 0>; /* gpio PH2 */ 448 cd-gpios = <&gpio 58 1>; /* gpio PH2 */
449 wp-gpios = <&gpio 59 0>; /* gpio PH3 */ 449 wp-gpios = <&gpio 59 0>; /* gpio PH3 */
450 power-gpios = <&gpio 70 0>; /* gpio PI6 */ 450 power-gpios = <&gpio 70 0>; /* gpio PI6 */
451 bus-width = <8>; 451 bus-width = <8>;
452 }; 452 };
453 453
454 clocks {
455 compatible = "simple-bus";
456 #address-cells = <1>;
457 #size-cells = <0>;
458
459 clk32k_in: clock {
460 compatible = "fixed-clock";
461 reg=<0>;
462 #clock-cells = <0>;
463 clock-frequency = <32768>;
464 };
465 };
466
454 kbc { 467 kbc {
455 status = "okay"; 468 status = "okay";
456 nvidia,debounce-delay-ms = <2>; 469 nvidia,debounce-delay-ms = <2>;
diff --git a/arch/arm/boot/dts/tegra20-paz00.dts b/arch/arm/boot/dts/tegra20-paz00.dts
index 54d6fce00a59..fd60940e4063 100644
--- a/arch/arm/boot/dts/tegra20-paz00.dts
+++ b/arch/arm/boot/dts/tegra20-paz00.dts
@@ -436,7 +436,7 @@
436 436
437 sdhci@c8000000 { 437 sdhci@c8000000 {
438 status = "okay"; 438 status = "okay";
439 cd-gpios = <&gpio 173 0>; /* gpio PV5 */ 439 cd-gpios = <&gpio 173 1>; /* gpio PV5 */
440 wp-gpios = <&gpio 57 0>; /* gpio PH1 */ 440 wp-gpios = <&gpio 57 0>; /* gpio PH1 */
441 power-gpios = <&gpio 169 0>; /* gpio PV1 */ 441 power-gpios = <&gpio 169 0>; /* gpio PV1 */
442 bus-width = <4>; 442 bus-width = <4>;
@@ -447,6 +447,19 @@
447 bus-width = <8>; 447 bus-width = <8>;
448 }; 448 };
449 449
450 clocks {
451 compatible = "simple-bus";
452 #address-cells = <1>;
453 #size-cells = <0>;
454
455 clk32k_in: clock {
456 compatible = "fixed-clock";
457 reg=<0>;
458 #clock-cells = <0>;
459 clock-frequency = <32768>;
460 };
461 };
462
450 gpio-keys { 463 gpio-keys {
451 compatible = "gpio-keys"; 464 compatible = "gpio-keys";
452 465
diff --git a/arch/arm/boot/dts/tegra20-seaboard.dts b/arch/arm/boot/dts/tegra20-seaboard.dts
index 37b3a57ec0f1..4ee700a33ca5 100644
--- a/arch/arm/boot/dts/tegra20-seaboard.dts
+++ b/arch/arm/boot/dts/tegra20-seaboard.dts
@@ -584,7 +584,7 @@
584 584
585 sdhci@c8000400 { 585 sdhci@c8000400 {
586 status = "okay"; 586 status = "okay";
587 cd-gpios = <&gpio 69 0>; /* gpio PI5 */ 587 cd-gpios = <&gpio 69 1>; /* gpio PI5 */
588 wp-gpios = <&gpio 57 0>; /* gpio PH1 */ 588 wp-gpios = <&gpio 57 0>; /* gpio PH1 */
589 power-gpios = <&gpio 70 0>; /* gpio PI6 */ 589 power-gpios = <&gpio 70 0>; /* gpio PI6 */
590 bus-width = <4>; 590 bus-width = <4>;
@@ -595,6 +595,19 @@
595 bus-width = <8>; 595 bus-width = <8>;
596 }; 596 };
597 597
598 clocks {
599 compatible = "simple-bus";
600 #address-cells = <1>;
601 #size-cells = <0>;
602
603 clk32k_in: clock {
604 compatible = "fixed-clock";
605 reg=<0>;
606 #clock-cells = <0>;
607 clock-frequency = <32768>;
608 };
609 };
610
598 gpio-keys { 611 gpio-keys {
599 compatible = "gpio-keys"; 612 compatible = "gpio-keys";
600 613
diff --git a/arch/arm/boot/dts/tegra20-tamonten.dtsi b/arch/arm/boot/dts/tegra20-tamonten.dtsi
index 4766abae7a72..c19025725918 100644
--- a/arch/arm/boot/dts/tegra20-tamonten.dtsi
+++ b/arch/arm/boot/dts/tegra20-tamonten.dtsi
@@ -465,12 +465,25 @@
465 }; 465 };
466 466
467 sdhci@c8000600 { 467 sdhci@c8000600 {
468 cd-gpios = <&gpio 58 0>; /* gpio PH2 */ 468 cd-gpios = <&gpio 58 1>; /* gpio PH2 */
469 wp-gpios = <&gpio 59 0>; /* gpio PH3 */ 469 wp-gpios = <&gpio 59 0>; /* gpio PH3 */
470 bus-width = <4>; 470 bus-width = <4>;
471 status = "okay"; 471 status = "okay";
472 }; 472 };
473 473
474 clocks {
475 compatible = "simple-bus";
476 #address-cells = <1>;
477 #size-cells = <0>;
478
479 clk32k_in: clock {
480 compatible = "fixed-clock";
481 reg=<0>;
482 #clock-cells = <0>;
483 clock-frequency = <32768>;
484 };
485 };
486
474 regulators { 487 regulators {
475 compatible = "simple-bus"; 488 compatible = "simple-bus";
476 489
diff --git a/arch/arm/boot/dts/tegra20-trimslice.dts b/arch/arm/boot/dts/tegra20-trimslice.dts
index 5d79e4fc49a6..a9f3f06580f5 100644
--- a/arch/arm/boot/dts/tegra20-trimslice.dts
+++ b/arch/arm/boot/dts/tegra20-trimslice.dts
@@ -325,11 +325,24 @@
325 325
326 sdhci@c8000600 { 326 sdhci@c8000600 {
327 status = "okay"; 327 status = "okay";
328 cd-gpios = <&gpio 121 0>; /* gpio PP1 */ 328 cd-gpios = <&gpio 121 1>; /* gpio PP1 */
329 wp-gpios = <&gpio 122 0>; /* gpio PP2 */ 329 wp-gpios = <&gpio 122 0>; /* gpio PP2 */
330 bus-width = <4>; 330 bus-width = <4>;
331 }; 331 };
332 332
333 clocks {
334 compatible = "simple-bus";
335 #address-cells = <1>;
336 #size-cells = <0>;
337
338 clk32k_in: clock {
339 compatible = "fixed-clock";
340 reg=<0>;
341 #clock-cells = <0>;
342 clock-frequency = <32768>;
343 };
344 };
345
333 poweroff { 346 poweroff {
334 compatible = "gpio-poweroff"; 347 compatible = "gpio-poweroff";
335 gpios = <&gpio 191 1>; /* gpio PX7, active low */ 348 gpios = <&gpio 191 1>; /* gpio PX7, active low */
diff --git a/arch/arm/boot/dts/tegra20-ventana.dts b/arch/arm/boot/dts/tegra20-ventana.dts
index 425c89000c20..f544806e9618 100644
--- a/arch/arm/boot/dts/tegra20-ventana.dts
+++ b/arch/arm/boot/dts/tegra20-ventana.dts
@@ -520,7 +520,7 @@
520 520
521 sdhci@c8000400 { 521 sdhci@c8000400 {
522 status = "okay"; 522 status = "okay";
523 cd-gpios = <&gpio 69 0>; /* gpio PI5 */ 523 cd-gpios = <&gpio 69 1>; /* gpio PI5 */
524 wp-gpios = <&gpio 57 0>; /* gpio PH1 */ 524 wp-gpios = <&gpio 57 0>; /* gpio PH1 */
525 power-gpios = <&gpio 70 0>; /* gpio PI6 */ 525 power-gpios = <&gpio 70 0>; /* gpio PI6 */
526 bus-width = <4>; 526 bus-width = <4>;
@@ -531,6 +531,19 @@
531 bus-width = <8>; 531 bus-width = <8>;
532 }; 532 };
533 533
534 clocks {
535 compatible = "simple-bus";
536 #address-cells = <1>;
537 #size-cells = <0>;
538
539 clk32k_in: clock {
540 compatible = "fixed-clock";
541 reg=<0>;
542 #clock-cells = <0>;
543 clock-frequency = <32768>;
544 };
545 };
546
534 regulators { 547 regulators {
535 compatible = "simple-bus"; 548 compatible = "simple-bus";
536 #address-cells = <1>; 549 #address-cells = <1>;
diff --git a/arch/arm/boot/dts/tegra20-whistler.dts b/arch/arm/boot/dts/tegra20-whistler.dts
index ea57c0f6dcce..258cf945f515 100644
--- a/arch/arm/boot/dts/tegra20-whistler.dts
+++ b/arch/arm/boot/dts/tegra20-whistler.dts
@@ -510,6 +510,7 @@
510 510
511 sdhci@c8000400 { 511 sdhci@c8000400 {
512 status = "okay"; 512 status = "okay";
513 cd-gpios = <&gpio 69 1>; /* gpio PI5 */
513 wp-gpios = <&gpio 173 0>; /* gpio PV5 */ 514 wp-gpios = <&gpio 173 0>; /* gpio PV5 */
514 bus-width = <8>; 515 bus-width = <8>;
515 }; 516 };
@@ -519,6 +520,19 @@
519 bus-width = <8>; 520 bus-width = <8>;
520 }; 521 };
521 522
523 clocks {
524 compatible = "simple-bus";
525 #address-cells = <1>;
526 #size-cells = <0>;
527
528 clk32k_in: clock {
529 compatible = "fixed-clock";
530 reg=<0>;
531 #clock-cells = <0>;
532 clock-frequency = <32768>;
533 };
534 };
535
522 kbc { 536 kbc {
523 status = "okay"; 537 status = "okay";
524 nvidia,debounce-delay-ms = <20>; 538 nvidia,debounce-delay-ms = <20>;
diff --git a/arch/arm/boot/dts/tegra20.dtsi b/arch/arm/boot/dts/tegra20.dtsi
index 3d3f64d2111a..fc7febc2b386 100644
--- a/arch/arm/boot/dts/tegra20.dtsi
+++ b/arch/arm/boot/dts/tegra20.dtsi
@@ -145,6 +145,7 @@
145 0 1 0x04 145 0 1 0x04
146 0 41 0x04 146 0 41 0x04
147 0 42 0x04>; 147 0 42 0x04>;
148 clocks = <&tegra_car 5>;
148 }; 149 };
149 150
150 tegra_car: clock { 151 tegra_car: clock {
@@ -304,6 +305,7 @@
304 compatible = "nvidia,tegra20-rtc"; 305 compatible = "nvidia,tegra20-rtc";
305 reg = <0x7000e000 0x100>; 306 reg = <0x7000e000 0x100>;
306 interrupts = <0 2 0x04>; 307 interrupts = <0 2 0x04>;
308 clocks = <&tegra_car 4>;
307 }; 309 };
308 310
309 i2c@7000c000 { 311 i2c@7000c000 {
@@ -416,6 +418,8 @@
416 pmc { 418 pmc {
417 compatible = "nvidia,tegra20-pmc"; 419 compatible = "nvidia,tegra20-pmc";
418 reg = <0x7000e400 0x400>; 420 reg = <0x7000e400 0x400>;
421 clocks = <&tegra_car 110>, <&clk32k_in>;
422 clock-names = "pclk", "clk32k_in";
419 }; 423 };
420 424
421 memory-controller@7000f000 { 425 memory-controller@7000f000 {
diff --git a/arch/arm/boot/dts/tegra30-beaver.dts b/arch/arm/boot/dts/tegra30-beaver.dts
index 8ff2ff20e4a3..6248b2445b32 100644
--- a/arch/arm/boot/dts/tegra30-beaver.dts
+++ b/arch/arm/boot/dts/tegra30-beaver.dts
@@ -257,7 +257,7 @@
257 257
258 sdhci@78000000 { 258 sdhci@78000000 {
259 status = "okay"; 259 status = "okay";
260 cd-gpios = <&gpio 69 0>; /* gpio PI5 */ 260 cd-gpios = <&gpio 69 1>; /* gpio PI5 */
261 wp-gpios = <&gpio 155 0>; /* gpio PT3 */ 261 wp-gpios = <&gpio 155 0>; /* gpio PT3 */
262 power-gpios = <&gpio 31 0>; /* gpio PD7 */ 262 power-gpios = <&gpio 31 0>; /* gpio PD7 */
263 bus-width = <4>; 263 bus-width = <4>;
@@ -268,6 +268,19 @@
268 bus-width = <8>; 268 bus-width = <8>;
269 }; 269 };
270 270
271 clocks {
272 compatible = "simple-bus";
273 #address-cells = <1>;
274 #size-cells = <0>;
275
276 clk32k_in: clock {
277 compatible = "fixed-clock";
278 reg=<0>;
279 #clock-cells = <0>;
280 clock-frequency = <32768>;
281 };
282 };
283
271 regulators { 284 regulators {
272 compatible = "simple-bus"; 285 compatible = "simple-bus";
273 #address-cells = <1>; 286 #address-cells = <1>;
diff --git a/arch/arm/boot/dts/tegra30-cardhu.dtsi b/arch/arm/boot/dts/tegra30-cardhu.dtsi
index 17499272a4ef..65bf2b63174e 100644
--- a/arch/arm/boot/dts/tegra30-cardhu.dtsi
+++ b/arch/arm/boot/dts/tegra30-cardhu.dtsi
@@ -311,7 +311,7 @@
311 311
312 sdhci@78000000 { 312 sdhci@78000000 {
313 status = "okay"; 313 status = "okay";
314 cd-gpios = <&gpio 69 0>; /* gpio PI5 */ 314 cd-gpios = <&gpio 69 1>; /* gpio PI5 */
315 wp-gpios = <&gpio 155 0>; /* gpio PT3 */ 315 wp-gpios = <&gpio 155 0>; /* gpio PT3 */
316 power-gpios = <&gpio 31 0>; /* gpio PD7 */ 316 power-gpios = <&gpio 31 0>; /* gpio PD7 */
317 bus-width = <4>; 317 bus-width = <4>;
@@ -322,6 +322,19 @@
322 bus-width = <8>; 322 bus-width = <8>;
323 }; 323 };
324 324
325 clocks {
326 compatible = "simple-bus";
327 #address-cells = <1>;
328 #size-cells = <0>;
329
330 clk32k_in: clock {
331 compatible = "fixed-clock";
332 reg=<0>;
333 #clock-cells = <0>;
334 clock-frequency = <32768>;
335 };
336 };
337
325 regulators { 338 regulators {
326 compatible = "simple-bus"; 339 compatible = "simple-bus";
327 #address-cells = <1>; 340 #address-cells = <1>;
diff --git a/arch/arm/boot/dts/tegra30.dtsi b/arch/arm/boot/dts/tegra30.dtsi
index dbf46c272562..9fe7a92b4c85 100644
--- a/arch/arm/boot/dts/tegra30.dtsi
+++ b/arch/arm/boot/dts/tegra30.dtsi
@@ -148,6 +148,7 @@
148 0 42 0x04 148 0 42 0x04
149 0 121 0x04 149 0 121 0x04
150 0 122 0x04>; 150 0 122 0x04>;
151 clocks = <&tegra_car 5>;
151 }; 152 };
152 153
153 tegra_car: clock { 154 tegra_car: clock {
@@ -291,6 +292,7 @@
291 compatible = "nvidia,tegra30-rtc", "nvidia,tegra20-rtc"; 292 compatible = "nvidia,tegra30-rtc", "nvidia,tegra20-rtc";
292 reg = <0x7000e000 0x100>; 293 reg = <0x7000e000 0x100>;
293 interrupts = <0 2 0x04>; 294 interrupts = <0 2 0x04>;
295 clocks = <&tegra_car 4>;
294 }; 296 };
295 297
296 i2c@7000c000 { 298 i2c@7000c000 {
@@ -423,8 +425,10 @@
423 }; 425 };
424 426
425 pmc { 427 pmc {
426 compatible = "nvidia,tegra20-pmc", "nvidia,tegra30-pmc"; 428 compatible = "nvidia,tegra30-pmc";
427 reg = <0x7000e400 0x400>; 429 reg = <0x7000e400 0x400>;
430 clocks = <&tegra_car 218>, <&clk32k_in>;
431 clock-names = "pclk", "clk32k_in";
428 }; 432 };
429 433
430 memory-controller { 434 memory-controller {
diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile
index f6b46ae2b7f8..e40326d0e29f 100644
--- a/arch/arm/mach-tegra/Makefile
+++ b/arch/arm/mach-tegra/Makefile
@@ -10,6 +10,7 @@ obj-y += pm.o
10obj-y += reset.o 10obj-y += reset.o
11obj-y += reset-handler.o 11obj-y += reset-handler.o
12obj-y += sleep.o 12obj-y += sleep.o
13obj-y += tegra.o
13obj-$(CONFIG_CPU_IDLE) += cpuidle.o 14obj-$(CONFIG_CPU_IDLE) += cpuidle.o
14obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra20_speedo.o 15obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra20_speedo.o
15obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra2_emc.o 16obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra2_emc.o
@@ -27,9 +28,7 @@ obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
27obj-$(CONFIG_CPU_FREQ) += cpu-tegra.o 28obj-$(CONFIG_CPU_FREQ) += cpu-tegra.o
28obj-$(CONFIG_TEGRA_PCI) += pcie.o 29obj-$(CONFIG_TEGRA_PCI) += pcie.o
29 30
30obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += board-dt-tegra20.o 31obj-$(CONFIG_ARCH_TEGRA_114_SOC) += tegra114_speedo.o
31obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += board-dt-tegra30.o
32obj-$(CONFIG_ARCH_TEGRA_114_SOC) += board-dt-tegra114.o
33ifeq ($(CONFIG_CPU_IDLE),y) 32ifeq ($(CONFIG_CPU_IDLE),y)
34obj-$(CONFIG_ARCH_TEGRA_114_SOC) += cpuidle-tegra114.o 33obj-$(CONFIG_ARCH_TEGRA_114_SOC) += cpuidle-tegra114.o
35endif 34endif
diff --git a/arch/arm/mach-tegra/board-dt-tegra114.c b/arch/arm/mach-tegra/board-dt-tegra114.c
deleted file mode 100644
index 085d63637b62..000000000000
--- a/arch/arm/mach-tegra/board-dt-tegra114.c
+++ /dev/null
@@ -1,46 +0,0 @@
1/*
2 * NVIDIA Tegra114 device tree board support
3 *
4 * Copyright (C) 2013 NVIDIA Corporation
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#include <linux/of.h>
18#include <linux/of_platform.h>
19#include <linux/clocksource.h>
20
21#include <asm/mach/arch.h>
22
23#include "board.h"
24#include "common.h"
25
26static void __init tegra114_dt_init(void)
27{
28 of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
29}
30
31static const char * const tegra114_dt_board_compat[] = {
32 "nvidia,tegra114",
33 NULL,
34};
35
36DT_MACHINE_START(TEGRA114_DT, "NVIDIA Tegra114 (Flattened Device Tree)")
37 .smp = smp_ops(tegra_smp_ops),
38 .map_io = tegra_map_common_io,
39 .init_early = tegra114_init_early,
40 .init_irq = tegra_dt_init_irq,
41 .init_time = clocksource_of_init,
42 .init_machine = tegra114_dt_init,
43 .init_late = tegra_init_late,
44 .restart = tegra_assert_system_reset,
45 .dt_compat = tegra114_dt_board_compat,
46MACHINE_END
diff --git a/arch/arm/mach-tegra/board-dt-tegra30.c b/arch/arm/mach-tegra/board-dt-tegra30.c
deleted file mode 100644
index bf68567e549d..000000000000
--- a/arch/arm/mach-tegra/board-dt-tegra30.c
+++ /dev/null
@@ -1,60 +0,0 @@
1/*
2 * arch/arm/mach-tegra/board-dt-tegra30.c
3 *
4 * NVIDIA Tegra30 device tree board support
5 *
6 * Copyright (C) 2011 NVIDIA Corporation
7 *
8 * Derived from:
9 *
10 * arch/arm/mach-tegra/board-dt-tegra20.c
11 *
12 * Copyright (C) 2010 Secret Lab Technologies, Ltd.
13 * Copyright (C) 2010 Google, Inc.
14 *
15 * This software is licensed under the terms of the GNU General Public
16 * License version 2, as published by the Free Software Foundation, and
17 * may be copied, distributed, and modified under those terms.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 */
25
26#include <linux/clocksource.h>
27#include <linux/kernel.h>
28#include <linux/of.h>
29#include <linux/of_address.h>
30#include <linux/of_fdt.h>
31#include <linux/of_irq.h>
32#include <linux/of_platform.h>
33
34#include <asm/mach/arch.h>
35
36#include "board.h"
37#include "common.h"
38#include "iomap.h"
39
40static void __init tegra30_dt_init(void)
41{
42 of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
43}
44
45static const char *tegra30_dt_board_compat[] = {
46 "nvidia,tegra30",
47 NULL
48};
49
50DT_MACHINE_START(TEGRA30_DT, "NVIDIA Tegra30 (Flattened Device Tree)")
51 .smp = smp_ops(tegra_smp_ops),
52 .map_io = tegra_map_common_io,
53 .init_early = tegra30_init_early,
54 .init_irq = tegra_dt_init_irq,
55 .init_time = clocksource_of_init,
56 .init_machine = tegra30_dt_init,
57 .init_late = tegra_init_late,
58 .restart = tegra_assert_system_reset,
59 .dt_compat = tegra30_dt_board_compat,
60MACHINE_END
diff --git a/arch/arm/mach-tegra/board-harmony-pcie.c b/arch/arm/mach-tegra/board-harmony-pcie.c
index 6d29e6a39540..035b240b9e15 100644
--- a/arch/arm/mach-tegra/board-harmony-pcie.c
+++ b/arch/arm/mach-tegra/board-harmony-pcie.c
@@ -62,7 +62,11 @@ int __init harmony_pcie_init(void)
62 goto err_reg; 62 goto err_reg;
63 } 63 }
64 64
65 regulator_enable(regulator); 65 err = regulator_enable(regulator);
66 if (err) {
67 pr_err("%s: regulator_enable failed: %d\n", __func__, err);
68 goto err_en;
69 }
66 70
67 err = tegra_pcie_init(true, true); 71 err = tegra_pcie_init(true, true);
68 if (err) { 72 if (err) {
@@ -74,6 +78,7 @@ int __init harmony_pcie_init(void)
74 78
75err_pcie: 79err_pcie:
76 regulator_disable(regulator); 80 regulator_disable(regulator);
81err_en:
77 regulator_put(regulator); 82 regulator_put(regulator);
78err_reg: 83err_reg:
79 gpio_free(en_vdd_1v05); 84 gpio_free(en_vdd_1v05);
diff --git a/arch/arm/mach-tegra/board.h b/arch/arm/mach-tegra/board.h
index 86851c81a350..60431de585ca 100644
--- a/arch/arm/mach-tegra/board.h
+++ b/arch/arm/mach-tegra/board.h
@@ -26,9 +26,7 @@
26 26
27void tegra_assert_system_reset(char mode, const char *cmd); 27void tegra_assert_system_reset(char mode, const char *cmd);
28 28
29void __init tegra20_init_early(void); 29void __init tegra_init_early(void);
30void __init tegra30_init_early(void);
31void __init tegra114_init_early(void);
32void __init tegra_map_common_io(void); 30void __init tegra_map_common_io(void);
33void __init tegra_init_irq(void); 31void __init tegra_init_irq(void);
34void __init tegra_dt_init_irq(void); 32void __init tegra_dt_init_irq(void);
diff --git a/arch/arm/mach-tegra/common.c b/arch/arm/mach-tegra/common.c
index 5449a3f2977b..eb1f3c8c74cc 100644
--- a/arch/arm/mach-tegra/common.c
+++ b/arch/arm/mach-tegra/common.c
@@ -33,6 +33,7 @@
33#include "common.h" 33#include "common.h"
34#include "fuse.h" 34#include "fuse.h"
35#include "iomap.h" 35#include "iomap.h"
36#include "irq.h"
36#include "pmc.h" 37#include "pmc.h"
37#include "apbio.h" 38#include "apbio.h"
38#include "sleep.h" 39#include "sleep.h"
@@ -61,8 +62,10 @@ u32 tegra_uart_config[4] = {
61void __init tegra_dt_init_irq(void) 62void __init tegra_dt_init_irq(void)
62{ 63{
63 tegra_clocks_init(); 64 tegra_clocks_init();
65 tegra_pmc_init();
64 tegra_init_irq(); 66 tegra_init_irq();
65 irqchip_init(); 67 irqchip_init();
68 tegra_legacy_irq_syscore_init();
66} 69}
67#endif 70#endif
68 71
@@ -94,40 +97,18 @@ static void __init tegra_init_cache(void)
94 97
95} 98}
96 99
97static void __init tegra_init_early(void) 100void __init tegra_init_early(void)
98{ 101{
99 tegra_cpu_reset_handler_init(); 102 tegra_cpu_reset_handler_init();
100 tegra_apb_io_init(); 103 tegra_apb_io_init();
101 tegra_init_fuse(); 104 tegra_init_fuse();
102 tegra_init_cache(); 105 tegra_init_cache();
103 tegra_pmc_init();
104 tegra_powergate_init(); 106 tegra_powergate_init();
107 tegra_hotplug_init();
105} 108}
106 109
107#ifdef CONFIG_ARCH_TEGRA_2x_SOC
108void __init tegra20_init_early(void)
109{
110 tegra_init_early();
111 tegra20_hotplug_init();
112}
113#endif
114
115#ifdef CONFIG_ARCH_TEGRA_3x_SOC
116void __init tegra30_init_early(void)
117{
118 tegra_init_early();
119 tegra30_hotplug_init();
120}
121#endif
122
123#ifdef CONFIG_ARCH_TEGRA_114_SOC
124void __init tegra114_init_early(void)
125{
126 tegra_init_early();
127}
128#endif
129
130void __init tegra_init_late(void) 110void __init tegra_init_late(void)
131{ 111{
112 tegra_init_suspend();
132 tegra_powergate_debugfs_init(); 113 tegra_powergate_debugfs_init();
133} 114}
diff --git a/arch/arm/mach-tegra/cpuidle-tegra20.c b/arch/arm/mach-tegra/cpuidle-tegra20.c
index 825ced4f7a40..8bbbdebed882 100644
--- a/arch/arm/mach-tegra/cpuidle-tegra20.c
+++ b/arch/arm/mach-tegra/cpuidle-tegra20.c
@@ -130,10 +130,6 @@ static bool tegra20_cpu_cluster_power_down(struct cpuidle_device *dev,
130 struct cpuidle_driver *drv, 130 struct cpuidle_driver *drv,
131 int index) 131 int index)
132{ 132{
133 struct cpuidle_state *state = &drv->states[index];
134 u32 cpu_on_time = state->exit_latency;
135 u32 cpu_off_time = state->target_residency - state->exit_latency;
136
137 while (tegra20_cpu_is_resettable_soon()) 133 while (tegra20_cpu_is_resettable_soon())
138 cpu_relax(); 134 cpu_relax();
139 135
@@ -142,7 +138,7 @@ static bool tegra20_cpu_cluster_power_down(struct cpuidle_device *dev,
142 138
143 clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &dev->cpu); 139 clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &dev->cpu);
144 140
145 tegra_idle_lp2_last(cpu_on_time, cpu_off_time); 141 tegra_idle_lp2_last();
146 142
147 clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &dev->cpu); 143 clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &dev->cpu);
148 144
diff --git a/arch/arm/mach-tegra/cpuidle-tegra30.c b/arch/arm/mach-tegra/cpuidle-tegra30.c
index 8b50cf4ddd6f..c0931c8bb3e5 100644
--- a/arch/arm/mach-tegra/cpuidle-tegra30.c
+++ b/arch/arm/mach-tegra/cpuidle-tegra30.c
@@ -72,10 +72,6 @@ static bool tegra30_cpu_cluster_power_down(struct cpuidle_device *dev,
72 struct cpuidle_driver *drv, 72 struct cpuidle_driver *drv,
73 int index) 73 int index)
74{ 74{
75 struct cpuidle_state *state = &drv->states[index];
76 u32 cpu_on_time = state->exit_latency;
77 u32 cpu_off_time = state->target_residency - state->exit_latency;
78
79 /* All CPUs entering LP2 is not working. 75 /* All CPUs entering LP2 is not working.
80 * Don't let CPU0 enter LP2 when any secondary CPU is online. 76 * Don't let CPU0 enter LP2 when any secondary CPU is online.
81 */ 77 */
@@ -86,7 +82,7 @@ static bool tegra30_cpu_cluster_power_down(struct cpuidle_device *dev,
86 82
87 clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &dev->cpu); 83 clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &dev->cpu);
88 84
89 tegra_idle_lp2_last(cpu_on_time, cpu_off_time); 85 tegra_idle_lp2_last();
90 86
91 clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &dev->cpu); 87 clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &dev->cpu);
92 88
@@ -102,12 +98,8 @@ static bool tegra30_cpu_core_power_down(struct cpuidle_device *dev,
102 98
103 smp_wmb(); 99 smp_wmb();
104 100
105 save_cpu_arch_register();
106
107 cpu_suspend(0, tegra30_sleep_cpu_secondary_finish); 101 cpu_suspend(0, tegra30_sleep_cpu_secondary_finish);
108 102
109 restore_cpu_arch_register();
110
111 clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &dev->cpu); 103 clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &dev->cpu);
112 104
113 return true; 105 return true;
diff --git a/arch/arm/mach-tegra/fuse.c b/arch/arm/mach-tegra/fuse.c
index f7db0782a6b6..e035cd284a6e 100644
--- a/arch/arm/mach-tegra/fuse.c
+++ b/arch/arm/mach-tegra/fuse.c
@@ -2,6 +2,7 @@
2 * arch/arm/mach-tegra/fuse.c 2 * arch/arm/mach-tegra/fuse.c
3 * 3 *
4 * Copyright (C) 2010 Google, Inc. 4 * Copyright (C) 2010 Google, Inc.
5 * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved.
5 * 6 *
6 * Author: 7 * Author:
7 * Colin Cross <ccross@android.com> 8 * Colin Cross <ccross@android.com>
@@ -137,6 +138,9 @@ void tegra_init_fuse(void)
137 tegra_fuse_spare_bit = TEGRA30_FUSE_SPARE_BIT; 138 tegra_fuse_spare_bit = TEGRA30_FUSE_SPARE_BIT;
138 tegra_init_speedo_data = &tegra30_init_speedo_data; 139 tegra_init_speedo_data = &tegra30_init_speedo_data;
139 break; 140 break;
141 case TEGRA114:
142 tegra_init_speedo_data = &tegra114_init_speedo_data;
143 break;
140 default: 144 default:
141 pr_warn("Tegra: unknown chip id %d\n", tegra_chip_id); 145 pr_warn("Tegra: unknown chip id %d\n", tegra_chip_id);
142 tegra_fuse_spare_bit = TEGRA20_FUSE_SPARE_BIT; 146 tegra_fuse_spare_bit = TEGRA20_FUSE_SPARE_BIT;
diff --git a/arch/arm/mach-tegra/fuse.h b/arch/arm/mach-tegra/fuse.h
index da78434678c7..aacc00d05980 100644
--- a/arch/arm/mach-tegra/fuse.h
+++ b/arch/arm/mach-tegra/fuse.h
@@ -1,5 +1,6 @@
1/* 1/*
2 * Copyright (C) 2010 Google, Inc. 2 * Copyright (C) 2010 Google, Inc.
3 * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved.
3 * 4 *
4 * Author: 5 * Author:
5 * Colin Cross <ccross@android.com> 6 * Colin Cross <ccross@android.com>
@@ -66,4 +67,10 @@ void tegra30_init_speedo_data(void);
66static inline void tegra30_init_speedo_data(void) {} 67static inline void tegra30_init_speedo_data(void) {}
67#endif 68#endif
68 69
70#ifdef CONFIG_ARCH_TEGRA_114_SOC
71void tegra114_init_speedo_data(void);
72#else
73static inline void tegra114_init_speedo_data(void) {}
74#endif
75
69#endif 76#endif
diff --git a/arch/arm/mach-tegra/headsmp.S b/arch/arm/mach-tegra/headsmp.S
index fd473f2b4c3d..045c16f2dd51 100644
--- a/arch/arm/mach-tegra/headsmp.S
+++ b/arch/arm/mach-tegra/headsmp.S
@@ -7,8 +7,5 @@
7 7
8ENTRY(tegra_secondary_startup) 8ENTRY(tegra_secondary_startup)
9 bl v7_invalidate_l1 9 bl v7_invalidate_l1
10 /* Enable coresight */
11 mov32 r0, 0xC5ACCE55
12 mcr p14, 0, r0, c7, c12, 6
13 b secondary_startup 10 b secondary_startup
14ENDPROC(tegra_secondary_startup) 11ENDPROC(tegra_secondary_startup)
diff --git a/arch/arm/mach-tegra/hotplug.c b/arch/arm/mach-tegra/hotplug.c
index a599f6e36dea..8da9f78475da 100644
--- a/arch/arm/mach-tegra/hotplug.c
+++ b/arch/arm/mach-tegra/hotplug.c
@@ -1,8 +1,7 @@
1/* 1/*
2 *
3 * Copyright (C) 2002 ARM Ltd. 2 * Copyright (C) 2002 ARM Ltd.
4 * All Rights Reserved 3 * All Rights Reserved
5 * Copyright (c) 2010, 2012 NVIDIA Corporation. All rights reserved. 4 * Copyright (c) 2010, 2012-2013, NVIDIA Corporation. All rights reserved.
6 * 5 *
7 * This program is free software; you can redistribute it and/or modify 6 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as 7 * it under the terms of the GNU General Public License version 2 as
@@ -15,6 +14,7 @@
15#include <asm/cacheflush.h> 14#include <asm/cacheflush.h>
16#include <asm/smp_plat.h> 15#include <asm/smp_plat.h>
17 16
17#include "fuse.h"
18#include "sleep.h" 18#include "sleep.h"
19 19
20static void (*tegra_hotplug_shutdown)(void); 20static void (*tegra_hotplug_shutdown)(void);
@@ -56,18 +56,13 @@ int tegra_cpu_disable(unsigned int cpu)
56 return cpu == 0 ? -EPERM : 0; 56 return cpu == 0 ? -EPERM : 0;
57} 57}
58 58
59#ifdef CONFIG_ARCH_TEGRA_2x_SOC 59void __init tegra_hotplug_init(void)
60extern void tegra20_hotplug_shutdown(void);
61void __init tegra20_hotplug_init(void)
62{ 60{
63 tegra_hotplug_shutdown = tegra20_hotplug_shutdown; 61 if (!IS_ENABLED(CONFIG_HOTPLUG_CPU))
64} 62 return;
65#endif
66 63
67#ifdef CONFIG_ARCH_TEGRA_3x_SOC 64 if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC) && tegra_chip_id == TEGRA20)
68extern void tegra30_hotplug_shutdown(void); 65 tegra_hotplug_shutdown = tegra20_hotplug_shutdown;
69void __init tegra30_hotplug_init(void) 66 if (IS_ENABLED(CONFIG_ARCH_TEGRA_3x_SOC) && tegra_chip_id == TEGRA30)
70{ 67 tegra_hotplug_shutdown = tegra30_hotplug_shutdown;
71 tegra_hotplug_shutdown = tegra30_hotplug_shutdown;
72} 68}
73#endif
diff --git a/arch/arm/mach-tegra/irq.c b/arch/arm/mach-tegra/irq.c
index 1952e82797cc..0de4eed1493d 100644
--- a/arch/arm/mach-tegra/irq.c
+++ b/arch/arm/mach-tegra/irq.c
@@ -4,7 +4,7 @@
4 * Author: 4 * Author:
5 * Colin Cross <ccross@android.com> 5 * Colin Cross <ccross@android.com>
6 * 6 *
7 * Copyright (C) 2010, NVIDIA Corporation 7 * Copyright (C) 2010,2013, NVIDIA Corporation
8 * 8 *
9 * 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
10 * License version 2, as published by the Free Software Foundation, and 10 * License version 2, as published by the Free Software Foundation, and
@@ -23,6 +23,7 @@
23#include <linux/io.h> 23#include <linux/io.h>
24#include <linux/of.h> 24#include <linux/of.h>
25#include <linux/irqchip/arm-gic.h> 25#include <linux/irqchip/arm-gic.h>
26#include <linux/syscore_ops.h>
26 27
27#include "board.h" 28#include "board.h"
28#include "iomap.h" 29#include "iomap.h"
@@ -43,6 +44,7 @@
43#define ICTLR_COP_IEP_CLASS 0x3c 44#define ICTLR_COP_IEP_CLASS 0x3c
44 45
45#define FIRST_LEGACY_IRQ 32 46#define FIRST_LEGACY_IRQ 32
47#define TEGRA_MAX_NUM_ICTLRS 5
46 48
47#define SGI_MASK 0xFFFF 49#define SGI_MASK 0xFFFF
48 50
@@ -56,6 +58,15 @@ static void __iomem *ictlr_reg_base[] = {
56 IO_ADDRESS(TEGRA_QUINARY_ICTLR_BASE), 58 IO_ADDRESS(TEGRA_QUINARY_ICTLR_BASE),
57}; 59};
58 60
61#ifdef CONFIG_PM_SLEEP
62static u32 cop_ier[TEGRA_MAX_NUM_ICTLRS];
63static u32 cop_iep[TEGRA_MAX_NUM_ICTLRS];
64static u32 cpu_ier[TEGRA_MAX_NUM_ICTLRS];
65static u32 cpu_iep[TEGRA_MAX_NUM_ICTLRS];
66
67static u32 ictlr_wake_mask[TEGRA_MAX_NUM_ICTLRS];
68#endif
69
59bool tegra_pending_sgi(void) 70bool tegra_pending_sgi(void)
60{ 71{
61 u32 pending_set; 72 u32 pending_set;
@@ -125,6 +136,87 @@ static int tegra_retrigger(struct irq_data *d)
125 return 1; 136 return 1;
126} 137}
127 138
139#ifdef CONFIG_PM_SLEEP
140static int tegra_set_wake(struct irq_data *d, unsigned int enable)
141{
142 u32 irq = d->irq;
143 u32 index, mask;
144
145 if (irq < FIRST_LEGACY_IRQ ||
146 irq >= FIRST_LEGACY_IRQ + num_ictlrs * 32)
147 return -EINVAL;
148
149 index = ((irq - FIRST_LEGACY_IRQ) / 32);
150 mask = BIT((irq - FIRST_LEGACY_IRQ) % 32);
151 if (enable)
152 ictlr_wake_mask[index] |= mask;
153 else
154 ictlr_wake_mask[index] &= ~mask;
155
156 return 0;
157}
158
159static int tegra_legacy_irq_suspend(void)
160{
161 unsigned long flags;
162 int i;
163
164 local_irq_save(flags);
165 for (i = 0; i < num_ictlrs; i++) {
166 void __iomem *ictlr = ictlr_reg_base[i];
167 /* Save interrupt state */
168 cpu_ier[i] = readl_relaxed(ictlr + ICTLR_CPU_IER);
169 cpu_iep[i] = readl_relaxed(ictlr + ICTLR_CPU_IEP_CLASS);
170 cop_ier[i] = readl_relaxed(ictlr + ICTLR_COP_IER);
171 cop_iep[i] = readl_relaxed(ictlr + ICTLR_COP_IEP_CLASS);
172
173 /* Disable COP interrupts */
174 writel_relaxed(~0ul, ictlr + ICTLR_COP_IER_CLR);
175
176 /* Disable CPU interrupts */
177 writel_relaxed(~0ul, ictlr + ICTLR_CPU_IER_CLR);
178
179 /* Enable the wakeup sources of ictlr */
180 writel_relaxed(ictlr_wake_mask[i], ictlr + ICTLR_CPU_IER_SET);
181 }
182 local_irq_restore(flags);
183
184 return 0;
185}
186
187static void tegra_legacy_irq_resume(void)
188{
189 unsigned long flags;
190 int i;
191
192 local_irq_save(flags);
193 for (i = 0; i < num_ictlrs; i++) {
194 void __iomem *ictlr = ictlr_reg_base[i];
195 writel_relaxed(cpu_iep[i], ictlr + ICTLR_CPU_IEP_CLASS);
196 writel_relaxed(~0ul, ictlr + ICTLR_CPU_IER_CLR);
197 writel_relaxed(cpu_ier[i], ictlr + ICTLR_CPU_IER_SET);
198 writel_relaxed(cop_iep[i], ictlr + ICTLR_COP_IEP_CLASS);
199 writel_relaxed(~0ul, ictlr + ICTLR_COP_IER_CLR);
200 writel_relaxed(cop_ier[i], ictlr + ICTLR_COP_IER_SET);
201 }
202 local_irq_restore(flags);
203}
204
205static struct syscore_ops tegra_legacy_irq_syscore_ops = {
206 .suspend = tegra_legacy_irq_suspend,
207 .resume = tegra_legacy_irq_resume,
208};
209
210int tegra_legacy_irq_syscore_init(void)
211{
212 register_syscore_ops(&tegra_legacy_irq_syscore_ops);
213
214 return 0;
215}
216#else
217#define tegra_set_wake NULL
218#endif
219
128void __init tegra_init_irq(void) 220void __init tegra_init_irq(void)
129{ 221{
130 int i; 222 int i;
@@ -150,6 +242,8 @@ void __init tegra_init_irq(void)
150 gic_arch_extn.irq_mask = tegra_mask; 242 gic_arch_extn.irq_mask = tegra_mask;
151 gic_arch_extn.irq_unmask = tegra_unmask; 243 gic_arch_extn.irq_unmask = tegra_unmask;
152 gic_arch_extn.irq_retrigger = tegra_retrigger; 244 gic_arch_extn.irq_retrigger = tegra_retrigger;
245 gic_arch_extn.irq_set_wake = tegra_set_wake;
246 gic_arch_extn.flags = IRQCHIP_MASK_ON_SUSPEND;
153 247
154 /* 248 /*
155 * Check if there is a devicetree present, since the GIC will be 249 * Check if there is a devicetree present, since the GIC will be
diff --git a/arch/arm/mach-tegra/irq.h b/arch/arm/mach-tegra/irq.h
index 5142649bba05..bc05ce5613fb 100644
--- a/arch/arm/mach-tegra/irq.h
+++ b/arch/arm/mach-tegra/irq.h
@@ -19,4 +19,10 @@
19 19
20bool tegra_pending_sgi(void); 20bool tegra_pending_sgi(void);
21 21
22#ifdef CONFIG_PM_SLEEP
23int tegra_legacy_irq_syscore_init(void);
24#else
25static inline int tegra_legacy_irq_syscore_init(void) { return 0; }
26#endif
27
22#endif 28#endif
diff --git a/arch/arm/mach-tegra/platsmp.c b/arch/arm/mach-tegra/platsmp.c
index 2c6b3d55213b..516aab28fe34 100644
--- a/arch/arm/mach-tegra/platsmp.c
+++ b/arch/arm/mach-tegra/platsmp.c
@@ -26,22 +26,16 @@
26#include <asm/smp_scu.h> 26#include <asm/smp_scu.h>
27#include <asm/smp_plat.h> 27#include <asm/smp_plat.h>
28 28
29#include <mach/powergate.h>
30
31#include "fuse.h" 29#include "fuse.h"
32#include "flowctrl.h" 30#include "flowctrl.h"
33#include "reset.h" 31#include "reset.h"
32#include "pmc.h"
34 33
35#include "common.h" 34#include "common.h"
36#include "iomap.h" 35#include "iomap.h"
37 36
38extern void tegra_secondary_startup(void);
39
40static cpumask_t tegra_cpu_init_mask; 37static cpumask_t tegra_cpu_init_mask;
41 38
42#define EVP_CPU_RESET_VECTOR \
43 (IO_ADDRESS(TEGRA_EXCEPTION_VECTORS_BASE) + 0x100)
44
45static void __cpuinit tegra_secondary_init(unsigned int cpu) 39static void __cpuinit tegra_secondary_init(unsigned int cpu)
46{ 40{
47 /* 41 /*
@@ -54,25 +48,43 @@ static void __cpuinit tegra_secondary_init(unsigned int cpu)
54 cpumask_set_cpu(cpu, &tegra_cpu_init_mask); 48 cpumask_set_cpu(cpu, &tegra_cpu_init_mask);
55} 49}
56 50
57static int tegra20_power_up_cpu(unsigned int cpu) 51
52static int tegra20_boot_secondary(unsigned int cpu, struct task_struct *idle)
58{ 53{
59 /* Enable the CPU clock. */ 54 cpu = cpu_logical_map(cpu);
60 tegra_enable_cpu_clock(cpu); 55
56 /*
57 * Force the CPU into reset. The CPU must remain in reset when
58 * the flow controller state is cleared (which will cause the
59 * flow controller to stop driving reset if the CPU has been
60 * power-gated via the flow controller). This will have no
61 * effect on first boot of the CPU since it should already be
62 * in reset.
63 */
64 tegra_put_cpu_in_reset(cpu);
61 65
62 /* Clear flow controller CSR. */ 66 /*
63 flowctrl_write_cpu_csr(cpu, 0); 67 * Unhalt the CPU. If the flow controller was used to
68 * power-gate the CPU this will cause the flow controller to
69 * stop driving reset. The CPU will remain in reset because the
70 * clock and reset block is now driving reset.
71 */
72 flowctrl_write_cpu_halt(cpu, 0);
64 73
74 tegra_enable_cpu_clock(cpu);
75 flowctrl_write_cpu_csr(cpu, 0); /* Clear flow controller CSR. */
76 tegra_cpu_out_of_reset(cpu);
65 return 0; 77 return 0;
66} 78}
67 79
68static int tegra30_power_up_cpu(unsigned int cpu) 80static int tegra30_boot_secondary(unsigned int cpu, struct task_struct *idle)
69{ 81{
70 int ret, pwrgateid; 82 int ret;
71 unsigned long timeout; 83 unsigned long timeout;
72 84
73 pwrgateid = tegra_cpu_powergate_id(cpu); 85 cpu = cpu_logical_map(cpu);
74 if (pwrgateid < 0) 86 tegra_put_cpu_in_reset(cpu);
75 return pwrgateid; 87 flowctrl_write_cpu_halt(cpu, 0);
76 88
77 /* 89 /*
78 * The power up sequence of cold boot CPU and warm boot CPU 90 * The power up sequence of cold boot CPU and warm boot CPU
@@ -85,13 +97,13 @@ static int tegra30_power_up_cpu(unsigned int cpu)
85 * the IO clamps. 97 * the IO clamps.
86 * For cold boot CPU, do not wait. After the cold boot CPU be 98 * For cold boot CPU, do not wait. After the cold boot CPU be
87 * booted, it will run to tegra_secondary_init() and set 99 * booted, it will run to tegra_secondary_init() and set
88 * tegra_cpu_init_mask which influences what tegra30_power_up_cpu() 100 * tegra_cpu_init_mask which influences what tegra30_boot_secondary()
89 * next time around. 101 * next time around.
90 */ 102 */
91 if (cpumask_test_cpu(cpu, &tegra_cpu_init_mask)) { 103 if (cpumask_test_cpu(cpu, &tegra_cpu_init_mask)) {
92 timeout = jiffies + msecs_to_jiffies(50); 104 timeout = jiffies + msecs_to_jiffies(50);
93 do { 105 do {
94 if (!tegra_powergate_is_powered(pwrgateid)) 106 if (tegra_pmc_cpu_is_powered(cpu))
95 goto remove_clamps; 107 goto remove_clamps;
96 udelay(10); 108 udelay(10);
97 } while (time_before(jiffies, timeout)); 109 } while (time_before(jiffies, timeout));
@@ -103,14 +115,14 @@ static int tegra30_power_up_cpu(unsigned int cpu)
103 * be un-gated by un-toggling the power gate register 115 * be un-gated by un-toggling the power gate register
104 * manually. 116 * manually.
105 */ 117 */
106 if (!tegra_powergate_is_powered(pwrgateid)) { 118 if (!tegra_pmc_cpu_is_powered(cpu)) {
107 ret = tegra_powergate_power_on(pwrgateid); 119 ret = tegra_pmc_cpu_power_on(cpu);
108 if (ret) 120 if (ret)
109 return ret; 121 return ret;
110 122
111 /* Wait for the power to come up. */ 123 /* Wait for the power to come up. */
112 timeout = jiffies + msecs_to_jiffies(100); 124 timeout = jiffies + msecs_to_jiffies(100);
113 while (tegra_powergate_is_powered(pwrgateid)) { 125 while (tegra_pmc_cpu_is_powered(cpu)) {
114 if (time_after(jiffies, timeout)) 126 if (time_after(jiffies, timeout))
115 return -ETIMEDOUT; 127 return -ETIMEDOUT;
116 udelay(10); 128 udelay(10);
@@ -123,57 +135,34 @@ remove_clamps:
123 udelay(10); 135 udelay(10);
124 136
125 /* Remove I/O clamps. */ 137 /* Remove I/O clamps. */
126 ret = tegra_powergate_remove_clamping(pwrgateid); 138 ret = tegra_pmc_cpu_remove_clamping(cpu);
127 udelay(10); 139 if (ret)
140 return ret;
128 141
129 /* Clear flow controller CSR. */ 142 udelay(10);
130 flowctrl_write_cpu_csr(cpu, 0);
131 143
144 flowctrl_write_cpu_csr(cpu, 0); /* Clear flow controller CSR. */
145 tegra_cpu_out_of_reset(cpu);
132 return 0; 146 return 0;
133} 147}
134 148
135static int __cpuinit tegra_boot_secondary(unsigned int cpu, struct task_struct *idle) 149static int tegra114_boot_secondary(unsigned int cpu, struct task_struct *idle)
136{ 150{
137 int status;
138
139 cpu = cpu_logical_map(cpu); 151 cpu = cpu_logical_map(cpu);
152 return tegra_pmc_cpu_power_on(cpu);
153}
140 154
141 /* 155static int __cpuinit tegra_boot_secondary(unsigned int cpu,
142 * Force the CPU into reset. The CPU must remain in reset when the 156 struct task_struct *idle)
143 * flow controller state is cleared (which will cause the flow 157{
144 * controller to stop driving reset if the CPU has been power-gated 158 if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC) && tegra_chip_id == TEGRA20)
145 * via the flow controller). This will have no effect on first boot 159 return tegra20_boot_secondary(cpu, idle);
146 * of the CPU since it should already be in reset. 160 if (IS_ENABLED(CONFIG_ARCH_TEGRA_3x_SOC) && tegra_chip_id == TEGRA30)
147 */ 161 return tegra30_boot_secondary(cpu, idle);
148 tegra_put_cpu_in_reset(cpu); 162 if (IS_ENABLED(CONFIG_ARCH_TEGRA_114_SOC) && tegra_chip_id == TEGRA114)
149 163 return tegra114_boot_secondary(cpu, idle);
150 /* 164
151 * Unhalt the CPU. If the flow controller was used to power-gate the 165 return -EINVAL;
152 * CPU this will cause the flow controller to stop driving reset.
153 * The CPU will remain in reset because the clock and reset block
154 * is now driving reset.
155 */
156 flowctrl_write_cpu_halt(cpu, 0);
157
158 switch (tegra_chip_id) {
159 case TEGRA20:
160 status = tegra20_power_up_cpu(cpu);
161 break;
162 case TEGRA30:
163 status = tegra30_power_up_cpu(cpu);
164 break;
165 default:
166 status = -EINVAL;
167 break;
168 }
169
170 if (status)
171 goto done;
172
173 /* Take the CPU out of reset. */
174 tegra_cpu_out_of_reset(cpu);
175done:
176 return status;
177} 166}
178 167
179static void __init tegra_smp_prepare_cpus(unsigned int max_cpus) 168static void __init tegra_smp_prepare_cpus(unsigned int max_cpus)
diff --git a/arch/arm/mach-tegra/pm.c b/arch/arm/mach-tegra/pm.c
index 523604de666f..d0b7400e4606 100644
--- a/arch/arm/mach-tegra/pm.c
+++ b/arch/arm/mach-tegra/pm.c
@@ -22,7 +22,7 @@
22#include <linux/cpumask.h> 22#include <linux/cpumask.h>
23#include <linux/delay.h> 23#include <linux/delay.h>
24#include <linux/cpu_pm.h> 24#include <linux/cpu_pm.h>
25#include <linux/clk.h> 25#include <linux/suspend.h>
26#include <linux/err.h> 26#include <linux/err.h>
27#include <linux/clk/tegra.h> 27#include <linux/clk/tegra.h>
28 28
@@ -37,67 +37,13 @@
37#include "reset.h" 37#include "reset.h"
38#include "flowctrl.h" 38#include "flowctrl.h"
39#include "fuse.h" 39#include "fuse.h"
40#include "pmc.h"
40#include "sleep.h" 41#include "sleep.h"
41 42
42#define TEGRA_POWER_CPU_PWRREQ_OE (1 << 16) /* CPU pwr req enable */
43
44#define PMC_CTRL 0x0
45#define PMC_CPUPWRGOOD_TIMER 0xc8
46#define PMC_CPUPWROFF_TIMER 0xcc
47
48#ifdef CONFIG_PM_SLEEP 43#ifdef CONFIG_PM_SLEEP
49static unsigned int g_diag_reg;
50static DEFINE_SPINLOCK(tegra_lp2_lock); 44static DEFINE_SPINLOCK(tegra_lp2_lock);
51static void __iomem *pmc = IO_ADDRESS(TEGRA_PMC_BASE);
52static struct clk *tegra_pclk;
53void (*tegra_tear_down_cpu)(void); 45void (*tegra_tear_down_cpu)(void);
54 46
55void save_cpu_arch_register(void)
56{
57 /* read diagnostic register */
58 asm("mrc p15, 0, %0, c15, c0, 1" : "=r"(g_diag_reg) : : "cc");
59 return;
60}
61
62void restore_cpu_arch_register(void)
63{
64 /* write diagnostic register */
65 asm("mcr p15, 0, %0, c15, c0, 1" : : "r"(g_diag_reg) : "cc");
66 return;
67}
68
69static void set_power_timers(unsigned long us_on, unsigned long us_off)
70{
71 unsigned long long ticks;
72 unsigned long long pclk;
73 unsigned long rate;
74 static unsigned long tegra_last_pclk;
75
76 if (tegra_pclk == NULL) {
77 tegra_pclk = clk_get_sys(NULL, "pclk");
78 WARN_ON(IS_ERR(tegra_pclk));
79 }
80
81 rate = clk_get_rate(tegra_pclk);
82
83 if (WARN_ON_ONCE(rate <= 0))
84 pclk = 100000000;
85 else
86 pclk = rate;
87
88 if ((rate != tegra_last_pclk)) {
89 ticks = (us_on * pclk) + 999999ull;
90 do_div(ticks, 1000000);
91 writel((unsigned long)ticks, pmc + PMC_CPUPWRGOOD_TIMER);
92
93 ticks = (us_off * pclk) + 999999ull;
94 do_div(ticks, 1000000);
95 writel((unsigned long)ticks, pmc + PMC_CPUPWROFF_TIMER);
96 wmb();
97 }
98 tegra_last_pclk = pclk;
99}
100
101/* 47/*
102 * restore_cpu_complex 48 * restore_cpu_complex
103 * 49 *
@@ -119,8 +65,6 @@ static void restore_cpu_complex(void)
119 tegra_cpu_clock_resume(); 65 tegra_cpu_clock_resume();
120 66
121 flowctrl_cpu_suspend_exit(cpu); 67 flowctrl_cpu_suspend_exit(cpu);
122
123 restore_cpu_arch_register();
124} 68}
125 69
126/* 70/*
@@ -145,8 +89,6 @@ static void suspend_cpu_complex(void)
145 tegra_cpu_clock_suspend(); 89 tegra_cpu_clock_suspend();
146 90
147 flowctrl_cpu_suspend_enter(cpu); 91 flowctrl_cpu_suspend_enter(cpu);
148
149 save_cpu_arch_register();
150} 92}
151 93
152void tegra_clear_cpu_in_lp2(int phy_cpu_id) 94void tegra_clear_cpu_in_lp2(int phy_cpu_id)
@@ -197,16 +139,9 @@ static int tegra_sleep_cpu(unsigned long v2p)
197 return 0; 139 return 0;
198} 140}
199 141
200void tegra_idle_lp2_last(u32 cpu_on_time, u32 cpu_off_time) 142void tegra_idle_lp2_last(void)
201{ 143{
202 u32 mode; 144 tegra_pmc_pm_set(TEGRA_SUSPEND_LP2);
203
204 /* Only the last cpu down does the final suspend steps */
205 mode = readl(pmc + PMC_CTRL);
206 mode |= TEGRA_POWER_CPU_PWRREQ_OE;
207 writel(mode, pmc + PMC_CTRL);
208
209 set_power_timers(cpu_on_time, cpu_off_time);
210 145
211 cpu_cluster_pm_enter(); 146 cpu_cluster_pm_enter();
212 suspend_cpu_complex(); 147 suspend_cpu_complex();
@@ -216,4 +151,81 @@ void tegra_idle_lp2_last(u32 cpu_on_time, u32 cpu_off_time)
216 restore_cpu_complex(); 151 restore_cpu_complex();
217 cpu_cluster_pm_exit(); 152 cpu_cluster_pm_exit();
218} 153}
154
155enum tegra_suspend_mode tegra_pm_validate_suspend_mode(
156 enum tegra_suspend_mode mode)
157{
158 /* Tegra114 didn't support any suspending mode yet. */
159 if (tegra_chip_id == TEGRA114)
160 return TEGRA_SUSPEND_NONE;
161
162 /*
163 * The Tegra devices only support suspending to LP2 currently.
164 */
165 if (mode > TEGRA_SUSPEND_LP2)
166 return TEGRA_SUSPEND_LP2;
167
168 return mode;
169}
170
171static const char *lp_state[TEGRA_MAX_SUSPEND_MODE] = {
172 [TEGRA_SUSPEND_NONE] = "none",
173 [TEGRA_SUSPEND_LP2] = "LP2",
174 [TEGRA_SUSPEND_LP1] = "LP1",
175 [TEGRA_SUSPEND_LP0] = "LP0",
176};
177
178static int __cpuinit tegra_suspend_enter(suspend_state_t state)
179{
180 enum tegra_suspend_mode mode = tegra_pmc_get_suspend_mode();
181
182 if (WARN_ON(mode < TEGRA_SUSPEND_NONE ||
183 mode >= TEGRA_MAX_SUSPEND_MODE))
184 return -EINVAL;
185
186 pr_info("Entering suspend state %s\n", lp_state[mode]);
187
188 tegra_pmc_pm_set(mode);
189
190 local_fiq_disable();
191
192 suspend_cpu_complex();
193 switch (mode) {
194 case TEGRA_SUSPEND_LP2:
195 tegra_set_cpu_in_lp2(0);
196 break;
197 default:
198 break;
199 }
200
201 cpu_suspend(PHYS_OFFSET - PAGE_OFFSET, &tegra_sleep_cpu);
202
203 switch (mode) {
204 case TEGRA_SUSPEND_LP2:
205 tegra_clear_cpu_in_lp2(0);
206 break;
207 default:
208 break;
209 }
210 restore_cpu_complex();
211
212 local_fiq_enable();
213
214 return 0;
215}
216
217static const struct platform_suspend_ops tegra_suspend_ops = {
218 .valid = suspend_valid_only_mem,
219 .enter = tegra_suspend_enter,
220};
221
222void __init tegra_init_suspend(void)
223{
224 if (tegra_pmc_get_suspend_mode() == TEGRA_SUSPEND_NONE)
225 return;
226
227 tegra_pmc_suspend_init();
228
229 suspend_set_ops(&tegra_suspend_ops);
230}
219#endif 231#endif
diff --git a/arch/arm/mach-tegra/pm.h b/arch/arm/mach-tegra/pm.h
index 787335cc964c..9d2d038bf12e 100644
--- a/arch/arm/mach-tegra/pm.h
+++ b/arch/arm/mach-tegra/pm.h
@@ -21,6 +21,8 @@
21#ifndef _MACH_TEGRA_PM_H_ 21#ifndef _MACH_TEGRA_PM_H_
22#define _MACH_TEGRA_PM_H_ 22#define _MACH_TEGRA_PM_H_
23 23
24#include "pmc.h"
25
24extern unsigned long l2x0_saved_regs_addr; 26extern unsigned long l2x0_saved_regs_addr;
25 27
26void save_cpu_arch_register(void); 28void save_cpu_arch_register(void);
@@ -29,7 +31,20 @@ void restore_cpu_arch_register(void);
29void tegra_clear_cpu_in_lp2(int phy_cpu_id); 31void tegra_clear_cpu_in_lp2(int phy_cpu_id);
30bool tegra_set_cpu_in_lp2(int phy_cpu_id); 32bool tegra_set_cpu_in_lp2(int phy_cpu_id);
31 33
32void tegra_idle_lp2_last(u32 cpu_on_time, u32 cpu_off_time); 34void tegra_idle_lp2_last(void);
33extern void (*tegra_tear_down_cpu)(void); 35extern void (*tegra_tear_down_cpu)(void);
34 36
37#ifdef CONFIG_PM_SLEEP
38enum tegra_suspend_mode tegra_pm_validate_suspend_mode(
39 enum tegra_suspend_mode mode);
40void tegra_init_suspend(void);
41#else
42enum tegra_suspend_mode tegra_pm_validate_suspend_mode(
43 enum tegra_suspend_mode mode)
44{
45 return TEGRA_SUSPEND_NONE;
46}
47static inline void tegra_init_suspend(void) {}
48#endif
49
35#endif /* _MACH_TEGRA_PM_H_ */ 50#endif /* _MACH_TEGRA_PM_H_ */
diff --git a/arch/arm/mach-tegra/pmc.c b/arch/arm/mach-tegra/pmc.c
index d4fdb5fcec20..32360e540ce6 100644
--- a/arch/arm/mach-tegra/pmc.c
+++ b/arch/arm/mach-tegra/pmc.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (C) 2012 NVIDIA CORPORATION. All rights reserved. 2 * Copyright (C) 2012,2013 NVIDIA CORPORATION. All rights reserved.
3 * 3 *
4 * This program is free software; you can redistribute it and/or modify it 4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License, 5 * under the terms and conditions of the GNU General Public License,
@@ -16,59 +16,313 @@
16 */ 16 */
17 17
18#include <linux/kernel.h> 18#include <linux/kernel.h>
19#include <linux/clk.h>
19#include <linux/io.h> 20#include <linux/io.h>
20#include <linux/of.h> 21#include <linux/of.h>
22#include <linux/of_address.h>
21 23
22#include "iomap.h" 24#include "fuse.h"
25#include "pm.h"
26#include "pmc.h"
27#include "sleep.h"
23 28
24#define PMC_CTRL 0x0 29#define TEGRA_POWER_EFFECT_LP0 (1 << 14) /* LP0 when CPU pwr gated */
25#define PMC_CTRL_INTR_LOW (1 << 17) 30#define TEGRA_POWER_CPU_PWRREQ_POLARITY (1 << 15) /* CPU pwr req polarity */
31#define TEGRA_POWER_CPU_PWRREQ_OE (1 << 16) /* CPU pwr req enable */
32
33#define PMC_CTRL 0x0
34#define PMC_CTRL_INTR_LOW (1 << 17)
35#define PMC_PWRGATE_TOGGLE 0x30
36#define PMC_PWRGATE_TOGGLE_START (1 << 8)
37#define PMC_REMOVE_CLAMPING 0x34
38#define PMC_PWRGATE_STATUS 0x38
39
40#define PMC_CPUPWRGOOD_TIMER 0xc8
41#define PMC_CPUPWROFF_TIMER 0xcc
42
43#define TEGRA_POWERGATE_PCIE 3
44#define TEGRA_POWERGATE_VDEC 4
45#define TEGRA_POWERGATE_CPU1 9
46#define TEGRA_POWERGATE_CPU2 10
47#define TEGRA_POWERGATE_CPU3 11
48
49static u8 tegra_cpu_domains[] = {
50 0xFF, /* not available for CPU0 */
51 TEGRA_POWERGATE_CPU1,
52 TEGRA_POWERGATE_CPU2,
53 TEGRA_POWERGATE_CPU3,
54};
55static DEFINE_SPINLOCK(tegra_powergate_lock);
56
57static void __iomem *tegra_pmc_base;
58static bool tegra_pmc_invert_interrupt;
59static struct clk *tegra_pclk;
60
61struct pmc_pm_data {
62 u32 cpu_good_time; /* CPU power good time in uS */
63 u32 cpu_off_time; /* CPU power off time in uS */
64 u32 core_osc_time; /* Core power good osc time in uS */
65 u32 core_pmu_time; /* Core power good pmu time in uS */
66 u32 core_off_time; /* Core power off time in uS */
67 bool corereq_high; /* Core power request active-high */
68 bool sysclkreq_high; /* System clock request active-high */
69 bool combined_req; /* Combined pwr req for CPU & Core */
70 bool cpu_pwr_good_en; /* CPU power good signal is enabled */
71 u32 lp0_vec_phy_addr; /* The phy addr of LP0 warm boot code */
72 u32 lp0_vec_size; /* The size of LP0 warm boot code */
73 enum tegra_suspend_mode suspend_mode;
74};
75static struct pmc_pm_data pmc_pm_data;
26 76
27static inline u32 tegra_pmc_readl(u32 reg) 77static inline u32 tegra_pmc_readl(u32 reg)
28{ 78{
29 return readl(IO_ADDRESS(TEGRA_PMC_BASE + reg)); 79 return readl(tegra_pmc_base + reg);
30} 80}
31 81
32static inline void tegra_pmc_writel(u32 val, u32 reg) 82static inline void tegra_pmc_writel(u32 val, u32 reg)
33{ 83{
34 writel(val, IO_ADDRESS(TEGRA_PMC_BASE + reg)); 84 writel(val, tegra_pmc_base + reg);
85}
86
87static int tegra_pmc_get_cpu_powerdomain_id(int cpuid)
88{
89 if (cpuid <= 0 || cpuid >= num_possible_cpus())
90 return -EINVAL;
91 return tegra_cpu_domains[cpuid];
92}
93
94static bool tegra_pmc_powergate_is_powered(int id)
95{
96 return (tegra_pmc_readl(PMC_PWRGATE_STATUS) >> id) & 1;
97}
98
99static int tegra_pmc_powergate_set(int id, bool new_state)
100{
101 bool old_state;
102 unsigned long flags;
103
104 spin_lock_irqsave(&tegra_powergate_lock, flags);
105
106 old_state = tegra_pmc_powergate_is_powered(id);
107 WARN_ON(old_state == new_state);
108
109 tegra_pmc_writel(PMC_PWRGATE_TOGGLE_START | id, PMC_PWRGATE_TOGGLE);
110
111 spin_unlock_irqrestore(&tegra_powergate_lock, flags);
112
113 return 0;
114}
115
116static int tegra_pmc_powergate_remove_clamping(int id)
117{
118 u32 mask;
119
120 /*
121 * Tegra has a bug where PCIE and VDE clamping masks are
122 * swapped relatively to the partition ids.
123 */
124 if (id == TEGRA_POWERGATE_VDEC)
125 mask = (1 << TEGRA_POWERGATE_PCIE);
126 else if (id == TEGRA_POWERGATE_PCIE)
127 mask = (1 << TEGRA_POWERGATE_VDEC);
128 else
129 mask = (1 << id);
130
131 tegra_pmc_writel(mask, PMC_REMOVE_CLAMPING);
132
133 return 0;
134}
135
136bool tegra_pmc_cpu_is_powered(int cpuid)
137{
138 int id;
139
140 id = tegra_pmc_get_cpu_powerdomain_id(cpuid);
141 if (id < 0)
142 return false;
143 return tegra_pmc_powergate_is_powered(id);
35} 144}
36 145
37#ifdef CONFIG_OF 146int tegra_pmc_cpu_power_on(int cpuid)
147{
148 int id;
149
150 id = tegra_pmc_get_cpu_powerdomain_id(cpuid);
151 if (id < 0)
152 return id;
153 return tegra_pmc_powergate_set(id, true);
154}
155
156int tegra_pmc_cpu_remove_clamping(int cpuid)
157{
158 int id;
159
160 id = tegra_pmc_get_cpu_powerdomain_id(cpuid);
161 if (id < 0)
162 return id;
163 return tegra_pmc_powergate_remove_clamping(id);
164}
165
166#ifdef CONFIG_PM_SLEEP
167static void set_power_timers(u32 us_on, u32 us_off, unsigned long rate)
168{
169 unsigned long long ticks;
170 unsigned long long pclk;
171 static unsigned long tegra_last_pclk;
172
173 if (WARN_ON_ONCE(rate <= 0))
174 pclk = 100000000;
175 else
176 pclk = rate;
177
178 if ((rate != tegra_last_pclk)) {
179 ticks = (us_on * pclk) + 999999ull;
180 do_div(ticks, 1000000);
181 tegra_pmc_writel((unsigned long)ticks, PMC_CPUPWRGOOD_TIMER);
182
183 ticks = (us_off * pclk) + 999999ull;
184 do_div(ticks, 1000000);
185 tegra_pmc_writel((unsigned long)ticks, PMC_CPUPWROFF_TIMER);
186 wmb();
187 }
188 tegra_last_pclk = pclk;
189}
190
191enum tegra_suspend_mode tegra_pmc_get_suspend_mode(void)
192{
193 return pmc_pm_data.suspend_mode;
194}
195
196void tegra_pmc_pm_set(enum tegra_suspend_mode mode)
197{
198 u32 reg;
199 unsigned long rate = 0;
200
201 reg = tegra_pmc_readl(PMC_CTRL);
202 reg |= TEGRA_POWER_CPU_PWRREQ_OE;
203 reg &= ~TEGRA_POWER_EFFECT_LP0;
204
205 switch (mode) {
206 case TEGRA_SUSPEND_LP2:
207 rate = clk_get_rate(tegra_pclk);
208 break;
209 default:
210 break;
211 }
212
213 set_power_timers(pmc_pm_data.cpu_good_time, pmc_pm_data.cpu_off_time,
214 rate);
215
216 tegra_pmc_writel(reg, PMC_CTRL);
217}
218
219void tegra_pmc_suspend_init(void)
220{
221 u32 reg;
222
223 /* Always enable CPU power request */
224 reg = tegra_pmc_readl(PMC_CTRL);
225 reg |= TEGRA_POWER_CPU_PWRREQ_OE;
226 tegra_pmc_writel(reg, PMC_CTRL);
227}
228#endif
229
38static const struct of_device_id matches[] __initconst = { 230static const struct of_device_id matches[] __initconst = {
231 { .compatible = "nvidia,tegra114-pmc" },
232 { .compatible = "nvidia,tegra30-pmc" },
39 { .compatible = "nvidia,tegra20-pmc" }, 233 { .compatible = "nvidia,tegra20-pmc" },
40 { } 234 { }
41}; 235};
42#endif
43 236
44void __init tegra_pmc_init(void) 237static void tegra_pmc_parse_dt(void)
45{ 238{
46 /* 239 struct device_node *np;
47 * For now, Harmony is the only board that uses the PMC, and it wants 240 u32 prop;
48 * the signal inverted. Seaboard would too if it used the PMC. 241 enum tegra_suspend_mode suspend_mode;
49 * Hopefully by the time other boards want to use the PMC, everything 242 u32 core_good_time[2] = {0, 0};
50 * will be device-tree, or they also want it inverted. 243 u32 lp0_vec[2] = {0, 0};
51 */
52 bool invert_interrupt = true;
53 u32 val;
54 244
55#ifdef CONFIG_OF 245 np = of_find_matching_node(NULL, matches);
56 if (of_have_populated_dt()) { 246 BUG_ON(!np);
57 struct device_node *np;
58 247
59 invert_interrupt = false; 248 tegra_pmc_base = of_iomap(np, 0);
60 249
61 np = of_find_matching_node(NULL, matches); 250 tegra_pmc_invert_interrupt = of_property_read_bool(np,
62 if (np) { 251 "nvidia,invert-interrupt");
63 if (of_find_property(np, "nvidia,invert-interrupt", 252 tegra_pclk = of_clk_get_by_name(np, "pclk");
64 NULL)) 253 WARN_ON(IS_ERR(tegra_pclk));
65 invert_interrupt = true; 254
255 /* Grabbing the power management configurations */
256 if (of_property_read_u32(np, "nvidia,suspend-mode", &prop)) {
257 suspend_mode = TEGRA_SUSPEND_NONE;
258 } else {
259 switch (prop) {
260 case 0:
261 suspend_mode = TEGRA_SUSPEND_LP0;
262 break;
263 case 1:
264 suspend_mode = TEGRA_SUSPEND_LP1;
265 break;
266 case 2:
267 suspend_mode = TEGRA_SUSPEND_LP2;
268 break;
269 default:
270 suspend_mode = TEGRA_SUSPEND_NONE;
271 break;
66 } 272 }
67 } 273 }
68#endif 274 suspend_mode = tegra_pm_validate_suspend_mode(suspend_mode);
275
276 if (of_property_read_u32(np, "nvidia,cpu-pwr-good-time", &prop))
277 suspend_mode = TEGRA_SUSPEND_NONE;
278 pmc_pm_data.cpu_good_time = prop;
279
280 if (of_property_read_u32(np, "nvidia,cpu-pwr-off-time", &prop))
281 suspend_mode = TEGRA_SUSPEND_NONE;
282 pmc_pm_data.cpu_off_time = prop;
283
284 if (of_property_read_u32_array(np, "nvidia,core-pwr-good-time",
285 core_good_time, ARRAY_SIZE(core_good_time)))
286 suspend_mode = TEGRA_SUSPEND_NONE;
287 pmc_pm_data.core_osc_time = core_good_time[0];
288 pmc_pm_data.core_pmu_time = core_good_time[1];
289
290 if (of_property_read_u32(np, "nvidia,core-pwr-off-time",
291 &prop))
292 suspend_mode = TEGRA_SUSPEND_NONE;
293 pmc_pm_data.core_off_time = prop;
294
295 pmc_pm_data.corereq_high = of_property_read_bool(np,
296 "nvidia,core-power-req-active-high");
297
298 pmc_pm_data.sysclkreq_high = of_property_read_bool(np,
299 "nvidia,sys-clock-req-active-high");
300
301 pmc_pm_data.combined_req = of_property_read_bool(np,
302 "nvidia,combined-power-req");
303
304 pmc_pm_data.cpu_pwr_good_en = of_property_read_bool(np,
305 "nvidia,cpu-pwr-good-en");
306
307 if (of_property_read_u32_array(np, "nvidia,lp0-vec", lp0_vec,
308 ARRAY_SIZE(lp0_vec)))
309 if (suspend_mode == TEGRA_SUSPEND_LP0)
310 suspend_mode = TEGRA_SUSPEND_LP1;
311
312 pmc_pm_data.lp0_vec_phy_addr = lp0_vec[0];
313 pmc_pm_data.lp0_vec_size = lp0_vec[1];
314
315 pmc_pm_data.suspend_mode = suspend_mode;
316}
317
318void __init tegra_pmc_init(void)
319{
320 u32 val;
321
322 tegra_pmc_parse_dt();
69 323
70 val = tegra_pmc_readl(PMC_CTRL); 324 val = tegra_pmc_readl(PMC_CTRL);
71 if (invert_interrupt) 325 if (tegra_pmc_invert_interrupt)
72 val |= PMC_CTRL_INTR_LOW; 326 val |= PMC_CTRL_INTR_LOW;
73 else 327 else
74 val &= ~PMC_CTRL_INTR_LOW; 328 val &= ~PMC_CTRL_INTR_LOW;
diff --git a/arch/arm/mach-tegra/pmc.h b/arch/arm/mach-tegra/pmc.h
index 8995ee4a8768..e1c2df272f7d 100644
--- a/arch/arm/mach-tegra/pmc.h
+++ b/arch/arm/mach-tegra/pmc.h
@@ -18,6 +18,24 @@
18#ifndef __MACH_TEGRA_PMC_H 18#ifndef __MACH_TEGRA_PMC_H
19#define __MACH_TEGRA_PMC_H 19#define __MACH_TEGRA_PMC_H
20 20
21enum tegra_suspend_mode {
22 TEGRA_SUSPEND_NONE = 0,
23 TEGRA_SUSPEND_LP2, /* CPU voltage off */
24 TEGRA_SUSPEND_LP1, /* CPU voltage off, DRAM self-refresh */
25 TEGRA_SUSPEND_LP0, /* CPU + core voltage off, DRAM self-refresh */
26 TEGRA_MAX_SUSPEND_MODE,
27};
28
29#ifdef CONFIG_PM_SLEEP
30enum tegra_suspend_mode tegra_pmc_get_suspend_mode(void);
31void tegra_pmc_pm_set(enum tegra_suspend_mode mode);
32void tegra_pmc_suspend_init(void);
33#endif
34
35bool tegra_pmc_cpu_is_powered(int cpuid);
36int tegra_pmc_cpu_power_on(int cpuid);
37int tegra_pmc_cpu_remove_clamping(int cpuid);
38
21void tegra_pmc_init(void); 39void tegra_pmc_init(void);
22 40
23#endif 41#endif
diff --git a/arch/arm/mach-tegra/reset-handler.S b/arch/arm/mach-tegra/reset-handler.S
index 54382ceade4a..1676aba5e7b8 100644
--- a/arch/arm/mach-tegra/reset-handler.S
+++ b/arch/arm/mach-tegra/reset-handler.S
@@ -41,9 +41,6 @@
41 */ 41 */
42ENTRY(tegra_resume) 42ENTRY(tegra_resume)
43 bl v7_invalidate_l1 43 bl v7_invalidate_l1
44 /* Enable coresight */
45 mov32 r0, 0xC5ACCE55
46 mcr p14, 0, r0, c7, c12, 6
47 44
48 cpu_id r0 45 cpu_id r0
49 cmp r0, #0 @ CPU0? 46 cmp r0, #0 @ CPU0?
@@ -99,6 +96,8 @@ ENTRY(__tegra_cpu_reset_handler_start)
99 * 96 *
100 * Register usage within the reset handler: 97 * Register usage within the reset handler:
101 * 98 *
99 * Others: scratch
100 * R6 = SoC ID << 8
102 * R7 = CPU present (to the OS) mask 101 * R7 = CPU present (to the OS) mask
103 * R8 = CPU in LP1 state mask 102 * R8 = CPU in LP1 state mask
104 * R9 = CPU in LP2 state mask 103 * R9 = CPU in LP2 state mask
@@ -114,6 +113,40 @@ ENTRY(__tegra_cpu_reset_handler_start)
114ENTRY(__tegra_cpu_reset_handler) 113ENTRY(__tegra_cpu_reset_handler)
115 114
116 cpsid aif, 0x13 @ SVC mode, interrupts disabled 115 cpsid aif, 0x13 @ SVC mode, interrupts disabled
116
117 mov32 r6, TEGRA_APB_MISC_BASE
118 ldr r6, [r6, #APB_MISC_GP_HIDREV]
119 and r6, r6, #0xff00
120#ifdef CONFIG_ARCH_TEGRA_2x_SOC
121t20_check:
122 cmp r6, #(0x20 << 8)
123 bne after_t20_check
124t20_errata:
125 # Tegra20 is a Cortex-A9 r1p1
126 mrc p15, 0, r0, c1, c0, 0 @ read system control register
127 orr r0, r0, #1 << 14 @ erratum 716044
128 mcr p15, 0, r0, c1, c0, 0 @ write system control register
129 mrc p15, 0, r0, c15, c0, 1 @ read diagnostic register
130 orr r0, r0, #1 << 4 @ erratum 742230
131 orr r0, r0, #1 << 11 @ erratum 751472
132 mcr p15, 0, r0, c15, c0, 1 @ write diagnostic register
133 b after_errata
134after_t20_check:
135#endif
136#ifdef CONFIG_ARCH_TEGRA_3x_SOC
137t30_check:
138 cmp r6, #(0x30 << 8)
139 bne after_t30_check
140t30_errata:
141 # Tegra30 is a Cortex-A9 r2p9
142 mrc p15, 0, r0, c15, c0, 1 @ read diagnostic register
143 orr r0, r0, #1 << 6 @ erratum 743622
144 orr r0, r0, #1 << 11 @ erratum 751472
145 mcr p15, 0, r0, c15, c0, 1 @ write diagnostic register
146 b after_errata
147after_t30_check:
148#endif
149after_errata:
117 mrc p15, 0, r10, c0, c0, 5 @ MPIDR 150 mrc p15, 0, r10, c0, c0, 5 @ MPIDR
118 and r10, r10, #0x3 @ R10 = CPU number 151 and r10, r10, #0x3 @ R10 = CPU number
119 mov r11, #1 152 mov r11, #1
@@ -129,16 +162,13 @@ ENTRY(__tegra_cpu_reset_handler)
129 162
130#ifdef CONFIG_ARCH_TEGRA_2x_SOC 163#ifdef CONFIG_ARCH_TEGRA_2x_SOC
131 /* Are we on Tegra20? */ 164 /* Are we on Tegra20? */
132 mov32 r6, TEGRA_APB_MISC_BASE 165 cmp r6, #(0x20 << 8)
133 ldr r0, [r6, #APB_MISC_GP_HIDREV]
134 and r0, r0, #0xff00
135 cmp r0, #(0x20 << 8)
136 bne 1f 166 bne 1f
137 /* If not CPU0, don't let CPU0 reset CPU1 now that CPU1 is coming up. */ 167 /* If not CPU0, don't let CPU0 reset CPU1 now that CPU1 is coming up. */
138 mov32 r6, TEGRA_PMC_BASE 168 mov32 r5, TEGRA_PMC_BASE
139 mov r0, #0 169 mov r0, #0
140 cmp r10, #0 170 cmp r10, #0
141 strne r0, [r6, #PMC_SCRATCH41] 171 strne r0, [r5, #PMC_SCRATCH41]
1421: 1721:
143#endif 173#endif
144 174
diff --git a/arch/arm/mach-tegra/sleep.h b/arch/arm/mach-tegra/sleep.h
index 4ffae541726e..970ebd5138b9 100644
--- a/arch/arm/mach-tegra/sleep.h
+++ b/arch/arm/mach-tegra/sleep.h
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (c) 2010-2012, NVIDIA Corporation. All rights reserved. 2 * Copyright (c) 2010-2013, NVIDIA Corporation. All rights reserved.
3 * 3 *
4 * This program is free software; you can redistribute it and/or modify it 4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License, 5 * under the terms and conditions of the GNU General Public License,
@@ -124,11 +124,11 @@ int tegra_sleep_cpu_finish(unsigned long);
124void tegra_disable_clean_inv_dcache(void); 124void tegra_disable_clean_inv_dcache(void);
125 125
126#ifdef CONFIG_HOTPLUG_CPU 126#ifdef CONFIG_HOTPLUG_CPU
127void tegra20_hotplug_init(void); 127void tegra20_hotplug_shutdown(void);
128void tegra30_hotplug_init(void); 128void tegra30_hotplug_shutdown(void);
129void tegra_hotplug_init(void);
129#else 130#else
130static inline void tegra20_hotplug_init(void) {} 131static inline void tegra_hotplug_init(void) {}
131static inline void tegra30_hotplug_init(void) {}
132#endif 132#endif
133 133
134void tegra20_cpu_shutdown(int cpu); 134void tegra20_cpu_shutdown(int cpu);
diff --git a/arch/arm/mach-tegra/board-dt-tegra20.c b/arch/arm/mach-tegra/tegra.c
index a0edf2510280..84deeab23ee7 100644
--- a/arch/arm/mach-tegra/board-dt-tegra20.c
+++ b/arch/arm/mach-tegra/tegra.c
@@ -1,6 +1,7 @@
1/* 1/*
2 * nVidia Tegra device tree board support 2 * NVIDIA Tegra SoC device tree board support
3 * 3 *
4 * Copyright (C) 2011, 2013, NVIDIA Corporation
4 * Copyright (C) 2010 Secret Lab Technologies, Ltd. 5 * Copyright (C) 2010 Secret Lab Technologies, Ltd.
5 * Copyright (C) 2010 Google, Inc. 6 * Copyright (C) 2010 Google, Inc.
6 * 7 *
@@ -32,6 +33,8 @@
32#include <linux/io.h> 33#include <linux/io.h>
33#include <linux/i2c.h> 34#include <linux/i2c.h>
34#include <linux/i2c-tegra.h> 35#include <linux/i2c-tegra.h>
36#include <linux/slab.h>
37#include <linux/sys_soc.h>
35#include <linux/usb/tegra_usb_phy.h> 38#include <linux/usb/tegra_usb_phy.h>
36 39
37#include <asm/mach-types.h> 40#include <asm/mach-types.h>
@@ -41,6 +44,7 @@
41 44
42#include "board.h" 45#include "board.h"
43#include "common.h" 46#include "common.h"
47#include "fuse.h"
44#include "iomap.h" 48#include "iomap.h"
45 49
46static struct tegra_ehci_platform_data tegra_ehci1_pdata = { 50static struct tegra_ehci_platform_data tegra_ehci1_pdata = {
@@ -79,12 +83,36 @@ static struct of_dev_auxdata tegra20_auxdata_lookup[] __initdata = {
79 83
80static void __init tegra_dt_init(void) 84static void __init tegra_dt_init(void)
81{ 85{
86 struct soc_device_attribute *soc_dev_attr;
87 struct soc_device *soc_dev;
88 struct device *parent = NULL;
89
90 soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
91 if (!soc_dev_attr)
92 goto out;
93
94 soc_dev_attr->family = kasprintf(GFP_KERNEL, "Tegra");
95 soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%d", tegra_revision);
96 soc_dev_attr->soc_id = kasprintf(GFP_KERNEL, "%d", tegra_chip_id);
97
98 soc_dev = soc_device_register(soc_dev_attr);
99 if (IS_ERR(soc_dev)) {
100 kfree(soc_dev_attr->family);
101 kfree(soc_dev_attr->revision);
102 kfree(soc_dev_attr->soc_id);
103 kfree(soc_dev_attr);
104 goto out;
105 }
106
107 parent = soc_device_to_device(soc_dev);
108
82 /* 109 /*
83 * Finished with the static registrations now; fill in the missing 110 * Finished with the static registrations now; fill in the missing
84 * devices 111 * devices
85 */ 112 */
113out:
86 of_platform_populate(NULL, of_default_bus_match_table, 114 of_platform_populate(NULL, of_default_bus_match_table,
87 tegra20_auxdata_lookup, NULL); 115 tegra20_auxdata_lookup, parent);
88} 116}
89 117
90static void __init trimslice_init(void) 118static void __init trimslice_init(void)
@@ -111,7 +139,8 @@ static void __init harmony_init(void)
111 139
112static void __init paz00_init(void) 140static void __init paz00_init(void)
113{ 141{
114 tegra_paz00_wifikill_init(); 142 if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC))
143 tegra_paz00_wifikill_init();
115} 144}
116 145
117static struct { 146static struct {
@@ -137,19 +166,21 @@ static void __init tegra_dt_init_late(void)
137 } 166 }
138} 167}
139 168
140static const char *tegra20_dt_board_compat[] = { 169static const char * const tegra_dt_board_compat[] = {
170 "nvidia,tegra114",
171 "nvidia,tegra30",
141 "nvidia,tegra20", 172 "nvidia,tegra20",
142 NULL 173 NULL
143}; 174};
144 175
145DT_MACHINE_START(TEGRA_DT, "nVidia Tegra20 (Flattened Device Tree)") 176DT_MACHINE_START(TEGRA_DT, "NVIDIA Tegra SoC (Flattened Device Tree)")
146 .map_io = tegra_map_common_io, 177 .map_io = tegra_map_common_io,
147 .smp = smp_ops(tegra_smp_ops), 178 .smp = smp_ops(tegra_smp_ops),
148 .init_early = tegra20_init_early, 179 .init_early = tegra_init_early,
149 .init_irq = tegra_dt_init_irq, 180 .init_irq = tegra_dt_init_irq,
150 .init_time = clocksource_of_init, 181 .init_time = clocksource_of_init,
151 .init_machine = tegra_dt_init, 182 .init_machine = tegra_dt_init,
152 .init_late = tegra_dt_init_late, 183 .init_late = tegra_dt_init_late,
153 .restart = tegra_assert_system_reset, 184 .restart = tegra_assert_system_reset,
154 .dt_compat = tegra20_dt_board_compat, 185 .dt_compat = tegra_dt_board_compat,
155MACHINE_END 186MACHINE_END
diff --git a/arch/arm/mach-tegra/tegra114_speedo.c b/arch/arm/mach-tegra/tegra114_speedo.c
new file mode 100644
index 000000000000..5218d4853cd3
--- /dev/null
+++ b/arch/arm/mach-tegra/tegra114_speedo.c
@@ -0,0 +1,104 @@
1/*
2 * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#include <linux/kernel.h>
18#include <linux/bug.h>
19
20#include "fuse.h"
21
22#define CORE_PROCESS_CORNERS_NUM 2
23#define CPU_PROCESS_CORNERS_NUM 2
24
25enum {
26 THRESHOLD_INDEX_0,
27 THRESHOLD_INDEX_1,
28 THRESHOLD_INDEX_COUNT,
29};
30
31static const u32 core_process_speedos[][CORE_PROCESS_CORNERS_NUM] = {
32 {1123, UINT_MAX},
33 {0, UINT_MAX},
34};
35
36static const u32 cpu_process_speedos[][CPU_PROCESS_CORNERS_NUM] = {
37 {1695, UINT_MAX},
38 {0, UINT_MAX},
39};
40
41static void rev_sku_to_speedo_ids(int rev, int sku, int *threshold)
42{
43 u32 tmp;
44
45 switch (sku) {
46 case 0x00:
47 case 0x10:
48 case 0x05:
49 case 0x06:
50 tegra_cpu_speedo_id = 1;
51 tegra_soc_speedo_id = 0;
52 *threshold = THRESHOLD_INDEX_0;
53 break;
54
55 case 0x03:
56 case 0x04:
57 tegra_cpu_speedo_id = 2;
58 tegra_soc_speedo_id = 1;
59 *threshold = THRESHOLD_INDEX_1;
60 break;
61
62 default:
63 pr_err("Tegra114 Unknown SKU %d\n", sku);
64 tegra_cpu_speedo_id = 0;
65 tegra_soc_speedo_id = 0;
66 *threshold = THRESHOLD_INDEX_0;
67 break;
68 }
69
70 if (rev == TEGRA_REVISION_A01) {
71 tmp = tegra_fuse_readl(0x270) << 1;
72 tmp |= tegra_fuse_readl(0x26c);
73 if (!tmp)
74 tegra_cpu_speedo_id = 0;
75 }
76}
77
78void tegra114_init_speedo_data(void)
79{
80 u32 cpu_speedo_val;
81 u32 core_speedo_val;
82 int threshold;
83 int i;
84
85 BUILD_BUG_ON(ARRAY_SIZE(cpu_process_speedos) !=
86 THRESHOLD_INDEX_COUNT);
87 BUILD_BUG_ON(ARRAY_SIZE(core_process_speedos) !=
88 THRESHOLD_INDEX_COUNT);
89
90 rev_sku_to_speedo_ids(tegra_revision, tegra_sku_id, &threshold);
91
92 cpu_speedo_val = tegra_fuse_readl(0x12c) + 1024;
93 core_speedo_val = tegra_fuse_readl(0x134);
94
95 for (i = 0; i < CPU_PROCESS_CORNERS_NUM; i++)
96 if (cpu_speedo_val < cpu_process_speedos[threshold][i])
97 break;
98 tegra_cpu_process_id = i;
99
100 for (i = 0; i < CORE_PROCESS_CORNERS_NUM; i++)
101 if (core_speedo_val < core_process_speedos[threshold][i])
102 break;
103 tegra_core_process_id = i;
104}
diff --git a/drivers/clk/tegra/clk-tegra20.c b/drivers/clk/tegra/clk-tegra20.c
index 1e2de7305362..b92d48be4cc9 100644
--- a/drivers/clk/tegra/clk-tegra20.c
+++ b/drivers/clk/tegra/clk-tegra20.c
@@ -711,8 +711,8 @@ static void tegra20_pll_init(void)
711} 711}
712 712
713static const char *cclk_parents[] = { "clk_m", "pll_c", "clk_32k", "pll_m", 713static const char *cclk_parents[] = { "clk_m", "pll_c", "clk_32k", "pll_m",
714 "pll_p_cclk", "pll_p_out4_cclk", 714 "pll_p", "pll_p_out4",
715 "pll_p_out3_cclk", "clk_d", "pll_x" }; 715 "pll_p_out3", "clk_d", "pll_x" };
716static const char *sclk_parents[] = { "clk_m", "pll_c_out1", "pll_p_out4", 716static const char *sclk_parents[] = { "clk_m", "pll_c_out1", "pll_p_out4",
717 "pll_p_out3", "pll_p_out2", "clk_d", 717 "pll_p_out3", "pll_p_out2", "clk_d",
718 "clk_32k", "pll_m_out1" }; 718 "clk_32k", "pll_m_out1" };
@@ -721,38 +721,6 @@ static void tegra20_super_clk_init(void)
721{ 721{
722 struct clk *clk; 722 struct clk *clk;
723 723
724 /*
725 * DIV_U71 dividers for CCLK, these dividers are used only
726 * if parent clock is fixed rate.
727 */
728
729 /*
730 * Clock input to cclk divided from pll_p using
731 * U71 divider of cclk.
732 */
733 clk = tegra_clk_register_divider("pll_p_cclk", "pll_p",
734 clk_base + SUPER_CCLK_DIVIDER, 0,
735 TEGRA_DIVIDER_INT, 16, 8, 1, NULL);
736 clk_register_clkdev(clk, "pll_p_cclk", NULL);
737
738 /*
739 * Clock input to cclk divided from pll_p_out3 using
740 * U71 divider of cclk.
741 */
742 clk = tegra_clk_register_divider("pll_p_out3_cclk", "pll_p_out3",
743 clk_base + SUPER_CCLK_DIVIDER, 0,
744 TEGRA_DIVIDER_INT, 16, 8, 1, NULL);
745 clk_register_clkdev(clk, "pll_p_out3_cclk", NULL);
746
747 /*
748 * Clock input to cclk divided from pll_p_out4 using
749 * U71 divider of cclk.
750 */
751 clk = tegra_clk_register_divider("pll_p_out4_cclk", "pll_p_out4",
752 clk_base + SUPER_CCLK_DIVIDER, 0,
753 TEGRA_DIVIDER_INT, 16, 8, 1, NULL);
754 clk_register_clkdev(clk, "pll_p_out4_cclk", NULL);
755
756 /* CCLK */ 724 /* CCLK */
757 clk = tegra_clk_register_super_mux("cclk", cclk_parents, 725 clk = tegra_clk_register_super_mux("cclk", cclk_parents,
758 ARRAY_SIZE(cclk_parents), CLK_SET_RATE_PARENT, 726 ARRAY_SIZE(cclk_parents), CLK_SET_RATE_PARENT,
diff --git a/drivers/clocksource/tegra20_timer.c b/drivers/clocksource/tegra20_timer.c
index 2e4d8a666c36..ae877b021b54 100644
--- a/drivers/clocksource/tegra20_timer.c
+++ b/drivers/clocksource/tegra20_timer.c
@@ -172,7 +172,7 @@ static void __init tegra20_init_timer(struct device_node *np)
172 BUG(); 172 BUG();
173 } 173 }
174 174
175 clk = clk_get_sys("timer", NULL); 175 clk = of_clk_get(np, 0);
176 if (IS_ERR(clk)) { 176 if (IS_ERR(clk)) {
177 pr_warn("Unable to get timer clock. Assuming 12Mhz input clock.\n"); 177 pr_warn("Unable to get timer clock. Assuming 12Mhz input clock.\n");
178 rate = 12000000; 178 rate = 12000000;
@@ -235,7 +235,7 @@ static void __init tegra20_init_rtc(struct device_node *np)
235 * rtc registers are used by read_persistent_clock, keep the rtc clock 235 * rtc registers are used by read_persistent_clock, keep the rtc clock
236 * enabled 236 * enabled
237 */ 237 */
238 clk = clk_get_sys("rtc-tegra", NULL); 238 clk = of_clk_get(np, 0);
239 if (IS_ERR(clk)) 239 if (IS_ERR(clk))
240 pr_warn("Unable to get rtc-tegra clock\n"); 240 pr_warn("Unable to get rtc-tegra clock\n");
241 else 241 else
diff --git a/drivers/gpio/gpio-tegra.c b/drivers/gpio/gpio-tegra.c
index 414ad912232f..e3956359202c 100644
--- a/drivers/gpio/gpio-tegra.c
+++ b/drivers/gpio/gpio-tegra.c
@@ -72,6 +72,7 @@ struct tegra_gpio_bank {
72 u32 oe[4]; 72 u32 oe[4];
73 u32 int_enb[4]; 73 u32 int_enb[4];
74 u32 int_lvl[4]; 74 u32 int_lvl[4];
75 u32 wake_enb[4];
75#endif 76#endif
76}; 77};
77 78
@@ -333,15 +334,31 @@ static int tegra_gpio_suspend(struct device *dev)
333 bank->oe[p] = tegra_gpio_readl(GPIO_OE(gpio)); 334 bank->oe[p] = tegra_gpio_readl(GPIO_OE(gpio));
334 bank->int_enb[p] = tegra_gpio_readl(GPIO_INT_ENB(gpio)); 335 bank->int_enb[p] = tegra_gpio_readl(GPIO_INT_ENB(gpio));
335 bank->int_lvl[p] = tegra_gpio_readl(GPIO_INT_LVL(gpio)); 336 bank->int_lvl[p] = tegra_gpio_readl(GPIO_INT_LVL(gpio));
337
338 /* Enable gpio irq for wake up source */
339 tegra_gpio_writel(bank->wake_enb[p],
340 GPIO_INT_ENB(gpio));
336 } 341 }
337 } 342 }
338 local_irq_restore(flags); 343 local_irq_restore(flags);
339 return 0; 344 return 0;
340} 345}
341 346
342static int tegra_gpio_wake_enable(struct irq_data *d, unsigned int enable) 347static int tegra_gpio_irq_set_wake(struct irq_data *d, unsigned int enable)
343{ 348{
344 struct tegra_gpio_bank *bank = irq_data_get_irq_chip_data(d); 349 struct tegra_gpio_bank *bank = irq_data_get_irq_chip_data(d);
350 int gpio = d->hwirq;
351 u32 port, bit, mask;
352
353 port = GPIO_PORT(gpio);
354 bit = GPIO_BIT(gpio);
355 mask = BIT(bit);
356
357 if (enable)
358 bank->wake_enb[port] |= mask;
359 else
360 bank->wake_enb[port] &= ~mask;
361
345 return irq_set_irq_wake(bank->irq, enable); 362 return irq_set_irq_wake(bank->irq, enable);
346} 363}
347#endif 364#endif
@@ -353,7 +370,7 @@ static struct irq_chip tegra_gpio_irq_chip = {
353 .irq_unmask = tegra_gpio_irq_unmask, 370 .irq_unmask = tegra_gpio_irq_unmask,
354 .irq_set_type = tegra_gpio_irq_set_type, 371 .irq_set_type = tegra_gpio_irq_set_type,
355#ifdef CONFIG_PM_SLEEP 372#ifdef CONFIG_PM_SLEEP
356 .irq_set_wake = tegra_gpio_wake_enable, 373 .irq_set_wake = tegra_gpio_irq_set_wake,
357#endif 374#endif
358}; 375};
359 376