mirror of https://gitee.com/openkylin/linux.git
Merge branch 'tegra/soc' into next/drivers
This is a dependency for the tegra/clk branch. Signed-off-by: Arnd Bergmann <arnd@arndb.de> Conflicts: drivers/clocksource/tegra20_timer.c
This commit is contained in:
commit
1194b152cd
|
@ -1,19 +1,84 @@
|
||||||
NVIDIA Tegra Power Management Controller (PMC)
|
NVIDIA Tegra Power Management Controller (PMC)
|
||||||
|
|
||||||
Properties:
|
The PMC block interacts with an external Power Management Unit. The PMC
|
||||||
|
mostly controls the entry and exit of the system from different sleep
|
||||||
|
modes. It provides power-gating controllers for SoC and CPU power-islands.
|
||||||
|
|
||||||
|
Required properties:
|
||||||
- name : Should be pmc
|
- name : Should be pmc
|
||||||
- compatible : Should contain "nvidia,tegra<chip>-pmc".
|
- compatible : Should contain "nvidia,tegra<chip>-pmc".
|
||||||
- reg : Offset and length of the register set for the device
|
- reg : Offset and length of the register set for the device
|
||||||
|
- clocks : Must contain an entry for each entry in clock-names.
|
||||||
|
- clock-names : Must include the following entries:
|
||||||
|
"pclk" (The Tegra clock of that name),
|
||||||
|
"clk32k_in" (The 32KHz clock input to Tegra).
|
||||||
|
|
||||||
|
Optional properties:
|
||||||
- nvidia,invert-interrupt : If present, inverts the PMU interrupt signal.
|
- nvidia,invert-interrupt : If present, inverts the PMU interrupt signal.
|
||||||
The PMU is an external Power Management Unit, whose interrupt output
|
The PMU is an external Power Management Unit, whose interrupt output
|
||||||
signal is fed into the PMC. This signal is optionally inverted, and then
|
signal is fed into the PMC. This signal is optionally inverted, and then
|
||||||
fed into the ARM GIC. The PMC is not involved in the detection or
|
fed into the ARM GIC. The PMC is not involved in the detection or
|
||||||
handling of this interrupt signal, merely its inversion.
|
handling of this interrupt signal, merely its inversion.
|
||||||
|
- nvidia,suspend-mode : The suspend mode that the platform should use.
|
||||||
|
Valid values are 0, 1 and 2:
|
||||||
|
0 (LP0): CPU + Core voltage off and DRAM in self-refresh
|
||||||
|
1 (LP1): CPU voltage off and DRAM in self-refresh
|
||||||
|
2 (LP2): CPU voltage off
|
||||||
|
- nvidia,core-power-req-active-high : Boolean, core power request active-high
|
||||||
|
- nvidia,sys-clock-req-active-high : Boolean, system clock request active-high
|
||||||
|
- nvidia,combined-power-req : Boolean, combined power request for CPU & Core
|
||||||
|
- nvidia,cpu-pwr-good-en : Boolean, CPU power good signal (from PMIC to PMC)
|
||||||
|
is enabled.
|
||||||
|
|
||||||
|
Required properties when nvidia,suspend-mode is specified:
|
||||||
|
- nvidia,cpu-pwr-good-time : CPU power good time in uS.
|
||||||
|
- nvidia,cpu-pwr-off-time : CPU power off time in uS.
|
||||||
|
- nvidia,core-pwr-good-time : <Oscillator-stable-time Power-stable-time>
|
||||||
|
Core power good time in uS.
|
||||||
|
- nvidia,core-pwr-off-time : Core power off time in uS.
|
||||||
|
|
||||||
|
Required properties when nvidia,suspend-mode=<0>:
|
||||||
|
- nvidia,lp0-vec : <start length> Starting address and length of LP0 vector
|
||||||
|
The LP0 vector contains the warm boot code that is executed by AVP when
|
||||||
|
resuming from the LP0 state. The AVP (Audio-Video Processor) is an ARM7
|
||||||
|
processor and always being the first boot processor when chip is power on
|
||||||
|
or resume from deep sleep mode. When the system is resumed from the deep
|
||||||
|
sleep mode, the warm boot code will restore some PLLs, clocks and then
|
||||||
|
bring up CPU0 for resuming the system.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
|
/ SoC dts including file
|
||||||
pmc@7000f400 {
|
pmc@7000f400 {
|
||||||
compatible = "nvidia,tegra20-pmc";
|
compatible = "nvidia,tegra20-pmc";
|
||||||
reg = <0x7000e400 0x400>;
|
reg = <0x7000e400 0x400>;
|
||||||
|
clocks = <&tegra_car 110>, <&clk32k_in>;
|
||||||
|
clock-names = "pclk", "clk32k_in";
|
||||||
nvidia,invert-interrupt;
|
nvidia,invert-interrupt;
|
||||||
|
nvidia,suspend-mode = <1>;
|
||||||
|
nvidia,cpu-pwr-good-time = <2000>;
|
||||||
|
nvidia,cpu-pwr-off-time = <100>;
|
||||||
|
nvidia,core-pwr-good-time = <3845 3845>;
|
||||||
|
nvidia,core-pwr-off-time = <458>;
|
||||||
|
nvidia,core-power-req-active-high;
|
||||||
|
nvidia,sys-clock-req-active-high;
|
||||||
|
nvidia,lp0-vec = <0xbdffd000 0x2000>;
|
||||||
|
};
|
||||||
|
|
||||||
|
/ Tegra board dts file
|
||||||
|
{
|
||||||
|
...
|
||||||
|
clocks {
|
||||||
|
compatible = "simple-bus";
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
|
||||||
|
clk32k_in: clock {
|
||||||
|
compatible = "fixed-clock";
|
||||||
|
reg=<0>;
|
||||||
|
#clock-cells = <0>;
|
||||||
|
clock-frequency = <32768>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
...
|
||||||
};
|
};
|
||||||
|
|
|
@ -673,6 +673,7 @@ config ARCH_TEGRA
|
||||||
select HAVE_CLK
|
select HAVE_CLK
|
||||||
select HAVE_SMP
|
select HAVE_SMP
|
||||||
select MIGHT_HAVE_CACHE_L2X0
|
select MIGHT_HAVE_CACHE_L2X0
|
||||||
|
select SOC_BUS
|
||||||
select SPARSE_IRQ
|
select SPARSE_IRQ
|
||||||
select USE_OF
|
select USE_OF
|
||||||
help
|
help
|
||||||
|
|
|
@ -18,4 +18,17 @@ serial@70006300 {
|
||||||
pmc {
|
pmc {
|
||||||
nvidia,invert-interrupt;
|
nvidia,invert-interrupt;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
clocks {
|
||||||
|
compatible = "simple-bus";
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
|
||||||
|
clk32k_in: clock {
|
||||||
|
compatible = "fixed-clock";
|
||||||
|
reg=<0>;
|
||||||
|
#clock-cells = <0>;
|
||||||
|
clock-frequency = <32768>;
|
||||||
|
};
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -18,4 +18,17 @@ serial@70006300 {
|
||||||
pmc {
|
pmc {
|
||||||
nvidia,invert-interrupt;
|
nvidia,invert-interrupt;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
clocks {
|
||||||
|
compatible = "simple-bus";
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
|
||||||
|
clk32k_in: clock {
|
||||||
|
compatible = "fixed-clock";
|
||||||
|
reg=<0>;
|
||||||
|
#clock-cells = <0>;
|
||||||
|
clock-frequency = <32768>;
|
||||||
|
};
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -99,8 +99,10 @@ rtc {
|
||||||
};
|
};
|
||||||
|
|
||||||
pmc {
|
pmc {
|
||||||
compatible = "nvidia,tegra114-pmc", "nvidia,tegra30-pmc";
|
compatible = "nvidia,tegra114-pmc";
|
||||||
reg = <0x7000e400 0x400>;
|
reg = <0x7000e400 0x400>;
|
||||||
|
clocks = <&tegra_car 261>, <&clk32k_in>;
|
||||||
|
clock-names = "pclk", "clk32k_in";
|
||||||
};
|
};
|
||||||
|
|
||||||
iommu {
|
iommu {
|
||||||
|
|
|
@ -444,7 +444,20 @@ usb@c5004000 {
|
||||||
};
|
};
|
||||||
|
|
||||||
sdhci@c8000600 {
|
sdhci@c8000600 {
|
||||||
cd-gpios = <&gpio 23 0>; /* gpio PC7 */
|
cd-gpios = <&gpio 23 1>; /* gpio PC7 */
|
||||||
|
};
|
||||||
|
|
||||||
|
clocks {
|
||||||
|
compatible = "simple-bus";
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
|
||||||
|
clk32k_in: clock {
|
||||||
|
compatible = "fixed-clock";
|
||||||
|
reg=<0>;
|
||||||
|
#clock-cells = <0>;
|
||||||
|
clock-frequency = <32768>;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
sound {
|
sound {
|
||||||
|
|
|
@ -437,7 +437,7 @@ usb-phy@c5004400 {
|
||||||
|
|
||||||
sdhci@c8000200 {
|
sdhci@c8000200 {
|
||||||
status = "okay";
|
status = "okay";
|
||||||
cd-gpios = <&gpio 69 0>; /* gpio PI5 */
|
cd-gpios = <&gpio 69 1>; /* gpio PI5 */
|
||||||
wp-gpios = <&gpio 57 0>; /* gpio PH1 */
|
wp-gpios = <&gpio 57 0>; /* gpio PH1 */
|
||||||
power-gpios = <&gpio 155 0>; /* gpio PT3 */
|
power-gpios = <&gpio 155 0>; /* gpio PT3 */
|
||||||
bus-width = <4>;
|
bus-width = <4>;
|
||||||
|
@ -445,12 +445,25 @@ sdhci@c8000200 {
|
||||||
|
|
||||||
sdhci@c8000600 {
|
sdhci@c8000600 {
|
||||||
status = "okay";
|
status = "okay";
|
||||||
cd-gpios = <&gpio 58 0>; /* gpio PH2 */
|
cd-gpios = <&gpio 58 1>; /* gpio PH2 */
|
||||||
wp-gpios = <&gpio 59 0>; /* gpio PH3 */
|
wp-gpios = <&gpio 59 0>; /* gpio PH3 */
|
||||||
power-gpios = <&gpio 70 0>; /* gpio PI6 */
|
power-gpios = <&gpio 70 0>; /* gpio PI6 */
|
||||||
bus-width = <8>;
|
bus-width = <8>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
clocks {
|
||||||
|
compatible = "simple-bus";
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
|
||||||
|
clk32k_in: clock {
|
||||||
|
compatible = "fixed-clock";
|
||||||
|
reg=<0>;
|
||||||
|
#clock-cells = <0>;
|
||||||
|
clock-frequency = <32768>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
kbc {
|
kbc {
|
||||||
status = "okay";
|
status = "okay";
|
||||||
nvidia,debounce-delay-ms = <2>;
|
nvidia,debounce-delay-ms = <2>;
|
||||||
|
|
|
@ -436,7 +436,7 @@ usb-phy@c5004400 {
|
||||||
|
|
||||||
sdhci@c8000000 {
|
sdhci@c8000000 {
|
||||||
status = "okay";
|
status = "okay";
|
||||||
cd-gpios = <&gpio 173 0>; /* gpio PV5 */
|
cd-gpios = <&gpio 173 1>; /* gpio PV5 */
|
||||||
wp-gpios = <&gpio 57 0>; /* gpio PH1 */
|
wp-gpios = <&gpio 57 0>; /* gpio PH1 */
|
||||||
power-gpios = <&gpio 169 0>; /* gpio PV1 */
|
power-gpios = <&gpio 169 0>; /* gpio PV1 */
|
||||||
bus-width = <4>;
|
bus-width = <4>;
|
||||||
|
@ -447,6 +447,19 @@ sdhci@c8000600 {
|
||||||
bus-width = <8>;
|
bus-width = <8>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
clocks {
|
||||||
|
compatible = "simple-bus";
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
|
||||||
|
clk32k_in: clock {
|
||||||
|
compatible = "fixed-clock";
|
||||||
|
reg=<0>;
|
||||||
|
#clock-cells = <0>;
|
||||||
|
clock-frequency = <32768>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
gpio-keys {
|
gpio-keys {
|
||||||
compatible = "gpio-keys";
|
compatible = "gpio-keys";
|
||||||
|
|
||||||
|
|
|
@ -584,7 +584,7 @@ sdhci@c8000000 {
|
||||||
|
|
||||||
sdhci@c8000400 {
|
sdhci@c8000400 {
|
||||||
status = "okay";
|
status = "okay";
|
||||||
cd-gpios = <&gpio 69 0>; /* gpio PI5 */
|
cd-gpios = <&gpio 69 1>; /* gpio PI5 */
|
||||||
wp-gpios = <&gpio 57 0>; /* gpio PH1 */
|
wp-gpios = <&gpio 57 0>; /* gpio PH1 */
|
||||||
power-gpios = <&gpio 70 0>; /* gpio PI6 */
|
power-gpios = <&gpio 70 0>; /* gpio PI6 */
|
||||||
bus-width = <4>;
|
bus-width = <4>;
|
||||||
|
@ -595,6 +595,19 @@ sdhci@c8000600 {
|
||||||
bus-width = <8>;
|
bus-width = <8>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
clocks {
|
||||||
|
compatible = "simple-bus";
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
|
||||||
|
clk32k_in: clock {
|
||||||
|
compatible = "fixed-clock";
|
||||||
|
reg=<0>;
|
||||||
|
#clock-cells = <0>;
|
||||||
|
clock-frequency = <32768>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
gpio-keys {
|
gpio-keys {
|
||||||
compatible = "gpio-keys";
|
compatible = "gpio-keys";
|
||||||
|
|
||||||
|
|
|
@ -465,12 +465,25 @@ usb@c5008000 {
|
||||||
};
|
};
|
||||||
|
|
||||||
sdhci@c8000600 {
|
sdhci@c8000600 {
|
||||||
cd-gpios = <&gpio 58 0>; /* gpio PH2 */
|
cd-gpios = <&gpio 58 1>; /* gpio PH2 */
|
||||||
wp-gpios = <&gpio 59 0>; /* gpio PH3 */
|
wp-gpios = <&gpio 59 0>; /* gpio PH3 */
|
||||||
bus-width = <4>;
|
bus-width = <4>;
|
||||||
status = "okay";
|
status = "okay";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
clocks {
|
||||||
|
compatible = "simple-bus";
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
|
||||||
|
clk32k_in: clock {
|
||||||
|
compatible = "fixed-clock";
|
||||||
|
reg=<0>;
|
||||||
|
#clock-cells = <0>;
|
||||||
|
clock-frequency = <32768>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
regulators {
|
regulators {
|
||||||
compatible = "simple-bus";
|
compatible = "simple-bus";
|
||||||
|
|
||||||
|
|
|
@ -325,11 +325,24 @@ sdhci@c8000000 {
|
||||||
|
|
||||||
sdhci@c8000600 {
|
sdhci@c8000600 {
|
||||||
status = "okay";
|
status = "okay";
|
||||||
cd-gpios = <&gpio 121 0>; /* gpio PP1 */
|
cd-gpios = <&gpio 121 1>; /* gpio PP1 */
|
||||||
wp-gpios = <&gpio 122 0>; /* gpio PP2 */
|
wp-gpios = <&gpio 122 0>; /* gpio PP2 */
|
||||||
bus-width = <4>;
|
bus-width = <4>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
clocks {
|
||||||
|
compatible = "simple-bus";
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
|
||||||
|
clk32k_in: clock {
|
||||||
|
compatible = "fixed-clock";
|
||||||
|
reg=<0>;
|
||||||
|
#clock-cells = <0>;
|
||||||
|
clock-frequency = <32768>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
poweroff {
|
poweroff {
|
||||||
compatible = "gpio-poweroff";
|
compatible = "gpio-poweroff";
|
||||||
gpios = <&gpio 191 1>; /* gpio PX7, active low */
|
gpios = <&gpio 191 1>; /* gpio PX7, active low */
|
||||||
|
|
|
@ -520,7 +520,7 @@ sdhci@c8000000 {
|
||||||
|
|
||||||
sdhci@c8000400 {
|
sdhci@c8000400 {
|
||||||
status = "okay";
|
status = "okay";
|
||||||
cd-gpios = <&gpio 69 0>; /* gpio PI5 */
|
cd-gpios = <&gpio 69 1>; /* gpio PI5 */
|
||||||
wp-gpios = <&gpio 57 0>; /* gpio PH1 */
|
wp-gpios = <&gpio 57 0>; /* gpio PH1 */
|
||||||
power-gpios = <&gpio 70 0>; /* gpio PI6 */
|
power-gpios = <&gpio 70 0>; /* gpio PI6 */
|
||||||
bus-width = <4>;
|
bus-width = <4>;
|
||||||
|
@ -531,6 +531,19 @@ sdhci@c8000600 {
|
||||||
bus-width = <8>;
|
bus-width = <8>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
clocks {
|
||||||
|
compatible = "simple-bus";
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
|
||||||
|
clk32k_in: clock {
|
||||||
|
compatible = "fixed-clock";
|
||||||
|
reg=<0>;
|
||||||
|
#clock-cells = <0>;
|
||||||
|
clock-frequency = <32768>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
regulators {
|
regulators {
|
||||||
compatible = "simple-bus";
|
compatible = "simple-bus";
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
|
|
|
@ -510,6 +510,7 @@ usb@c5008000 {
|
||||||
|
|
||||||
sdhci@c8000400 {
|
sdhci@c8000400 {
|
||||||
status = "okay";
|
status = "okay";
|
||||||
|
cd-gpios = <&gpio 69 1>; /* gpio PI5 */
|
||||||
wp-gpios = <&gpio 173 0>; /* gpio PV5 */
|
wp-gpios = <&gpio 173 0>; /* gpio PV5 */
|
||||||
bus-width = <8>;
|
bus-width = <8>;
|
||||||
};
|
};
|
||||||
|
@ -519,6 +520,19 @@ sdhci@c8000600 {
|
||||||
bus-width = <8>;
|
bus-width = <8>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
clocks {
|
||||||
|
compatible = "simple-bus";
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
|
||||||
|
clk32k_in: clock {
|
||||||
|
compatible = "fixed-clock";
|
||||||
|
reg=<0>;
|
||||||
|
#clock-cells = <0>;
|
||||||
|
clock-frequency = <32768>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
kbc {
|
kbc {
|
||||||
status = "okay";
|
status = "okay";
|
||||||
nvidia,debounce-delay-ms = <20>;
|
nvidia,debounce-delay-ms = <20>;
|
||||||
|
|
|
@ -145,6 +145,7 @@ timer@60005000 {
|
||||||
0 1 0x04
|
0 1 0x04
|
||||||
0 41 0x04
|
0 41 0x04
|
||||||
0 42 0x04>;
|
0 42 0x04>;
|
||||||
|
clocks = <&tegra_car 5>;
|
||||||
};
|
};
|
||||||
|
|
||||||
tegra_car: clock {
|
tegra_car: clock {
|
||||||
|
@ -304,6 +305,7 @@ rtc {
|
||||||
compatible = "nvidia,tegra20-rtc";
|
compatible = "nvidia,tegra20-rtc";
|
||||||
reg = <0x7000e000 0x100>;
|
reg = <0x7000e000 0x100>;
|
||||||
interrupts = <0 2 0x04>;
|
interrupts = <0 2 0x04>;
|
||||||
|
clocks = <&tegra_car 4>;
|
||||||
};
|
};
|
||||||
|
|
||||||
i2c@7000c000 {
|
i2c@7000c000 {
|
||||||
|
@ -416,6 +418,8 @@ kbc {
|
||||||
pmc {
|
pmc {
|
||||||
compatible = "nvidia,tegra20-pmc";
|
compatible = "nvidia,tegra20-pmc";
|
||||||
reg = <0x7000e400 0x400>;
|
reg = <0x7000e400 0x400>;
|
||||||
|
clocks = <&tegra_car 110>, <&clk32k_in>;
|
||||||
|
clock-names = "pclk", "clk32k_in";
|
||||||
};
|
};
|
||||||
|
|
||||||
memory-controller@7000f000 {
|
memory-controller@7000f000 {
|
||||||
|
|
|
@ -257,7 +257,7 @@ pmc {
|
||||||
|
|
||||||
sdhci@78000000 {
|
sdhci@78000000 {
|
||||||
status = "okay";
|
status = "okay";
|
||||||
cd-gpios = <&gpio 69 0>; /* gpio PI5 */
|
cd-gpios = <&gpio 69 1>; /* gpio PI5 */
|
||||||
wp-gpios = <&gpio 155 0>; /* gpio PT3 */
|
wp-gpios = <&gpio 155 0>; /* gpio PT3 */
|
||||||
power-gpios = <&gpio 31 0>; /* gpio PD7 */
|
power-gpios = <&gpio 31 0>; /* gpio PD7 */
|
||||||
bus-width = <4>;
|
bus-width = <4>;
|
||||||
|
@ -268,6 +268,19 @@ sdhci@78000600 {
|
||||||
bus-width = <8>;
|
bus-width = <8>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
clocks {
|
||||||
|
compatible = "simple-bus";
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
|
||||||
|
clk32k_in: clock {
|
||||||
|
compatible = "fixed-clock";
|
||||||
|
reg=<0>;
|
||||||
|
#clock-cells = <0>;
|
||||||
|
clock-frequency = <32768>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
regulators {
|
regulators {
|
||||||
compatible = "simple-bus";
|
compatible = "simple-bus";
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
|
|
|
@ -311,7 +311,7 @@ pmc {
|
||||||
|
|
||||||
sdhci@78000000 {
|
sdhci@78000000 {
|
||||||
status = "okay";
|
status = "okay";
|
||||||
cd-gpios = <&gpio 69 0>; /* gpio PI5 */
|
cd-gpios = <&gpio 69 1>; /* gpio PI5 */
|
||||||
wp-gpios = <&gpio 155 0>; /* gpio PT3 */
|
wp-gpios = <&gpio 155 0>; /* gpio PT3 */
|
||||||
power-gpios = <&gpio 31 0>; /* gpio PD7 */
|
power-gpios = <&gpio 31 0>; /* gpio PD7 */
|
||||||
bus-width = <4>;
|
bus-width = <4>;
|
||||||
|
@ -322,6 +322,19 @@ sdhci@78000600 {
|
||||||
bus-width = <8>;
|
bus-width = <8>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
clocks {
|
||||||
|
compatible = "simple-bus";
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
|
||||||
|
clk32k_in: clock {
|
||||||
|
compatible = "fixed-clock";
|
||||||
|
reg=<0>;
|
||||||
|
#clock-cells = <0>;
|
||||||
|
clock-frequency = <32768>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
regulators {
|
regulators {
|
||||||
compatible = "simple-bus";
|
compatible = "simple-bus";
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
|
|
|
@ -148,6 +148,7 @@ timer@60005000 {
|
||||||
0 42 0x04
|
0 42 0x04
|
||||||
0 121 0x04
|
0 121 0x04
|
||||||
0 122 0x04>;
|
0 122 0x04>;
|
||||||
|
clocks = <&tegra_car 5>;
|
||||||
};
|
};
|
||||||
|
|
||||||
tegra_car: clock {
|
tegra_car: clock {
|
||||||
|
@ -291,6 +292,7 @@ rtc {
|
||||||
compatible = "nvidia,tegra30-rtc", "nvidia,tegra20-rtc";
|
compatible = "nvidia,tegra30-rtc", "nvidia,tegra20-rtc";
|
||||||
reg = <0x7000e000 0x100>;
|
reg = <0x7000e000 0x100>;
|
||||||
interrupts = <0 2 0x04>;
|
interrupts = <0 2 0x04>;
|
||||||
|
clocks = <&tegra_car 4>;
|
||||||
};
|
};
|
||||||
|
|
||||||
i2c@7000c000 {
|
i2c@7000c000 {
|
||||||
|
@ -423,8 +425,10 @@ kbc {
|
||||||
};
|
};
|
||||||
|
|
||||||
pmc {
|
pmc {
|
||||||
compatible = "nvidia,tegra20-pmc", "nvidia,tegra30-pmc";
|
compatible = "nvidia,tegra30-pmc";
|
||||||
reg = <0x7000e400 0x400>;
|
reg = <0x7000e400 0x400>;
|
||||||
|
clocks = <&tegra_car 218>, <&clk32k_in>;
|
||||||
|
clock-names = "pclk", "clk32k_in";
|
||||||
};
|
};
|
||||||
|
|
||||||
memory-controller {
|
memory-controller {
|
||||||
|
|
|
@ -10,6 +10,7 @@ obj-y += pm.o
|
||||||
obj-y += reset.o
|
obj-y += reset.o
|
||||||
obj-y += reset-handler.o
|
obj-y += reset-handler.o
|
||||||
obj-y += sleep.o
|
obj-y += sleep.o
|
||||||
|
obj-y += tegra.o
|
||||||
obj-$(CONFIG_CPU_IDLE) += cpuidle.o
|
obj-$(CONFIG_CPU_IDLE) += cpuidle.o
|
||||||
obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra20_speedo.o
|
obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra20_speedo.o
|
||||||
obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra2_emc.o
|
obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra2_emc.o
|
||||||
|
@ -27,9 +28,7 @@ obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
|
||||||
obj-$(CONFIG_CPU_FREQ) += cpu-tegra.o
|
obj-$(CONFIG_CPU_FREQ) += cpu-tegra.o
|
||||||
obj-$(CONFIG_TEGRA_PCI) += pcie.o
|
obj-$(CONFIG_TEGRA_PCI) += pcie.o
|
||||||
|
|
||||||
obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += board-dt-tegra20.o
|
obj-$(CONFIG_ARCH_TEGRA_114_SOC) += tegra114_speedo.o
|
||||||
obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += board-dt-tegra30.o
|
|
||||||
obj-$(CONFIG_ARCH_TEGRA_114_SOC) += board-dt-tegra114.o
|
|
||||||
ifeq ($(CONFIG_CPU_IDLE),y)
|
ifeq ($(CONFIG_CPU_IDLE),y)
|
||||||
obj-$(CONFIG_ARCH_TEGRA_114_SOC) += cpuidle-tegra114.o
|
obj-$(CONFIG_ARCH_TEGRA_114_SOC) += cpuidle-tegra114.o
|
||||||
endif
|
endif
|
||||||
|
|
|
@ -1,46 +0,0 @@
|
||||||
/*
|
|
||||||
* NVIDIA Tegra114 device tree board support
|
|
||||||
*
|
|
||||||
* Copyright (C) 2013 NVIDIA Corporation
|
|
||||||
*
|
|
||||||
* This software is licensed under the terms of the GNU General Public
|
|
||||||
* License version 2, as published by the Free Software Foundation, and
|
|
||||||
* may be copied, distributed, and modified under those terms.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <linux/of.h>
|
|
||||||
#include <linux/of_platform.h>
|
|
||||||
#include <linux/clocksource.h>
|
|
||||||
|
|
||||||
#include <asm/mach/arch.h>
|
|
||||||
|
|
||||||
#include "board.h"
|
|
||||||
#include "common.h"
|
|
||||||
|
|
||||||
static void __init tegra114_dt_init(void)
|
|
||||||
{
|
|
||||||
of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const char * const tegra114_dt_board_compat[] = {
|
|
||||||
"nvidia,tegra114",
|
|
||||||
NULL,
|
|
||||||
};
|
|
||||||
|
|
||||||
DT_MACHINE_START(TEGRA114_DT, "NVIDIA Tegra114 (Flattened Device Tree)")
|
|
||||||
.smp = smp_ops(tegra_smp_ops),
|
|
||||||
.map_io = tegra_map_common_io,
|
|
||||||
.init_early = tegra114_init_early,
|
|
||||||
.init_irq = tegra_dt_init_irq,
|
|
||||||
.init_time = clocksource_of_init,
|
|
||||||
.init_machine = tegra114_dt_init,
|
|
||||||
.init_late = tegra_init_late,
|
|
||||||
.restart = tegra_assert_system_reset,
|
|
||||||
.dt_compat = tegra114_dt_board_compat,
|
|
||||||
MACHINE_END
|
|
|
@ -1,60 +0,0 @@
|
||||||
/*
|
|
||||||
* arch/arm/mach-tegra/board-dt-tegra30.c
|
|
||||||
*
|
|
||||||
* NVIDIA Tegra30 device tree board support
|
|
||||||
*
|
|
||||||
* Copyright (C) 2011 NVIDIA Corporation
|
|
||||||
*
|
|
||||||
* Derived from:
|
|
||||||
*
|
|
||||||
* arch/arm/mach-tegra/board-dt-tegra20.c
|
|
||||||
*
|
|
||||||
* Copyright (C) 2010 Secret Lab Technologies, Ltd.
|
|
||||||
* Copyright (C) 2010 Google, Inc.
|
|
||||||
*
|
|
||||||
* This software is licensed under the terms of the GNU General Public
|
|
||||||
* License version 2, as published by the Free Software Foundation, and
|
|
||||||
* may be copied, distributed, and modified under those terms.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <linux/clocksource.h>
|
|
||||||
#include <linux/kernel.h>
|
|
||||||
#include <linux/of.h>
|
|
||||||
#include <linux/of_address.h>
|
|
||||||
#include <linux/of_fdt.h>
|
|
||||||
#include <linux/of_irq.h>
|
|
||||||
#include <linux/of_platform.h>
|
|
||||||
|
|
||||||
#include <asm/mach/arch.h>
|
|
||||||
|
|
||||||
#include "board.h"
|
|
||||||
#include "common.h"
|
|
||||||
#include "iomap.h"
|
|
||||||
|
|
||||||
static void __init tegra30_dt_init(void)
|
|
||||||
{
|
|
||||||
of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const char *tegra30_dt_board_compat[] = {
|
|
||||||
"nvidia,tegra30",
|
|
||||||
NULL
|
|
||||||
};
|
|
||||||
|
|
||||||
DT_MACHINE_START(TEGRA30_DT, "NVIDIA Tegra30 (Flattened Device Tree)")
|
|
||||||
.smp = smp_ops(tegra_smp_ops),
|
|
||||||
.map_io = tegra_map_common_io,
|
|
||||||
.init_early = tegra30_init_early,
|
|
||||||
.init_irq = tegra_dt_init_irq,
|
|
||||||
.init_time = clocksource_of_init,
|
|
||||||
.init_machine = tegra30_dt_init,
|
|
||||||
.init_late = tegra_init_late,
|
|
||||||
.restart = tegra_assert_system_reset,
|
|
||||||
.dt_compat = tegra30_dt_board_compat,
|
|
||||||
MACHINE_END
|
|
|
@ -62,7 +62,11 @@ int __init harmony_pcie_init(void)
|
||||||
goto err_reg;
|
goto err_reg;
|
||||||
}
|
}
|
||||||
|
|
||||||
regulator_enable(regulator);
|
err = regulator_enable(regulator);
|
||||||
|
if (err) {
|
||||||
|
pr_err("%s: regulator_enable failed: %d\n", __func__, err);
|
||||||
|
goto err_en;
|
||||||
|
}
|
||||||
|
|
||||||
err = tegra_pcie_init(true, true);
|
err = tegra_pcie_init(true, true);
|
||||||
if (err) {
|
if (err) {
|
||||||
|
@ -74,6 +78,7 @@ int __init harmony_pcie_init(void)
|
||||||
|
|
||||||
err_pcie:
|
err_pcie:
|
||||||
regulator_disable(regulator);
|
regulator_disable(regulator);
|
||||||
|
err_en:
|
||||||
regulator_put(regulator);
|
regulator_put(regulator);
|
||||||
err_reg:
|
err_reg:
|
||||||
gpio_free(en_vdd_1v05);
|
gpio_free(en_vdd_1v05);
|
||||||
|
|
|
@ -26,9 +26,7 @@
|
||||||
|
|
||||||
void tegra_assert_system_reset(char mode, const char *cmd);
|
void tegra_assert_system_reset(char mode, const char *cmd);
|
||||||
|
|
||||||
void __init tegra20_init_early(void);
|
void __init tegra_init_early(void);
|
||||||
void __init tegra30_init_early(void);
|
|
||||||
void __init tegra114_init_early(void);
|
|
||||||
void __init tegra_map_common_io(void);
|
void __init tegra_map_common_io(void);
|
||||||
void __init tegra_init_irq(void);
|
void __init tegra_init_irq(void);
|
||||||
void __init tegra_dt_init_irq(void);
|
void __init tegra_dt_init_irq(void);
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "fuse.h"
|
#include "fuse.h"
|
||||||
#include "iomap.h"
|
#include "iomap.h"
|
||||||
|
#include "irq.h"
|
||||||
#include "pmc.h"
|
#include "pmc.h"
|
||||||
#include "apbio.h"
|
#include "apbio.h"
|
||||||
#include "sleep.h"
|
#include "sleep.h"
|
||||||
|
@ -61,8 +62,10 @@ u32 tegra_uart_config[4] = {
|
||||||
void __init tegra_dt_init_irq(void)
|
void __init tegra_dt_init_irq(void)
|
||||||
{
|
{
|
||||||
tegra_clocks_init();
|
tegra_clocks_init();
|
||||||
|
tegra_pmc_init();
|
||||||
tegra_init_irq();
|
tegra_init_irq();
|
||||||
irqchip_init();
|
irqchip_init();
|
||||||
|
tegra_legacy_irq_syscore_init();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -94,40 +97,18 @@ static void __init tegra_init_cache(void)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __init tegra_init_early(void)
|
void __init tegra_init_early(void)
|
||||||
{
|
{
|
||||||
tegra_cpu_reset_handler_init();
|
tegra_cpu_reset_handler_init();
|
||||||
tegra_apb_io_init();
|
tegra_apb_io_init();
|
||||||
tegra_init_fuse();
|
tegra_init_fuse();
|
||||||
tegra_init_cache();
|
tegra_init_cache();
|
||||||
tegra_pmc_init();
|
|
||||||
tegra_powergate_init();
|
tegra_powergate_init();
|
||||||
|
tegra_hotplug_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_ARCH_TEGRA_2x_SOC
|
|
||||||
void __init tegra20_init_early(void)
|
|
||||||
{
|
|
||||||
tegra_init_early();
|
|
||||||
tegra20_hotplug_init();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef CONFIG_ARCH_TEGRA_3x_SOC
|
|
||||||
void __init tegra30_init_early(void)
|
|
||||||
{
|
|
||||||
tegra_init_early();
|
|
||||||
tegra30_hotplug_init();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef CONFIG_ARCH_TEGRA_114_SOC
|
|
||||||
void __init tegra114_init_early(void)
|
|
||||||
{
|
|
||||||
tegra_init_early();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void __init tegra_init_late(void)
|
void __init tegra_init_late(void)
|
||||||
{
|
{
|
||||||
|
tegra_init_suspend();
|
||||||
tegra_powergate_debugfs_init();
|
tegra_powergate_debugfs_init();
|
||||||
}
|
}
|
||||||
|
|
|
@ -130,10 +130,6 @@ static bool tegra20_cpu_cluster_power_down(struct cpuidle_device *dev,
|
||||||
struct cpuidle_driver *drv,
|
struct cpuidle_driver *drv,
|
||||||
int index)
|
int index)
|
||||||
{
|
{
|
||||||
struct cpuidle_state *state = &drv->states[index];
|
|
||||||
u32 cpu_on_time = state->exit_latency;
|
|
||||||
u32 cpu_off_time = state->target_residency - state->exit_latency;
|
|
||||||
|
|
||||||
while (tegra20_cpu_is_resettable_soon())
|
while (tegra20_cpu_is_resettable_soon())
|
||||||
cpu_relax();
|
cpu_relax();
|
||||||
|
|
||||||
|
@ -142,7 +138,7 @@ static bool tegra20_cpu_cluster_power_down(struct cpuidle_device *dev,
|
||||||
|
|
||||||
clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &dev->cpu);
|
clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &dev->cpu);
|
||||||
|
|
||||||
tegra_idle_lp2_last(cpu_on_time, cpu_off_time);
|
tegra_idle_lp2_last();
|
||||||
|
|
||||||
clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &dev->cpu);
|
clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &dev->cpu);
|
||||||
|
|
||||||
|
|
|
@ -72,10 +72,6 @@ static bool tegra30_cpu_cluster_power_down(struct cpuidle_device *dev,
|
||||||
struct cpuidle_driver *drv,
|
struct cpuidle_driver *drv,
|
||||||
int index)
|
int index)
|
||||||
{
|
{
|
||||||
struct cpuidle_state *state = &drv->states[index];
|
|
||||||
u32 cpu_on_time = state->exit_latency;
|
|
||||||
u32 cpu_off_time = state->target_residency - state->exit_latency;
|
|
||||||
|
|
||||||
/* All CPUs entering LP2 is not working.
|
/* All CPUs entering LP2 is not working.
|
||||||
* Don't let CPU0 enter LP2 when any secondary CPU is online.
|
* Don't let CPU0 enter LP2 when any secondary CPU is online.
|
||||||
*/
|
*/
|
||||||
|
@ -86,7 +82,7 @@ static bool tegra30_cpu_cluster_power_down(struct cpuidle_device *dev,
|
||||||
|
|
||||||
clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &dev->cpu);
|
clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &dev->cpu);
|
||||||
|
|
||||||
tegra_idle_lp2_last(cpu_on_time, cpu_off_time);
|
tegra_idle_lp2_last();
|
||||||
|
|
||||||
clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &dev->cpu);
|
clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &dev->cpu);
|
||||||
|
|
||||||
|
@ -102,12 +98,8 @@ static bool tegra30_cpu_core_power_down(struct cpuidle_device *dev,
|
||||||
|
|
||||||
smp_wmb();
|
smp_wmb();
|
||||||
|
|
||||||
save_cpu_arch_register();
|
|
||||||
|
|
||||||
cpu_suspend(0, tegra30_sleep_cpu_secondary_finish);
|
cpu_suspend(0, tegra30_sleep_cpu_secondary_finish);
|
||||||
|
|
||||||
restore_cpu_arch_register();
|
|
||||||
|
|
||||||
clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &dev->cpu);
|
clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &dev->cpu);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
* arch/arm/mach-tegra/fuse.c
|
* arch/arm/mach-tegra/fuse.c
|
||||||
*
|
*
|
||||||
* Copyright (C) 2010 Google, Inc.
|
* Copyright (C) 2010 Google, Inc.
|
||||||
|
* Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved.
|
||||||
*
|
*
|
||||||
* Author:
|
* Author:
|
||||||
* Colin Cross <ccross@android.com>
|
* Colin Cross <ccross@android.com>
|
||||||
|
@ -137,6 +138,9 @@ void tegra_init_fuse(void)
|
||||||
tegra_fuse_spare_bit = TEGRA30_FUSE_SPARE_BIT;
|
tegra_fuse_spare_bit = TEGRA30_FUSE_SPARE_BIT;
|
||||||
tegra_init_speedo_data = &tegra30_init_speedo_data;
|
tegra_init_speedo_data = &tegra30_init_speedo_data;
|
||||||
break;
|
break;
|
||||||
|
case TEGRA114:
|
||||||
|
tegra_init_speedo_data = &tegra114_init_speedo_data;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
pr_warn("Tegra: unknown chip id %d\n", tegra_chip_id);
|
pr_warn("Tegra: unknown chip id %d\n", tegra_chip_id);
|
||||||
tegra_fuse_spare_bit = TEGRA20_FUSE_SPARE_BIT;
|
tegra_fuse_spare_bit = TEGRA20_FUSE_SPARE_BIT;
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2010 Google, Inc.
|
* Copyright (C) 2010 Google, Inc.
|
||||||
|
* Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved.
|
||||||
*
|
*
|
||||||
* Author:
|
* Author:
|
||||||
* Colin Cross <ccross@android.com>
|
* Colin Cross <ccross@android.com>
|
||||||
|
@ -66,4 +67,10 @@ void tegra30_init_speedo_data(void);
|
||||||
static inline void tegra30_init_speedo_data(void) {}
|
static inline void tegra30_init_speedo_data(void) {}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_ARCH_TEGRA_114_SOC
|
||||||
|
void tegra114_init_speedo_data(void);
|
||||||
|
#else
|
||||||
|
static inline void tegra114_init_speedo_data(void) {}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -7,8 +7,5 @@
|
||||||
|
|
||||||
ENTRY(tegra_secondary_startup)
|
ENTRY(tegra_secondary_startup)
|
||||||
bl v7_invalidate_l1
|
bl v7_invalidate_l1
|
||||||
/* Enable coresight */
|
|
||||||
mov32 r0, 0xC5ACCE55
|
|
||||||
mcr p14, 0, r0, c7, c12, 6
|
|
||||||
b secondary_startup
|
b secondary_startup
|
||||||
ENDPROC(tegra_secondary_startup)
|
ENDPROC(tegra_secondary_startup)
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
/*
|
/*
|
||||||
*
|
|
||||||
* Copyright (C) 2002 ARM Ltd.
|
* Copyright (C) 2002 ARM Ltd.
|
||||||
* All Rights Reserved
|
* All Rights Reserved
|
||||||
* Copyright (c) 2010, 2012 NVIDIA Corporation. All rights reserved.
|
* Copyright (c) 2010, 2012-2013, NVIDIA Corporation. All rights reserved.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License version 2 as
|
* it under the terms of the GNU General Public License version 2 as
|
||||||
|
@ -15,6 +14,7 @@
|
||||||
#include <asm/cacheflush.h>
|
#include <asm/cacheflush.h>
|
||||||
#include <asm/smp_plat.h>
|
#include <asm/smp_plat.h>
|
||||||
|
|
||||||
|
#include "fuse.h"
|
||||||
#include "sleep.h"
|
#include "sleep.h"
|
||||||
|
|
||||||
static void (*tegra_hotplug_shutdown)(void);
|
static void (*tegra_hotplug_shutdown)(void);
|
||||||
|
@ -56,18 +56,13 @@ int tegra_cpu_disable(unsigned int cpu)
|
||||||
return cpu == 0 ? -EPERM : 0;
|
return cpu == 0 ? -EPERM : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_ARCH_TEGRA_2x_SOC
|
void __init tegra_hotplug_init(void)
|
||||||
extern void tegra20_hotplug_shutdown(void);
|
|
||||||
void __init tegra20_hotplug_init(void)
|
|
||||||
{
|
{
|
||||||
tegra_hotplug_shutdown = tegra20_hotplug_shutdown;
|
if (!IS_ENABLED(CONFIG_HOTPLUG_CPU))
|
||||||
}
|
return;
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef CONFIG_ARCH_TEGRA_3x_SOC
|
if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC) && tegra_chip_id == TEGRA20)
|
||||||
extern void tegra30_hotplug_shutdown(void);
|
tegra_hotplug_shutdown = tegra20_hotplug_shutdown;
|
||||||
void __init tegra30_hotplug_init(void)
|
if (IS_ENABLED(CONFIG_ARCH_TEGRA_3x_SOC) && tegra_chip_id == TEGRA30)
|
||||||
{
|
tegra_hotplug_shutdown = tegra30_hotplug_shutdown;
|
||||||
tegra_hotplug_shutdown = tegra30_hotplug_shutdown;
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
* Author:
|
* Author:
|
||||||
* Colin Cross <ccross@android.com>
|
* Colin Cross <ccross@android.com>
|
||||||
*
|
*
|
||||||
* Copyright (C) 2010, NVIDIA Corporation
|
* Copyright (C) 2010,2013, NVIDIA Corporation
|
||||||
*
|
*
|
||||||
* This software is licensed under the terms of the GNU General Public
|
* This software is licensed under the terms of the GNU General Public
|
||||||
* License version 2, as published by the Free Software Foundation, and
|
* License version 2, as published by the Free Software Foundation, and
|
||||||
|
@ -23,6 +23,7 @@
|
||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
#include <linux/of.h>
|
#include <linux/of.h>
|
||||||
#include <linux/irqchip/arm-gic.h>
|
#include <linux/irqchip/arm-gic.h>
|
||||||
|
#include <linux/syscore_ops.h>
|
||||||
|
|
||||||
#include "board.h"
|
#include "board.h"
|
||||||
#include "iomap.h"
|
#include "iomap.h"
|
||||||
|
@ -43,6 +44,7 @@
|
||||||
#define ICTLR_COP_IEP_CLASS 0x3c
|
#define ICTLR_COP_IEP_CLASS 0x3c
|
||||||
|
|
||||||
#define FIRST_LEGACY_IRQ 32
|
#define FIRST_LEGACY_IRQ 32
|
||||||
|
#define TEGRA_MAX_NUM_ICTLRS 5
|
||||||
|
|
||||||
#define SGI_MASK 0xFFFF
|
#define SGI_MASK 0xFFFF
|
||||||
|
|
||||||
|
@ -56,6 +58,15 @@ static void __iomem *ictlr_reg_base[] = {
|
||||||
IO_ADDRESS(TEGRA_QUINARY_ICTLR_BASE),
|
IO_ADDRESS(TEGRA_QUINARY_ICTLR_BASE),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef CONFIG_PM_SLEEP
|
||||||
|
static u32 cop_ier[TEGRA_MAX_NUM_ICTLRS];
|
||||||
|
static u32 cop_iep[TEGRA_MAX_NUM_ICTLRS];
|
||||||
|
static u32 cpu_ier[TEGRA_MAX_NUM_ICTLRS];
|
||||||
|
static u32 cpu_iep[TEGRA_MAX_NUM_ICTLRS];
|
||||||
|
|
||||||
|
static u32 ictlr_wake_mask[TEGRA_MAX_NUM_ICTLRS];
|
||||||
|
#endif
|
||||||
|
|
||||||
bool tegra_pending_sgi(void)
|
bool tegra_pending_sgi(void)
|
||||||
{
|
{
|
||||||
u32 pending_set;
|
u32 pending_set;
|
||||||
|
@ -125,6 +136,87 @@ static int tegra_retrigger(struct irq_data *d)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_PM_SLEEP
|
||||||
|
static int tegra_set_wake(struct irq_data *d, unsigned int enable)
|
||||||
|
{
|
||||||
|
u32 irq = d->irq;
|
||||||
|
u32 index, mask;
|
||||||
|
|
||||||
|
if (irq < FIRST_LEGACY_IRQ ||
|
||||||
|
irq >= FIRST_LEGACY_IRQ + num_ictlrs * 32)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
index = ((irq - FIRST_LEGACY_IRQ) / 32);
|
||||||
|
mask = BIT((irq - FIRST_LEGACY_IRQ) % 32);
|
||||||
|
if (enable)
|
||||||
|
ictlr_wake_mask[index] |= mask;
|
||||||
|
else
|
||||||
|
ictlr_wake_mask[index] &= ~mask;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tegra_legacy_irq_suspend(void)
|
||||||
|
{
|
||||||
|
unsigned long flags;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
local_irq_save(flags);
|
||||||
|
for (i = 0; i < num_ictlrs; i++) {
|
||||||
|
void __iomem *ictlr = ictlr_reg_base[i];
|
||||||
|
/* Save interrupt state */
|
||||||
|
cpu_ier[i] = readl_relaxed(ictlr + ICTLR_CPU_IER);
|
||||||
|
cpu_iep[i] = readl_relaxed(ictlr + ICTLR_CPU_IEP_CLASS);
|
||||||
|
cop_ier[i] = readl_relaxed(ictlr + ICTLR_COP_IER);
|
||||||
|
cop_iep[i] = readl_relaxed(ictlr + ICTLR_COP_IEP_CLASS);
|
||||||
|
|
||||||
|
/* Disable COP interrupts */
|
||||||
|
writel_relaxed(~0ul, ictlr + ICTLR_COP_IER_CLR);
|
||||||
|
|
||||||
|
/* Disable CPU interrupts */
|
||||||
|
writel_relaxed(~0ul, ictlr + ICTLR_CPU_IER_CLR);
|
||||||
|
|
||||||
|
/* Enable the wakeup sources of ictlr */
|
||||||
|
writel_relaxed(ictlr_wake_mask[i], ictlr + ICTLR_CPU_IER_SET);
|
||||||
|
}
|
||||||
|
local_irq_restore(flags);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tegra_legacy_irq_resume(void)
|
||||||
|
{
|
||||||
|
unsigned long flags;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
local_irq_save(flags);
|
||||||
|
for (i = 0; i < num_ictlrs; i++) {
|
||||||
|
void __iomem *ictlr = ictlr_reg_base[i];
|
||||||
|
writel_relaxed(cpu_iep[i], ictlr + ICTLR_CPU_IEP_CLASS);
|
||||||
|
writel_relaxed(~0ul, ictlr + ICTLR_CPU_IER_CLR);
|
||||||
|
writel_relaxed(cpu_ier[i], ictlr + ICTLR_CPU_IER_SET);
|
||||||
|
writel_relaxed(cop_iep[i], ictlr + ICTLR_COP_IEP_CLASS);
|
||||||
|
writel_relaxed(~0ul, ictlr + ICTLR_COP_IER_CLR);
|
||||||
|
writel_relaxed(cop_ier[i], ictlr + ICTLR_COP_IER_SET);
|
||||||
|
}
|
||||||
|
local_irq_restore(flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct syscore_ops tegra_legacy_irq_syscore_ops = {
|
||||||
|
.suspend = tegra_legacy_irq_suspend,
|
||||||
|
.resume = tegra_legacy_irq_resume,
|
||||||
|
};
|
||||||
|
|
||||||
|
int tegra_legacy_irq_syscore_init(void)
|
||||||
|
{
|
||||||
|
register_syscore_ops(&tegra_legacy_irq_syscore_ops);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#define tegra_set_wake NULL
|
||||||
|
#endif
|
||||||
|
|
||||||
void __init tegra_init_irq(void)
|
void __init tegra_init_irq(void)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
@ -150,6 +242,8 @@ void __init tegra_init_irq(void)
|
||||||
gic_arch_extn.irq_mask = tegra_mask;
|
gic_arch_extn.irq_mask = tegra_mask;
|
||||||
gic_arch_extn.irq_unmask = tegra_unmask;
|
gic_arch_extn.irq_unmask = tegra_unmask;
|
||||||
gic_arch_extn.irq_retrigger = tegra_retrigger;
|
gic_arch_extn.irq_retrigger = tegra_retrigger;
|
||||||
|
gic_arch_extn.irq_set_wake = tegra_set_wake;
|
||||||
|
gic_arch_extn.flags = IRQCHIP_MASK_ON_SUSPEND;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check if there is a devicetree present, since the GIC will be
|
* Check if there is a devicetree present, since the GIC will be
|
||||||
|
|
|
@ -19,4 +19,10 @@
|
||||||
|
|
||||||
bool tegra_pending_sgi(void);
|
bool tegra_pending_sgi(void);
|
||||||
|
|
||||||
|
#ifdef CONFIG_PM_SLEEP
|
||||||
|
int tegra_legacy_irq_syscore_init(void);
|
||||||
|
#else
|
||||||
|
static inline int tegra_legacy_irq_syscore_init(void) { return 0; }
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -26,22 +26,16 @@
|
||||||
#include <asm/smp_scu.h>
|
#include <asm/smp_scu.h>
|
||||||
#include <asm/smp_plat.h>
|
#include <asm/smp_plat.h>
|
||||||
|
|
||||||
#include <mach/powergate.h>
|
|
||||||
|
|
||||||
#include "fuse.h"
|
#include "fuse.h"
|
||||||
#include "flowctrl.h"
|
#include "flowctrl.h"
|
||||||
#include "reset.h"
|
#include "reset.h"
|
||||||
|
#include "pmc.h"
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "iomap.h"
|
#include "iomap.h"
|
||||||
|
|
||||||
extern void tegra_secondary_startup(void);
|
|
||||||
|
|
||||||
static cpumask_t tegra_cpu_init_mask;
|
static cpumask_t tegra_cpu_init_mask;
|
||||||
|
|
||||||
#define EVP_CPU_RESET_VECTOR \
|
|
||||||
(IO_ADDRESS(TEGRA_EXCEPTION_VECTORS_BASE) + 0x100)
|
|
||||||
|
|
||||||
static void __cpuinit tegra_secondary_init(unsigned int cpu)
|
static void __cpuinit tegra_secondary_init(unsigned int cpu)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
@ -54,25 +48,43 @@ static void __cpuinit tegra_secondary_init(unsigned int cpu)
|
||||||
cpumask_set_cpu(cpu, &tegra_cpu_init_mask);
|
cpumask_set_cpu(cpu, &tegra_cpu_init_mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int tegra20_power_up_cpu(unsigned int cpu)
|
|
||||||
|
static int tegra20_boot_secondary(unsigned int cpu, struct task_struct *idle)
|
||||||
{
|
{
|
||||||
/* Enable the CPU clock. */
|
cpu = cpu_logical_map(cpu);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Force the CPU into reset. The CPU must remain in reset when
|
||||||
|
* the flow controller state is cleared (which will cause the
|
||||||
|
* flow controller to stop driving reset if the CPU has been
|
||||||
|
* power-gated via the flow controller). This will have no
|
||||||
|
* effect on first boot of the CPU since it should already be
|
||||||
|
* in reset.
|
||||||
|
*/
|
||||||
|
tegra_put_cpu_in_reset(cpu);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Unhalt the CPU. If the flow controller was used to
|
||||||
|
* power-gate the CPU this will cause the flow controller to
|
||||||
|
* stop driving reset. The CPU will remain in reset because the
|
||||||
|
* clock and reset block is now driving reset.
|
||||||
|
*/
|
||||||
|
flowctrl_write_cpu_halt(cpu, 0);
|
||||||
|
|
||||||
tegra_enable_cpu_clock(cpu);
|
tegra_enable_cpu_clock(cpu);
|
||||||
|
flowctrl_write_cpu_csr(cpu, 0); /* Clear flow controller CSR. */
|
||||||
/* Clear flow controller CSR. */
|
tegra_cpu_out_of_reset(cpu);
|
||||||
flowctrl_write_cpu_csr(cpu, 0);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int tegra30_power_up_cpu(unsigned int cpu)
|
static int tegra30_boot_secondary(unsigned int cpu, struct task_struct *idle)
|
||||||
{
|
{
|
||||||
int ret, pwrgateid;
|
int ret;
|
||||||
unsigned long timeout;
|
unsigned long timeout;
|
||||||
|
|
||||||
pwrgateid = tegra_cpu_powergate_id(cpu);
|
cpu = cpu_logical_map(cpu);
|
||||||
if (pwrgateid < 0)
|
tegra_put_cpu_in_reset(cpu);
|
||||||
return pwrgateid;
|
flowctrl_write_cpu_halt(cpu, 0);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The power up sequence of cold boot CPU and warm boot CPU
|
* 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)
|
||||||
* the IO clamps.
|
* the IO clamps.
|
||||||
* For cold boot CPU, do not wait. After the cold boot CPU be
|
* For cold boot CPU, do not wait. After the cold boot CPU be
|
||||||
* booted, it will run to tegra_secondary_init() and set
|
* booted, it will run to tegra_secondary_init() and set
|
||||||
* tegra_cpu_init_mask which influences what tegra30_power_up_cpu()
|
* tegra_cpu_init_mask which influences what tegra30_boot_secondary()
|
||||||
* next time around.
|
* next time around.
|
||||||
*/
|
*/
|
||||||
if (cpumask_test_cpu(cpu, &tegra_cpu_init_mask)) {
|
if (cpumask_test_cpu(cpu, &tegra_cpu_init_mask)) {
|
||||||
timeout = jiffies + msecs_to_jiffies(50);
|
timeout = jiffies + msecs_to_jiffies(50);
|
||||||
do {
|
do {
|
||||||
if (!tegra_powergate_is_powered(pwrgateid))
|
if (tegra_pmc_cpu_is_powered(cpu))
|
||||||
goto remove_clamps;
|
goto remove_clamps;
|
||||||
udelay(10);
|
udelay(10);
|
||||||
} while (time_before(jiffies, timeout));
|
} while (time_before(jiffies, timeout));
|
||||||
|
@ -103,14 +115,14 @@ static int tegra30_power_up_cpu(unsigned int cpu)
|
||||||
* be un-gated by un-toggling the power gate register
|
* be un-gated by un-toggling the power gate register
|
||||||
* manually.
|
* manually.
|
||||||
*/
|
*/
|
||||||
if (!tegra_powergate_is_powered(pwrgateid)) {
|
if (!tegra_pmc_cpu_is_powered(cpu)) {
|
||||||
ret = tegra_powergate_power_on(pwrgateid);
|
ret = tegra_pmc_cpu_power_on(cpu);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
/* Wait for the power to come up. */
|
/* Wait for the power to come up. */
|
||||||
timeout = jiffies + msecs_to_jiffies(100);
|
timeout = jiffies + msecs_to_jiffies(100);
|
||||||
while (tegra_powergate_is_powered(pwrgateid)) {
|
while (tegra_pmc_cpu_is_powered(cpu)) {
|
||||||
if (time_after(jiffies, timeout))
|
if (time_after(jiffies, timeout))
|
||||||
return -ETIMEDOUT;
|
return -ETIMEDOUT;
|
||||||
udelay(10);
|
udelay(10);
|
||||||
|
@ -123,57 +135,34 @@ static int tegra30_power_up_cpu(unsigned int cpu)
|
||||||
udelay(10);
|
udelay(10);
|
||||||
|
|
||||||
/* Remove I/O clamps. */
|
/* Remove I/O clamps. */
|
||||||
ret = tegra_powergate_remove_clamping(pwrgateid);
|
ret = tegra_pmc_cpu_remove_clamping(cpu);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
udelay(10);
|
udelay(10);
|
||||||
|
|
||||||
/* Clear flow controller CSR. */
|
flowctrl_write_cpu_csr(cpu, 0); /* Clear flow controller CSR. */
|
||||||
flowctrl_write_cpu_csr(cpu, 0);
|
tegra_cpu_out_of_reset(cpu);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __cpuinit tegra_boot_secondary(unsigned int cpu, struct task_struct *idle)
|
static int tegra114_boot_secondary(unsigned int cpu, struct task_struct *idle)
|
||||||
{
|
{
|
||||||
int status;
|
|
||||||
|
|
||||||
cpu = cpu_logical_map(cpu);
|
cpu = cpu_logical_map(cpu);
|
||||||
|
return tegra_pmc_cpu_power_on(cpu);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
static int __cpuinit tegra_boot_secondary(unsigned int cpu,
|
||||||
* Force the CPU into reset. The CPU must remain in reset when the
|
struct task_struct *idle)
|
||||||
* flow controller state is cleared (which will cause the flow
|
{
|
||||||
* controller to stop driving reset if the CPU has been power-gated
|
if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC) && tegra_chip_id == TEGRA20)
|
||||||
* via the flow controller). This will have no effect on first boot
|
return tegra20_boot_secondary(cpu, idle);
|
||||||
* of the CPU since it should already be in reset.
|
if (IS_ENABLED(CONFIG_ARCH_TEGRA_3x_SOC) && tegra_chip_id == TEGRA30)
|
||||||
*/
|
return tegra30_boot_secondary(cpu, idle);
|
||||||
tegra_put_cpu_in_reset(cpu);
|
if (IS_ENABLED(CONFIG_ARCH_TEGRA_114_SOC) && tegra_chip_id == TEGRA114)
|
||||||
|
return tegra114_boot_secondary(cpu, idle);
|
||||||
|
|
||||||
/*
|
return -EINVAL;
|
||||||
* Unhalt the CPU. If the flow controller was used to power-gate the
|
|
||||||
* CPU this will cause the flow controller to stop driving reset.
|
|
||||||
* The CPU will remain in reset because the clock and reset block
|
|
||||||
* is now driving reset.
|
|
||||||
*/
|
|
||||||
flowctrl_write_cpu_halt(cpu, 0);
|
|
||||||
|
|
||||||
switch (tegra_chip_id) {
|
|
||||||
case TEGRA20:
|
|
||||||
status = tegra20_power_up_cpu(cpu);
|
|
||||||
break;
|
|
||||||
case TEGRA30:
|
|
||||||
status = tegra30_power_up_cpu(cpu);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
status = -EINVAL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (status)
|
|
||||||
goto done;
|
|
||||||
|
|
||||||
/* Take the CPU out of reset. */
|
|
||||||
tegra_cpu_out_of_reset(cpu);
|
|
||||||
done:
|
|
||||||
return status;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __init tegra_smp_prepare_cpus(unsigned int max_cpus)
|
static void __init tegra_smp_prepare_cpus(unsigned int max_cpus)
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
#include <linux/cpumask.h>
|
#include <linux/cpumask.h>
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
#include <linux/cpu_pm.h>
|
#include <linux/cpu_pm.h>
|
||||||
#include <linux/clk.h>
|
#include <linux/suspend.h>
|
||||||
#include <linux/err.h>
|
#include <linux/err.h>
|
||||||
#include <linux/clk/tegra.h>
|
#include <linux/clk/tegra.h>
|
||||||
|
|
||||||
|
@ -37,67 +37,13 @@
|
||||||
#include "reset.h"
|
#include "reset.h"
|
||||||
#include "flowctrl.h"
|
#include "flowctrl.h"
|
||||||
#include "fuse.h"
|
#include "fuse.h"
|
||||||
|
#include "pmc.h"
|
||||||
#include "sleep.h"
|
#include "sleep.h"
|
||||||
|
|
||||||
#define TEGRA_POWER_CPU_PWRREQ_OE (1 << 16) /* CPU pwr req enable */
|
|
||||||
|
|
||||||
#define PMC_CTRL 0x0
|
|
||||||
#define PMC_CPUPWRGOOD_TIMER 0xc8
|
|
||||||
#define PMC_CPUPWROFF_TIMER 0xcc
|
|
||||||
|
|
||||||
#ifdef CONFIG_PM_SLEEP
|
#ifdef CONFIG_PM_SLEEP
|
||||||
static unsigned int g_diag_reg;
|
|
||||||
static DEFINE_SPINLOCK(tegra_lp2_lock);
|
static DEFINE_SPINLOCK(tegra_lp2_lock);
|
||||||
static void __iomem *pmc = IO_ADDRESS(TEGRA_PMC_BASE);
|
|
||||||
static struct clk *tegra_pclk;
|
|
||||||
void (*tegra_tear_down_cpu)(void);
|
void (*tegra_tear_down_cpu)(void);
|
||||||
|
|
||||||
void save_cpu_arch_register(void)
|
|
||||||
{
|
|
||||||
/* read diagnostic register */
|
|
||||||
asm("mrc p15, 0, %0, c15, c0, 1" : "=r"(g_diag_reg) : : "cc");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
void restore_cpu_arch_register(void)
|
|
||||||
{
|
|
||||||
/* write diagnostic register */
|
|
||||||
asm("mcr p15, 0, %0, c15, c0, 1" : : "r"(g_diag_reg) : "cc");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void set_power_timers(unsigned long us_on, unsigned long us_off)
|
|
||||||
{
|
|
||||||
unsigned long long ticks;
|
|
||||||
unsigned long long pclk;
|
|
||||||
unsigned long rate;
|
|
||||||
static unsigned long tegra_last_pclk;
|
|
||||||
|
|
||||||
if (tegra_pclk == NULL) {
|
|
||||||
tegra_pclk = clk_get_sys(NULL, "pclk");
|
|
||||||
WARN_ON(IS_ERR(tegra_pclk));
|
|
||||||
}
|
|
||||||
|
|
||||||
rate = clk_get_rate(tegra_pclk);
|
|
||||||
|
|
||||||
if (WARN_ON_ONCE(rate <= 0))
|
|
||||||
pclk = 100000000;
|
|
||||||
else
|
|
||||||
pclk = rate;
|
|
||||||
|
|
||||||
if ((rate != tegra_last_pclk)) {
|
|
||||||
ticks = (us_on * pclk) + 999999ull;
|
|
||||||
do_div(ticks, 1000000);
|
|
||||||
writel((unsigned long)ticks, pmc + PMC_CPUPWRGOOD_TIMER);
|
|
||||||
|
|
||||||
ticks = (us_off * pclk) + 999999ull;
|
|
||||||
do_div(ticks, 1000000);
|
|
||||||
writel((unsigned long)ticks, pmc + PMC_CPUPWROFF_TIMER);
|
|
||||||
wmb();
|
|
||||||
}
|
|
||||||
tegra_last_pclk = pclk;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* restore_cpu_complex
|
* restore_cpu_complex
|
||||||
*
|
*
|
||||||
|
@ -119,8 +65,6 @@ static void restore_cpu_complex(void)
|
||||||
tegra_cpu_clock_resume();
|
tegra_cpu_clock_resume();
|
||||||
|
|
||||||
flowctrl_cpu_suspend_exit(cpu);
|
flowctrl_cpu_suspend_exit(cpu);
|
||||||
|
|
||||||
restore_cpu_arch_register();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -145,8 +89,6 @@ static void suspend_cpu_complex(void)
|
||||||
tegra_cpu_clock_suspend();
|
tegra_cpu_clock_suspend();
|
||||||
|
|
||||||
flowctrl_cpu_suspend_enter(cpu);
|
flowctrl_cpu_suspend_enter(cpu);
|
||||||
|
|
||||||
save_cpu_arch_register();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void tegra_clear_cpu_in_lp2(int phy_cpu_id)
|
void tegra_clear_cpu_in_lp2(int phy_cpu_id)
|
||||||
|
@ -197,16 +139,9 @@ static int tegra_sleep_cpu(unsigned long v2p)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void tegra_idle_lp2_last(u32 cpu_on_time, u32 cpu_off_time)
|
void tegra_idle_lp2_last(void)
|
||||||
{
|
{
|
||||||
u32 mode;
|
tegra_pmc_pm_set(TEGRA_SUSPEND_LP2);
|
||||||
|
|
||||||
/* Only the last cpu down does the final suspend steps */
|
|
||||||
mode = readl(pmc + PMC_CTRL);
|
|
||||||
mode |= TEGRA_POWER_CPU_PWRREQ_OE;
|
|
||||||
writel(mode, pmc + PMC_CTRL);
|
|
||||||
|
|
||||||
set_power_timers(cpu_on_time, cpu_off_time);
|
|
||||||
|
|
||||||
cpu_cluster_pm_enter();
|
cpu_cluster_pm_enter();
|
||||||
suspend_cpu_complex();
|
suspend_cpu_complex();
|
||||||
|
@ -216,4 +151,81 @@ void tegra_idle_lp2_last(u32 cpu_on_time, u32 cpu_off_time)
|
||||||
restore_cpu_complex();
|
restore_cpu_complex();
|
||||||
cpu_cluster_pm_exit();
|
cpu_cluster_pm_exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum tegra_suspend_mode tegra_pm_validate_suspend_mode(
|
||||||
|
enum tegra_suspend_mode mode)
|
||||||
|
{
|
||||||
|
/* Tegra114 didn't support any suspending mode yet. */
|
||||||
|
if (tegra_chip_id == TEGRA114)
|
||||||
|
return TEGRA_SUSPEND_NONE;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The Tegra devices only support suspending to LP2 currently.
|
||||||
|
*/
|
||||||
|
if (mode > TEGRA_SUSPEND_LP2)
|
||||||
|
return TEGRA_SUSPEND_LP2;
|
||||||
|
|
||||||
|
return mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *lp_state[TEGRA_MAX_SUSPEND_MODE] = {
|
||||||
|
[TEGRA_SUSPEND_NONE] = "none",
|
||||||
|
[TEGRA_SUSPEND_LP2] = "LP2",
|
||||||
|
[TEGRA_SUSPEND_LP1] = "LP1",
|
||||||
|
[TEGRA_SUSPEND_LP0] = "LP0",
|
||||||
|
};
|
||||||
|
|
||||||
|
static int __cpuinit tegra_suspend_enter(suspend_state_t state)
|
||||||
|
{
|
||||||
|
enum tegra_suspend_mode mode = tegra_pmc_get_suspend_mode();
|
||||||
|
|
||||||
|
if (WARN_ON(mode < TEGRA_SUSPEND_NONE ||
|
||||||
|
mode >= TEGRA_MAX_SUSPEND_MODE))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
pr_info("Entering suspend state %s\n", lp_state[mode]);
|
||||||
|
|
||||||
|
tegra_pmc_pm_set(mode);
|
||||||
|
|
||||||
|
local_fiq_disable();
|
||||||
|
|
||||||
|
suspend_cpu_complex();
|
||||||
|
switch (mode) {
|
||||||
|
case TEGRA_SUSPEND_LP2:
|
||||||
|
tegra_set_cpu_in_lp2(0);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
cpu_suspend(PHYS_OFFSET - PAGE_OFFSET, &tegra_sleep_cpu);
|
||||||
|
|
||||||
|
switch (mode) {
|
||||||
|
case TEGRA_SUSPEND_LP2:
|
||||||
|
tegra_clear_cpu_in_lp2(0);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
restore_cpu_complex();
|
||||||
|
|
||||||
|
local_fiq_enable();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct platform_suspend_ops tegra_suspend_ops = {
|
||||||
|
.valid = suspend_valid_only_mem,
|
||||||
|
.enter = tegra_suspend_enter,
|
||||||
|
};
|
||||||
|
|
||||||
|
void __init tegra_init_suspend(void)
|
||||||
|
{
|
||||||
|
if (tegra_pmc_get_suspend_mode() == TEGRA_SUSPEND_NONE)
|
||||||
|
return;
|
||||||
|
|
||||||
|
tegra_pmc_suspend_init();
|
||||||
|
|
||||||
|
suspend_set_ops(&tegra_suspend_ops);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -21,6 +21,8 @@
|
||||||
#ifndef _MACH_TEGRA_PM_H_
|
#ifndef _MACH_TEGRA_PM_H_
|
||||||
#define _MACH_TEGRA_PM_H_
|
#define _MACH_TEGRA_PM_H_
|
||||||
|
|
||||||
|
#include "pmc.h"
|
||||||
|
|
||||||
extern unsigned long l2x0_saved_regs_addr;
|
extern unsigned long l2x0_saved_regs_addr;
|
||||||
|
|
||||||
void save_cpu_arch_register(void);
|
void save_cpu_arch_register(void);
|
||||||
|
@ -29,7 +31,20 @@ void restore_cpu_arch_register(void);
|
||||||
void tegra_clear_cpu_in_lp2(int phy_cpu_id);
|
void tegra_clear_cpu_in_lp2(int phy_cpu_id);
|
||||||
bool tegra_set_cpu_in_lp2(int phy_cpu_id);
|
bool tegra_set_cpu_in_lp2(int phy_cpu_id);
|
||||||
|
|
||||||
void tegra_idle_lp2_last(u32 cpu_on_time, u32 cpu_off_time);
|
void tegra_idle_lp2_last(void);
|
||||||
extern void (*tegra_tear_down_cpu)(void);
|
extern void (*tegra_tear_down_cpu)(void);
|
||||||
|
|
||||||
|
#ifdef CONFIG_PM_SLEEP
|
||||||
|
enum tegra_suspend_mode tegra_pm_validate_suspend_mode(
|
||||||
|
enum tegra_suspend_mode mode);
|
||||||
|
void tegra_init_suspend(void);
|
||||||
|
#else
|
||||||
|
enum tegra_suspend_mode tegra_pm_validate_suspend_mode(
|
||||||
|
enum tegra_suspend_mode mode)
|
||||||
|
{
|
||||||
|
return TEGRA_SUSPEND_NONE;
|
||||||
|
}
|
||||||
|
static inline void tegra_init_suspend(void) {}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* _MACH_TEGRA_PM_H_ */
|
#endif /* _MACH_TEGRA_PM_H_ */
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2012 NVIDIA CORPORATION. All rights reserved.
|
* Copyright (C) 2012,2013 NVIDIA CORPORATION. All rights reserved.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
* under the terms and conditions of the GNU General Public License,
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
@ -16,59 +16,313 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/clk.h>
|
||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
#include <linux/of.h>
|
#include <linux/of.h>
|
||||||
|
#include <linux/of_address.h>
|
||||||
|
|
||||||
#include "iomap.h"
|
#include "fuse.h"
|
||||||
|
#include "pm.h"
|
||||||
|
#include "pmc.h"
|
||||||
|
#include "sleep.h"
|
||||||
|
|
||||||
#define PMC_CTRL 0x0
|
#define TEGRA_POWER_EFFECT_LP0 (1 << 14) /* LP0 when CPU pwr gated */
|
||||||
#define PMC_CTRL_INTR_LOW (1 << 17)
|
#define TEGRA_POWER_CPU_PWRREQ_POLARITY (1 << 15) /* CPU pwr req polarity */
|
||||||
|
#define TEGRA_POWER_CPU_PWRREQ_OE (1 << 16) /* CPU pwr req enable */
|
||||||
|
|
||||||
|
#define PMC_CTRL 0x0
|
||||||
|
#define PMC_CTRL_INTR_LOW (1 << 17)
|
||||||
|
#define PMC_PWRGATE_TOGGLE 0x30
|
||||||
|
#define PMC_PWRGATE_TOGGLE_START (1 << 8)
|
||||||
|
#define PMC_REMOVE_CLAMPING 0x34
|
||||||
|
#define PMC_PWRGATE_STATUS 0x38
|
||||||
|
|
||||||
|
#define PMC_CPUPWRGOOD_TIMER 0xc8
|
||||||
|
#define PMC_CPUPWROFF_TIMER 0xcc
|
||||||
|
|
||||||
|
#define TEGRA_POWERGATE_PCIE 3
|
||||||
|
#define TEGRA_POWERGATE_VDEC 4
|
||||||
|
#define TEGRA_POWERGATE_CPU1 9
|
||||||
|
#define TEGRA_POWERGATE_CPU2 10
|
||||||
|
#define TEGRA_POWERGATE_CPU3 11
|
||||||
|
|
||||||
|
static u8 tegra_cpu_domains[] = {
|
||||||
|
0xFF, /* not available for CPU0 */
|
||||||
|
TEGRA_POWERGATE_CPU1,
|
||||||
|
TEGRA_POWERGATE_CPU2,
|
||||||
|
TEGRA_POWERGATE_CPU3,
|
||||||
|
};
|
||||||
|
static DEFINE_SPINLOCK(tegra_powergate_lock);
|
||||||
|
|
||||||
|
static void __iomem *tegra_pmc_base;
|
||||||
|
static bool tegra_pmc_invert_interrupt;
|
||||||
|
static struct clk *tegra_pclk;
|
||||||
|
|
||||||
|
struct pmc_pm_data {
|
||||||
|
u32 cpu_good_time; /* CPU power good time in uS */
|
||||||
|
u32 cpu_off_time; /* CPU power off time in uS */
|
||||||
|
u32 core_osc_time; /* Core power good osc time in uS */
|
||||||
|
u32 core_pmu_time; /* Core power good pmu time in uS */
|
||||||
|
u32 core_off_time; /* Core power off time in uS */
|
||||||
|
bool corereq_high; /* Core power request active-high */
|
||||||
|
bool sysclkreq_high; /* System clock request active-high */
|
||||||
|
bool combined_req; /* Combined pwr req for CPU & Core */
|
||||||
|
bool cpu_pwr_good_en; /* CPU power good signal is enabled */
|
||||||
|
u32 lp0_vec_phy_addr; /* The phy addr of LP0 warm boot code */
|
||||||
|
u32 lp0_vec_size; /* The size of LP0 warm boot code */
|
||||||
|
enum tegra_suspend_mode suspend_mode;
|
||||||
|
};
|
||||||
|
static struct pmc_pm_data pmc_pm_data;
|
||||||
|
|
||||||
static inline u32 tegra_pmc_readl(u32 reg)
|
static inline u32 tegra_pmc_readl(u32 reg)
|
||||||
{
|
{
|
||||||
return readl(IO_ADDRESS(TEGRA_PMC_BASE + reg));
|
return readl(tegra_pmc_base + reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void tegra_pmc_writel(u32 val, u32 reg)
|
static inline void tegra_pmc_writel(u32 val, u32 reg)
|
||||||
{
|
{
|
||||||
writel(val, IO_ADDRESS(TEGRA_PMC_BASE + reg));
|
writel(val, tegra_pmc_base + reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_OF
|
static int tegra_pmc_get_cpu_powerdomain_id(int cpuid)
|
||||||
|
{
|
||||||
|
if (cpuid <= 0 || cpuid >= num_possible_cpus())
|
||||||
|
return -EINVAL;
|
||||||
|
return tegra_cpu_domains[cpuid];
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool tegra_pmc_powergate_is_powered(int id)
|
||||||
|
{
|
||||||
|
return (tegra_pmc_readl(PMC_PWRGATE_STATUS) >> id) & 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tegra_pmc_powergate_set(int id, bool new_state)
|
||||||
|
{
|
||||||
|
bool old_state;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&tegra_powergate_lock, flags);
|
||||||
|
|
||||||
|
old_state = tegra_pmc_powergate_is_powered(id);
|
||||||
|
WARN_ON(old_state == new_state);
|
||||||
|
|
||||||
|
tegra_pmc_writel(PMC_PWRGATE_TOGGLE_START | id, PMC_PWRGATE_TOGGLE);
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&tegra_powergate_lock, flags);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tegra_pmc_powergate_remove_clamping(int id)
|
||||||
|
{
|
||||||
|
u32 mask;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Tegra has a bug where PCIE and VDE clamping masks are
|
||||||
|
* swapped relatively to the partition ids.
|
||||||
|
*/
|
||||||
|
if (id == TEGRA_POWERGATE_VDEC)
|
||||||
|
mask = (1 << TEGRA_POWERGATE_PCIE);
|
||||||
|
else if (id == TEGRA_POWERGATE_PCIE)
|
||||||
|
mask = (1 << TEGRA_POWERGATE_VDEC);
|
||||||
|
else
|
||||||
|
mask = (1 << id);
|
||||||
|
|
||||||
|
tegra_pmc_writel(mask, PMC_REMOVE_CLAMPING);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool tegra_pmc_cpu_is_powered(int cpuid)
|
||||||
|
{
|
||||||
|
int id;
|
||||||
|
|
||||||
|
id = tegra_pmc_get_cpu_powerdomain_id(cpuid);
|
||||||
|
if (id < 0)
|
||||||
|
return false;
|
||||||
|
return tegra_pmc_powergate_is_powered(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
int tegra_pmc_cpu_power_on(int cpuid)
|
||||||
|
{
|
||||||
|
int id;
|
||||||
|
|
||||||
|
id = tegra_pmc_get_cpu_powerdomain_id(cpuid);
|
||||||
|
if (id < 0)
|
||||||
|
return id;
|
||||||
|
return tegra_pmc_powergate_set(id, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
int tegra_pmc_cpu_remove_clamping(int cpuid)
|
||||||
|
{
|
||||||
|
int id;
|
||||||
|
|
||||||
|
id = tegra_pmc_get_cpu_powerdomain_id(cpuid);
|
||||||
|
if (id < 0)
|
||||||
|
return id;
|
||||||
|
return tegra_pmc_powergate_remove_clamping(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_PM_SLEEP
|
||||||
|
static void set_power_timers(u32 us_on, u32 us_off, unsigned long rate)
|
||||||
|
{
|
||||||
|
unsigned long long ticks;
|
||||||
|
unsigned long long pclk;
|
||||||
|
static unsigned long tegra_last_pclk;
|
||||||
|
|
||||||
|
if (WARN_ON_ONCE(rate <= 0))
|
||||||
|
pclk = 100000000;
|
||||||
|
else
|
||||||
|
pclk = rate;
|
||||||
|
|
||||||
|
if ((rate != tegra_last_pclk)) {
|
||||||
|
ticks = (us_on * pclk) + 999999ull;
|
||||||
|
do_div(ticks, 1000000);
|
||||||
|
tegra_pmc_writel((unsigned long)ticks, PMC_CPUPWRGOOD_TIMER);
|
||||||
|
|
||||||
|
ticks = (us_off * pclk) + 999999ull;
|
||||||
|
do_div(ticks, 1000000);
|
||||||
|
tegra_pmc_writel((unsigned long)ticks, PMC_CPUPWROFF_TIMER);
|
||||||
|
wmb();
|
||||||
|
}
|
||||||
|
tegra_last_pclk = pclk;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum tegra_suspend_mode tegra_pmc_get_suspend_mode(void)
|
||||||
|
{
|
||||||
|
return pmc_pm_data.suspend_mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
void tegra_pmc_pm_set(enum tegra_suspend_mode mode)
|
||||||
|
{
|
||||||
|
u32 reg;
|
||||||
|
unsigned long rate = 0;
|
||||||
|
|
||||||
|
reg = tegra_pmc_readl(PMC_CTRL);
|
||||||
|
reg |= TEGRA_POWER_CPU_PWRREQ_OE;
|
||||||
|
reg &= ~TEGRA_POWER_EFFECT_LP0;
|
||||||
|
|
||||||
|
switch (mode) {
|
||||||
|
case TEGRA_SUSPEND_LP2:
|
||||||
|
rate = clk_get_rate(tegra_pclk);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
set_power_timers(pmc_pm_data.cpu_good_time, pmc_pm_data.cpu_off_time,
|
||||||
|
rate);
|
||||||
|
|
||||||
|
tegra_pmc_writel(reg, PMC_CTRL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void tegra_pmc_suspend_init(void)
|
||||||
|
{
|
||||||
|
u32 reg;
|
||||||
|
|
||||||
|
/* Always enable CPU power request */
|
||||||
|
reg = tegra_pmc_readl(PMC_CTRL);
|
||||||
|
reg |= TEGRA_POWER_CPU_PWRREQ_OE;
|
||||||
|
tegra_pmc_writel(reg, PMC_CTRL);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static const struct of_device_id matches[] __initconst = {
|
static const struct of_device_id matches[] __initconst = {
|
||||||
|
{ .compatible = "nvidia,tegra114-pmc" },
|
||||||
|
{ .compatible = "nvidia,tegra30-pmc" },
|
||||||
{ .compatible = "nvidia,tegra20-pmc" },
|
{ .compatible = "nvidia,tegra20-pmc" },
|
||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
#endif
|
|
||||||
|
static void tegra_pmc_parse_dt(void)
|
||||||
|
{
|
||||||
|
struct device_node *np;
|
||||||
|
u32 prop;
|
||||||
|
enum tegra_suspend_mode suspend_mode;
|
||||||
|
u32 core_good_time[2] = {0, 0};
|
||||||
|
u32 lp0_vec[2] = {0, 0};
|
||||||
|
|
||||||
|
np = of_find_matching_node(NULL, matches);
|
||||||
|
BUG_ON(!np);
|
||||||
|
|
||||||
|
tegra_pmc_base = of_iomap(np, 0);
|
||||||
|
|
||||||
|
tegra_pmc_invert_interrupt = of_property_read_bool(np,
|
||||||
|
"nvidia,invert-interrupt");
|
||||||
|
tegra_pclk = of_clk_get_by_name(np, "pclk");
|
||||||
|
WARN_ON(IS_ERR(tegra_pclk));
|
||||||
|
|
||||||
|
/* Grabbing the power management configurations */
|
||||||
|
if (of_property_read_u32(np, "nvidia,suspend-mode", &prop)) {
|
||||||
|
suspend_mode = TEGRA_SUSPEND_NONE;
|
||||||
|
} else {
|
||||||
|
switch (prop) {
|
||||||
|
case 0:
|
||||||
|
suspend_mode = TEGRA_SUSPEND_LP0;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
suspend_mode = TEGRA_SUSPEND_LP1;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
suspend_mode = TEGRA_SUSPEND_LP2;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
suspend_mode = TEGRA_SUSPEND_NONE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
suspend_mode = tegra_pm_validate_suspend_mode(suspend_mode);
|
||||||
|
|
||||||
|
if (of_property_read_u32(np, "nvidia,cpu-pwr-good-time", &prop))
|
||||||
|
suspend_mode = TEGRA_SUSPEND_NONE;
|
||||||
|
pmc_pm_data.cpu_good_time = prop;
|
||||||
|
|
||||||
|
if (of_property_read_u32(np, "nvidia,cpu-pwr-off-time", &prop))
|
||||||
|
suspend_mode = TEGRA_SUSPEND_NONE;
|
||||||
|
pmc_pm_data.cpu_off_time = prop;
|
||||||
|
|
||||||
|
if (of_property_read_u32_array(np, "nvidia,core-pwr-good-time",
|
||||||
|
core_good_time, ARRAY_SIZE(core_good_time)))
|
||||||
|
suspend_mode = TEGRA_SUSPEND_NONE;
|
||||||
|
pmc_pm_data.core_osc_time = core_good_time[0];
|
||||||
|
pmc_pm_data.core_pmu_time = core_good_time[1];
|
||||||
|
|
||||||
|
if (of_property_read_u32(np, "nvidia,core-pwr-off-time",
|
||||||
|
&prop))
|
||||||
|
suspend_mode = TEGRA_SUSPEND_NONE;
|
||||||
|
pmc_pm_data.core_off_time = prop;
|
||||||
|
|
||||||
|
pmc_pm_data.corereq_high = of_property_read_bool(np,
|
||||||
|
"nvidia,core-power-req-active-high");
|
||||||
|
|
||||||
|
pmc_pm_data.sysclkreq_high = of_property_read_bool(np,
|
||||||
|
"nvidia,sys-clock-req-active-high");
|
||||||
|
|
||||||
|
pmc_pm_data.combined_req = of_property_read_bool(np,
|
||||||
|
"nvidia,combined-power-req");
|
||||||
|
|
||||||
|
pmc_pm_data.cpu_pwr_good_en = of_property_read_bool(np,
|
||||||
|
"nvidia,cpu-pwr-good-en");
|
||||||
|
|
||||||
|
if (of_property_read_u32_array(np, "nvidia,lp0-vec", lp0_vec,
|
||||||
|
ARRAY_SIZE(lp0_vec)))
|
||||||
|
if (suspend_mode == TEGRA_SUSPEND_LP0)
|
||||||
|
suspend_mode = TEGRA_SUSPEND_LP1;
|
||||||
|
|
||||||
|
pmc_pm_data.lp0_vec_phy_addr = lp0_vec[0];
|
||||||
|
pmc_pm_data.lp0_vec_size = lp0_vec[1];
|
||||||
|
|
||||||
|
pmc_pm_data.suspend_mode = suspend_mode;
|
||||||
|
}
|
||||||
|
|
||||||
void __init tegra_pmc_init(void)
|
void __init tegra_pmc_init(void)
|
||||||
{
|
{
|
||||||
/*
|
|
||||||
* For now, Harmony is the only board that uses the PMC, and it wants
|
|
||||||
* the signal inverted. Seaboard would too if it used the PMC.
|
|
||||||
* Hopefully by the time other boards want to use the PMC, everything
|
|
||||||
* will be device-tree, or they also want it inverted.
|
|
||||||
*/
|
|
||||||
bool invert_interrupt = true;
|
|
||||||
u32 val;
|
u32 val;
|
||||||
|
|
||||||
#ifdef CONFIG_OF
|
tegra_pmc_parse_dt();
|
||||||
if (of_have_populated_dt()) {
|
|
||||||
struct device_node *np;
|
|
||||||
|
|
||||||
invert_interrupt = false;
|
|
||||||
|
|
||||||
np = of_find_matching_node(NULL, matches);
|
|
||||||
if (np) {
|
|
||||||
if (of_find_property(np, "nvidia,invert-interrupt",
|
|
||||||
NULL))
|
|
||||||
invert_interrupt = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
val = tegra_pmc_readl(PMC_CTRL);
|
val = tegra_pmc_readl(PMC_CTRL);
|
||||||
if (invert_interrupt)
|
if (tegra_pmc_invert_interrupt)
|
||||||
val |= PMC_CTRL_INTR_LOW;
|
val |= PMC_CTRL_INTR_LOW;
|
||||||
else
|
else
|
||||||
val &= ~PMC_CTRL_INTR_LOW;
|
val &= ~PMC_CTRL_INTR_LOW;
|
||||||
|
|
|
@ -18,6 +18,24 @@
|
||||||
#ifndef __MACH_TEGRA_PMC_H
|
#ifndef __MACH_TEGRA_PMC_H
|
||||||
#define __MACH_TEGRA_PMC_H
|
#define __MACH_TEGRA_PMC_H
|
||||||
|
|
||||||
|
enum tegra_suspend_mode {
|
||||||
|
TEGRA_SUSPEND_NONE = 0,
|
||||||
|
TEGRA_SUSPEND_LP2, /* CPU voltage off */
|
||||||
|
TEGRA_SUSPEND_LP1, /* CPU voltage off, DRAM self-refresh */
|
||||||
|
TEGRA_SUSPEND_LP0, /* CPU + core voltage off, DRAM self-refresh */
|
||||||
|
TEGRA_MAX_SUSPEND_MODE,
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef CONFIG_PM_SLEEP
|
||||||
|
enum tegra_suspend_mode tegra_pmc_get_suspend_mode(void);
|
||||||
|
void tegra_pmc_pm_set(enum tegra_suspend_mode mode);
|
||||||
|
void tegra_pmc_suspend_init(void);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bool tegra_pmc_cpu_is_powered(int cpuid);
|
||||||
|
int tegra_pmc_cpu_power_on(int cpuid);
|
||||||
|
int tegra_pmc_cpu_remove_clamping(int cpuid);
|
||||||
|
|
||||||
void tegra_pmc_init(void);
|
void tegra_pmc_init(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -41,9 +41,6 @@
|
||||||
*/
|
*/
|
||||||
ENTRY(tegra_resume)
|
ENTRY(tegra_resume)
|
||||||
bl v7_invalidate_l1
|
bl v7_invalidate_l1
|
||||||
/* Enable coresight */
|
|
||||||
mov32 r0, 0xC5ACCE55
|
|
||||||
mcr p14, 0, r0, c7, c12, 6
|
|
||||||
|
|
||||||
cpu_id r0
|
cpu_id r0
|
||||||
cmp r0, #0 @ CPU0?
|
cmp r0, #0 @ CPU0?
|
||||||
|
@ -99,6 +96,8 @@ ENTRY(__tegra_cpu_reset_handler_start)
|
||||||
*
|
*
|
||||||
* Register usage within the reset handler:
|
* Register usage within the reset handler:
|
||||||
*
|
*
|
||||||
|
* Others: scratch
|
||||||
|
* R6 = SoC ID << 8
|
||||||
* R7 = CPU present (to the OS) mask
|
* R7 = CPU present (to the OS) mask
|
||||||
* R8 = CPU in LP1 state mask
|
* R8 = CPU in LP1 state mask
|
||||||
* R9 = CPU in LP2 state mask
|
* R9 = CPU in LP2 state mask
|
||||||
|
@ -114,6 +113,40 @@ ENTRY(__tegra_cpu_reset_handler_start)
|
||||||
ENTRY(__tegra_cpu_reset_handler)
|
ENTRY(__tegra_cpu_reset_handler)
|
||||||
|
|
||||||
cpsid aif, 0x13 @ SVC mode, interrupts disabled
|
cpsid aif, 0x13 @ SVC mode, interrupts disabled
|
||||||
|
|
||||||
|
mov32 r6, TEGRA_APB_MISC_BASE
|
||||||
|
ldr r6, [r6, #APB_MISC_GP_HIDREV]
|
||||||
|
and r6, r6, #0xff00
|
||||||
|
#ifdef CONFIG_ARCH_TEGRA_2x_SOC
|
||||||
|
t20_check:
|
||||||
|
cmp r6, #(0x20 << 8)
|
||||||
|
bne after_t20_check
|
||||||
|
t20_errata:
|
||||||
|
# Tegra20 is a Cortex-A9 r1p1
|
||||||
|
mrc p15, 0, r0, c1, c0, 0 @ read system control register
|
||||||
|
orr r0, r0, #1 << 14 @ erratum 716044
|
||||||
|
mcr p15, 0, r0, c1, c0, 0 @ write system control register
|
||||||
|
mrc p15, 0, r0, c15, c0, 1 @ read diagnostic register
|
||||||
|
orr r0, r0, #1 << 4 @ erratum 742230
|
||||||
|
orr r0, r0, #1 << 11 @ erratum 751472
|
||||||
|
mcr p15, 0, r0, c15, c0, 1 @ write diagnostic register
|
||||||
|
b after_errata
|
||||||
|
after_t20_check:
|
||||||
|
#endif
|
||||||
|
#ifdef CONFIG_ARCH_TEGRA_3x_SOC
|
||||||
|
t30_check:
|
||||||
|
cmp r6, #(0x30 << 8)
|
||||||
|
bne after_t30_check
|
||||||
|
t30_errata:
|
||||||
|
# Tegra30 is a Cortex-A9 r2p9
|
||||||
|
mrc p15, 0, r0, c15, c0, 1 @ read diagnostic register
|
||||||
|
orr r0, r0, #1 << 6 @ erratum 743622
|
||||||
|
orr r0, r0, #1 << 11 @ erratum 751472
|
||||||
|
mcr p15, 0, r0, c15, c0, 1 @ write diagnostic register
|
||||||
|
b after_errata
|
||||||
|
after_t30_check:
|
||||||
|
#endif
|
||||||
|
after_errata:
|
||||||
mrc p15, 0, r10, c0, c0, 5 @ MPIDR
|
mrc p15, 0, r10, c0, c0, 5 @ MPIDR
|
||||||
and r10, r10, #0x3 @ R10 = CPU number
|
and r10, r10, #0x3 @ R10 = CPU number
|
||||||
mov r11, #1
|
mov r11, #1
|
||||||
|
@ -129,16 +162,13 @@ ENTRY(__tegra_cpu_reset_handler)
|
||||||
|
|
||||||
#ifdef CONFIG_ARCH_TEGRA_2x_SOC
|
#ifdef CONFIG_ARCH_TEGRA_2x_SOC
|
||||||
/* Are we on Tegra20? */
|
/* Are we on Tegra20? */
|
||||||
mov32 r6, TEGRA_APB_MISC_BASE
|
cmp r6, #(0x20 << 8)
|
||||||
ldr r0, [r6, #APB_MISC_GP_HIDREV]
|
|
||||||
and r0, r0, #0xff00
|
|
||||||
cmp r0, #(0x20 << 8)
|
|
||||||
bne 1f
|
bne 1f
|
||||||
/* If not CPU0, don't let CPU0 reset CPU1 now that CPU1 is coming up. */
|
/* If not CPU0, don't let CPU0 reset CPU1 now that CPU1 is coming up. */
|
||||||
mov32 r6, TEGRA_PMC_BASE
|
mov32 r5, TEGRA_PMC_BASE
|
||||||
mov r0, #0
|
mov r0, #0
|
||||||
cmp r10, #0
|
cmp r10, #0
|
||||||
strne r0, [r6, #PMC_SCRATCH41]
|
strne r0, [r5, #PMC_SCRATCH41]
|
||||||
1:
|
1:
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2010-2012, NVIDIA Corporation. All rights reserved.
|
* Copyright (c) 2010-2013, NVIDIA Corporation. All rights reserved.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
* under the terms and conditions of the GNU General Public License,
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
@ -124,11 +124,11 @@ int tegra_sleep_cpu_finish(unsigned long);
|
||||||
void tegra_disable_clean_inv_dcache(void);
|
void tegra_disable_clean_inv_dcache(void);
|
||||||
|
|
||||||
#ifdef CONFIG_HOTPLUG_CPU
|
#ifdef CONFIG_HOTPLUG_CPU
|
||||||
void tegra20_hotplug_init(void);
|
void tegra20_hotplug_shutdown(void);
|
||||||
void tegra30_hotplug_init(void);
|
void tegra30_hotplug_shutdown(void);
|
||||||
|
void tegra_hotplug_init(void);
|
||||||
#else
|
#else
|
||||||
static inline void tegra20_hotplug_init(void) {}
|
static inline void tegra_hotplug_init(void) {}
|
||||||
static inline void tegra30_hotplug_init(void) {}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void tegra20_cpu_shutdown(int cpu);
|
void tegra20_cpu_shutdown(int cpu);
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* nVidia Tegra device tree board support
|
* NVIDIA Tegra SoC device tree board support
|
||||||
*
|
*
|
||||||
|
* Copyright (C) 2011, 2013, NVIDIA Corporation
|
||||||
* Copyright (C) 2010 Secret Lab Technologies, Ltd.
|
* Copyright (C) 2010 Secret Lab Technologies, Ltd.
|
||||||
* Copyright (C) 2010 Google, Inc.
|
* Copyright (C) 2010 Google, Inc.
|
||||||
*
|
*
|
||||||
|
@ -32,6 +33,8 @@
|
||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
#include <linux/i2c.h>
|
#include <linux/i2c.h>
|
||||||
#include <linux/i2c-tegra.h>
|
#include <linux/i2c-tegra.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
#include <linux/sys_soc.h>
|
||||||
#include <linux/usb/tegra_usb_phy.h>
|
#include <linux/usb/tegra_usb_phy.h>
|
||||||
|
|
||||||
#include <asm/mach-types.h>
|
#include <asm/mach-types.h>
|
||||||
|
@ -41,6 +44,7 @@
|
||||||
|
|
||||||
#include "board.h"
|
#include "board.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
#include "fuse.h"
|
||||||
#include "iomap.h"
|
#include "iomap.h"
|
||||||
|
|
||||||
static struct tegra_ehci_platform_data tegra_ehci1_pdata = {
|
static struct tegra_ehci_platform_data tegra_ehci1_pdata = {
|
||||||
|
@ -79,12 +83,36 @@ static struct of_dev_auxdata tegra20_auxdata_lookup[] __initdata = {
|
||||||
|
|
||||||
static void __init tegra_dt_init(void)
|
static void __init tegra_dt_init(void)
|
||||||
{
|
{
|
||||||
|
struct soc_device_attribute *soc_dev_attr;
|
||||||
|
struct soc_device *soc_dev;
|
||||||
|
struct device *parent = NULL;
|
||||||
|
|
||||||
|
soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
|
||||||
|
if (!soc_dev_attr)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
soc_dev_attr->family = kasprintf(GFP_KERNEL, "Tegra");
|
||||||
|
soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%d", tegra_revision);
|
||||||
|
soc_dev_attr->soc_id = kasprintf(GFP_KERNEL, "%d", tegra_chip_id);
|
||||||
|
|
||||||
|
soc_dev = soc_device_register(soc_dev_attr);
|
||||||
|
if (IS_ERR(soc_dev)) {
|
||||||
|
kfree(soc_dev_attr->family);
|
||||||
|
kfree(soc_dev_attr->revision);
|
||||||
|
kfree(soc_dev_attr->soc_id);
|
||||||
|
kfree(soc_dev_attr);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
parent = soc_device_to_device(soc_dev);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Finished with the static registrations now; fill in the missing
|
* Finished with the static registrations now; fill in the missing
|
||||||
* devices
|
* devices
|
||||||
*/
|
*/
|
||||||
|
out:
|
||||||
of_platform_populate(NULL, of_default_bus_match_table,
|
of_platform_populate(NULL, of_default_bus_match_table,
|
||||||
tegra20_auxdata_lookup, NULL);
|
tegra20_auxdata_lookup, parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __init trimslice_init(void)
|
static void __init trimslice_init(void)
|
||||||
|
@ -111,7 +139,8 @@ static void __init harmony_init(void)
|
||||||
|
|
||||||
static void __init paz00_init(void)
|
static void __init paz00_init(void)
|
||||||
{
|
{
|
||||||
tegra_paz00_wifikill_init();
|
if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC))
|
||||||
|
tegra_paz00_wifikill_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct {
|
static struct {
|
||||||
|
@ -137,19 +166,21 @@ static void __init tegra_dt_init_late(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *tegra20_dt_board_compat[] = {
|
static const char * const tegra_dt_board_compat[] = {
|
||||||
|
"nvidia,tegra114",
|
||||||
|
"nvidia,tegra30",
|
||||||
"nvidia,tegra20",
|
"nvidia,tegra20",
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
DT_MACHINE_START(TEGRA_DT, "nVidia Tegra20 (Flattened Device Tree)")
|
DT_MACHINE_START(TEGRA_DT, "NVIDIA Tegra SoC (Flattened Device Tree)")
|
||||||
.map_io = tegra_map_common_io,
|
.map_io = tegra_map_common_io,
|
||||||
.smp = smp_ops(tegra_smp_ops),
|
.smp = smp_ops(tegra_smp_ops),
|
||||||
.init_early = tegra20_init_early,
|
.init_early = tegra_init_early,
|
||||||
.init_irq = tegra_dt_init_irq,
|
.init_irq = tegra_dt_init_irq,
|
||||||
.init_time = clocksource_of_init,
|
.init_time = clocksource_of_init,
|
||||||
.init_machine = tegra_dt_init,
|
.init_machine = tegra_dt_init,
|
||||||
.init_late = tegra_dt_init_late,
|
.init_late = tegra_dt_init_late,
|
||||||
.restart = tegra_assert_system_reset,
|
.restart = tegra_assert_system_reset,
|
||||||
.dt_compat = tegra20_dt_board_compat,
|
.dt_compat = tegra_dt_board_compat,
|
||||||
MACHINE_END
|
MACHINE_END
|
|
@ -0,0 +1,104 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/bug.h>
|
||||||
|
|
||||||
|
#include "fuse.h"
|
||||||
|
|
||||||
|
#define CORE_PROCESS_CORNERS_NUM 2
|
||||||
|
#define CPU_PROCESS_CORNERS_NUM 2
|
||||||
|
|
||||||
|
enum {
|
||||||
|
THRESHOLD_INDEX_0,
|
||||||
|
THRESHOLD_INDEX_1,
|
||||||
|
THRESHOLD_INDEX_COUNT,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const u32 core_process_speedos[][CORE_PROCESS_CORNERS_NUM] = {
|
||||||
|
{1123, UINT_MAX},
|
||||||
|
{0, UINT_MAX},
|
||||||
|
};
|
||||||
|
|
||||||
|
static const u32 cpu_process_speedos[][CPU_PROCESS_CORNERS_NUM] = {
|
||||||
|
{1695, UINT_MAX},
|
||||||
|
{0, UINT_MAX},
|
||||||
|
};
|
||||||
|
|
||||||
|
static void rev_sku_to_speedo_ids(int rev, int sku, int *threshold)
|
||||||
|
{
|
||||||
|
u32 tmp;
|
||||||
|
|
||||||
|
switch (sku) {
|
||||||
|
case 0x00:
|
||||||
|
case 0x10:
|
||||||
|
case 0x05:
|
||||||
|
case 0x06:
|
||||||
|
tegra_cpu_speedo_id = 1;
|
||||||
|
tegra_soc_speedo_id = 0;
|
||||||
|
*threshold = THRESHOLD_INDEX_0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x03:
|
||||||
|
case 0x04:
|
||||||
|
tegra_cpu_speedo_id = 2;
|
||||||
|
tegra_soc_speedo_id = 1;
|
||||||
|
*threshold = THRESHOLD_INDEX_1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
pr_err("Tegra114 Unknown SKU %d\n", sku);
|
||||||
|
tegra_cpu_speedo_id = 0;
|
||||||
|
tegra_soc_speedo_id = 0;
|
||||||
|
*threshold = THRESHOLD_INDEX_0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rev == TEGRA_REVISION_A01) {
|
||||||
|
tmp = tegra_fuse_readl(0x270) << 1;
|
||||||
|
tmp |= tegra_fuse_readl(0x26c);
|
||||||
|
if (!tmp)
|
||||||
|
tegra_cpu_speedo_id = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void tegra114_init_speedo_data(void)
|
||||||
|
{
|
||||||
|
u32 cpu_speedo_val;
|
||||||
|
u32 core_speedo_val;
|
||||||
|
int threshold;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
BUILD_BUG_ON(ARRAY_SIZE(cpu_process_speedos) !=
|
||||||
|
THRESHOLD_INDEX_COUNT);
|
||||||
|
BUILD_BUG_ON(ARRAY_SIZE(core_process_speedos) !=
|
||||||
|
THRESHOLD_INDEX_COUNT);
|
||||||
|
|
||||||
|
rev_sku_to_speedo_ids(tegra_revision, tegra_sku_id, &threshold);
|
||||||
|
|
||||||
|
cpu_speedo_val = tegra_fuse_readl(0x12c) + 1024;
|
||||||
|
core_speedo_val = tegra_fuse_readl(0x134);
|
||||||
|
|
||||||
|
for (i = 0; i < CPU_PROCESS_CORNERS_NUM; i++)
|
||||||
|
if (cpu_speedo_val < cpu_process_speedos[threshold][i])
|
||||||
|
break;
|
||||||
|
tegra_cpu_process_id = i;
|
||||||
|
|
||||||
|
for (i = 0; i < CORE_PROCESS_CORNERS_NUM; i++)
|
||||||
|
if (core_speedo_val < core_process_speedos[threshold][i])
|
||||||
|
break;
|
||||||
|
tegra_core_process_id = i;
|
||||||
|
}
|
|
@ -711,8 +711,8 @@ static void tegra20_pll_init(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *cclk_parents[] = { "clk_m", "pll_c", "clk_32k", "pll_m",
|
static const char *cclk_parents[] = { "clk_m", "pll_c", "clk_32k", "pll_m",
|
||||||
"pll_p_cclk", "pll_p_out4_cclk",
|
"pll_p", "pll_p_out4",
|
||||||
"pll_p_out3_cclk", "clk_d", "pll_x" };
|
"pll_p_out3", "clk_d", "pll_x" };
|
||||||
static const char *sclk_parents[] = { "clk_m", "pll_c_out1", "pll_p_out4",
|
static const char *sclk_parents[] = { "clk_m", "pll_c_out1", "pll_p_out4",
|
||||||
"pll_p_out3", "pll_p_out2", "clk_d",
|
"pll_p_out3", "pll_p_out2", "clk_d",
|
||||||
"clk_32k", "pll_m_out1" };
|
"clk_32k", "pll_m_out1" };
|
||||||
|
@ -721,38 +721,6 @@ static void tegra20_super_clk_init(void)
|
||||||
{
|
{
|
||||||
struct clk *clk;
|
struct clk *clk;
|
||||||
|
|
||||||
/*
|
|
||||||
* DIV_U71 dividers for CCLK, these dividers are used only
|
|
||||||
* if parent clock is fixed rate.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Clock input to cclk divided from pll_p using
|
|
||||||
* U71 divider of cclk.
|
|
||||||
*/
|
|
||||||
clk = tegra_clk_register_divider("pll_p_cclk", "pll_p",
|
|
||||||
clk_base + SUPER_CCLK_DIVIDER, 0,
|
|
||||||
TEGRA_DIVIDER_INT, 16, 8, 1, NULL);
|
|
||||||
clk_register_clkdev(clk, "pll_p_cclk", NULL);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Clock input to cclk divided from pll_p_out3 using
|
|
||||||
* U71 divider of cclk.
|
|
||||||
*/
|
|
||||||
clk = tegra_clk_register_divider("pll_p_out3_cclk", "pll_p_out3",
|
|
||||||
clk_base + SUPER_CCLK_DIVIDER, 0,
|
|
||||||
TEGRA_DIVIDER_INT, 16, 8, 1, NULL);
|
|
||||||
clk_register_clkdev(clk, "pll_p_out3_cclk", NULL);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Clock input to cclk divided from pll_p_out4 using
|
|
||||||
* U71 divider of cclk.
|
|
||||||
*/
|
|
||||||
clk = tegra_clk_register_divider("pll_p_out4_cclk", "pll_p_out4",
|
|
||||||
clk_base + SUPER_CCLK_DIVIDER, 0,
|
|
||||||
TEGRA_DIVIDER_INT, 16, 8, 1, NULL);
|
|
||||||
clk_register_clkdev(clk, "pll_p_out4_cclk", NULL);
|
|
||||||
|
|
||||||
/* CCLK */
|
/* CCLK */
|
||||||
clk = tegra_clk_register_super_mux("cclk", cclk_parents,
|
clk = tegra_clk_register_super_mux("cclk", cclk_parents,
|
||||||
ARRAY_SIZE(cclk_parents), CLK_SET_RATE_PARENT,
|
ARRAY_SIZE(cclk_parents), CLK_SET_RATE_PARENT,
|
||||||
|
|
|
@ -172,7 +172,7 @@ static void __init tegra20_init_timer(struct device_node *np)
|
||||||
BUG();
|
BUG();
|
||||||
}
|
}
|
||||||
|
|
||||||
clk = clk_get_sys("timer", NULL);
|
clk = of_clk_get(np, 0);
|
||||||
if (IS_ERR(clk)) {
|
if (IS_ERR(clk)) {
|
||||||
pr_warn("Unable to get timer clock. Assuming 12Mhz input clock.\n");
|
pr_warn("Unable to get timer clock. Assuming 12Mhz input clock.\n");
|
||||||
rate = 12000000;
|
rate = 12000000;
|
||||||
|
@ -235,7 +235,7 @@ static void __init tegra20_init_rtc(struct device_node *np)
|
||||||
* rtc registers are used by read_persistent_clock, keep the rtc clock
|
* rtc registers are used by read_persistent_clock, keep the rtc clock
|
||||||
* enabled
|
* enabled
|
||||||
*/
|
*/
|
||||||
clk = clk_get_sys("rtc-tegra", NULL);
|
clk = of_clk_get(np, 0);
|
||||||
if (IS_ERR(clk))
|
if (IS_ERR(clk))
|
||||||
pr_warn("Unable to get rtc-tegra clock\n");
|
pr_warn("Unable to get rtc-tegra clock\n");
|
||||||
else
|
else
|
||||||
|
|
|
@ -72,6 +72,7 @@ struct tegra_gpio_bank {
|
||||||
u32 oe[4];
|
u32 oe[4];
|
||||||
u32 int_enb[4];
|
u32 int_enb[4];
|
||||||
u32 int_lvl[4];
|
u32 int_lvl[4];
|
||||||
|
u32 wake_enb[4];
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -333,15 +334,31 @@ static int tegra_gpio_suspend(struct device *dev)
|
||||||
bank->oe[p] = tegra_gpio_readl(GPIO_OE(gpio));
|
bank->oe[p] = tegra_gpio_readl(GPIO_OE(gpio));
|
||||||
bank->int_enb[p] = tegra_gpio_readl(GPIO_INT_ENB(gpio));
|
bank->int_enb[p] = tegra_gpio_readl(GPIO_INT_ENB(gpio));
|
||||||
bank->int_lvl[p] = tegra_gpio_readl(GPIO_INT_LVL(gpio));
|
bank->int_lvl[p] = tegra_gpio_readl(GPIO_INT_LVL(gpio));
|
||||||
|
|
||||||
|
/* Enable gpio irq for wake up source */
|
||||||
|
tegra_gpio_writel(bank->wake_enb[p],
|
||||||
|
GPIO_INT_ENB(gpio));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
local_irq_restore(flags);
|
local_irq_restore(flags);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int tegra_gpio_wake_enable(struct irq_data *d, unsigned int enable)
|
static int tegra_gpio_irq_set_wake(struct irq_data *d, unsigned int enable)
|
||||||
{
|
{
|
||||||
struct tegra_gpio_bank *bank = irq_data_get_irq_chip_data(d);
|
struct tegra_gpio_bank *bank = irq_data_get_irq_chip_data(d);
|
||||||
|
int gpio = d->hwirq;
|
||||||
|
u32 port, bit, mask;
|
||||||
|
|
||||||
|
port = GPIO_PORT(gpio);
|
||||||
|
bit = GPIO_BIT(gpio);
|
||||||
|
mask = BIT(bit);
|
||||||
|
|
||||||
|
if (enable)
|
||||||
|
bank->wake_enb[port] |= mask;
|
||||||
|
else
|
||||||
|
bank->wake_enb[port] &= ~mask;
|
||||||
|
|
||||||
return irq_set_irq_wake(bank->irq, enable);
|
return irq_set_irq_wake(bank->irq, enable);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -353,7 +370,7 @@ static struct irq_chip tegra_gpio_irq_chip = {
|
||||||
.irq_unmask = tegra_gpio_irq_unmask,
|
.irq_unmask = tegra_gpio_irq_unmask,
|
||||||
.irq_set_type = tegra_gpio_irq_set_type,
|
.irq_set_type = tegra_gpio_irq_set_type,
|
||||||
#ifdef CONFIG_PM_SLEEP
|
#ifdef CONFIG_PM_SLEEP
|
||||||
.irq_set_wake = tegra_gpio_wake_enable,
|
.irq_set_wake = tegra_gpio_irq_set_wake,
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue