aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm
diff options
context:
space:
mode:
authorStephen Warren <swarren@nvidia.com>2013-04-04 18:08:06 -0400
committerStephen Warren <swarren@nvidia.com>2013-04-04 18:08:06 -0400
commit8aa15d82df291b398d604b527a20310f10c1c706 (patch)
tree2e72fa6d6cdcb62c63f31bbd0f15a28909db7625 /arch/arm
parent8bb9660418e05bb1845ac1a2428444d78e322cc7 (diff)
parent4d82d0587b4a964ea3a7c73aa044b433000527dd (diff)
Merge branch 'for-3.10/soc' into for-3.10/clk
Diffstat (limited to 'arch/arm')
-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.c151
-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
39 files changed, 956 insertions, 366 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 13b739469c51..0f7bbe7696f0 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 48d00a099ce3..0dad7007bd49 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 9d87a3ffe998..9d7869f7151f 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 3cdc1bb8254c..d195db09ea32 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..84d8742bdb1e 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,14 @@
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#include "pmc.h"
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 43
48#ifdef CONFIG_PM_SLEEP 44#ifdef CONFIG_PM_SLEEP
49static unsigned int g_diag_reg;
50static DEFINE_SPINLOCK(tegra_lp2_lock); 45static 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); 46void (*tegra_tear_down_cpu)(void);
54 47
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/* 48/*
102 * restore_cpu_complex 49 * restore_cpu_complex
103 * 50 *
@@ -119,8 +66,6 @@ static void restore_cpu_complex(void)
119 tegra_cpu_clock_resume(); 66 tegra_cpu_clock_resume();
120 67
121 flowctrl_cpu_suspend_exit(cpu); 68 flowctrl_cpu_suspend_exit(cpu);
122
123 restore_cpu_arch_register();
124} 69}
125 70
126/* 71/*
@@ -145,8 +90,6 @@ static void suspend_cpu_complex(void)
145 tegra_cpu_clock_suspend(); 90 tegra_cpu_clock_suspend();
146 91
147 flowctrl_cpu_suspend_enter(cpu); 92 flowctrl_cpu_suspend_enter(cpu);
148
149 save_cpu_arch_register();
150} 93}
151 94
152void tegra_clear_cpu_in_lp2(int phy_cpu_id) 95void tegra_clear_cpu_in_lp2(int phy_cpu_id)
@@ -197,16 +140,9 @@ static int tegra_sleep_cpu(unsigned long v2p)
197 return 0; 140 return 0;
198} 141}
199 142
200void tegra_idle_lp2_last(u32 cpu_on_time, u32 cpu_off_time) 143void tegra_idle_lp2_last(void)
201{ 144{
202 u32 mode; 145 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 146
211 cpu_cluster_pm_enter(); 147 cpu_cluster_pm_enter();
212 suspend_cpu_complex(); 148 suspend_cpu_complex();
@@ -216,4 +152,81 @@ void tegra_idle_lp2_last(u32 cpu_on_time, u32 cpu_off_time)
216 restore_cpu_complex(); 152 restore_cpu_complex();
217 cpu_cluster_pm_exit(); 153 cpu_cluster_pm_exit();
218} 154}
155
156enum tegra_suspend_mode tegra_pm_validate_suspend_mode(
157 enum tegra_suspend_mode mode)
158{
159 /* Tegra114 didn't support any suspending mode yet. */
160 if (tegra_chip_id == TEGRA114)
161 return TEGRA_SUSPEND_NONE;
162
163 /*
164 * The Tegra devices only support suspending to LP2 currently.
165 */
166 if (mode > TEGRA_SUSPEND_LP2)
167 return TEGRA_SUSPEND_LP2;
168
169 return mode;
170}
171
172static const char *lp_state[TEGRA_MAX_SUSPEND_MODE] = {
173 [TEGRA_SUSPEND_NONE] = "none",
174 [TEGRA_SUSPEND_LP2] = "LP2",
175 [TEGRA_SUSPEND_LP1] = "LP1",
176 [TEGRA_SUSPEND_LP0] = "LP0",
177};
178
179static int __cpuinit tegra_suspend_enter(suspend_state_t state)
180{
181 enum tegra_suspend_mode mode = tegra_pmc_get_suspend_mode();
182
183 if (WARN_ON(mode < TEGRA_SUSPEND_NONE ||
184 mode >= TEGRA_MAX_SUSPEND_MODE))
185 return -EINVAL;
186
187 pr_info("Entering suspend state %s\n", lp_state[mode]);
188
189 tegra_pmc_pm_set(mode);
190
191 local_fiq_disable();
192
193 suspend_cpu_complex();
194 switch (mode) {
195 case TEGRA_SUSPEND_LP2:
196 tegra_set_cpu_in_lp2(0);
197 break;
198 default:
199 break;
200 }
201
202 cpu_suspend(PHYS_OFFSET - PAGE_OFFSET, &tegra_sleep_cpu);
203
204 switch (mode) {
205 case TEGRA_SUSPEND_LP2:
206 tegra_clear_cpu_in_lp2(0);
207 break;
208 default:
209 break;
210 }
211 restore_cpu_complex();
212
213 local_fiq_enable();
214
215 return 0;
216}
217
218static const struct platform_suspend_ops tegra_suspend_ops = {
219 .valid = suspend_valid_only_mem,
220 .enter = tegra_suspend_enter,
221};
222
223void __init tegra_init_suspend(void)
224{
225 if (tegra_pmc_get_suspend_mode() == TEGRA_SUSPEND_NONE)
226 return;
227
228 tegra_pmc_suspend_init();
229
230 suspend_set_ops(&tegra_suspend_ops);
231}
219#endif 232#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}