aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm')
-rw-r--r--arch/arm/boot/dts/tegra-harmony.dts45
-rw-r--r--arch/arm/boot/dts/tegra-paz00.dts30
-rw-r--r--arch/arm/boot/dts/tegra-seaboard.dts78
-rw-r--r--arch/arm/boot/dts/tegra-trimslice.dts12
-rw-r--r--arch/arm/boot/dts/tegra-ventana.dts42
-rw-r--r--arch/arm/boot/dts/tegra20.dtsi43
-rw-r--r--arch/arm/boot/dts/tegra30.dtsi53
-rw-r--r--arch/arm/mach-tegra/Makefile3
-rw-r--r--arch/arm/mach-tegra/apbio.c145
-rw-r--r--arch/arm/mach-tegra/apbio.h39
-rw-r--r--arch/arm/mach-tegra/board-harmony-power.c15
-rw-r--r--arch/arm/mach-tegra/board-harmony.c2
-rw-r--r--arch/arm/mach-tegra/board-seaboard.c5
-rw-r--r--arch/arm/mach-tegra/common.c20
-rw-r--r--arch/arm/mach-tegra/dma.c128
-rw-r--r--arch/arm/mach-tegra/fuse.c107
-rw-r--r--arch/arm/mach-tegra/fuse.h34
-rw-r--r--arch/arm/mach-tegra/include/mach/debug-macro.S88
-rw-r--r--arch/arm/mach-tegra/include/mach/gpio-tegra.h2
-rw-r--r--arch/arm/mach-tegra/include/mach/irammap.h35
-rw-r--r--arch/arm/mach-tegra/include/mach/uncompress.h118
-rw-r--r--arch/arm/mach-tegra/pmc.c76
-rw-r--r--arch/arm/mach-tegra/pmc.h23
-rw-r--r--arch/arm/mach-tegra/tegra2_clocks.c2
-rw-r--r--arch/arm/mach-tegra/tegra2_emc.c224
-rw-r--r--arch/arm/mach-tegra/tegra2_emc.h11
26 files changed, 1202 insertions, 178 deletions
diff --git a/arch/arm/boot/dts/tegra-harmony.dts b/arch/arm/boot/dts/tegra-harmony.dts
index 80afa1b70b80..6e8447dc0202 100644
--- a/arch/arm/boot/dts/tegra-harmony.dts
+++ b/arch/arm/boot/dts/tegra-harmony.dts
@@ -10,19 +10,25 @@
10 reg = < 0x00000000 0x40000000 >; 10 reg = < 0x00000000 0x40000000 >;
11 }; 11 };
12 12
13 pmc@7000f400 {
14 nvidia,invert-interrupt;
15 };
16
13 i2c@7000c000 { 17 i2c@7000c000 {
14 clock-frequency = <400000>; 18 clock-frequency = <400000>;
15 19
16 codec: wm8903@1a { 20 wm8903: wm8903@1a {
17 compatible = "wlf,wm8903"; 21 compatible = "wlf,wm8903";
18 reg = <0x1a>; 22 reg = <0x1a>;
19 interrupts = < 347 >; 23 interrupt-parent = <&gpio>;
24 interrupts = < 187 0x04 >;
20 25
21 gpio-controller; 26 gpio-controller;
22 #gpio-cells = <2>; 27 #gpio-cells = <2>;
23 28
24 /* 0x8000 = Not configured */ 29 micdet-cfg = <0>;
25 gpio-cfg = < 0x8000 0x8000 0 0x8000 0x8000 >; 30 micdet-delay = <100>;
31 gpio-cfg = < 0xffffffff 0xffffffff 0 0xffffffff 0xffffffff >;
26 }; 32 };
27 }; 33 };
28 34
@@ -38,13 +44,32 @@
38 clock-frequency = <400000>; 44 clock-frequency = <400000>;
39 }; 45 };
40 46
41 sound { 47 i2s@70002a00 {
42 compatible = "nvidia,harmony-sound", "nvidia,tegra-wm8903"; 48 status = "disable";
49 };
43 50
44 spkr-en-gpios = <&codec 2 0>; 51 sound {
45 hp-det-gpios = <&gpio 178 0>; 52 compatible = "nvidia,tegra-audio-wm8903-harmony",
46 int-mic-en-gpios = <&gpio 184 0>; 53 "nvidia,tegra-audio-wm8903";
47 ext-mic-en-gpios = <&gpio 185 0>; 54 nvidia,model = "NVIDIA Tegra Harmony";
55
56 nvidia,audio-routing =
57 "Headphone Jack", "HPOUTR",
58 "Headphone Jack", "HPOUTL",
59 "Int Spk", "ROP",
60 "Int Spk", "RON",
61 "Int Spk", "LOP",
62 "Int Spk", "LON",
63 "Mic Jack", "MICBIAS",
64 "IN1L", "Mic Jack";
65
66 nvidia,i2s-controller = <&tegra_i2s1>;
67 nvidia,audio-codec = <&wm8903>;
68
69 nvidia,spkr-en-gpios = <&wm8903 2 0>;
70 nvidia,hp-det-gpios = <&gpio 178 0>; /* gpio PW2 */
71 nvidia,int-mic-en-gpios = <&gpio 184 0>; /*gpio PX0 */
72 nvidia,ext-mic-en-gpios = <&gpio 185 0>; /* gpio PX1 */
48 }; 73 };
49 74
50 serial@70006000 { 75 serial@70006000 {
diff --git a/arch/arm/boot/dts/tegra-paz00.dts b/arch/arm/boot/dts/tegra-paz00.dts
index 825d2957da0b..e4b552b46fe2 100644
--- a/arch/arm/boot/dts/tegra-paz00.dts
+++ b/arch/arm/boot/dts/tegra-paz00.dts
@@ -12,6 +12,13 @@
12 12
13 i2c@7000c000 { 13 i2c@7000c000 {
14 clock-frequency = <400000>; 14 clock-frequency = <400000>;
15
16 alc5632: alc5632@1e {
17 compatible = "realtek,alc5632";
18 reg = <0x1e>;
19 gpio-controller;
20 #gpio-cells = <2>;
21 };
15 }; 22 };
16 23
17 i2c@7000c400 { 24 i2c@7000c400 {
@@ -37,6 +44,29 @@
37 clock-frequency = <400000>; 44 clock-frequency = <400000>;
38 }; 45 };
39 46
47 i2s@70002a00 {
48 status = "disable";
49 };
50
51 sound {
52 compatible = "nvidia,tegra-audio-alc5632-paz00",
53 "nvidia,tegra-audio-alc5632";
54
55 nvidia,model = "Compal PAZ00";
56
57 nvidia,audio-routing =
58 "Int Spk", "SPKOUT",
59 "Int Spk", "SPKOUTN",
60 "Headset Mic", "MICBIAS1",
61 "MIC1", "Headset Mic",
62 "Headset Stereophone", "HPR",
63 "Headset Stereophone", "HPL";
64
65 nvidia,audio-codec = <&alc5632>;
66 nvidia,i2s-controller = <&tegra_i2s1>;
67 nvidia,hp-det-gpios = <&gpio 178 0>; /* gpio PW2 */
68 };
69
40 serial@70006000 { 70 serial@70006000 {
41 clock-frequency = <216000000>; 71 clock-frequency = <216000000>;
42 }; 72 };
diff --git a/arch/arm/boot/dts/tegra-seaboard.dts b/arch/arm/boot/dts/tegra-seaboard.dts
index b55a02e34ba7..876d5c92ce36 100644
--- a/arch/arm/boot/dts/tegra-seaboard.dts
+++ b/arch/arm/boot/dts/tegra-seaboard.dts
@@ -13,6 +13,20 @@
13 13
14 i2c@7000c000 { 14 i2c@7000c000 {
15 clock-frequency = <400000>; 15 clock-frequency = <400000>;
16
17 wm8903: wm8903@1a {
18 compatible = "wlf,wm8903";
19 reg = <0x1a>;
20 interrupt-parent = <&gpio>;
21 interrupts = < 187 0x04 >;
22
23 gpio-controller;
24 #gpio-cells = <2>;
25
26 micdet-cfg = <0>;
27 micdet-delay = <100>;
28 gpio-cfg = < 0xffffffff 0xffffffff 0 0xffffffff 0xffffffff >;
29 };
16 }; 30 };
17 31
18 i2c@7000c400 { 32 i2c@7000c400 {
@@ -32,6 +46,32 @@
32 }; 46 };
33 }; 47 };
34 48
49 i2s@70002a00 {
50 status = "disable";
51 };
52
53 sound {
54 compatible = "nvidia,tegra-audio-wm8903-seaboard",
55 "nvidia,tegra-audio-wm8903";
56 nvidia,model = "NVIDIA Tegra Seaboard";
57
58 nvidia,audio-routing =
59 "Headphone Jack", "HPOUTR",
60 "Headphone Jack", "HPOUTL",
61 "Int Spk", "ROP",
62 "Int Spk", "RON",
63 "Int Spk", "LOP",
64 "Int Spk", "LON",
65 "Mic Jack", "MICBIAS",
66 "IN1R", "Mic Jack";
67
68 nvidia,i2s-controller = <&tegra_i2s1>;
69 nvidia,audio-codec = <&wm8903>;
70
71 nvidia,spkr-en-gpios = <&wm8903 2 0>;
72 nvidia,hp-det-gpios = <&gpio 185 0>; /* gpio PX1 */
73 };
74
35 serial@70006000 { 75 serial@70006000 {
36 status = "disable"; 76 status = "disable";
37 }; 77 };
@@ -93,4 +133,42 @@
93 gpio-key,wakeup; 133 gpio-key,wakeup;
94 }; 134 };
95 }; 135 };
136
137 emc@7000f400 {
138 emc-table@190000 {
139 reg = < 190000 >;
140 compatible = "nvidia,tegra20-emc-table";
141 clock-frequency = < 190000 >;
142 nvidia,emc-registers = < 0x0000000c 0x00000026
143 0x00000009 0x00000003 0x00000004 0x00000004
144 0x00000002 0x0000000c 0x00000003 0x00000003
145 0x00000002 0x00000001 0x00000004 0x00000005
146 0x00000004 0x00000009 0x0000000d 0x0000059f
147 0x00000000 0x00000003 0x00000003 0x00000003
148 0x00000003 0x00000001 0x0000000b 0x000000c8
149 0x00000003 0x00000007 0x00000004 0x0000000f
150 0x00000002 0x00000000 0x00000000 0x00000002
151 0x00000000 0x00000000 0x00000083 0xa06204ae
152 0x007dc010 0x00000000 0x00000000 0x00000000
153 0x00000000 0x00000000 0x00000000 0x00000000 >;
154 };
155
156 emc-table@380000 {
157 reg = < 380000 >;
158 compatible = "nvidia,tegra20-emc-table";
159 clock-frequency = < 380000 >;
160 nvidia,emc-registers = < 0x00000017 0x0000004b
161 0x00000012 0x00000006 0x00000004 0x00000005
162 0x00000003 0x0000000c 0x00000006 0x00000006
163 0x00000003 0x00000001 0x00000004 0x00000005
164 0x00000004 0x00000009 0x0000000d 0x00000b5f
165 0x00000000 0x00000003 0x00000003 0x00000006
166 0x00000006 0x00000001 0x00000011 0x000000c8
167 0x00000003 0x0000000e 0x00000007 0x0000000f
168 0x00000002 0x00000000 0x00000000 0x00000002
169 0x00000000 0x00000000 0x00000083 0xe044048b
170 0x007d8010 0x00000000 0x00000000 0x00000000
171 0x00000000 0x00000000 0x00000000 0x00000000 >;
172 };
173 };
96}; 174};
diff --git a/arch/arm/boot/dts/tegra-trimslice.dts b/arch/arm/boot/dts/tegra-trimslice.dts
index 3b3ee7db99f3..252476867b54 100644
--- a/arch/arm/boot/dts/tegra-trimslice.dts
+++ b/arch/arm/boot/dts/tegra-trimslice.dts
@@ -26,6 +26,18 @@
26 status = "disable"; 26 status = "disable";
27 }; 27 };
28 28
29 i2s@70002800 {
30 status = "disable";
31 };
32
33 i2s@70002a00 {
34 status = "disable";
35 };
36
37 das@70000c00 {
38 status = "disable";
39 };
40
29 serial@70006000 { 41 serial@70006000 {
30 clock-frequency = < 216000000 >; 42 clock-frequency = < 216000000 >;
31 }; 43 };
diff --git a/arch/arm/boot/dts/tegra-ventana.dts b/arch/arm/boot/dts/tegra-ventana.dts
index c7d3b87f29df..2dcff8728e90 100644
--- a/arch/arm/boot/dts/tegra-ventana.dts
+++ b/arch/arm/boot/dts/tegra-ventana.dts
@@ -12,6 +12,20 @@
12 12
13 i2c@7000c000 { 13 i2c@7000c000 {
14 clock-frequency = <400000>; 14 clock-frequency = <400000>;
15
16 wm8903: wm8903@1a {
17 compatible = "wlf,wm8903";
18 reg = <0x1a>;
19 interrupt-parent = <&gpio>;
20 interrupts = < 187 0x04 >;
21
22 gpio-controller;
23 #gpio-cells = <2>;
24
25 micdet-cfg = <0>;
26 micdet-delay = <100>;
27 gpio-cfg = < 0xffffffff 0xffffffff 0 0xffffffff 0xffffffff >;
28 };
15 }; 29 };
16 30
17 i2c@7000c400 { 31 i2c@7000c400 {
@@ -26,6 +40,34 @@
26 clock-frequency = <400000>; 40 clock-frequency = <400000>;
27 }; 41 };
28 42
43 i2s@70002a00 {
44 status = "disable";
45 };
46
47 sound {
48 compatible = "nvidia,tegra-audio-wm8903-ventana",
49 "nvidia,tegra-audio-wm8903";
50 nvidia,model = "NVIDIA Tegra Ventana";
51
52 nvidia,audio-routing =
53 "Headphone Jack", "HPOUTR",
54 "Headphone Jack", "HPOUTL",
55 "Int Spk", "ROP",
56 "Int Spk", "RON",
57 "Int Spk", "LOP",
58 "Int Spk", "LON",
59 "Mic Jack", "MICBIAS",
60 "IN1L", "Mic Jack";
61
62 nvidia,i2s-controller = <&tegra_i2s1>;
63 nvidia,audio-codec = <&wm8903>;
64
65 nvidia,spkr-en-gpios = <&wm8903 2 0>;
66 nvidia,hp-det-gpios = <&gpio 178 0>; /* gpio PW2 */
67 nvidia,int-mic-en-gpios = <&gpio 184 0>; /*gpio PX0 */
68 nvidia,ext-mic-en-gpios = <&gpio 185 0>; /* gpio PX1 */
69 };
70
29 serial@70006000 { 71 serial@70006000 {
30 status = "disable"; 72 status = "disable";
31 }; 73 };
diff --git a/arch/arm/boot/dts/tegra20.dtsi b/arch/arm/boot/dts/tegra20.dtsi
index 3da7afd45322..ec1f0101c79c 100644
--- a/arch/arm/boot/dts/tegra20.dtsi
+++ b/arch/arm/boot/dts/tegra20.dtsi
@@ -4,6 +4,11 @@
4 compatible = "nvidia,tegra20"; 4 compatible = "nvidia,tegra20";
5 interrupt-parent = <&intc>; 5 interrupt-parent = <&intc>;
6 6
7 pmc@7000f400 {
8 compatible = "nvidia,tegra20-pmc";
9 reg = <0x7000e400 0x400>;
10 };
11
7 intc: interrupt-controller@50041000 { 12 intc: interrupt-controller@50041000 {
8 compatible = "arm,cortex-a9-gic"; 13 compatible = "arm,cortex-a9-gic";
9 interrupt-controller; 14 interrupt-controller;
@@ -12,6 +17,27 @@
12 < 0x50040100 0x0100 >; 17 < 0x50040100 0x0100 >;
13 }; 18 };
14 19
20 apbdma: dma@6000a000 {
21 compatible = "nvidia,tegra20-apbdma";
22 reg = <0x6000a000 0x1200>;
23 interrupts = < 0 104 0x04
24 0 105 0x04
25 0 106 0x04
26 0 107 0x04
27 0 108 0x04
28 0 109 0x04
29 0 110 0x04
30 0 111 0x04
31 0 112 0x04
32 0 113 0x04
33 0 114 0x04
34 0 115 0x04
35 0 116 0x04
36 0 117 0x04
37 0 118 0x04
38 0 119 0x04 >;
39 };
40
15 i2c@7000c000 { 41 i2c@7000c000 {
16 #address-cells = <1>; 42 #address-cells = <1>;
17 #size-cells = <0>; 43 #size-cells = <0>;
@@ -44,18 +70,18 @@
44 interrupts = < 0 53 0x04 >; 70 interrupts = < 0 53 0x04 >;
45 }; 71 };
46 72
47 i2s@70002800 { 73 tegra_i2s1: i2s@70002800 {
48 compatible = "nvidia,tegra20-i2s"; 74 compatible = "nvidia,tegra20-i2s";
49 reg = <0x70002800 0x200>; 75 reg = <0x70002800 0x200>;
50 interrupts = < 0 13 0x04 >; 76 interrupts = < 0 13 0x04 >;
51 dma-channel = < 2 >; 77 nvidia,dma-request-selector = < &apbdma 2 >;
52 }; 78 };
53 79
54 i2s@70002a00 { 80 tegra_i2s2: i2s@70002a00 {
55 compatible = "nvidia,tegra20-i2s"; 81 compatible = "nvidia,tegra20-i2s";
56 reg = <0x70002a00 0x200>; 82 reg = <0x70002a00 0x200>;
57 interrupts = < 0 3 0x04 >; 83 interrupts = < 0 3 0x04 >;
58 dma-channel = < 1 >; 84 nvidia,dma-request-selector = < &apbdma 1 >;
59 }; 85 };
60 86
61 das@70000c00 { 87 das@70000c00 {
@@ -75,6 +101,8 @@
75 0 89 0x04 >; 101 0 89 0x04 >;
76 #gpio-cells = <2>; 102 #gpio-cells = <2>;
77 gpio-controller; 103 gpio-controller;
104 #interrupt-cells = <2>;
105 interrupt-controller;
78 }; 106 };
79 107
80 pinmux: pinmux@70000000 { 108 pinmux: pinmux@70000000 {
@@ -120,6 +148,13 @@
120 interrupts = < 0 91 0x04 >; 148 interrupts = < 0 91 0x04 >;
121 }; 149 };
122 150
151 emc@7000f400 {
152 #address-cells = <1>;
153 #size-cells = <0>;
154 compatible = "nvidia,tegra20-emc";
155 reg = <0x7000f400 0x200>;
156 };
157
123 sdhci@c8000000 { 158 sdhci@c8000000 {
124 compatible = "nvidia,tegra20-sdhci"; 159 compatible = "nvidia,tegra20-sdhci";
125 reg = <0xc8000000 0x200>; 160 reg = <0xc8000000 0x200>;
diff --git a/arch/arm/boot/dts/tegra30.dtsi b/arch/arm/boot/dts/tegra30.dtsi
index ee7db9892e02..ac4b75cb26c0 100644
--- a/arch/arm/boot/dts/tegra30.dtsi
+++ b/arch/arm/boot/dts/tegra30.dtsi
@@ -4,6 +4,11 @@
4 compatible = "nvidia,tegra30"; 4 compatible = "nvidia,tegra30";
5 interrupt-parent = <&intc>; 5 interrupt-parent = <&intc>;
6 6
7 pmc@7000f400 {
8 compatible = "nvidia,tegra20-pmc", "nvidia,tegra30-pmc";
9 reg = <0x7000e400 0x400>;
10 };
11
7 intc: interrupt-controller@50041000 { 12 intc: interrupt-controller@50041000 {
8 compatible = "arm,cortex-a9-gic"; 13 compatible = "arm,cortex-a9-gic";
9 interrupt-controller; 14 interrupt-controller;
@@ -12,6 +17,43 @@
12 < 0x50040100 0x0100 >; 17 < 0x50040100 0x0100 >;
13 }; 18 };
14 19
20 apbdma: dma@6000a000 {
21 compatible = "nvidia,tegra30-apbdma", "nvidia,tegra20-apbdma";
22 reg = <0x6000a000 0x1400>;
23 interrupts = < 0 104 0x04
24 0 105 0x04
25 0 106 0x04
26 0 107 0x04
27 0 108 0x04
28 0 109 0x04
29 0 110 0x04
30 0 111 0x04
31 0 112 0x04
32 0 113 0x04
33 0 114 0x04
34 0 115 0x04
35 0 116 0x04
36 0 117 0x04
37 0 118 0x04
38 0 119 0x04
39 0 128 0x04
40 0 129 0x04
41 0 130 0x04
42 0 131 0x04
43 0 132 0x04
44 0 133 0x04
45 0 134 0x04
46 0 135 0x04
47 0 136 0x04
48 0 137 0x04
49 0 138 0x04
50 0 139 0x04
51 0 140 0x04
52 0 141 0x04
53 0 142 0x04
54 0 143 0x04 >;
55 };
56
15 i2c@7000c000 { 57 i2c@7000c000 {
16 #address-cells = <1>; 58 #address-cells = <1>;
17 #size-cells = <0>; 59 #size-cells = <0>;
@@ -55,9 +97,18 @@
55 gpio: gpio@6000d000 { 97 gpio: gpio@6000d000 {
56 compatible = "nvidia,tegra30-gpio", "nvidia,tegra20-gpio"; 98 compatible = "nvidia,tegra30-gpio", "nvidia,tegra20-gpio";
57 reg = < 0x6000d000 0x1000 >; 99 reg = < 0x6000d000 0x1000 >;
58 interrupts = < 0 32 0x04 0 33 0x04 0 34 0x04 0 35 0x04 0 55 0x04 0 87 0x04 0 89 0x04 >; 100 interrupts = < 0 32 0x04
101 0 33 0x04
102 0 34 0x04
103 0 35 0x04
104 0 55 0x04
105 0 87 0x04
106 0 89 0x04
107 0 125 0x04 >;
59 #gpio-cells = <2>; 108 #gpio-cells = <2>;
60 gpio-controller; 109 gpio-controller;
110 #interrupt-cells = <2>;
111 interrupt-controller;
61 }; 112 };
62 113
63 serial@70006000 { 114 serial@70006000 {
diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile
index fc4ebe35f484..e5373fb94b9a 100644
--- a/arch/arm/mach-tegra/Makefile
+++ b/arch/arm/mach-tegra/Makefile
@@ -7,6 +7,7 @@ obj-y += clock.o
7obj-y += timer.o 7obj-y += timer.o
8obj-y += pinmux.o 8obj-y += pinmux.o
9obj-y += fuse.o 9obj-y += fuse.o
10obj-y += pmc.o
10obj-$(CONFIG_CPU_IDLE) += cpuidle.o 11obj-$(CONFIG_CPU_IDLE) += cpuidle.o
11obj-$(CONFIG_CPU_IDLE) += sleep.o 12obj-$(CONFIG_CPU_IDLE) += sleep.o
12obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += powergate.o 13obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += powergate.o
@@ -18,7 +19,7 @@ obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += board-dt-tegra30.o
18obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += tegra30_clocks.o 19obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += tegra30_clocks.o
19obj-$(CONFIG_SMP) += platsmp.o localtimer.o headsmp.o 20obj-$(CONFIG_SMP) += platsmp.o localtimer.o headsmp.o
20obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o 21obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
21obj-$(CONFIG_TEGRA_SYSTEM_DMA) += dma.o 22obj-$(CONFIG_TEGRA_SYSTEM_DMA) += dma.o apbio.o
22obj-$(CONFIG_CPU_FREQ) += cpu-tegra.o 23obj-$(CONFIG_CPU_FREQ) += cpu-tegra.o
23obj-$(CONFIG_TEGRA_PCI) += pcie.o 24obj-$(CONFIG_TEGRA_PCI) += pcie.o
24obj-$(CONFIG_USB_SUPPORT) += usb_phy.o 25obj-$(CONFIG_USB_SUPPORT) += usb_phy.o
diff --git a/arch/arm/mach-tegra/apbio.c b/arch/arm/mach-tegra/apbio.c
new file mode 100644
index 000000000000..e75451e517bd
--- /dev/null
+++ b/arch/arm/mach-tegra/apbio.c
@@ -0,0 +1,145 @@
1/*
2 * Copyright (C) 2010 NVIDIA Corporation.
3 * Copyright (C) 2010 Google, Inc.
4 *
5 * This software is licensed under the terms of the GNU General Public
6 * License version 2, as published by the Free Software Foundation, and
7 * may be copied, distributed, and modified under those terms.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 */
15
16#include <linux/kernel.h>
17#include <linux/io.h>
18#include <linux/dma-mapping.h>
19#include <linux/spinlock.h>
20#include <linux/completion.h>
21#include <linux/sched.h>
22#include <linux/mutex.h>
23
24#include <mach/dma.h>
25#include <mach/iomap.h>
26
27#include "apbio.h"
28
29static DEFINE_MUTEX(tegra_apb_dma_lock);
30
31static struct tegra_dma_channel *tegra_apb_dma;
32static u32 *tegra_apb_bb;
33static dma_addr_t tegra_apb_bb_phys;
34static DECLARE_COMPLETION(tegra_apb_wait);
35
36bool tegra_apb_init(void)
37{
38 struct tegra_dma_channel *ch;
39
40 mutex_lock(&tegra_apb_dma_lock);
41
42 /* Check to see if we raced to setup */
43 if (tegra_apb_dma)
44 goto out;
45
46 ch = tegra_dma_allocate_channel(TEGRA_DMA_MODE_ONESHOT |
47 TEGRA_DMA_SHARED);
48
49 if (!ch)
50 goto out_fail;
51
52 tegra_apb_bb = dma_alloc_coherent(NULL, sizeof(u32),
53 &tegra_apb_bb_phys, GFP_KERNEL);
54 if (!tegra_apb_bb) {
55 pr_err("%s: can not allocate bounce buffer\n", __func__);
56 tegra_dma_free_channel(ch);
57 goto out_fail;
58 }
59
60 tegra_apb_dma = ch;
61out:
62 mutex_unlock(&tegra_apb_dma_lock);
63 return true;
64
65out_fail:
66 mutex_unlock(&tegra_apb_dma_lock);
67 return false;
68}
69
70static void apb_dma_complete(struct tegra_dma_req *req)
71{
72 complete(&tegra_apb_wait);
73}
74
75u32 tegra_apb_readl(unsigned long offset)
76{
77 struct tegra_dma_req req;
78 int ret;
79
80 if (!tegra_apb_dma && !tegra_apb_init())
81 return readl(IO_TO_VIRT(offset));
82
83 mutex_lock(&tegra_apb_dma_lock);
84 req.complete = apb_dma_complete;
85 req.to_memory = 1;
86 req.dest_addr = tegra_apb_bb_phys;
87 req.dest_bus_width = 32;
88 req.dest_wrap = 1;
89 req.source_addr = offset;
90 req.source_bus_width = 32;
91 req.source_wrap = 4;
92 req.req_sel = TEGRA_DMA_REQ_SEL_CNTR;
93 req.size = 4;
94
95 INIT_COMPLETION(tegra_apb_wait);
96
97 tegra_dma_enqueue_req(tegra_apb_dma, &req);
98
99 ret = wait_for_completion_timeout(&tegra_apb_wait,
100 msecs_to_jiffies(50));
101
102 if (WARN(ret == 0, "apb read dma timed out")) {
103 tegra_dma_dequeue_req(tegra_apb_dma, &req);
104 *(u32 *)tegra_apb_bb = 0;
105 }
106
107 mutex_unlock(&tegra_apb_dma_lock);
108 return *((u32 *)tegra_apb_bb);
109}
110
111void tegra_apb_writel(u32 value, unsigned long offset)
112{
113 struct tegra_dma_req req;
114 int ret;
115
116 if (!tegra_apb_dma && !tegra_apb_init()) {
117 writel(value, IO_TO_VIRT(offset));
118 return;
119 }
120
121 mutex_lock(&tegra_apb_dma_lock);
122 *((u32 *)tegra_apb_bb) = value;
123 req.complete = apb_dma_complete;
124 req.to_memory = 0;
125 req.dest_addr = offset;
126 req.dest_wrap = 4;
127 req.dest_bus_width = 32;
128 req.source_addr = tegra_apb_bb_phys;
129 req.source_bus_width = 32;
130 req.source_wrap = 1;
131 req.req_sel = TEGRA_DMA_REQ_SEL_CNTR;
132 req.size = 4;
133
134 INIT_COMPLETION(tegra_apb_wait);
135
136 tegra_dma_enqueue_req(tegra_apb_dma, &req);
137
138 ret = wait_for_completion_timeout(&tegra_apb_wait,
139 msecs_to_jiffies(50));
140
141 if (WARN(ret == 0, "apb write dma timed out"))
142 tegra_dma_dequeue_req(tegra_apb_dma, &req);
143
144 mutex_unlock(&tegra_apb_dma_lock);
145}
diff --git a/arch/arm/mach-tegra/apbio.h b/arch/arm/mach-tegra/apbio.h
new file mode 100644
index 000000000000..8b49e8c89a64
--- /dev/null
+++ b/arch/arm/mach-tegra/apbio.h
@@ -0,0 +1,39 @@
1/*
2 * Copyright (C) 2010 NVIDIA Corporation.
3 * Copyright (C) 2010 Google, Inc.
4 *
5 * This software is licensed under the terms of the GNU General Public
6 * License version 2, as published by the Free Software Foundation, and
7 * may be copied, distributed, and modified under those terms.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 */
15
16#ifndef __MACH_TEGRA_APBIO_H
17#define __MACH_TEGRA_APBIO_H
18
19#ifdef CONFIG_TEGRA_SYSTEM_DMA
20
21u32 tegra_apb_readl(unsigned long offset);
22void tegra_apb_writel(u32 value, unsigned long offset);
23
24#else
25#include <asm/io.h>
26#include <mach/io.h>
27
28static inline u32 tegra_apb_readl(unsigned long offset)
29{
30 return readl(IO_TO_VIRT(offset));
31}
32
33static inline void tegra_apb_writel(u32 value, unsigned long offset)
34{
35 writel(value, IO_TO_VIRT(offset));
36}
37#endif
38
39#endif
diff --git a/arch/arm/mach-tegra/board-harmony-power.c b/arch/arm/mach-tegra/board-harmony-power.c
index 21d1285731b3..976edfb05912 100644
--- a/arch/arm/mach-tegra/board-harmony-power.c
+++ b/arch/arm/mach-tegra/board-harmony-power.c
@@ -18,18 +18,13 @@
18#include <linux/i2c.h> 18#include <linux/i2c.h>
19#include <linux/platform_device.h> 19#include <linux/platform_device.h>
20#include <linux/gpio.h> 20#include <linux/gpio.h>
21#include <linux/io.h>
22#include <linux/regulator/machine.h> 21#include <linux/regulator/machine.h>
23#include <linux/mfd/tps6586x.h> 22#include <linux/mfd/tps6586x.h>
24 23
25#include <mach/iomap.h>
26#include <mach/irqs.h> 24#include <mach/irqs.h>
27 25
28#include "board-harmony.h" 26#include "board-harmony.h"
29 27
30#define PMC_CTRL 0x0
31#define PMC_CTRL_INTR_LOW (1 << 17)
32
33static struct regulator_consumer_supply tps658621_ldo0_supply[] = { 28static struct regulator_consumer_supply tps658621_ldo0_supply[] = {
34 REGULATOR_SUPPLY("pex_clk", NULL), 29 REGULATOR_SUPPLY("pex_clk", NULL),
35}; 30};
@@ -114,16 +109,6 @@ static struct i2c_board_info __initdata harmony_regulators[] = {
114 109
115int __init harmony_regulator_init(void) 110int __init harmony_regulator_init(void)
116{ 111{
117 void __iomem *pmc = IO_ADDRESS(TEGRA_PMC_BASE);
118 u32 pmc_ctrl;
119
120 /*
121 * Configure the power management controller to trigger PMU
122 * interrupts when low
123 */
124 pmc_ctrl = readl(pmc + PMC_CTRL);
125 writel(pmc_ctrl | PMC_CTRL_INTR_LOW, pmc + PMC_CTRL);
126
127 i2c_register_board_info(3, harmony_regulators, 1); 112 i2c_register_board_info(3, harmony_regulators, 1);
128 113
129 return 0; 114 return 0;
diff --git a/arch/arm/mach-tegra/board-harmony.c b/arch/arm/mach-tegra/board-harmony.c
index 789bdc9e8f91..c00aadb01e09 100644
--- a/arch/arm/mach-tegra/board-harmony.c
+++ b/arch/arm/mach-tegra/board-harmony.c
@@ -101,7 +101,6 @@ static struct wm8903_platform_data harmony_wm8903_pdata = {
101static struct i2c_board_info __initdata wm8903_board_info = { 101static struct i2c_board_info __initdata wm8903_board_info = {
102 I2C_BOARD_INFO("wm8903", 0x1a), 102 I2C_BOARD_INFO("wm8903", 0x1a),
103 .platform_data = &harmony_wm8903_pdata, 103 .platform_data = &harmony_wm8903_pdata,
104 .irq = TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_CDC_IRQ),
105}; 104};
106 105
107static void __init harmony_i2c_init(void) 106static void __init harmony_i2c_init(void)
@@ -111,6 +110,7 @@ static void __init harmony_i2c_init(void)
111 platform_device_register(&tegra_i2c_device3); 110 platform_device_register(&tegra_i2c_device3);
112 platform_device_register(&tegra_i2c_device4); 111 platform_device_register(&tegra_i2c_device4);
113 112
113 wm8903_board_info.irq = gpio_to_irq(TEGRA_GPIO_CDC_IRQ);
114 i2c_register_board_info(0, &wm8903_board_info, 1); 114 i2c_register_board_info(0, &wm8903_board_info, 1);
115} 115}
116 116
diff --git a/arch/arm/mach-tegra/board-seaboard.c b/arch/arm/mach-tegra/board-seaboard.c
index ebac65f52510..d669847f0485 100644
--- a/arch/arm/mach-tegra/board-seaboard.c
+++ b/arch/arm/mach-tegra/board-seaboard.c
@@ -159,7 +159,6 @@ static struct platform_device *seaboard_devices[] __initdata = {
159 159
160static struct i2c_board_info __initdata isl29018_device = { 160static struct i2c_board_info __initdata isl29018_device = {
161 I2C_BOARD_INFO("isl29018", 0x44), 161 I2C_BOARD_INFO("isl29018", 0x44),
162 .irq = TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_ISL29018_IRQ),
163}; 162};
164 163
165static struct i2c_board_info __initdata adt7461_device = { 164static struct i2c_board_info __initdata adt7461_device = {
@@ -183,7 +182,6 @@ static struct wm8903_platform_data wm8903_pdata = {
183static struct i2c_board_info __initdata wm8903_device = { 182static struct i2c_board_info __initdata wm8903_device = {
184 I2C_BOARD_INFO("wm8903", 0x1a), 183 I2C_BOARD_INFO("wm8903", 0x1a),
185 .platform_data = &wm8903_pdata, 184 .platform_data = &wm8903_pdata,
186 .irq = TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_CDC_IRQ),
187}; 185};
188 186
189static int seaboard_ehci_init(void) 187static int seaboard_ehci_init(void)
@@ -214,7 +212,10 @@ static void __init seaboard_i2c_init(void)
214 gpio_request(TEGRA_GPIO_ISL29018_IRQ, "isl29018"); 212 gpio_request(TEGRA_GPIO_ISL29018_IRQ, "isl29018");
215 gpio_direction_input(TEGRA_GPIO_ISL29018_IRQ); 213 gpio_direction_input(TEGRA_GPIO_ISL29018_IRQ);
216 214
215 isl29018_device.irq = gpio_to_irq(TEGRA_GPIO_ISL29018_IRQ);
217 i2c_register_board_info(0, &isl29018_device, 1); 216 i2c_register_board_info(0, &isl29018_device, 1);
217
218 wm8903_device.irq = gpio_to_irq(TEGRA_GPIO_CDC_IRQ);
218 i2c_register_board_info(0, &wm8903_device, 1); 219 i2c_register_board_info(0, &wm8903_device, 1);
219 220
220 i2c_register_board_info(3, &adt7461_device, 1); 221 i2c_register_board_info(3, &adt7461_device, 1);
diff --git a/arch/arm/mach-tegra/common.c b/arch/arm/mach-tegra/common.c
index 029558114236..1cdcda13a0f7 100644
--- a/arch/arm/mach-tegra/common.c
+++ b/arch/arm/mach-tegra/common.c
@@ -32,6 +32,24 @@
32#include "board.h" 32#include "board.h"
33#include "clock.h" 33#include "clock.h"
34#include "fuse.h" 34#include "fuse.h"
35#include "pmc.h"
36
37/*
38 * Storage for debug-macro.S's state.
39 *
40 * This must be in .data not .bss so that it gets initialized each time the
41 * kernel is loaded. The data is declared here rather than debug-macro.S so
42 * that multiple inclusions of debug-macro.S point at the same data.
43 */
44#define TEGRA_DEBUG_UART_OFFSET (TEGRA_DEBUG_UART_BASE & 0xFFFF)
45u32 tegra_uart_config[3] = {
46 /* Debug UART initialization required */
47 1,
48 /* Debug UART physical address */
49 (u32)(IO_APB_PHYS + TEGRA_DEBUG_UART_OFFSET),
50 /* Debug UART virtual address */
51 (u32)(IO_APB_VIRT + TEGRA_DEBUG_UART_OFFSET),
52};
35 53
36#ifdef CONFIG_OF 54#ifdef CONFIG_OF
37static const struct of_device_id tegra_dt_irq_match[] __initconst = { 55static const struct of_device_id tegra_dt_irq_match[] __initconst = {
@@ -100,6 +118,7 @@ void __init tegra20_init_early(void)
100 tegra2_init_clocks(); 118 tegra2_init_clocks();
101 tegra_clk_init_from_table(tegra20_clk_init_table); 119 tegra_clk_init_from_table(tegra20_clk_init_table);
102 tegra_init_cache(0x331, 0x441); 120 tegra_init_cache(0x331, 0x441);
121 tegra_pmc_init();
103} 122}
104#endif 123#endif
105#ifdef CONFIG_ARCH_TEGRA_3x_SOC 124#ifdef CONFIG_ARCH_TEGRA_3x_SOC
@@ -107,5 +126,6 @@ void __init tegra30_init_early(void)
107{ 126{
108 tegra30_init_clocks(); 127 tegra30_init_clocks();
109 tegra_init_cache(0x441, 0x551); 128 tegra_init_cache(0x441, 0x551);
129 tegra_pmc_init();
110} 130}
111#endif 131#endif
diff --git a/arch/arm/mach-tegra/dma.c b/arch/arm/mach-tegra/dma.c
index c0cf967e47d3..abea4f6e2dd5 100644
--- a/arch/arm/mach-tegra/dma.c
+++ b/arch/arm/mach-tegra/dma.c
@@ -33,6 +33,8 @@
33#include <mach/iomap.h> 33#include <mach/iomap.h>
34#include <mach/suspend.h> 34#include <mach/suspend.h>
35 35
36#include "apbio.h"
37
36#define APB_DMA_GEN 0x000 38#define APB_DMA_GEN 0x000
37#define GEN_ENABLE (1<<31) 39#define GEN_ENABLE (1<<31)
38 40
@@ -50,8 +52,6 @@
50#define CSR_ONCE (1<<27) 52#define CSR_ONCE (1<<27)
51#define CSR_FLOW (1<<21) 53#define CSR_FLOW (1<<21)
52#define CSR_REQ_SEL_SHIFT 16 54#define CSR_REQ_SEL_SHIFT 16
53#define CSR_REQ_SEL_MASK (0x1F<<CSR_REQ_SEL_SHIFT)
54#define CSR_REQ_SEL_INVALID (31<<CSR_REQ_SEL_SHIFT)
55#define CSR_WCOUNT_SHIFT 2 55#define CSR_WCOUNT_SHIFT 2
56#define CSR_WCOUNT_MASK 0xFFFC 56#define CSR_WCOUNT_MASK 0xFFFC
57 57
@@ -133,6 +133,7 @@ struct tegra_dma_channel {
133 133
134static bool tegra_dma_initialized; 134static bool tegra_dma_initialized;
135static DEFINE_MUTEX(tegra_dma_lock); 135static DEFINE_MUTEX(tegra_dma_lock);
136static DEFINE_SPINLOCK(enable_lock);
136 137
137static DECLARE_BITMAP(channel_usage, NV_DMA_MAX_CHANNELS); 138static DECLARE_BITMAP(channel_usage, NV_DMA_MAX_CHANNELS);
138static struct tegra_dma_channel dma_channels[NV_DMA_MAX_CHANNELS]; 139static struct tegra_dma_channel dma_channels[NV_DMA_MAX_CHANNELS];
@@ -180,36 +181,94 @@ static void tegra_dma_stop(struct tegra_dma_channel *ch)
180 181
181static int tegra_dma_cancel(struct tegra_dma_channel *ch) 182static int tegra_dma_cancel(struct tegra_dma_channel *ch)
182{ 183{
183 u32 csr;
184 unsigned long irq_flags; 184 unsigned long irq_flags;
185 185
186 spin_lock_irqsave(&ch->lock, irq_flags); 186 spin_lock_irqsave(&ch->lock, irq_flags);
187 while (!list_empty(&ch->list)) 187 while (!list_empty(&ch->list))
188 list_del(ch->list.next); 188 list_del(ch->list.next);
189 189
190 csr = readl(ch->addr + APB_DMA_CHAN_CSR);
191 csr &= ~CSR_REQ_SEL_MASK;
192 csr |= CSR_REQ_SEL_INVALID;
193 writel(csr, ch->addr + APB_DMA_CHAN_CSR);
194
195 tegra_dma_stop(ch); 190 tegra_dma_stop(ch);
196 191
197 spin_unlock_irqrestore(&ch->lock, irq_flags); 192 spin_unlock_irqrestore(&ch->lock, irq_flags);
198 return 0; 193 return 0;
199} 194}
200 195
196static unsigned int get_channel_status(struct tegra_dma_channel *ch,
197 struct tegra_dma_req *req, bool is_stop_dma)
198{
199 void __iomem *addr = IO_ADDRESS(TEGRA_APB_DMA_BASE);
200 unsigned int status;
201
202 if (is_stop_dma) {
203 /*
204 * STOP the DMA and get the transfer count.
205 * Getting the transfer count is tricky.
206 * - Globally disable DMA on all channels
207 * - Read the channel's status register to know the number
208 * of pending bytes to be transfered.
209 * - Stop the dma channel
210 * - Globally re-enable DMA to resume other transfers
211 */
212 spin_lock(&enable_lock);
213 writel(0, addr + APB_DMA_GEN);
214 udelay(20);
215 status = readl(ch->addr + APB_DMA_CHAN_STA);
216 tegra_dma_stop(ch);
217 writel(GEN_ENABLE, addr + APB_DMA_GEN);
218 spin_unlock(&enable_lock);
219 if (status & STA_ISE_EOC) {
220 pr_err("Got Dma Int here clearing");
221 writel(status, ch->addr + APB_DMA_CHAN_STA);
222 }
223 req->status = TEGRA_DMA_REQ_ERROR_ABORTED;
224 } else {
225 status = readl(ch->addr + APB_DMA_CHAN_STA);
226 }
227 return status;
228}
229
230/* should be called with the channel lock held */
231static unsigned int dma_active_count(struct tegra_dma_channel *ch,
232 struct tegra_dma_req *req, unsigned int status)
233{
234 unsigned int to_transfer;
235 unsigned int req_transfer_count;
236 unsigned int bytes_transferred;
237
238 to_transfer = ((status & STA_COUNT_MASK) >> STA_COUNT_SHIFT) + 1;
239 req_transfer_count = ch->req_transfer_count + 1;
240 bytes_transferred = req_transfer_count;
241 if (status & STA_BUSY)
242 bytes_transferred -= to_transfer;
243 /*
244 * In continuous transfer mode, DMA only tracks the count of the
245 * half DMA buffer. So, if the DMA already finished half the DMA
246 * then add the half buffer to the completed count.
247 */
248 if (ch->mode & TEGRA_DMA_MODE_CONTINOUS) {
249 if (req->buffer_status == TEGRA_DMA_REQ_BUF_STATUS_HALF_FULL)
250 bytes_transferred += req_transfer_count;
251 if (status & STA_ISE_EOC)
252 bytes_transferred += req_transfer_count;
253 }
254 bytes_transferred *= 4;
255 return bytes_transferred;
256}
257
201int tegra_dma_dequeue_req(struct tegra_dma_channel *ch, 258int tegra_dma_dequeue_req(struct tegra_dma_channel *ch,
202 struct tegra_dma_req *_req) 259 struct tegra_dma_req *_req)
203{ 260{
204 unsigned int csr;
205 unsigned int status; 261 unsigned int status;
206 struct tegra_dma_req *req = NULL; 262 struct tegra_dma_req *req = NULL;
207 int found = 0; 263 int found = 0;
208 unsigned long irq_flags; 264 unsigned long irq_flags;
209 int to_transfer; 265 int stop = 0;
210 int req_transfer_count;
211 266
212 spin_lock_irqsave(&ch->lock, irq_flags); 267 spin_lock_irqsave(&ch->lock, irq_flags);
268
269 if (list_entry(ch->list.next, struct tegra_dma_req, node) == _req)
270 stop = 1;
271
213 list_for_each_entry(req, &ch->list, node) { 272 list_for_each_entry(req, &ch->list, node) {
214 if (req == _req) { 273 if (req == _req) {
215 list_del(&req->node); 274 list_del(&req->node);
@@ -222,47 +281,12 @@ int tegra_dma_dequeue_req(struct tegra_dma_channel *ch,
222 return 0; 281 return 0;
223 } 282 }
224 283
225 /* STOP the DMA and get the transfer count. 284 if (!stop)
226 * Getting the transfer count is tricky. 285 goto skip_stop_dma;
227 * - Change the source selector to invalid to stop the DMA from
228 * FIFO to memory.
229 * - Read the status register to know the number of pending
230 * bytes to be transferred.
231 * - Finally stop or program the DMA to the next buffer in the
232 * list.
233 */
234 csr = readl(ch->addr + APB_DMA_CHAN_CSR);
235 csr &= ~CSR_REQ_SEL_MASK;
236 csr |= CSR_REQ_SEL_INVALID;
237 writel(csr, ch->addr + APB_DMA_CHAN_CSR);
238
239 /* Get the transfer count */
240 status = readl(ch->addr + APB_DMA_CHAN_STA);
241 to_transfer = (status & STA_COUNT_MASK) >> STA_COUNT_SHIFT;
242 req_transfer_count = ch->req_transfer_count;
243 req_transfer_count += 1;
244 to_transfer += 1;
245
246 req->bytes_transferred = req_transfer_count;
247
248 if (status & STA_BUSY)
249 req->bytes_transferred -= to_transfer;
250
251 /* In continuous transfer mode, DMA only tracks the count of the
252 * half DMA buffer. So, if the DMA already finished half the DMA
253 * then add the half buffer to the completed count.
254 *
255 * FIXME: There can be a race here. What if the req to
256 * dequue happens at the same time as the DMA just moved to
257 * the new buffer and SW didn't yet received the interrupt?
258 */
259 if (ch->mode & TEGRA_DMA_MODE_CONTINOUS)
260 if (req->buffer_status == TEGRA_DMA_REQ_BUF_STATUS_HALF_FULL)
261 req->bytes_transferred += req_transfer_count;
262 286
263 req->bytes_transferred *= 4; 287 status = get_channel_status(ch, req, true);
288 req->bytes_transferred = dma_active_count(ch, req, status);
264 289
265 tegra_dma_stop(ch);
266 if (!list_empty(&ch->list)) { 290 if (!list_empty(&ch->list)) {
267 /* if the list is not empty, queue the next request */ 291 /* if the list is not empty, queue the next request */
268 struct tegra_dma_req *next_req; 292 struct tegra_dma_req *next_req;
@@ -270,6 +294,8 @@ int tegra_dma_dequeue_req(struct tegra_dma_channel *ch,
270 typeof(*next_req), node); 294 typeof(*next_req), node);
271 tegra_dma_update_hw(ch, next_req); 295 tegra_dma_update_hw(ch, next_req);
272 } 296 }
297
298skip_stop_dma:
273 req->status = -TEGRA_DMA_REQ_ERROR_ABORTED; 299 req->status = -TEGRA_DMA_REQ_ERROR_ABORTED;
274 300
275 spin_unlock_irqrestore(&ch->lock, irq_flags); 301 spin_unlock_irqrestore(&ch->lock, irq_flags);
@@ -357,7 +383,7 @@ struct tegra_dma_channel *tegra_dma_allocate_channel(int mode)
357 int channel; 383 int channel;
358 struct tegra_dma_channel *ch = NULL; 384 struct tegra_dma_channel *ch = NULL;
359 385
360 if (WARN_ON(!tegra_dma_initialized)) 386 if (!tegra_dma_initialized)
361 return NULL; 387 return NULL;
362 388
363 mutex_lock(&tegra_dma_lock); 389 mutex_lock(&tegra_dma_lock);
diff --git a/arch/arm/mach-tegra/fuse.c b/arch/arm/mach-tegra/fuse.c
index 1fa26d9a1a68..17fdd4086e6f 100644
--- a/arch/arm/mach-tegra/fuse.c
+++ b/arch/arm/mach-tegra/fuse.c
@@ -23,20 +23,70 @@
23#include <mach/iomap.h> 23#include <mach/iomap.h>
24 24
25#include "fuse.h" 25#include "fuse.h"
26#include "apbio.h"
26 27
27#define FUSE_UID_LOW 0x108 28#define FUSE_UID_LOW 0x108
28#define FUSE_UID_HIGH 0x10c 29#define FUSE_UID_HIGH 0x10c
29#define FUSE_SKU_INFO 0x110 30#define FUSE_SKU_INFO 0x110
30#define FUSE_SPARE_BIT 0x200 31#define FUSE_SPARE_BIT 0x200
31 32
32static inline u32 fuse_readl(unsigned long offset) 33int tegra_sku_id;
34int tegra_cpu_process_id;
35int tegra_core_process_id;
36enum tegra_revision tegra_revision;
37
38/* The BCT to use at boot is specified by board straps that can be read
39 * through a APB misc register and decoded. 2 bits, i.e. 4 possible BCTs.
40 */
41int tegra_bct_strapping;
42
43#define STRAP_OPT 0x008
44#define GMI_AD0 (1 << 4)
45#define GMI_AD1 (1 << 5)
46#define RAM_ID_MASK (GMI_AD0 | GMI_AD1)
47#define RAM_CODE_SHIFT 4
48
49static const char *tegra_revision_name[TEGRA_REVISION_MAX] = {
50 [TEGRA_REVISION_UNKNOWN] = "unknown",
51 [TEGRA_REVISION_A01] = "A01",
52 [TEGRA_REVISION_A02] = "A02",
53 [TEGRA_REVISION_A03] = "A03",
54 [TEGRA_REVISION_A03p] = "A03 prime",
55 [TEGRA_REVISION_A04] = "A04",
56};
57
58static inline u32 tegra_fuse_readl(unsigned long offset)
59{
60 return tegra_apb_readl(TEGRA_FUSE_BASE + offset);
61}
62
63static inline bool get_spare_fuse(int bit)
33{ 64{
34 return readl(IO_TO_VIRT(TEGRA_FUSE_BASE + offset)); 65 return tegra_fuse_readl(FUSE_SPARE_BIT + bit * 4);
35} 66}
36 67
37static inline void fuse_writel(u32 value, unsigned long offset) 68static enum tegra_revision tegra_get_revision(void)
38{ 69{
39 writel(value, IO_TO_VIRT(TEGRA_FUSE_BASE + offset)); 70 void __iomem *chip_id = IO_ADDRESS(TEGRA_APB_MISC_BASE) + 0x804;
71 u32 id = readl(chip_id);
72 u32 minor_rev = (id >> 16) & 0xf;
73 u32 chipid = (id >> 8) & 0xff;
74
75 switch (minor_rev) {
76 case 1:
77 return TEGRA_REVISION_A01;
78 case 2:
79 return TEGRA_REVISION_A02;
80 case 3:
81 if (chipid == 0x20 && (get_spare_fuse(18) || get_spare_fuse(19)))
82 return TEGRA_REVISION_A03p;
83 else
84 return TEGRA_REVISION_A03;
85 case 4:
86 return TEGRA_REVISION_A04;
87 default:
88 return TEGRA_REVISION_UNKNOWN;
89 }
40} 90}
41 91
42void tegra_init_fuse(void) 92void tegra_init_fuse(void)
@@ -45,40 +95,31 @@ void tegra_init_fuse(void)
45 reg |= 1 << 28; 95 reg |= 1 << 28;
46 writel(reg, IO_TO_VIRT(TEGRA_CLK_RESET_BASE + 0x48)); 96 writel(reg, IO_TO_VIRT(TEGRA_CLK_RESET_BASE + 0x48));
47 97
48 pr_info("Tegra SKU: %d CPU Process: %d Core Process: %d\n", 98 reg = tegra_fuse_readl(FUSE_SKU_INFO);
49 tegra_sku_id(), tegra_cpu_process_id(), 99 tegra_sku_id = reg & 0xFF;
50 tegra_core_process_id());
51}
52 100
53unsigned long long tegra_chip_uid(void) 101 reg = tegra_fuse_readl(FUSE_SPARE_BIT);
54{ 102 tegra_cpu_process_id = (reg >> 6) & 3;
55 unsigned long long lo, hi;
56 103
57 lo = fuse_readl(FUSE_UID_LOW); 104 reg = tegra_fuse_readl(FUSE_SPARE_BIT);
58 hi = fuse_readl(FUSE_UID_HIGH); 105 tegra_core_process_id = (reg >> 12) & 3;
59 return (hi << 32ull) | lo;
60}
61 106
62int tegra_sku_id(void) 107 reg = tegra_apb_readl(TEGRA_APB_MISC_BASE + STRAP_OPT);
63{ 108 tegra_bct_strapping = (reg & RAM_ID_MASK) >> RAM_CODE_SHIFT;
64 int sku_id;
65 u32 reg = fuse_readl(FUSE_SKU_INFO);
66 sku_id = reg & 0xFF;
67 return sku_id;
68}
69 109
70int tegra_cpu_process_id(void) 110 tegra_revision = tegra_get_revision();
71{ 111
72 int cpu_process_id; 112 pr_info("Tegra Revision: %s SKU: %d CPU Process: %d Core Process: %d\n",
73 u32 reg = fuse_readl(FUSE_SPARE_BIT); 113 tegra_revision_name[tegra_get_revision()],
74 cpu_process_id = (reg >> 6) & 3; 114 tegra_sku_id, tegra_cpu_process_id,
75 return cpu_process_id; 115 tegra_core_process_id);
76} 116}
77 117
78int tegra_core_process_id(void) 118unsigned long long tegra_chip_uid(void)
79{ 119{
80 int core_process_id; 120 unsigned long long lo, hi;
81 u32 reg = fuse_readl(FUSE_SPARE_BIT); 121
82 core_process_id = (reg >> 12) & 3; 122 lo = tegra_fuse_readl(FUSE_UID_LOW);
83 return core_process_id; 123 hi = tegra_fuse_readl(FUSE_UID_HIGH);
124 return (hi << 32ull) | lo;
84} 125}
diff --git a/arch/arm/mach-tegra/fuse.h b/arch/arm/mach-tegra/fuse.h
index 584b2e27dbda..d65d2abf803b 100644
--- a/arch/arm/mach-tegra/fuse.h
+++ b/arch/arm/mach-tegra/fuse.h
@@ -1,6 +1,4 @@
1/* 1/*
2 * arch/arm/mach-tegra/fuse.c
3 *
4 * Copyright (C) 2010 Google, Inc. 2 * Copyright (C) 2010 Google, Inc.
5 * 3 *
6 * Author: 4 * Author:
@@ -17,8 +15,34 @@
17 * 15 *
18 */ 16 */
19 17
18#ifndef __MACH_TEGRA_FUSE_H
19#define __MACH_TEGRA_FUSE_H
20
21enum tegra_revision {
22 TEGRA_REVISION_UNKNOWN = 0,
23 TEGRA_REVISION_A01,
24 TEGRA_REVISION_A02,
25 TEGRA_REVISION_A03,
26 TEGRA_REVISION_A03p,
27 TEGRA_REVISION_A04,
28 TEGRA_REVISION_MAX,
29};
30
31#define SKU_ID_T20 8
32#define SKU_ID_T25SE 20
33#define SKU_ID_AP25 23
34#define SKU_ID_T25 24
35#define SKU_ID_AP25E 27
36#define SKU_ID_T25E 28
37
38extern int tegra_sku_id;
39extern int tegra_cpu_process_id;
40extern int tegra_core_process_id;
41extern enum tegra_revision tegra_revision;
42
43extern int tegra_bct_strapping;
44
20unsigned long long tegra_chip_uid(void); 45unsigned long long tegra_chip_uid(void);
21int tegra_sku_id(void);
22int tegra_cpu_process_id(void);
23int tegra_core_process_id(void);
24void tegra_init_fuse(void); 46void tegra_init_fuse(void);
47
48#endif
diff --git a/arch/arm/mach-tegra/include/mach/debug-macro.S b/arch/arm/mach-tegra/include/mach/debug-macro.S
index 619abc63aee8..90069abd37bd 100644
--- a/arch/arm/mach-tegra/include/mach/debug-macro.S
+++ b/arch/arm/mach-tegra/include/mach/debug-macro.S
@@ -1,11 +1,17 @@
1/* 1/*
2 * arch/arm/mach-tegra/include/mach/debug-macro.S 2 * arch/arm/mach-tegra/include/mach/debug-macro.S
3 * 3 *
4 * Copyright (C) 2010 Google, Inc. 4 * Copyright (C) 2010,2011 Google, Inc.
5 * Copyright (C) 2011-2012 NVIDIA CORPORATION. All Rights Reserved.
5 * 6 *
6 * Author: 7 * Author:
7 * Colin Cross <ccross@google.com> 8 * Colin Cross <ccross@google.com>
8 * Erik Gilling <konkers@google.com> 9 * Erik Gilling <konkers@google.com>
10 * Doug Anderson <dianders@chromium.org>
11 * Stephen Warren <swarren@nvidia.com>
12 *
13 * Portions based on mach-omap2's debug-macro.S
14 * Copyright (C) 1994-1999 Russell King
9 * 15 *
10 * This software is licensed under the terms of the GNU General Public 16 * This software is licensed under the terms of the GNU General Public
11 * License version 2, as published by the Free Software Foundation, and 17 * License version 2, as published by the Free Software Foundation, and
@@ -18,18 +24,78 @@
18 * 24 *
19 */ 25 */
20 26
27#include <linux/serial_reg.h>
28
21#include <mach/io.h> 29#include <mach/io.h>
22#include <mach/iomap.h> 30#include <mach/iomap.h>
31#include <mach/irammap.h>
32
33 .macro addruart, rp, rv, tmp
34 adr \rp, 99f @ actual addr of 99f
35 ldr \rv, [\rp] @ linked addr is stored there
36 sub \rv, \rv, \rp @ offset between the two
37 ldr \rp, [\rp, #4] @ linked tegra_uart_config
38 sub \tmp, \rp, \rv @ actual tegra_uart_config
39 ldr \rp, [\tmp] @ Load tegra_uart_config
40 cmp \rp, #1 @ needs intitialization?
41 bne 100f @ no; go load the addresses
42 mov \rv, #0 @ yes; record init is done
43 str \rv, [\tmp]
44 mov \rp, #TEGRA_IRAM_BASE @ See if cookie is in IRAM
45 ldr \rv, [\rp, #TEGRA_IRAM_DEBUG_UART_OFFSET]
46 movw \rp, #TEGRA_IRAM_DEBUG_UART_COOKIE & 0xffff
47 movt \rp, #TEGRA_IRAM_DEBUG_UART_COOKIE >> 16
48 cmp \rv, \rp @ Cookie present?
49 bne 100f @ No, use default UART
50 mov \rp, #TEGRA_IRAM_BASE @ Load UART address from IRAM
51 ldr \rv, [\rp, #TEGRA_IRAM_DEBUG_UART_OFFSET + 4]
52 str \rv, [\tmp, #4] @ Store in tegra_uart_phys
53 sub \rv, \rv, #IO_APB_PHYS @ Calculate virt address
54 add \rv, \rv, #IO_APB_VIRT
55 str \rv, [\tmp, #8] @ Store in tegra_uart_virt
56 b 100f
57
58 .align
5999: .word .
60 .word tegra_uart_config
61 .ltorg
62
63100: ldr \rp, [\tmp, #4] @ Load tegra_uart_phys
64 ldr \rv, [\tmp, #8] @ Load tegra_uart_virt
65 .endm
66
67#define UART_SHIFT 2
68
69/*
70 * Code below is swiped from <asm/hardware/debug-8250.S>, but add an extra
71 * check to make sure that we aren't in the CONFIG_TEGRA_DEBUG_UART_NONE case.
72 * We use the fact that all 5 valid UART addresses all have something in the
73 * 2nd-to-lowest byte.
74 */
23 75
24 .macro addruart, rp, rv, tmp 76 .macro senduart, rd, rx
25 ldr \rp, =IO_APB_PHYS @ physical 77 tst \rx, #0x0000ff00
26 ldr \rv, =IO_APB_VIRT @ virtual 78 strneb \rd, [\rx, #UART_TX << UART_SHIFT]
27 orr \rp, \rp, #(TEGRA_DEBUG_UART_BASE & 0xFF) 791001:
28 orr \rp, \rp, #(TEGRA_DEBUG_UART_BASE & 0xFF00) 80 .endm
29 orr \rv, \rv, #(TEGRA_DEBUG_UART_BASE & 0xFF)
30 orr \rv, \rv, #(TEGRA_DEBUG_UART_BASE & 0xFF00)
31 .endm
32 81
33#define UART_SHIFT 2 82 .macro busyuart, rd, rx
34#include <asm/hardware/debug-8250.S> 83 tst \rx, #0x0000ff00
84 beq 1002f
851001: ldrb \rd, [\rx, #UART_LSR << UART_SHIFT]
86 and \rd, \rd, #UART_LSR_TEMT | UART_LSR_THRE
87 teq \rd, #UART_LSR_TEMT | UART_LSR_THRE
88 bne 1001b
891002:
90 .endm
35 91
92 .macro waituart, rd, rx
93#ifdef FLOW_CONTROL
94 tst \rx, #0x0000ff00
95 beq 1002f
961001: ldrb \rd, [\rx, #UART_MSR << UART_SHIFT]
97 tst \rd, #UART_MSR_CTS
98 beq 1001b
991002:
100#endif
101 .endm
diff --git a/arch/arm/mach-tegra/include/mach/gpio-tegra.h b/arch/arm/mach-tegra/include/mach/gpio-tegra.h
index 87d37fdf5084..6140820555e1 100644
--- a/arch/arm/mach-tegra/include/mach/gpio-tegra.h
+++ b/arch/arm/mach-tegra/include/mach/gpio-tegra.h
@@ -25,8 +25,6 @@
25 25
26#define TEGRA_NR_GPIOS INT_GPIO_NR 26#define TEGRA_NR_GPIOS INT_GPIO_NR
27 27
28#define TEGRA_GPIO_TO_IRQ(gpio) (INT_GPIO_BASE + (gpio))
29
30struct tegra_gpio_table { 28struct tegra_gpio_table {
31 int gpio; /* GPIO number */ 29 int gpio; /* GPIO number */
32 bool enable; /* Enable for GPIO at init? */ 30 bool enable; /* Enable for GPIO at init? */
diff --git a/arch/arm/mach-tegra/include/mach/irammap.h b/arch/arm/mach-tegra/include/mach/irammap.h
new file mode 100644
index 000000000000..0cbe63261854
--- /dev/null
+++ b/arch/arm/mach-tegra/include/mach/irammap.h
@@ -0,0 +1,35 @@
1/*
2 * Copyright (c) 2012, 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#ifndef __MACH_TEGRA_IRAMMAP_H
18#define __MACH_TEGRA_IRAMMAP_H
19
20#include <asm/sizes.h>
21
22/* The first 1K of IRAM is permanently reserved for the CPU reset handler */
23#define TEGRA_IRAM_RESET_HANDLER_OFFSET 0
24#define TEGRA_IRAM_RESET_HANDLER_SIZE SZ_1K
25
26/*
27 * These locations are written to by uncompress.h, and read by debug-macro.S.
28 * The first word holds the cookie value if the data is valid. The second
29 * word holds the UART physical address.
30 */
31#define TEGRA_IRAM_DEBUG_UART_OFFSET SZ_1K
32#define TEGRA_IRAM_DEBUG_UART_SIZE 8
33#define TEGRA_IRAM_DEBUG_UART_COOKIE 0x55415254
34
35#endif
diff --git a/arch/arm/mach-tegra/include/mach/uncompress.h b/arch/arm/mach-tegra/include/mach/uncompress.h
index 4e8323770c79..b066ba0ee3c3 100644
--- a/arch/arm/mach-tegra/include/mach/uncompress.h
+++ b/arch/arm/mach-tegra/include/mach/uncompress.h
@@ -2,10 +2,14 @@
2 * arch/arm/mach-tegra/include/mach/uncompress.h 2 * arch/arm/mach-tegra/include/mach/uncompress.h
3 * 3 *
4 * Copyright (C) 2010 Google, Inc. 4 * Copyright (C) 2010 Google, Inc.
5 * Copyright (C) 2011 Google, Inc.
6 * Copyright (C) 2011-2012 NVIDIA CORPORATION. All Rights Reserved.
5 * 7 *
6 * Author: 8 * Author:
7 * Colin Cross <ccross@google.com> 9 * Colin Cross <ccross@google.com>
8 * Erik Gilling <konkers@google.com> 10 * Erik Gilling <konkers@google.com>
11 * Doug Anderson <dianders@chromium.org>
12 * Stephen Warren <swarren@nvidia.com>
9 * 13 *
10 * This software is licensed under the terms of the GNU General Public 14 * This software is licensed under the terms of the GNU General Public
11 * License version 2, as published by the Free Software Foundation, and 15 * License version 2, as published by the Free Software Foundation, and
@@ -21,40 +25,132 @@
21#ifndef __MACH_TEGRA_UNCOMPRESS_H 25#ifndef __MACH_TEGRA_UNCOMPRESS_H
22#define __MACH_TEGRA_UNCOMPRESS_H 26#define __MACH_TEGRA_UNCOMPRESS_H
23 27
28#include <linux/kernel.h>
24#include <linux/types.h> 29#include <linux/types.h>
25#include <linux/serial_reg.h> 30#include <linux/serial_reg.h>
26 31
27#include <mach/iomap.h> 32#include <mach/iomap.h>
33#include <mach/irammap.h>
34
35#define DEBUG_UART_SHIFT 2
36
37volatile u8 *uart;
28 38
29static void putc(int c) 39static void putc(int c)
30{ 40{
31 volatile u8 *uart = (volatile u8 *)TEGRA_DEBUG_UART_BASE;
32 int shift = 2;
33
34 if (uart == NULL) 41 if (uart == NULL)
35 return; 42 return;
36 43
37 while (!(uart[UART_LSR << shift] & UART_LSR_THRE)) 44 while (!(uart[UART_LSR << DEBUG_UART_SHIFT] & UART_LSR_THRE))
38 barrier(); 45 barrier();
39 uart[UART_TX << shift] = c; 46 uart[UART_TX << DEBUG_UART_SHIFT] = c;
40} 47}
41 48
42static inline void flush(void) 49static inline void flush(void)
43{ 50{
44} 51}
45 52
53static inline void save_uart_address(void)
54{
55 u32 *buf = (u32 *)(TEGRA_IRAM_BASE + TEGRA_IRAM_DEBUG_UART_OFFSET);
56
57 if (uart) {
58 buf[0] = TEGRA_IRAM_DEBUG_UART_COOKIE;
59 buf[1] = (u32)uart;
60 } else
61 buf[0] = 0;
62}
63
64/*
65 * Setup before decompression. This is where we do UART selection for
66 * earlyprintk and init the uart_base register.
67 */
46static inline void arch_decomp_setup(void) 68static inline void arch_decomp_setup(void)
47{ 69{
48 volatile u8 *uart = (volatile u8 *)TEGRA_DEBUG_UART_BASE; 70 static const struct {
49 int shift = 2; 71 u32 base;
72 u32 reset_reg;
73 u32 clock_reg;
74 u32 bit;
75 } uarts[] = {
76 {
77 TEGRA_UARTA_BASE,
78 TEGRA_CLK_RESET_BASE + 0x04,
79 TEGRA_CLK_RESET_BASE + 0x10,
80 6,
81 },
82 {
83 TEGRA_UARTB_BASE,
84 TEGRA_CLK_RESET_BASE + 0x04,
85 TEGRA_CLK_RESET_BASE + 0x10,
86 7,
87 },
88 {
89 TEGRA_UARTC_BASE,
90 TEGRA_CLK_RESET_BASE + 0x08,
91 TEGRA_CLK_RESET_BASE + 0x14,
92 23,
93 },
94 {
95 TEGRA_UARTD_BASE,
96 TEGRA_CLK_RESET_BASE + 0x0c,
97 TEGRA_CLK_RESET_BASE + 0x18,
98 1,
99 },
100 {
101 TEGRA_UARTE_BASE,
102 TEGRA_CLK_RESET_BASE + 0x0c,
103 TEGRA_CLK_RESET_BASE + 0x18,
104 2,
105 },
106 };
107 int i;
108 volatile u32 *apb_misc = (volatile u32 *)TEGRA_APB_MISC_BASE;
109 u32 chip, div;
110
111 /*
112 * Look for the first UART that:
113 * a) Is not in reset.
114 * b) Is clocked.
115 * c) Has a 'D' in the scratchpad register.
116 *
117 * Note that on Tegra30, the first two conditions are required, since
118 * if not true, accesses to the UART scratch register will hang.
119 * Tegra20 doesn't have this issue.
120 *
121 * The intent is that the bootloader will tell the kernel which UART
122 * to use by setting up those conditions. If nothing found, we'll fall
123 * back to what's specified in TEGRA_DEBUG_UART_BASE.
124 */
125 for (i = 0; i < ARRAY_SIZE(uarts); i++) {
126 if (*(u8 *)uarts[i].reset_reg & BIT(uarts[i].bit))
127 continue;
50 128
129 if (!(*(u8 *)uarts[i].clock_reg & BIT(uarts[i].bit)))
130 continue;
131
132 uart = (volatile u8 *)uarts[i].base;
133 if (uart[UART_SCR << DEBUG_UART_SHIFT] != 'D')
134 continue;
135
136 break;
137 }
138 if (i == ARRAY_SIZE(uarts))
139 uart = (volatile u8 *)TEGRA_DEBUG_UART_BASE;
140 save_uart_address();
51 if (uart == NULL) 141 if (uart == NULL)
52 return; 142 return;
53 143
54 uart[UART_LCR << shift] |= UART_LCR_DLAB; 144 chip = (apb_misc[0x804 / 4] >> 8) & 0xff;
55 uart[UART_DLL << shift] = 0x75; 145 if (chip == 0x20)
56 uart[UART_DLM << shift] = 0x0; 146 div = 0x0075;
57 uart[UART_LCR << shift] = 3; 147 else
148 div = 0x00dd;
149
150 uart[UART_LCR << DEBUG_UART_SHIFT] |= UART_LCR_DLAB;
151 uart[UART_DLL << DEBUG_UART_SHIFT] = div & 0xff;
152 uart[UART_DLM << DEBUG_UART_SHIFT] = div >> 8;
153 uart[UART_LCR << DEBUG_UART_SHIFT] = 3;
58} 154}
59 155
60static inline void arch_decomp_wdog(void) 156static inline void arch_decomp_wdog(void)
diff --git a/arch/arm/mach-tegra/pmc.c b/arch/arm/mach-tegra/pmc.c
new file mode 100644
index 000000000000..7af6a54404be
--- /dev/null
+++ b/arch/arm/mach-tegra/pmc.c
@@ -0,0 +1,76 @@
1/*
2 * Copyright (C) 2012 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
18#include <linux/kernel.h>
19#include <linux/io.h>
20#include <linux/of.h>
21
22#include <mach/iomap.h>
23
24#define PMC_CTRL 0x0
25#define PMC_CTRL_INTR_LOW (1 << 17)
26
27static inline u32 tegra_pmc_readl(u32 reg)
28{
29 return readl(IO_ADDRESS(TEGRA_PMC_BASE + reg));
30}
31
32static inline void tegra_pmc_writel(u32 val, u32 reg)
33{
34 writel(val, IO_ADDRESS(TEGRA_PMC_BASE + reg));
35}
36
37#ifdef CONFIG_OF
38static const struct of_device_id matches[] __initconst = {
39 { .compatible = "nvidia,tegra20-pmc" },
40 { }
41};
42#endif
43
44void __init tegra_pmc_init(void)
45{
46 /*
47 * For now, Harmony is the only board that uses the PMC, and it wants
48 * the signal inverted. Seaboard would too if it used the PMC.
49 * Hopefully by the time other boards want to use the PMC, everything
50 * will be device-tree, or they also want it inverted.
51 */
52 bool invert_interrupt = true;
53 u32 val;
54
55#ifdef CONFIG_OF
56 if (of_have_populated_dt()) {
57 struct device_node *np;
58
59 invert_interrupt = false;
60
61 np = of_find_matching_node(NULL, matches);
62 if (np) {
63 if (of_find_property(np, "nvidia,invert-interrupt",
64 NULL))
65 invert_interrupt = true;
66 }
67 }
68#endif
69
70 val = tegra_pmc_readl(PMC_CTRL);
71 if (invert_interrupt)
72 val |= PMC_CTRL_INTR_LOW;
73 else
74 val &= ~PMC_CTRL_INTR_LOW;
75 tegra_pmc_writel(val, PMC_CTRL);
76}
diff --git a/arch/arm/mach-tegra/pmc.h b/arch/arm/mach-tegra/pmc.h
new file mode 100644
index 000000000000..8995ee4a8768
--- /dev/null
+++ b/arch/arm/mach-tegra/pmc.h
@@ -0,0 +1,23 @@
1/*
2 * Copyright (C) 2012 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
18#ifndef __MACH_TEGRA_PMC_H
19#define __MACH_TEGRA_PMC_H
20
21void tegra_pmc_init(void);
22
23#endif
diff --git a/arch/arm/mach-tegra/tegra2_clocks.c b/arch/arm/mach-tegra/tegra2_clocks.c
index 1976e934cdd9..592a4eeb5328 100644
--- a/arch/arm/mach-tegra/tegra2_clocks.c
+++ b/arch/arm/mach-tegra/tegra2_clocks.c
@@ -720,7 +720,7 @@ static void tegra2_pllx_clk_init(struct clk *c)
720{ 720{
721 tegra2_pll_clk_init(c); 721 tegra2_pll_clk_init(c);
722 722
723 if (tegra_sku_id() == 7) 723 if (tegra_sku_id == 7)
724 c->max_rate = 750000000; 724 c->max_rate = 750000000;
725} 725}
726 726
diff --git a/arch/arm/mach-tegra/tegra2_emc.c b/arch/arm/mach-tegra/tegra2_emc.c
index 0f7ae6e90b55..5070d833bdd1 100644
--- a/arch/arm/mach-tegra/tegra2_emc.c
+++ b/arch/arm/mach-tegra/tegra2_emc.c
@@ -16,14 +16,19 @@
16 */ 16 */
17 17
18#include <linux/kernel.h> 18#include <linux/kernel.h>
19#include <linux/device.h>
19#include <linux/clk.h> 20#include <linux/clk.h>
20#include <linux/err.h> 21#include <linux/err.h>
21#include <linux/io.h> 22#include <linux/io.h>
22#include <linux/module.h> 23#include <linux/module.h>
24#include <linux/of.h>
25#include <linux/platform_device.h>
26#include <linux/platform_data/tegra_emc.h>
23 27
24#include <mach/iomap.h> 28#include <mach/iomap.h>
25 29
26#include "tegra2_emc.h" 30#include "tegra2_emc.h"
31#include "fuse.h"
27 32
28#ifdef CONFIG_TEGRA_EMC_SCALING_ENABLE 33#ifdef CONFIG_TEGRA_EMC_SCALING_ENABLE
29static bool emc_enable = true; 34static bool emc_enable = true;
@@ -32,18 +37,17 @@ static bool emc_enable;
32#endif 37#endif
33module_param(emc_enable, bool, 0644); 38module_param(emc_enable, bool, 0644);
34 39
35static void __iomem *emc = IO_ADDRESS(TEGRA_EMC_BASE); 40static struct platform_device *emc_pdev;
36static const struct tegra_emc_table *tegra_emc_table; 41static void __iomem *emc_regbase;
37static int tegra_emc_table_size;
38 42
39static inline void emc_writel(u32 val, unsigned long addr) 43static inline void emc_writel(u32 val, unsigned long addr)
40{ 44{
41 writel(val, emc + addr); 45 writel(val, emc_regbase + addr);
42} 46}
43 47
44static inline u32 emc_readl(unsigned long addr) 48static inline u32 emc_readl(unsigned long addr)
45{ 49{
46 return readl(emc + addr); 50 return readl(emc_regbase + addr);
47} 51}
48 52
49static const unsigned long emc_reg_addr[TEGRA_EMC_NUM_REGS] = { 53static const unsigned long emc_reg_addr[TEGRA_EMC_NUM_REGS] = {
@@ -98,15 +102,15 @@ static const unsigned long emc_reg_addr[TEGRA_EMC_NUM_REGS] = {
98/* Select the closest EMC rate that is higher than the requested rate */ 102/* Select the closest EMC rate that is higher than the requested rate */
99long tegra_emc_round_rate(unsigned long rate) 103long tegra_emc_round_rate(unsigned long rate)
100{ 104{
105 struct tegra_emc_pdata *pdata;
101 int i; 106 int i;
102 int best = -1; 107 int best = -1;
103 unsigned long distance = ULONG_MAX; 108 unsigned long distance = ULONG_MAX;
104 109
105 if (!tegra_emc_table) 110 if (!emc_pdev)
106 return -EINVAL; 111 return -EINVAL;
107 112
108 if (!emc_enable) 113 pdata = emc_pdev->dev.platform_data;
109 return -EINVAL;
110 114
111 pr_debug("%s: %lu\n", __func__, rate); 115 pr_debug("%s: %lu\n", __func__, rate);
112 116
@@ -116,10 +120,10 @@ long tegra_emc_round_rate(unsigned long rate)
116 */ 120 */
117 rate = rate / 2 / 1000; 121 rate = rate / 2 / 1000;
118 122
119 for (i = 0; i < tegra_emc_table_size; i++) { 123 for (i = 0; i < pdata->num_tables; i++) {
120 if (tegra_emc_table[i].rate >= rate && 124 if (pdata->tables[i].rate >= rate &&
121 (tegra_emc_table[i].rate - rate) < distance) { 125 (pdata->tables[i].rate - rate) < distance) {
122 distance = tegra_emc_table[i].rate - rate; 126 distance = pdata->tables[i].rate - rate;
123 best = i; 127 best = i;
124 } 128 }
125 } 129 }
@@ -127,9 +131,9 @@ long tegra_emc_round_rate(unsigned long rate)
127 if (best < 0) 131 if (best < 0)
128 return -EINVAL; 132 return -EINVAL;
129 133
130 pr_debug("%s: using %lu\n", __func__, tegra_emc_table[best].rate); 134 pr_debug("%s: using %lu\n", __func__, pdata->tables[best].rate);
131 135
132 return tegra_emc_table[best].rate * 2 * 1000; 136 return pdata->tables[best].rate * 2 * 1000;
133} 137}
134 138
135/* 139/*
@@ -142,37 +146,211 @@ long tegra_emc_round_rate(unsigned long rate)
142 */ 146 */
143int tegra_emc_set_rate(unsigned long rate) 147int tegra_emc_set_rate(unsigned long rate)
144{ 148{
149 struct tegra_emc_pdata *pdata;
145 int i; 150 int i;
146 int j; 151 int j;
147 152
148 if (!tegra_emc_table) 153 if (!emc_pdev)
149 return -EINVAL; 154 return -EINVAL;
150 155
156 pdata = emc_pdev->dev.platform_data;
157
151 /* 158 /*
152 * The EMC clock rate is twice the bus rate, and the bus rate is 159 * The EMC clock rate is twice the bus rate, and the bus rate is
153 * measured in kHz 160 * measured in kHz
154 */ 161 */
155 rate = rate / 2 / 1000; 162 rate = rate / 2 / 1000;
156 163
157 for (i = 0; i < tegra_emc_table_size; i++) 164 for (i = 0; i < pdata->num_tables; i++)
158 if (tegra_emc_table[i].rate == rate) 165 if (pdata->tables[i].rate == rate)
159 break; 166 break;
160 167
161 if (i >= tegra_emc_table_size) 168 if (i >= pdata->num_tables)
162 return -EINVAL; 169 return -EINVAL;
163 170
164 pr_debug("%s: setting to %lu\n", __func__, rate); 171 pr_debug("%s: setting to %lu\n", __func__, rate);
165 172
166 for (j = 0; j < TEGRA_EMC_NUM_REGS; j++) 173 for (j = 0; j < TEGRA_EMC_NUM_REGS; j++)
167 emc_writel(tegra_emc_table[i].regs[j], emc_reg_addr[j]); 174 emc_writel(pdata->tables[i].regs[j], emc_reg_addr[j]);
168 175
169 emc_readl(tegra_emc_table[i].regs[TEGRA_EMC_NUM_REGS - 1]); 176 emc_readl(pdata->tables[i].regs[TEGRA_EMC_NUM_REGS - 1]);
170 177
171 return 0; 178 return 0;
172} 179}
173 180
174void tegra_init_emc(const struct tegra_emc_table *table, int table_size) 181#ifdef CONFIG_OF
182static struct device_node *tegra_emc_ramcode_devnode(struct device_node *np)
183{
184 struct device_node *iter;
185 u32 reg;
186
187 for_each_child_of_node(np, iter) {
188 if (of_property_read_u32(np, "nvidia,ram-code", &reg))
189 continue;
190 if (reg == tegra_bct_strapping)
191 return of_node_get(iter);
192 }
193
194 return NULL;
195}
196
197static struct tegra_emc_pdata *tegra_emc_dt_parse_pdata(
198 struct platform_device *pdev)
199{
200 struct device_node *np = pdev->dev.of_node;
201 struct device_node *tnp, *iter;
202 struct tegra_emc_pdata *pdata;
203 int ret, i, num_tables;
204
205 if (!np)
206 return NULL;
207
208 if (of_find_property(np, "nvidia,use-ram-code", NULL)) {
209 tnp = tegra_emc_ramcode_devnode(np);
210 if (!tnp)
211 dev_warn(&pdev->dev,
212 "can't find emc table for ram-code 0x%02x\n",
213 tegra_bct_strapping);
214 } else
215 tnp = of_node_get(np);
216
217 if (!tnp)
218 return NULL;
219
220 num_tables = 0;
221 for_each_child_of_node(tnp, iter)
222 if (of_device_is_compatible(iter, "nvidia,tegra20-emc-table"))
223 num_tables++;
224
225 if (!num_tables) {
226 pdata = NULL;
227 goto out;
228 }
229
230 pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
231 pdata->tables = devm_kzalloc(&pdev->dev,
232 sizeof(*pdata->tables) * num_tables,
233 GFP_KERNEL);
234
235 i = 0;
236 for_each_child_of_node(tnp, iter) {
237 u32 prop;
238
239 ret = of_property_read_u32(iter, "clock-frequency", &prop);
240 if (ret) {
241 dev_err(&pdev->dev, "no clock-frequency in %s\n",
242 iter->full_name);
243 continue;
244 }
245 pdata->tables[i].rate = prop;
246
247 ret = of_property_read_u32_array(iter, "nvidia,emc-registers",
248 pdata->tables[i].regs,
249 TEGRA_EMC_NUM_REGS);
250 if (ret) {
251 dev_err(&pdev->dev,
252 "malformed emc-registers property in %s\n",
253 iter->full_name);
254 continue;
255 }
256
257 i++;
258 }
259 pdata->num_tables = i;
260
261out:
262 of_node_put(tnp);
263 return pdata;
264}
265#else
266static struct tegra_emc_pdata *tegra_emc_dt_parse_pdata(
267 struct platform_device *pdev)
268{
269 return NULL;
270}
271#endif
272
273static struct tegra_emc_pdata __devinit *tegra_emc_fill_pdata(struct platform_device *pdev)
274{
275 struct clk *c = clk_get_sys(NULL, "emc");
276 struct tegra_emc_pdata *pdata;
277 unsigned long khz;
278 int i;
279
280 WARN_ON(pdev->dev.platform_data);
281 BUG_ON(IS_ERR_OR_NULL(c));
282
283 pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
284 pdata->tables = devm_kzalloc(&pdev->dev, sizeof(*pdata->tables),
285 GFP_KERNEL);
286
287 pdata->tables[0].rate = clk_get_rate(c) / 2 / 1000;
288
289 for (i = 0; i < TEGRA_EMC_NUM_REGS; i++)
290 pdata->tables[0].regs[i] = emc_readl(emc_reg_addr[i]);
291
292 pdata->num_tables = 1;
293
294 khz = pdata->tables[0].rate;
295 dev_info(&pdev->dev, "no tables provided, using %ld kHz emc, "
296 "%ld kHz mem\n", khz * 2, khz);
297
298 return pdata;
299}
300
301static int __devinit tegra_emc_probe(struct platform_device *pdev)
302{
303 struct tegra_emc_pdata *pdata;
304 struct resource *res;
305
306 if (!emc_enable) {
307 dev_err(&pdev->dev, "disabled per module parameter\n");
308 return -ENODEV;
309 }
310
311 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
312 if (!res) {
313 dev_err(&pdev->dev, "missing register base\n");
314 return -ENOMEM;
315 }
316
317 emc_regbase = devm_request_and_ioremap(&pdev->dev, res);
318 if (!emc_regbase) {
319 dev_err(&pdev->dev, "failed to remap registers\n");
320 return -ENOMEM;
321 }
322
323 pdata = pdev->dev.platform_data;
324
325 if (!pdata)
326 pdata = tegra_emc_dt_parse_pdata(pdev);
327
328 if (!pdata)
329 pdata = tegra_emc_fill_pdata(pdev);
330
331 pdev->dev.platform_data = pdata;
332
333 emc_pdev = pdev;
334
335 return 0;
336}
337
338static struct of_device_id tegra_emc_of_match[] __devinitdata = {
339 { .compatible = "nvidia,tegra20-emc", },
340 { },
341};
342
343static struct platform_driver tegra_emc_driver = {
344 .driver = {
345 .name = "tegra-emc",
346 .owner = THIS_MODULE,
347 .of_match_table = tegra_emc_of_match,
348 },
349 .probe = tegra_emc_probe,
350};
351
352static int __init tegra_emc_init(void)
175{ 353{
176 tegra_emc_table = table; 354 return platform_driver_register(&tegra_emc_driver);
177 tegra_emc_table_size = table_size;
178} 355}
356device_initcall(tegra_emc_init);
diff --git a/arch/arm/mach-tegra/tegra2_emc.h b/arch/arm/mach-tegra/tegra2_emc.h
index 19f08cb31603..f61409b54cb7 100644
--- a/arch/arm/mach-tegra/tegra2_emc.h
+++ b/arch/arm/mach-tegra/tegra2_emc.h
@@ -15,13 +15,10 @@
15 * 15 *
16 */ 16 */
17 17
18#define TEGRA_EMC_NUM_REGS 46 18#ifndef __MACH_TEGRA_TEGRA2_EMC_H_
19 19#define __MACH_TEGRA_TEGRA2_EMC_H
20struct tegra_emc_table {
21 unsigned long rate;
22 u32 regs[TEGRA_EMC_NUM_REGS];
23};
24 20
25int tegra_emc_set_rate(unsigned long rate); 21int tegra_emc_set_rate(unsigned long rate);
26long tegra_emc_round_rate(unsigned long rate); 22long tegra_emc_round_rate(unsigned long rate);
27void tegra_init_emc(const struct tegra_emc_table *table, int table_size); 23
24#endif