summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNicolas Chauvet <kwizart@gmail.com>2014-07-15 21:21:38 +0200
committerNicolas Chauvet <kwizart@gmail.com>2014-08-09 22:11:38 +0200
commit186a708bb62ba479c094d3f2ba5dd5199ebfb657 (patch)
treef59e1ddfb97d7a2eb4dea955891277fed16f0f5a
parent81a6ef5279efc4fdb7f37eed27bbebde1ddad376 (diff)
downloadkernel-186a708bb62ba479c094d3f2ba5dd5199ebfb657.tar.gz
kernel-186a708bb62ba479c094d3f2ba5dd5199ebfb657.tar.xz
kernel-186a708bb62ba479c094d3f2ba5dd5199ebfb657.zip
Resync with tegra-next 20140715
-rw-r--r--tegra-bp-next-3.17.patch4941
1 files changed, 4407 insertions, 534 deletions
diff --git a/tegra-bp-next-3.17.patch b/tegra-bp-next-3.17.patch
index 946f8707..05f1dd20 100644
--- a/tegra-bp-next-3.17.patch
+++ b/tegra-bp-next-3.17.patch
@@ -74,6 +74,55 @@ index 0000000..d8c98c7
+ };
+
+
+diff --git a/Documentation/devicetree/bindings/gpu/nvidia,gk20a.txt b/Documentation/devicetree/bindings/gpu/nvidia,gk20a.txt
+new file mode 100644
+index 0000000..23bfe8e
+--- /dev/null
++++ b/Documentation/devicetree/bindings/gpu/nvidia,gk20a.txt
+@@ -0,0 +1,43 @@
++NVIDIA GK20A Graphics Processing Unit
++
++Required properties:
++- compatible: "nvidia,<chip>-<gpu>"
++ Currently recognized values:
++ - nvidia,tegra124-gk20a
++- reg: Physical base address and length of the controller's registers.
++ Must contain two entries:
++ - first entry for bar0
++ - second entry for bar1
++- interrupts: Must contain an entry for each entry in interrupt-names.
++ See ../interrupt-controller/interrupts.txt for details.
++- interrupt-names: Must include the following entries:
++ - stall
++ - nonstall
++- vdd-supply: regulator for supply voltage.
++- clocks: Must contain an entry for each entry in clock-names.
++ See ../clocks/clock-bindings.txt for details.
++- clock-names: Must include the following entries:
++ - gpu
++ - pwr
++- resets: Must contain an entry for each entry in reset-names.
++ See ../reset/reset.txt for details.
++- reset-names: Must include the following entries:
++ - gpu
++
++Example:
++
++ gpu@0,57000000 {
++ compatible = "nvidia,gk20a";
++ reg = <0x0 0x57000000 0x0 0x01000000>,
++ <0x0 0x58000000 0x0 0x01000000>;
++ interrupts = <GIC_SPI 157 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 158 IRQ_TYPE_LEVEL_HIGH>;
++ interrupt-names = "stall", "nonstall";
++ vdd-supply = <&vdd_gpu>;
++ clocks = <&tegra_car TEGRA124_CLK_GPU>,
++ <&tegra_car TEGRA124_CLK_PLL_P_OUT5>;
++ clock-names = "gpu", "pwr";
++ resets = <&tegra_car 184>;
++ reset-names = "gpu";
++ status = "disabled";
++ };
diff --git a/Documentation/devicetree/bindings/misc/nvidia,tegra20-apbmisc.txt b/Documentation/devicetree/bindings/misc/nvidia,tegra20-apbmisc.txt
new file mode 100644
index 0000000..b97b8be
@@ -141,6 +190,139 @@ index c300391..0823362 100644
Root ports are defined as subnodes of the PCIe controller node.
Required properties:
+diff --git a/Documentation/devicetree/bindings/pinctrl/nvidia,tegra124-xusb-padctl.txt b/Documentation/devicetree/bindings/pinctrl/nvidia,tegra124-xusb-padctl.txt
+new file mode 100644
+index 0000000..2f9c0bd
+--- /dev/null
++++ b/Documentation/devicetree/bindings/pinctrl/nvidia,tegra124-xusb-padctl.txt
+@@ -0,0 +1,127 @@
++Device tree binding for NVIDIA Tegra XUSB pad controller
++========================================================
++
++The Tegra XUSB pad controller manages a set of lanes, each of which can be
++assigned to one out of a set of different pads. Some of these pads have an
++associated PHY that must be powered up before the pad can be used.
++
++This document defines the device-specific binding for the XUSB pad controller.
++
++Refer to pinctrl-bindings.txt in this directory for generic information about
++pin controller device tree bindings and ../phy/phy-bindings.txt for details on
++how to describe and reference PHYs in device trees.
++
++Required properties:
++--------------------
++- compatible: should be "nvidia,tegra124-xusb-padctl"
++- reg: Physical base address and length of the controller's registers.
++- resets: Must contain an entry for each entry in reset-names.
++ See ../reset/reset.txt for details.
++- reset-names: Must include the following entries:
++ - padctl
++- #phy-cells: Should be 1. The specifier is the index of the PHY to reference.
++ See <dt-bindings/pinctrl/pinctrl-tegra-xusb.h> for the list of valid values.
++
++Lane muxing:
++------------
++
++Child nodes contain the pinmux configurations following the conventions from
++the pinctrl-bindings.txt document. Typically a single, static configuration is
++given and applied at boot time.
++
++Each subnode describes groups of lanes along with parameters and pads that
++they should be assigned to. The name of these subnodes is not important. All
++subnodes should be parsed solely based on their content.
++
++Each subnode only applies the parameters that are explicitly listed. In other
++words, if a subnode that lists a function but no pin configuration parameters
++implies no information about any pin configuration parameters. Similarly, a
++subnode that describes only an IDDQ parameter implies no information about
++what function the pins are assigned to. For this reason even seemingly boolean
++values are actually tristates in this binding: unspecified, off or on.
++Unspecified is represented as an absent property, and off/on are represented
++as integer values 0 and 1.
++
++Required properties:
++- nvidia,lanes: An array of strings. Each string is the name of a lane.
++
++Optional properties:
++- nvidia,function: A string that is the name of the function (pad) that the
++ pin or group should be assigned to. Valid values for function names are
++ listed below.
++- nvidia,iddq: Enables IDDQ mode of the lane. (0: no, 1: yes)
++
++Note that not all of these properties are valid for all lanes. Lanes can be
++divided into three groups:
++
++ - otg-0, otg-1, otg-2:
++
++ Valid functions for this group are: "snps", "xusb", "uart", "rsvd".
++
++ The nvidia,iddq property does not apply to this group.
++
++ - ulpi-0, hsic-0, hsic-1:
++
++ Valid functions for this group are: "snps", "xusb".
++
++ The nvidia,iddq property does not apply to this group.
++
++ - pcie-0, pcie-1, pcie-2, pcie-3, pcie-4, sata-0:
++
++ Valid functions for this group are: "pcie", "usb3", "sata", "rsvd".
++
++
++Example:
++========
++
++SoC file extract:
++-----------------
++
++ padctl@0,7009f000 {
++ compatible = "nvidia,tegra124-xusb-padctl";
++ reg = <0x0 0x7009f000 0x0 0x1000>;
++ resets = <&tegra_car 142>;
++ reset-names = "padctl";
++
++ #phy-cells = <1>;
++ };
++
++Board file extract:
++-------------------
++
++ pcie-controller@0,01003000 {
++ ...
++
++ phys = <&padctl 0>;
++ phy-names = "pcie";
++
++ ...
++ };
++
++ ...
++
++ padctl: padctl@0,7009f000 {
++ pinctrl-0 = <&padctl_default>;
++ pinctrl-names = "default";
++
++ padctl_default: pinmux {
++ usb3 {
++ nvidia,lanes = "pcie-0", "pcie-1";
++ nvidia,function = "usb3";
++ nvidia,iddq = <0>;
++ };
++
++ pcie {
++ nvidia,lanes = "pcie-2", "pcie-3",
++ "pcie-4";
++ nvidia,function = "pcie";
++ nvidia,iddq = <0>;
++ };
++
++ sata {
++ nvidia,lanes = "sata-0";
++ nvidia,function = "sata";
++ nvidia,iddq = <0>;
++ };
++ };
++ };
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index 5986ff6..906fb67 100644
--- a/arch/arm/boot/dts/Makefile
@@ -379,6 +561,119 @@ index 079fdf9..7bd2df1 100644
};
+
+#include "cros-ec-keyboard.dtsi"
+diff --git a/arch/arm/boot/dts/tegra114-roth.dts b/arch/arm/boot/dts/tegra114-roth.dts
+index 0b0e8e0..c7c6825 100644
+--- a/arch/arm/boot/dts/tegra114-roth.dts
++++ b/arch/arm/boot/dts/tegra114-roth.dts
+@@ -28,6 +28,22 @@
+ reg = <0x80000000 0x79600000>;
+ };
+
++ host1x@50000000 {
++ dsi@54300000 {
++ status = "okay";
++
++ vdd-supply = <&vdd_1v2_ap>;
++
++ panel@0 {
++ compatible = "lg,lh500wx1-sd03";
++ reg = <0>;
++
++ power-supply = <&vdd_lcd>;
++ backlight = <&backlight>;
++ };
++ };
++ };
++
+ pinmux@70000868 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&state_default>;
+@@ -244,7 +260,7 @@
+ nvidia,function = "sdmmc1";
+ nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+ nvidia,tristate = <TEGRA_PIN_DISABLE>;
+- nvidia,enable-input = <TEGRA_PIN_DISABLE>;
++ nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+ };
+ sdmmc1_cmd_pz1 {
+ nvidia,pins = "sdmmc1_cmd_pz1",
+@@ -262,7 +278,7 @@
+ nvidia,function = "sdmmc3";
+ nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+ nvidia,tristate = <TEGRA_PIN_DISABLE>;
+- nvidia,enable-input = <TEGRA_PIN_DISABLE>;
++ nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+ };
+ sdmmc3_cmd_pa7 {
+ nvidia,pins = "sdmmc3_cmd_pa7",
+@@ -290,7 +306,7 @@
+ nvidia,function = "sdmmc4";
+ nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+ nvidia,tristate = <TEGRA_PIN_DISABLE>;
+- nvidia,enable-input = <TEGRA_PIN_DISABLE>;
++ nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+ };
+ sdmmc4_cmd_pt7 {
+ nvidia,pins = "sdmmc4_cmd_pt7",
+@@ -730,7 +746,6 @@
+ nvidia,pins = "drive_sdio1";
+ nvidia,high-speed-mode = <TEGRA_PIN_ENABLE>;
+ nvidia,schmitt = <TEGRA_PIN_DISABLE>;
+- nvidia,low-power-mode = <TEGRA_PIN_LP_DRIVE_DIV_1>;
+ nvidia,pull-down-strength = <36>;
+ nvidia,pull-up-strength = <20>;
+ nvidia,slew-rate-rising = <TEGRA_PIN_SLEW_RATE_SLOW>;
+@@ -740,7 +755,6 @@
+ nvidia,pins = "drive_sdio3";
+ nvidia,high-speed-mode = <TEGRA_PIN_ENABLE>;
+ nvidia,schmitt = <TEGRA_PIN_DISABLE>;
+- nvidia,low-power-mode = <TEGRA_PIN_LP_DRIVE_DIV_1>;
+ nvidia,pull-down-strength = <36>;
+ nvidia,pull-up-strength = <20>;
+ nvidia,slew-rate-rising = <TEGRA_PIN_SLEW_RATE_FASTEST>;
+@@ -750,12 +764,10 @@
+ nvidia,pins = "drive_gma";
+ nvidia,high-speed-mode = <TEGRA_PIN_ENABLE>;
+ nvidia,schmitt = <TEGRA_PIN_DISABLE>;
+- nvidia,low-power-mode = <TEGRA_PIN_LP_DRIVE_DIV_1>;
+ nvidia,pull-down-strength = <2>;
+ nvidia,pull-up-strength = <2>;
+ nvidia,slew-rate-rising = <TEGRA_PIN_SLEW_RATE_FASTEST>;
+ nvidia,slew-rate-falling = <TEGRA_PIN_SLEW_RATE_FASTEST>;
+- nvidia,drive-type = <1>;
+ };
+ };
+ };
+@@ -815,7 +827,6 @@
+ regulator-name = "vdd-1v8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+- regulator-always-on;
+ regulator-boot-on;
+ };
+
+@@ -862,10 +873,11 @@
+ regulator-name = "vdd-2v8-display";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
++ regulator-always-on;
+ regulator-boot-on;
+ };
+
+- ldo3 {
++ vdd_1v2_ap: ldo3 {
+ regulator-name = "avdd-1v2";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+@@ -1052,7 +1064,7 @@
+ regulator-boot-on;
+ };
+
+- regulator@1 {
++ vdd_lcd: regulator@1 {
+ compatible = "regulator-fixed";
+ reg = <1>;
+ regulator-name = "vdd_lcd_1v8";
diff --git a/arch/arm/boot/dts/tegra114.dtsi b/arch/arm/boot/dts/tegra114.dtsi
index fdc559a..335a1d8 100644
--- a/arch/arm/boot/dts/tegra114.dtsi
@@ -413,10 +708,70 @@ index fdc559a..335a1d8 100644
compatible = "nvidia,tegra114-smmu", "nvidia,tegra30-smmu";
reg = <0x70019010 0x02c
diff --git a/arch/arm/boot/dts/tegra124-jetson-tk1.dts b/arch/arm/boot/dts/tegra124-jetson-tk1.dts
-index e31fb61..16082c0 100644
+index e31fb61..624b0fb 100644
--- a/arch/arm/boot/dts/tegra124-jetson-tk1.dts
+++ b/arch/arm/boot/dts/tegra124-jetson-tk1.dts
-@@ -1633,6 +1633,7 @@
+@@ -1461,7 +1461,7 @@
+ regulator-max-microamp = <3500000>;
+ regulator-always-on;
+ regulator-boot-on;
+- ams,external-control = <2>;
++ ams,ext-control = <2>;
+ };
+
+ sd1 {
+@@ -1472,7 +1472,7 @@
+ regulator-max-microamp = <2500000>;
+ regulator-always-on;
+ regulator-boot-on;
+- ams,external-control = <1>;
++ ams,ext-control = <1>;
+ };
+
+ vdd_1v35_lp0: sd2 {
+@@ -1521,7 +1521,7 @@
+ regulator-max-microvolt = <1050000>;
+ regulator-boot-on;
+ regulator-always-on;
+- ams,external-control = <1>;
++ ams,ext-control = <1>;
+ };
+
+ ldo1 {
+@@ -1619,6 +1619,32 @@
+ nvidia,sys-clock-req-active-high;
+ };
+
++ padctl@0,7009f000 {
++ pinctrl-0 = <&padctl_default>;
++ pinctrl-names = "default";
++
++ padctl_default: pinmux {
++ usb3 {
++ nvidia,lanes = "pcie-0", "pcie-1";
++ nvidia,function = "usb3";
++ nvidia,iddq = <0>;
++ };
++
++ pcie {
++ nvidia,lanes = "pcie-2", "pcie-3",
++ "pcie-4";
++ nvidia,function = "pcie";
++ nvidia,iddq = <0>;
++ };
++
++ sata {
++ nvidia,lanes = "sata-0";
++ nvidia,function = "sata";
++ nvidia,iddq = <0>;
++ };
++ };
++ };
++
+ /* SD card */
+ sdhci@0,700b0400 {
+ status = "okay";
+@@ -1633,6 +1659,7 @@
sdhci@0,700b0600 {
status = "okay";
bus-width = <8>;
@@ -425,9 +780,36 @@ index e31fb61..16082c0 100644
ahub@0,70300000 {
diff --git a/arch/arm/boot/dts/tegra124-venice2.dts b/arch/arm/boot/dts/tegra124-venice2.dts
-index f0bb842..f1a5bac 100644
+index f0bb842..70ad91d 100644
--- a/arch/arm/boot/dts/tegra124-venice2.dts
+++ b/arch/arm/boot/dts/tegra124-venice2.dts
+@@ -682,7 +682,7 @@
+ regulator-max-microamp = <3500000>;
+ regulator-always-on;
+ regulator-boot-on;
+- ams,external-control = <2>;
++ ams,ext-control = <2>;
+ };
+
+ sd1 {
+@@ -693,7 +693,7 @@
+ regulator-max-microamp = <2500000>;
+ regulator-always-on;
+ regulator-boot-on;
+- ams,external-control = <1>;
++ ams,ext-control = <1>;
+ };
+
+ vdd_1v35_lp0: sd2 {
+@@ -742,7 +742,7 @@
+ regulator-max-microvolt = <1050000>;
+ regulator-boot-on;
+ regulator-always-on;
+- ams,external-control = <1>;
++ ams,ext-control = <1>;
+ };
+
+ ldo1 {
@@ -816,7 +816,7 @@
spi@0,7000d400 {
status = "okay";
@@ -576,10 +958,40 @@ index f0bb842..f1a5bac 100644
+
+#include "cros-ec-keyboard.dtsi"
diff --git a/arch/arm/boot/dts/tegra124.dtsi b/arch/arm/boot/dts/tegra124.dtsi
-index 6e6bc4e..d675186 100644
+index 6e6bc4e..3af46d3 100644
--- a/arch/arm/boot/dts/tegra124.dtsi
+++ b/arch/arm/boot/dts/tegra124.dtsi
-@@ -179,6 +179,12 @@
+@@ -1,6 +1,7 @@
+ #include <dt-bindings/clock/tegra124-car.h>
+ #include <dt-bindings/gpio/tegra-gpio.h>
+ #include <dt-bindings/pinctrl/pinctrl-tegra.h>
++#include <dt-bindings/pinctrl/pinctrl-tegra-xusb.h>
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+ #include "skeleton.dtsi"
+@@ -102,6 +103,21 @@
+ (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
+ };
+
++ gpu@0,57000000 {
++ compatible = "nvidia,gk20a";
++ reg = <0x0 0x57000000 0x0 0x01000000>,
++ <0x0 0x58000000 0x0 0x01000000>;
++ interrupts = <GIC_SPI 157 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 158 IRQ_TYPE_LEVEL_HIGH>;
++ interrupt-names = "stall", "nonstall";
++ clocks = <&tegra_car TEGRA124_CLK_GPU>,
++ <&tegra_car TEGRA124_CLK_PLL_P_OUT5>;
++ clock-names = "gpu", "pwr";
++ resets = <&tegra_car 184>;
++ reset-names = "gpu";
++ status = "disabled";
++ };
++
+ timer@0,60005000 {
+ compatible = "nvidia,tegra124-timer", "nvidia,tegra20-timer";
+ reg = <0x0 0x60005000 0x0 0x400>;
+@@ -179,6 +195,12 @@
#dma-cells = <1>;
};
@@ -592,7 +1004,7 @@ index 6e6bc4e..d675186 100644
pinmux: pinmux@0,70000868 {
compatible = "nvidia,tegra124-pinmux";
reg = <0x0 0x70000868 0x0 0x164>, /* Pad control registers */
-@@ -449,6 +455,30 @@
+@@ -449,6 +471,39 @@
clock-names = "pclk", "clk32k_in";
};
@@ -620,6 +1032,15 @@ index 6e6bc4e..d675186 100644
+ status = "disabled";
+ };
+
++ padctl: padctl@0,7009f000 {
++ compatible = "nvidia,tegra124-xusb-padctl";
++ reg = <0x0 0x7009f000 0x0 0x1000>;
++ resets = <&tegra_car 142>;
++ reset-names = "padctl";
++
++ #phy-cells = <1>;
++ };
++
sdhci@0,700b0000 {
compatible = "nvidia,tegra124-sdhci";
reg = <0x0 0x700b0000 0x0 0x200>;
@@ -1958,10 +2379,43 @@ index dec4fc8..0b1ede9 100644
compatible = "nvidia,tegra30-ahub";
reg = <0x70080000 0x200
diff --git a/arch/arm/configs/tegra_defconfig b/arch/arm/configs/tegra_defconfig
-index 157a4f1..285c433 100644
+index fb25e29..285c433 100644
--- a/arch/arm/configs/tegra_defconfig
+++ b/arch/arm/configs/tegra_defconfig
-@@ -104,6 +104,7 @@ CONFIG_SCSI_MULTI_LUN=y
+@@ -23,14 +23,11 @@ CONFIG_MODULE_FORCE_UNLOAD=y
+ CONFIG_PARTITION_ADVANCED=y
+ # CONFIG_IOSCHED_DEADLINE is not set
+ # CONFIG_IOSCHED_CFQ is not set
+-CONFIG_GPIO_PCA953X=y
+ CONFIG_ARCH_TEGRA=y
+ CONFIG_ARCH_TEGRA_2x_SOC=y
+ CONFIG_ARCH_TEGRA_3x_SOC=y
+ CONFIG_ARCH_TEGRA_114_SOC=y
+ CONFIG_ARCH_TEGRA_124_SOC=y
+-CONFIG_TEGRA_EMC_SCALING_ENABLE=y
+-CONFIG_TRUSTED_FOUNDATIONS=y
+ CONFIG_PCI=y
+ CONFIG_PCI_MSI=y
+ CONFIG_PCI_TEGRA=y
+@@ -74,9 +71,6 @@ CONFIG_IPV6_MIP6=y
+ CONFIG_IPV6_TUNNEL=y
+ CONFIG_IPV6_MULTIPLE_TABLES=y
+ CONFIG_CAN=y
+-CONFIG_CAN_RAW=y
+-CONFIG_CAN_BCM=y
+-CONFIG_CAN_DEV=y
+ CONFIG_CAN_MCP251X=y
+ CONFIG_BT=y
+ CONFIG_BT_RFCOMM=y
+@@ -96,7 +90,6 @@ CONFIG_CMA_SIZE_MBYTES=64
+ CONFIG_MTD=y
+ CONFIG_MTD_M25P80=y
+ CONFIG_MTD_SPI_NOR=y
+-CONFIG_PROC_DEVICETREE=y
+ CONFIG_BLK_DEV_LOOP=y
+ CONFIG_AD525X_DPOT=y
+ CONFIG_AD525X_DPOT_I2C=y
+@@ -111,6 +104,7 @@ CONFIG_SCSI_MULTI_LUN=y
# CONFIG_SCSI_LOWLEVEL is not set
CONFIG_NETDEVICES=y
CONFIG_DUMMY=y
@@ -1969,7 +2423,7 @@ index 157a4f1..285c433 100644
CONFIG_R8169=y
CONFIG_USB_PEGASUS=y
CONFIG_USB_USBNET=y
-@@ -118,6 +119,8 @@ CONFIG_KEYBOARD_GPIO=y
+@@ -125,6 +119,8 @@ CONFIG_KEYBOARD_GPIO=y
CONFIG_KEYBOARD_TEGRA=y
CONFIG_KEYBOARD_CROS_EC=y
CONFIG_MOUSE_PS2_ELANTECH=y
@@ -1978,7 +2432,7 @@ index 157a4f1..285c433 100644
CONFIG_INPUT_MISC=y
CONFIG_INPUT_MPU3050=y
# CONFIG_LEGACY_PTYS is not set
-@@ -128,6 +131,7 @@ CONFIG_SERIAL_TEGRA=y
+@@ -135,6 +131,7 @@ CONFIG_SERIAL_TEGRA=y
CONFIG_SERIAL_OF_PLATFORM=y
# CONFIG_HW_RANDOM is not set
# CONFIG_I2C_COMPAT is not set
@@ -1986,7 +2440,15 @@ index 157a4f1..285c433 100644
CONFIG_I2C_MUX_PCA954x=y
CONFIG_I2C_MUX_PINCTRL=y
CONFIG_I2C_TEGRA=y
-@@ -149,10 +153,12 @@ CONFIG_POWER_RESET=y
+@@ -144,6 +141,7 @@ CONFIG_SPI_TEGRA20_SFLASH=y
+ CONFIG_SPI_TEGRA20_SLINK=y
+ CONFIG_PINCTRL_AS3722=y
+ CONFIG_PINCTRL_PALMAS=y
++CONFIG_GPIO_PCA953X=y
+ CONFIG_GPIO_PCA953X_IRQ=y
+ CONFIG_GPIO_PALMAS=y
+ CONFIG_GPIO_TPS6586X=y
+@@ -155,10 +153,12 @@ CONFIG_POWER_RESET=y
CONFIG_POWER_RESET_AS3722=y
CONFIG_POWER_RESET_GPIO=y
CONFIG_SENSORS_LM90=y
@@ -1999,7 +2461,7 @@ index 157a4f1..285c433 100644
CONFIG_MFD_PALMAS=y
CONFIG_MFD_TPS65090=y
CONFIG_MFD_TPS6586X=y
-@@ -215,6 +221,7 @@ CONFIG_MMC_SDHCI_TEGRA=y
+@@ -221,6 +221,7 @@ CONFIG_MMC_SDHCI_TEGRA=y
CONFIG_NEW_LEDS=y
CONFIG_LEDS_CLASS=y
CONFIG_LEDS_GPIO=y
@@ -2007,6 +2469,12 @@ index 157a4f1..285c433 100644
CONFIG_LEDS_TRIGGERS=y
CONFIG_LEDS_TRIGGER_TIMER=y
CONFIG_LEDS_TRIGGER_ONESHOT=y
+@@ -291,5 +292,4 @@ CONFIG_DEBUG_LL=y
+ CONFIG_EARLY_PRINTK=y
+ CONFIG_CRYPTO_TWOFISH=y
+ # CONFIG_CRYPTO_ANSI_CPRNG is not set
+-CONFIG_CRYPTO_DEV_TEGRA_AES=y
+ CONFIG_CRC_CCITT=y
diff --git a/arch/arm/lib/delay.c b/arch/arm/lib/delay.c
index 5306de3..312d43e 100644
--- a/arch/arm/lib/delay.c
@@ -2078,23 +2546,24 @@ index 5306de3..312d43e 100644
+ delay_calibrated = true;
+}
diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile
-index 6fbfbb7..c303b55 100644
+index 6fbfbb7..34c05b7 100644
--- a/arch/arm/mach-tegra/Makefile
+++ b/arch/arm/mach-tegra/Makefile
-@@ -2,24 +2,20 @@ asflags-y += -march=armv7-a
+@@ -2,24 +2,19 @@ asflags-y += -march=armv7-a
obj-y += io.o
obj-y += irq.o
-obj-y += fuse.o
- obj-y += pmc.o
+-obj-y += pmc.o
obj-y += flowctrl.o
- obj-y += powergate.o
+-obj-y += powergate.o
-obj-y += apbio.o
obj-y += pm.o
obj-y += reset.o
obj-y += reset-handler.o
obj-y += sleep.o
obj-y += tegra.o
++obj-y += tegra-pmc.o
obj-$(CONFIG_CPU_IDLE) += cpuidle.o
-obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra20_speedo.o
obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += sleep-tegra20.o
@@ -2106,7 +2575,7 @@ index 6fbfbb7..c303b55 100644
obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += sleep-tegra30.o
obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += pm-tegra30.o
ifeq ($(CONFIG_CPU_IDLE),y)
-@@ -28,7 +24,6 @@ endif
+@@ -28,7 +23,6 @@ endif
obj-$(CONFIG_SMP) += platsmp.o headsmp.o
obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
@@ -2354,11 +2823,134 @@ index f05d71c..0000000
-u32 tegra_apb_readl(unsigned long offset);
-void tegra_apb_writel(u32 value, unsigned long offset);
-#endif
+diff --git a/arch/arm/mach-tegra/board-paz00.c b/arch/arm/mach-tegra/board-paz00.c
+index 9c6029b..bb4782a 100644
+--- a/arch/arm/mach-tegra/board-paz00.c
++++ b/arch/arm/mach-tegra/board-paz00.c
+@@ -17,9 +17,10 @@
+ *
+ */
+
+-#include <linux/platform_device.h>
+ #include <linux/gpio/driver.h>
++#include <linux/platform_device.h>
+ #include <linux/rfkill-gpio.h>
++
+ #include "board.h"
+
+ static struct rfkill_gpio_platform_data wifi_rfkill_platform_data = {
+diff --git a/arch/arm/mach-tegra/board.h b/arch/arm/mach-tegra/board.h
+index bcf5dbf..da90c89 100644
+--- a/arch/arm/mach-tegra/board.h
++++ b/arch/arm/mach-tegra/board.h
+@@ -28,13 +28,6 @@
+ void __init tegra_map_common_io(void);
+ void __init tegra_init_irq(void);
+
+-int __init tegra_powergate_init(void);
+-#if defined(CONFIG_ARCH_TEGRA_2x_SOC) && defined(CONFIG_DEBUG_FS)
+-int __init tegra_powergate_debugfs_init(void);
+-#else
+-static inline int tegra_powergate_debugfs_init(void) { return 0; }
+-#endif
+-
+ void __init tegra_paz00_wifikill_init(void);
+
+ #endif
+diff --git a/arch/arm/mach-tegra/cpuidle-tegra114.c b/arch/arm/mach-tegra/cpuidle-tegra114.c
+index b5fb7c1..e3ebdce 100644
+--- a/arch/arm/mach-tegra/cpuidle-tegra114.c
++++ b/arch/arm/mach-tegra/cpuidle-tegra114.c
+@@ -14,16 +14,16 @@
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+-#include <linux/kernel.h>
+-#include <linux/module.h>
++#include <asm/firmware.h>
++#include <linux/clockchips.h>
+ #include <linux/cpuidle.h>
+ #include <linux/cpu_pm.h>
+-#include <linux/clockchips.h>
+-#include <asm/firmware.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
+
+ #include <asm/cpuidle.h>
+-#include <asm/suspend.h>
+ #include <asm/smp_plat.h>
++#include <asm/suspend.h>
+
+ #include "pm.h"
+ #include "sleep.h"
+diff --git a/arch/arm/mach-tegra/cpuidle-tegra20.c b/arch/arm/mach-tegra/cpuidle-tegra20.c
+index b82dcae..b30bf5c 100644
+--- a/arch/arm/mach-tegra/cpuidle-tegra20.c
++++ b/arch/arm/mach-tegra/cpuidle-tegra20.c
+@@ -19,23 +19,23 @@
+ * more details.
+ */
+
+-#include <linux/kernel.h>
+-#include <linux/module.h>
++#include <linux/clk/tegra.h>
++#include <linux/clockchips.h>
+ #include <linux/cpuidle.h>
+ #include <linux/cpu_pm.h>
+-#include <linux/clockchips.h>
+-#include <linux/clk/tegra.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
+
+ #include <asm/cpuidle.h>
+ #include <asm/proc-fns.h>
+-#include <asm/suspend.h>
+ #include <asm/smp_plat.h>
++#include <asm/suspend.h>
+
+-#include "pm.h"
+-#include "sleep.h"
++#include "flowctrl.h"
+ #include "iomap.h"
+ #include "irq.h"
+-#include "flowctrl.h"
++#include "pm.h"
++#include "sleep.h"
+
+ #ifdef CONFIG_PM_SLEEP
+ static bool abort_flag;
+diff --git a/arch/arm/mach-tegra/cpuidle-tegra30.c b/arch/arm/mach-tegra/cpuidle-tegra30.c
+index ed2a2a7..3556127 100644
+--- a/arch/arm/mach-tegra/cpuidle-tegra30.c
++++ b/arch/arm/mach-tegra/cpuidle-tegra30.c
+@@ -19,17 +19,17 @@
+ * more details.
+ */
+
+-#include <linux/kernel.h>
+-#include <linux/module.h>
++#include <linux/clk/tegra.h>
++#include <linux/clockchips.h>
+ #include <linux/cpuidle.h>
+ #include <linux/cpu_pm.h>
+-#include <linux/clockchips.h>
+-#include <linux/clk/tegra.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
+
+ #include <asm/cpuidle.h>
+ #include <asm/proc-fns.h>
+-#include <asm/suspend.h>
+ #include <asm/smp_plat.h>
++#include <asm/suspend.h>
+
+ #include "pm.h"
+ #include "sleep.h"
diff --git a/arch/arm/mach-tegra/cpuidle.c b/arch/arm/mach-tegra/cpuidle.c
-index 7bc5d8d..ff0a10b 100644
+index 7bc5d8d..b27330c 100644
--- a/arch/arm/mach-tegra/cpuidle.c
+++ b/arch/arm/mach-tegra/cpuidle.c
-@@ -23,8 +23,8 @@
+@@ -23,13 +23,13 @@
#include <linux/kernel.h>
#include <linux/module.h>
@@ -2368,14 +2960,35 @@ index 7bc5d8d..ff0a10b 100644
#include "cpuidle.h"
void __init tegra_cpuidle_init(void)
+ {
+- switch (tegra_chip_id) {
++ switch (tegra_get_chip_id()) {
+ case TEGRA20:
+ if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC))
+ tegra20_cpuidle_init();
+@@ -49,7 +49,7 @@ void __init tegra_cpuidle_init(void)
+
+ void tegra_cpuidle_pcie_irqs_in_use(void)
+ {
+- switch (tegra_chip_id) {
++ switch (tegra_get_chip_id()) {
+ case TEGRA20:
+ if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC))
+ tegra20_cpuidle_pcie_irqs_in_use();
diff --git a/arch/arm/mach-tegra/flowctrl.c b/arch/arm/mach-tegra/flowctrl.c
-index ce8ab8a..4b31091 100644
+index ce8ab8a..2106b3d 100644
--- a/arch/arm/mach-tegra/flowctrl.c
+++ b/arch/arm/mach-tegra/flowctrl.c
-@@ -22,10 +22,10 @@
- #include <linux/kernel.h>
+@@ -18,14 +18,14 @@
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
++#include <linux/cpumask.h>
+ #include <linux/init.h>
+-#include <linux/kernel.h>
#include <linux/io.h>
- #include <linux/cpumask.h>
+-#include <linux/cpumask.h>
++#include <linux/kernel.h>
+#include <linux/tegra-soc.h>
#include "flowctrl.h"
@@ -2384,6 +2997,24 @@ index ce8ab8a..4b31091 100644
static u8 flowctrl_offset_halt_cpu[] = {
FLOW_CTRL_HALT_CPU0_EVENTS,
+@@ -76,7 +76,7 @@ void flowctrl_cpu_suspend_enter(unsigned int cpuid)
+ int i;
+
+ reg = flowctrl_read_cpu_csr(cpuid);
+- switch (tegra_chip_id) {
++ switch (tegra_get_chip_id()) {
+ case TEGRA20:
+ /* clear wfe bitmap */
+ reg &= ~TEGRA20_FLOW_CTRL_CSR_WFE_BITMAP;
+@@ -117,7 +117,7 @@ void flowctrl_cpu_suspend_exit(unsigned int cpuid)
+
+ /* Disable powergating via flow controller for CPU0 */
+ reg = flowctrl_read_cpu_csr(cpuid);
+- switch (tegra_chip_id) {
++ switch (tegra_get_chip_id()) {
+ case TEGRA20:
+ /* clear wfe bitmap */
+ reg &= ~TEGRA20_FLOW_CTRL_CSR_WFE_BITMAP;
diff --git a/arch/arm/mach-tegra/fuse.c b/arch/arm/mach-tegra/fuse.c
deleted file mode 100644
index c9ac23b..0000000
@@ -2728,13 +3359,18 @@ index c01d047..0000000
-
-#endif
diff --git a/arch/arm/mach-tegra/hotplug.c b/arch/arm/mach-tegra/hotplug.c
-index ff26af2..38c5170 100644
+index ff26af2..e2ea4aa 100644
--- a/arch/arm/mach-tegra/hotplug.c
+++ b/arch/arm/mach-tegra/hotplug.c
-@@ -10,10 +10,10 @@
+@@ -7,13 +7,14 @@
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
++
++#include <linux/clk/tegra.h>
#include <linux/kernel.h>
#include <linux/smp.h>
- #include <linux/clk/tegra.h>
+-#include <linux/clk/tegra.h>
+#include <linux/tegra-soc.h>
#include <asm/smp_plat.h>
@@ -2743,79 +3379,444 @@ index ff26af2..38c5170 100644
#include "sleep.h"
static void (*tegra_hotplug_shutdown)(void);
+@@ -36,6 +37,11 @@ int tegra_cpu_kill(unsigned cpu)
+ */
+ void __ref tegra_cpu_die(unsigned int cpu)
+ {
++ if (!tegra_hotplug_shutdown) {
++ WARN(1, "hotplug is not yet initialized\n");
++ return;
++ }
++
+ /* Clean L1 data cache */
+ tegra_disable_clean_inv_dcache(TEGRA_FLUSH_CACHE_LOUIS);
+
+@@ -46,17 +52,20 @@ void __ref tegra_cpu_die(unsigned int cpu)
+ BUG();
+ }
+
+-void __init tegra_hotplug_init(void)
++static int __init tegra_hotplug_init(void)
+ {
+ if (!IS_ENABLED(CONFIG_HOTPLUG_CPU))
+- return;
++ return 0;
+
+- if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC) && tegra_chip_id == TEGRA20)
++ if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC) && tegra_get_chip_id() == TEGRA20)
+ tegra_hotplug_shutdown = tegra20_hotplug_shutdown;
+- if (IS_ENABLED(CONFIG_ARCH_TEGRA_3x_SOC) && tegra_chip_id == TEGRA30)
++ if (IS_ENABLED(CONFIG_ARCH_TEGRA_3x_SOC) && tegra_get_chip_id() == TEGRA30)
+ tegra_hotplug_shutdown = tegra30_hotplug_shutdown;
+- if (IS_ENABLED(CONFIG_ARCH_TEGRA_114_SOC) && tegra_chip_id == TEGRA114)
++ if (IS_ENABLED(CONFIG_ARCH_TEGRA_114_SOC) && tegra_get_chip_id() == TEGRA114)
+ tegra_hotplug_shutdown = tegra30_hotplug_shutdown;
+- if (IS_ENABLED(CONFIG_ARCH_TEGRA_124_SOC) && tegra_chip_id == TEGRA124)
++ if (IS_ENABLED(CONFIG_ARCH_TEGRA_124_SOC) && tegra_get_chip_id() == TEGRA124)
+ tegra_hotplug_shutdown = tegra30_hotplug_shutdown;
++
++ return 0;
+ }
++pure_initcall(tegra_hotplug_init);
+diff --git a/arch/arm/mach-tegra/io.c b/arch/arm/mach-tegra/io.c
+index bb9c9c2..352de15 100644
+--- a/arch/arm/mach-tegra/io.c
++++ b/arch/arm/mach-tegra/io.c
+@@ -18,14 +18,14 @@
+ *
+ */
+
+-#include <linux/kernel.h>
+-#include <linux/module.h>
+ #include <linux/init.h>
+-#include <linux/mm.h>
+ #include <linux/io.h>
++#include <linux/kernel.h>
++#include <linux/mm.h>
++#include <linux/module.h>
+
+-#include <asm/page.h>
+ #include <asm/mach/map.h>
++#include <asm/page.h>
+
+ #include "board.h"
+ #include "iomap.h"
+diff --git a/arch/arm/mach-tegra/irq.c b/arch/arm/mach-tegra/irq.c
+index 1a74d56..da7be13 100644
+--- a/arch/arm/mach-tegra/irq.c
++++ b/arch/arm/mach-tegra/irq.c
+@@ -17,14 +17,14 @@
+ *
+ */
+
+-#include <linux/kernel.h>
+ #include <linux/cpu_pm.h>
+ #include <linux/interrupt.h>
+-#include <linux/irq.h>
+ #include <linux/io.h>
+-#include <linux/of.h>
+-#include <linux/of_address.h>
+ #include <linux/irqchip/arm-gic.h>
++#include <linux/irq.h>
++#include <linux/kernel.h>
++#include <linux/of_address.h>
++#include <linux/of.h>
+ #include <linux/syscore_ops.h>
+
+ #include "board.h"
diff --git a/arch/arm/mach-tegra/platsmp.c b/arch/arm/mach-tegra/platsmp.c
-index 929d104..d9878ac 100644
+index 929d104..53e8442 100644
--- a/arch/arm/mach-tegra/platsmp.c
+++ b/arch/arm/mach-tegra/platsmp.c
-@@ -19,13 +19,13 @@
+@@ -11,27 +11,26 @@
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+-#include <linux/init.h>
+-#include <linux/errno.h>
++
++#include <linux/clk/tegra.h>
+ #include <linux/delay.h>
+ #include <linux/device.h>
++#include <linux/errno.h>
++#include <linux/init.h>
++#include <linux/io.h>
+ #include <linux/jiffies.h>
#include <linux/smp.h>
- #include <linux/io.h>
- #include <linux/clk/tegra.h>
+-#include <linux/io.h>
+-#include <linux/clk/tegra.h>
+#include <linux/tegra-soc.h>
#include <asm/cacheflush.h>
#include <asm/mach-types.h>
- #include <asm/smp_scu.h>
+-#include <asm/smp_scu.h>
#include <asm/smp_plat.h>
-
+-
-#include "fuse.h"
- #include "flowctrl.h"
- #include "reset.h"
- #include "pmc.h"
+-#include "flowctrl.h"
+-#include "reset.h"
+-#include "pmc.h"
++#include <asm/smp_scu.h>
+
+ #include "common.h"
++#include "flowctrl.h"
+ #include "iomap.h"
++#include "reset.h"
+
+ static cpumask_t tegra_cpu_init_mask;
+
+@@ -170,13 +169,13 @@ static int tegra114_boot_secondary(unsigned int cpu, struct task_struct *idle)
+ static int tegra_boot_secondary(unsigned int cpu,
+ struct task_struct *idle)
+ {
+- if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC) && tegra_chip_id == TEGRA20)
++ if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC) && tegra_get_chip_id() == TEGRA20)
+ return tegra20_boot_secondary(cpu, idle);
+- if (IS_ENABLED(CONFIG_ARCH_TEGRA_3x_SOC) && tegra_chip_id == TEGRA30)
++ if (IS_ENABLED(CONFIG_ARCH_TEGRA_3x_SOC) && tegra_get_chip_id() == TEGRA30)
+ return tegra30_boot_secondary(cpu, idle);
+- if (IS_ENABLED(CONFIG_ARCH_TEGRA_114_SOC) && tegra_chip_id == TEGRA114)
++ if (IS_ENABLED(CONFIG_ARCH_TEGRA_114_SOC) && tegra_get_chip_id() == TEGRA114)
+ return tegra114_boot_secondary(cpu, idle);
+- if (IS_ENABLED(CONFIG_ARCH_TEGRA_124_SOC) && tegra_chip_id == TEGRA124)
++ if (IS_ENABLED(CONFIG_ARCH_TEGRA_124_SOC) && tegra_get_chip_id() == TEGRA124)
+ return tegra114_boot_secondary(cpu, idle);
+
+ return -EINVAL;
+diff --git a/arch/arm/mach-tegra/pm-tegra20.c b/arch/arm/mach-tegra/pm-tegra20.c
+index d65e1d7..39ac2b7 100644
+--- a/arch/arm/mach-tegra/pm-tegra20.c
++++ b/arch/arm/mach-tegra/pm-tegra20.c
+@@ -13,6 +13,7 @@
+ * 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 "pm.h"
+diff --git a/arch/arm/mach-tegra/pm-tegra30.c b/arch/arm/mach-tegra/pm-tegra30.c
+index 8fa326d..46cc19d 100644
+--- a/arch/arm/mach-tegra/pm-tegra30.c
++++ b/arch/arm/mach-tegra/pm-tegra30.c
+@@ -13,6 +13,7 @@
+ * 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 "pm.h"
diff --git a/arch/arm/mach-tegra/pm.c b/arch/arm/mach-tegra/pm.c
-index f55b05a..d7e6370 100644
+index f55b05a..d9637d8 100644
--- a/arch/arm/mach-tegra/pm.c
+++ b/arch/arm/mach-tegra/pm.c
-@@ -26,6 +26,7 @@
+@@ -16,30 +16,29 @@
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+-#include <linux/kernel.h>
+-#include <linux/spinlock.h>
+-#include <linux/io.h>
++#include <linux/clk/tegra.h>
+ #include <linux/cpumask.h>
+-#include <linux/delay.h>
+ #include <linux/cpu_pm.h>
+-#include <linux/suspend.h>
++#include <linux/delay.h>
#include <linux/err.h>
++#include <linux/io.h>
++#include <linux/kernel.h>
#include <linux/slab.h>
- #include <linux/clk/tegra.h>
+-#include <linux/clk/tegra.h>
++#include <linux/spinlock.h>
++#include <linux/suspend.h>
+#include <linux/tegra-soc.h>
- #include <asm/smp_plat.h>
+-#include <asm/smp_plat.h>
#include <asm/cacheflush.h>
-@@ -37,7 +38,6 @@
- #include "iomap.h"
- #include "reset.h"
+-#include <asm/suspend.h>
+ #include <asm/idmap.h>
+ #include <asm/proc-fns.h>
++#include <asm/smp_plat.h>
++#include <asm/suspend.h>
+ #include <asm/tlbflush.h>
+
+-#include "iomap.h"
+-#include "reset.h"
#include "flowctrl.h"
-#include "fuse.h"
++#include "iomap.h"
#include "pm.h"
- #include "pmc.h"
+-#include "pmc.h"
++#include "reset.h"
#include "sleep.h"
-diff --git a/arch/arm/mach-tegra/pmc.c b/arch/arm/mach-tegra/pmc.c
-index 7c7123e..e1677c0 100644
---- a/arch/arm/mach-tegra/pmc.c
-+++ b/arch/arm/mach-tegra/pmc.c
-@@ -17,13 +17,12 @@
- #include <linux/kernel.h>
- #include <linux/clk.h>
--#include <linux/io.h>
- #include <linux/of.h>
- #include <linux/of_address.h>
- #include <linux/tegra-powergate.h>
-+#include <linux/tegra-soc.h>
+ #ifdef CONFIG_PM_SLEEP
+@@ -53,7 +52,7 @@ static int (*tegra_sleep_func)(unsigned long v2p);
- #include "flowctrl.h"
--#include "fuse.h"
- #include "pm.h"
- #include "pmc.h"
- #include "sleep.h"
-@@ -60,9 +59,9 @@ static u8 tegra_cpu_domains[] = {
- };
- static DEFINE_SPINLOCK(tegra_powergate_lock);
+ static void tegra_tear_down_cpu_init(void)
+ {
+- switch (tegra_chip_id) {
++ switch (tegra_get_chip_id()) {
+ case TEGRA20:
+ if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC))
+ tegra_tear_down_cpu = tegra20_tear_down_cpu;
+@@ -143,7 +142,7 @@ bool tegra_set_cpu_in_lp2(void)
+
+ if ((phy_cpu_id == 0) && cpumask_equal(cpu_lp2_mask, cpu_online_mask))
+ last_cpu = true;
+- else if (tegra_chip_id == TEGRA20 && phy_cpu_id == 1)
++ else if (tegra_get_chip_id() == TEGRA20 && phy_cpu_id == 1)
+ tegra20_cpu_set_resettable_soon();
+
+ spin_unlock(&tegra_lp2_lock);
+@@ -166,9 +165,29 @@ static int tegra_sleep_cpu(unsigned long v2p)
+ return 0;
+ }
--static void __iomem *tegra_pmc_base;
- static bool tegra_pmc_invert_interrupt;
- static struct clk *tegra_pclk;
-+void __iomem *tegra_pmc_base;
++static void tegra_pm_set(enum tegra_suspend_mode mode)
++{
++ u32 value;
++
++ switch (tegra_get_chip_id()) {
++ case TEGRA20:
++ case TEGRA30:
++ break;
++ default:
++ /* Turn off CRAIL */
++ value = flowctrl_read_cpu_csr(0);
++ value &= ~FLOW_CTRL_CSR_ENABLE_EXT_MASK;
++ value |= FLOW_CTRL_CSR_ENABLE_EXT_CRAIL;
++ flowctrl_write_cpu_csr(0, value);
++ break;
++ }
++
++ tegra_pmc_enter_suspend_mode(mode);
++}
++
+ void tegra_idle_lp2_last(void)
+ {
+- tegra_pmc_pm_set(TEGRA_SUSPEND_LP2);
++ tegra_pm_set(TEGRA_SUSPEND_LP2);
- struct pmc_pm_data {
- u32 cpu_good_time; /* CPU power good time in uS */
-@@ -80,16 +79,6 @@ struct pmc_pm_data {
+ cpu_cluster_pm_enter();
+ suspend_cpu_complex();
+@@ -212,7 +231,7 @@ static int tegra_sleep_core(unsigned long v2p)
+ */
+ static bool tegra_lp1_iram_hook(void)
+ {
+- switch (tegra_chip_id) {
++ switch (tegra_get_chip_id()) {
+ case TEGRA20:
+ if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC))
+ tegra20_lp1_iram_hook();
+@@ -242,7 +261,7 @@ static bool tegra_lp1_iram_hook(void)
+
+ static bool tegra_sleep_core_init(void)
+ {
+- switch (tegra_chip_id) {
++ switch (tegra_get_chip_id()) {
+ case TEGRA20:
+ if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC))
+ tegra20_sleep_core_init();
+@@ -267,8 +286,6 @@ static bool tegra_sleep_core_init(void)
+
+ static void tegra_suspend_enter_lp1(void)
+ {
+- tegra_pmc_suspend();
+-
+ /* copy the reset vector & SDRAM shutdown code into IRAM */
+ memcpy(iram_save_addr, IO_ADDRESS(TEGRA_IRAM_LPx_RESUME_AREA),
+ iram_save_size);
+@@ -280,8 +297,6 @@ static void tegra_suspend_enter_lp1(void)
+
+ static void tegra_suspend_exit_lp1(void)
+ {
+- tegra_pmc_resume();
+-
+ /* restore IRAM */
+ memcpy(IO_ADDRESS(TEGRA_IRAM_LPx_RESUME_AREA), iram_save_addr,
+ iram_save_size);
+@@ -306,7 +321,7 @@ static int tegra_suspend_enter(suspend_state_t state)
+
+ pr_info("Entering suspend state %s\n", lp_state[mode]);
+
+- tegra_pmc_pm_set(mode);
++ tegra_pm_set(mode);
+
+ local_fiq_disable();
+
+@@ -354,7 +369,6 @@ void __init tegra_init_suspend(void)
+ return;
+
+ tegra_tear_down_cpu_init();
+- tegra_pmc_suspend_init();
+
+ if (mode >= TEGRA_SUSPEND_LP1) {
+ if (!tegra_lp1_iram_hook() || !tegra_sleep_core_init()) {
+diff --git a/arch/arm/mach-tegra/pm.h b/arch/arm/mach-tegra/pm.h
+index f4a8969..83bc875 100644
+--- a/arch/arm/mach-tegra/pm.h
++++ b/arch/arm/mach-tegra/pm.h
+@@ -21,12 +21,11 @@
+ #ifndef _MACH_TEGRA_PM_H_
+ #define _MACH_TEGRA_PM_H_
+
+-#include "pmc.h"
+-
+ struct tegra_lp1_iram {
+ void *start_addr;
+ void *end_addr;
};
- static struct pmc_pm_data pmc_pm_data;
++
+ extern struct tegra_lp1_iram tegra_lp1_iram;
+ extern void (*tegra_sleep_core_finish)(unsigned long v2p);
+
+@@ -42,15 +41,8 @@ void tegra_idle_lp2_last(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
+-static inline 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
+
+diff --git a/arch/arm/mach-tegra/pmc.c b/arch/arm/mach-tegra/pmc.c
+deleted file mode 100644
+index 7c7123e..0000000
+--- a/arch/arm/mach-tegra/pmc.c
++++ /dev/null
+@@ -1,413 +0,0 @@
+-/*
+- * Copyright (C) 2012,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/clk.h>
+-#include <linux/io.h>
+-#include <linux/of.h>
+-#include <linux/of_address.h>
+-#include <linux/tegra-powergate.h>
+-
+-#include "flowctrl.h"
+-#include "fuse.h"
+-#include "pm.h"
+-#include "pmc.h"
+-#include "sleep.h"
+-
+-#define TEGRA_POWER_SYSCLK_POLARITY (1 << 10) /* sys clk polarity */
+-#define TEGRA_POWER_SYSCLK_OE (1 << 11) /* system clock enable */
+-#define TEGRA_POWER_EFFECT_LP0 (1 << 14) /* LP0 when CPU pwr gated */
+-#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_SCRATCH0 0x50
+-#define PMC_SCRATCH0_MODE_RECOVERY (1 << 31)
+-#define PMC_SCRATCH0_MODE_BOOTLOADER (1 << 30)
+-#define PMC_SCRATCH0_MODE_RCM (1 << 1)
+-#define PMC_SCRATCH0_MODE_MASK (PMC_SCRATCH0_MODE_RECOVERY | \
+- PMC_SCRATCH0_MODE_BOOTLOADER | \
+- PMC_SCRATCH0_MODE_RCM)
+-
+-#define PMC_CPUPWRGOOD_TIMER 0xc8
+-#define PMC_CPUPWROFF_TIMER 0xcc
+-
+-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)
-{
- return readl(tegra_pmc_base + reg);
@@ -2826,60 +3827,475 @@ index 7c7123e..e1677c0 100644
- writel(val, tegra_pmc_base + reg);
-}
-
- static int tegra_pmc_get_cpu_powerdomain_id(int cpuid)
- {
- if (cpuid <= 0 || cpuid >= num_possible_cpus())
+-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);
+-}
+-
+-void tegra_pmc_restart(enum reboot_mode mode, const char *cmd)
+-{
+- u32 val;
+-
+- val = tegra_pmc_readl(PMC_SCRATCH0);
+- val &= ~PMC_SCRATCH0_MODE_MASK;
+-
+- if (cmd) {
+- if (strcmp(cmd, "recovery") == 0)
+- val |= PMC_SCRATCH0_MODE_RECOVERY;
+-
+- if (strcmp(cmd, "bootloader") == 0)
+- val |= PMC_SCRATCH0_MODE_BOOTLOADER;
+-
+- if (strcmp(cmd, "forced-recovery") == 0)
+- val |= PMC_SCRATCH0_MODE_RCM;
+- }
+-
+- tegra_pmc_writel(val, PMC_SCRATCH0);
+-
+- val = tegra_pmc_readl(0);
+- val |= 0x10;
+- tegra_pmc_writel(val, 0);
+-}
+-
+-#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_set_suspend_mode(enum tegra_suspend_mode mode)
+-{
+- if (mode < TEGRA_SUSPEND_NONE || mode >= TEGRA_MAX_SUSPEND_MODE)
+- return;
+-
+- pmc_pm_data.suspend_mode = mode;
+-}
+-
+-void tegra_pmc_suspend(void)
+-{
+- tegra_pmc_writel(virt_to_phys(tegra_resume), PMC_SCRATCH41);
+-}
+-
+-void tegra_pmc_resume(void)
+-{
+- tegra_pmc_writel(0x0, PMC_SCRATCH41);
+-}
+-
+-void tegra_pmc_pm_set(enum tegra_suspend_mode mode)
+-{
+- u32 reg, csr_reg;
+- unsigned long rate = 0;
+-
+- reg = tegra_pmc_readl(PMC_CTRL);
+- reg |= TEGRA_POWER_CPU_PWRREQ_OE;
+- reg &= ~TEGRA_POWER_EFFECT_LP0;
+-
+- switch (tegra_chip_id) {
+- case TEGRA20:
+- case TEGRA30:
+- break;
+- default:
+- /* Turn off CRAIL */
+- csr_reg = flowctrl_read_cpu_csr(0);
+- csr_reg &= ~FLOW_CTRL_CSR_ENABLE_EXT_MASK;
+- csr_reg |= FLOW_CTRL_CSR_ENABLE_EXT_CRAIL;
+- flowctrl_write_cpu_csr(0, csr_reg);
+- break;
+- }
+-
+- switch (mode) {
+- case TEGRA_SUSPEND_LP1:
+- rate = 32768;
+- break;
+- 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);
+-
+- reg = tegra_pmc_readl(PMC_CTRL);
+-
+- if (!pmc_pm_data.sysclkreq_high)
+- reg |= TEGRA_POWER_SYSCLK_POLARITY;
+- else
+- reg &= ~TEGRA_POWER_SYSCLK_POLARITY;
+-
+- /* configure the output polarity while the request is tristated */
+- tegra_pmc_writel(reg, PMC_CTRL);
+-
+- /* now enable the request */
+- reg |= TEGRA_POWER_SYSCLK_OE;
+- tegra_pmc_writel(reg, PMC_CTRL);
+-}
+-#endif
+-
+-static const struct of_device_id matches[] __initconst = {
+- { .compatible = "nvidia,tegra124-pmc" },
+- { .compatible = "nvidia,tegra114-pmc" },
+- { .compatible = "nvidia,tegra30-pmc" },
+- { .compatible = "nvidia,tegra20-pmc" },
+- { }
+-};
+-
+-void __init tegra_pmc_init_irq(void)
+-{
+- struct device_node *np;
+- u32 val;
+-
+- 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");
+-
+- val = tegra_pmc_readl(PMC_CTRL);
+- if (tegra_pmc_invert_interrupt)
+- val |= PMC_CTRL_INTR_LOW;
+- else
+- val &= ~PMC_CTRL_INTR_LOW;
+- tegra_pmc_writel(val, PMC_CTRL);
+-}
+-
+-void __init tegra_pmc_init(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_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;
+-}
diff --git a/arch/arm/mach-tegra/pmc.h b/arch/arm/mach-tegra/pmc.h
-index 59e19c34..139a3086 100644
+deleted file mode 100644
+index 59e19c34..0000000
--- a/arch/arm/mach-tegra/pmc.h
-+++ b/arch/arm/mach-tegra/pmc.h
-@@ -18,6 +18,7 @@
- #ifndef __MACH_TEGRA_PMC_H
- #define __MACH_TEGRA_PMC_H
-
-+#include <linux/io.h>
- #include <linux/reboot.h>
-
- enum tegra_suspend_mode {
-@@ -37,6 +38,18 @@ void tegra_pmc_pm_set(enum tegra_suspend_mode mode);
- void tegra_pmc_suspend_init(void);
- #endif
-
-+extern void __iomem *tegra_pmc_base;
-+
-+static inline u32 tegra_pmc_readl(u32 reg)
-+{
-+ return readl(tegra_pmc_base + reg);
-+}
-+
-+static inline void tegra_pmc_writel(u32 val, u32 reg)
-+{
-+ writel(val, tegra_pmc_base + reg);
-+}
-+
- bool tegra_pmc_cpu_is_powered(int cpuid);
- int tegra_pmc_cpu_power_on(int cpuid);
- int tegra_pmc_cpu_remove_clamping(int cpuid);
++++ /dev/null
+@@ -1,49 +0,0 @@
+-/*
+- * Copyright (C) 2012 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/>.
+- *
+- */
+-
+-#ifndef __MACH_TEGRA_PMC_H
+-#define __MACH_TEGRA_PMC_H
+-
+-#include <linux/reboot.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_set_suspend_mode(enum tegra_suspend_mode mode);
+-void tegra_pmc_suspend(void);
+-void tegra_pmc_resume(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_restart(enum reboot_mode mode, const char *cmd);
+-
+-void tegra_pmc_init_irq(void);
+-void tegra_pmc_init(void);
+-
+-#endif
diff --git a/arch/arm/mach-tegra/powergate.c b/arch/arm/mach-tegra/powergate.c
-index 4cefc5c..c90f303 100644
+deleted file mode 100644
+index 4cefc5c..0000000
--- a/arch/arm/mach-tegra/powergate.c
-+++ b/arch/arm/mach-tegra/powergate.c
-@@ -30,9 +30,9 @@
- #include <linux/spinlock.h>
- #include <linux/clk/tegra.h>
- #include <linux/tegra-powergate.h>
-+#include <linux/tegra-soc.h>
-
++++ /dev/null
+@@ -1,515 +0,0 @@
+-/*
+- * drivers/powergate/tegra-powergate.c
+- *
+- * Copyright (c) 2010 Google, Inc
+- *
+- * Author:
+- * Colin Cross <ccross@google.com>
+- *
+- * 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/kernel.h>
+-#include <linux/clk.h>
+-#include <linux/debugfs.h>
+-#include <linux/delay.h>
+-#include <linux/err.h>
+-#include <linux/export.h>
+-#include <linux/init.h>
+-#include <linux/io.h>
+-#include <linux/reset.h>
+-#include <linux/seq_file.h>
+-#include <linux/spinlock.h>
+-#include <linux/clk/tegra.h>
+-#include <linux/tegra-powergate.h>
+-
-#include "fuse.h"
-#include "iomap.h"
-+#include "pmc.h"
-
- #define DPD_SAMPLE 0x020
- #define DPD_SAMPLE_ENABLE (1 << 0)
-@@ -85,18 +85,6 @@ static const u8 tegra124_cpu_domains[] = {
-
- static DEFINE_SPINLOCK(tegra_powergate_lock);
-
+-
+-#define DPD_SAMPLE 0x020
+-#define DPD_SAMPLE_ENABLE (1 << 0)
+-#define DPD_SAMPLE_DISABLE (0 << 0)
+-
+-#define PWRGATE_TOGGLE 0x30
+-#define PWRGATE_TOGGLE_START (1 << 8)
+-
+-#define REMOVE_CLAMPING 0x34
+-
+-#define PWRGATE_STATUS 0x38
+-
+-#define IO_DPD_REQ 0x1b8
+-#define IO_DPD_REQ_CODE_IDLE (0 << 30)
+-#define IO_DPD_REQ_CODE_OFF (1 << 30)
+-#define IO_DPD_REQ_CODE_ON (2 << 30)
+-#define IO_DPD_REQ_CODE_MASK (3 << 30)
+-
+-#define IO_DPD_STATUS 0x1bc
+-#define IO_DPD2_REQ 0x1c0
+-#define IO_DPD2_STATUS 0x1c4
+-#define SEL_DPD_TIM 0x1c8
+-
+-#define GPU_RG_CNTRL 0x2d4
+-
+-static int tegra_num_powerdomains;
+-static int tegra_num_cpu_domains;
+-static const u8 *tegra_cpu_domains;
+-
+-static const u8 tegra30_cpu_domains[] = {
+- TEGRA_POWERGATE_CPU,
+- TEGRA_POWERGATE_CPU1,
+- TEGRA_POWERGATE_CPU2,
+- TEGRA_POWERGATE_CPU3,
+-};
+-
+-static const u8 tegra114_cpu_domains[] = {
+- TEGRA_POWERGATE_CPU0,
+- TEGRA_POWERGATE_CPU1,
+- TEGRA_POWERGATE_CPU2,
+- TEGRA_POWERGATE_CPU3,
+-};
+-
+-static const u8 tegra124_cpu_domains[] = {
+- TEGRA_POWERGATE_CPU0,
+- TEGRA_POWERGATE_CPU1,
+- TEGRA_POWERGATE_CPU2,
+- TEGRA_POWERGATE_CPU3,
+-};
+-
+-static DEFINE_SPINLOCK(tegra_powergate_lock);
+-
-static void __iomem *pmc = IO_ADDRESS(TEGRA_PMC_BASE);
-
-static u32 pmc_read(unsigned long reg)
@@ -2892,138 +4308,464 @@ index 4cefc5c..c90f303 100644
- writel(val, pmc + reg);
-}
-
- static int tegra_powergate_set(int id, bool new_state)
- {
- bool status;
-@@ -104,14 +92,14 @@ static int tegra_powergate_set(int id, bool new_state)
-
- spin_lock_irqsave(&tegra_powergate_lock, flags);
-
+-static int tegra_powergate_set(int id, bool new_state)
+-{
+- bool status;
+- unsigned long flags;
+-
+- spin_lock_irqsave(&tegra_powergate_lock, flags);
+-
- status = pmc_read(PWRGATE_STATUS) & (1 << id);
-+ status = tegra_pmc_readl(PWRGATE_STATUS) & (1 << id);
-
- if (status == new_state) {
- spin_unlock_irqrestore(&tegra_powergate_lock, flags);
- return 0;
- }
-
+-
+- if (status == new_state) {
+- spin_unlock_irqrestore(&tegra_powergate_lock, flags);
+- return 0;
+- }
+-
- pmc_write(PWRGATE_TOGGLE_START | id, PWRGATE_TOGGLE);
-+ tegra_pmc_writel(PWRGATE_TOGGLE_START | id, PWRGATE_TOGGLE);
-
- spin_unlock_irqrestore(&tegra_powergate_lock, flags);
-
-@@ -142,7 +130,7 @@ int tegra_powergate_is_powered(int id)
- if (id < 0 || id >= tegra_num_powerdomains)
- return -EINVAL;
-
+-
+- spin_unlock_irqrestore(&tegra_powergate_lock, flags);
+-
+- return 0;
+-}
+-
+-int tegra_powergate_power_on(int id)
+-{
+- if (id < 0 || id >= tegra_num_powerdomains)
+- return -EINVAL;
+-
+- return tegra_powergate_set(id, true);
+-}
+-
+-int tegra_powergate_power_off(int id)
+-{
+- if (id < 0 || id >= tegra_num_powerdomains)
+- return -EINVAL;
+-
+- return tegra_powergate_set(id, false);
+-}
+-EXPORT_SYMBOL(tegra_powergate_power_off);
+-
+-int tegra_powergate_is_powered(int id)
+-{
+- u32 status;
+-
+- if (id < 0 || id >= tegra_num_powerdomains)
+- return -EINVAL;
+-
- status = pmc_read(PWRGATE_STATUS) & (1 << id);
-+ status = tegra_pmc_readl(PWRGATE_STATUS) & (1 << id);
- return !!status;
- }
-
-@@ -159,7 +147,7 @@ int tegra_powergate_remove_clamping(int id)
- */
- if (tegra_chip_id == TEGRA124) {
- if (id == TEGRA_POWERGATE_3D) {
+- return !!status;
+-}
+-
+-int tegra_powergate_remove_clamping(int id)
+-{
+- u32 mask;
+-
+- if (id < 0 || id >= tegra_num_powerdomains)
+- return -EINVAL;
+-
+- /*
+- * The Tegra124 GPU has a separate register (with different semantics)
+- * to remove clamps.
+- */
+- if (tegra_chip_id == TEGRA124) {
+- if (id == TEGRA_POWERGATE_3D) {
- pmc_write(0, GPU_RG_CNTRL);
-+ tegra_pmc_writel(0, GPU_RG_CNTRL);
- return 0;
- }
- }
-@@ -175,7 +163,7 @@ int tegra_powergate_remove_clamping(int id)
- else
- mask = (1 << id);
-
+- return 0;
+- }
+- }
+-
+- /*
+- * Tegra 2 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);
+-
- pmc_write(mask, REMOVE_CLAMPING);
-+ tegra_pmc_writel(mask, REMOVE_CLAMPING);
-
- return 0;
- }
-@@ -425,12 +413,12 @@ static int tegra_io_rail_prepare(int id, unsigned long *request,
- rate = clk_get_rate(clk);
- clk_put(clk);
-
+-
+- return 0;
+-}
+-EXPORT_SYMBOL(tegra_powergate_remove_clamping);
+-
+-/* Must be called with clk disabled, and returns with clk enabled */
+-int tegra_powergate_sequence_power_up(int id, struct clk *clk,
+- struct reset_control *rst)
+-{
+- int ret;
+-
+- reset_control_assert(rst);
+-
+- ret = tegra_powergate_power_on(id);
+- if (ret)
+- goto err_power;
+-
+- ret = clk_prepare_enable(clk);
+- if (ret)
+- goto err_clk;
+-
+- udelay(10);
+-
+- ret = tegra_powergate_remove_clamping(id);
+- if (ret)
+- goto err_clamp;
+-
+- udelay(10);
+- reset_control_deassert(rst);
+-
+- return 0;
+-
+-err_clamp:
+- clk_disable_unprepare(clk);
+-err_clk:
+- tegra_powergate_power_off(id);
+-err_power:
+- return ret;
+-}
+-EXPORT_SYMBOL(tegra_powergate_sequence_power_up);
+-
+-int tegra_cpu_powergate_id(int cpuid)
+-{
+- if (cpuid > 0 && cpuid < tegra_num_cpu_domains)
+- return tegra_cpu_domains[cpuid];
+-
+- return -EINVAL;
+-}
+-
+-int __init tegra_powergate_init(void)
+-{
+- switch (tegra_chip_id) {
+- case TEGRA20:
+- tegra_num_powerdomains = 7;
+- break;
+- case TEGRA30:
+- tegra_num_powerdomains = 14;
+- tegra_num_cpu_domains = 4;
+- tegra_cpu_domains = tegra30_cpu_domains;
+- break;
+- case TEGRA114:
+- tegra_num_powerdomains = 23;
+- tegra_num_cpu_domains = 4;
+- tegra_cpu_domains = tegra114_cpu_domains;
+- break;
+- case TEGRA124:
+- tegra_num_powerdomains = 25;
+- tegra_num_cpu_domains = 4;
+- tegra_cpu_domains = tegra124_cpu_domains;
+- break;
+- default:
+- /* Unknown Tegra variant. Disable powergating */
+- tegra_num_powerdomains = 0;
+- break;
+- }
+-
+- return 0;
+-}
+-
+-#ifdef CONFIG_DEBUG_FS
+-
+-static const char * const *powergate_name;
+-
+-static const char * const powergate_name_t20[] = {
+- [TEGRA_POWERGATE_CPU] = "cpu",
+- [TEGRA_POWERGATE_3D] = "3d",
+- [TEGRA_POWERGATE_VENC] = "venc",
+- [TEGRA_POWERGATE_VDEC] = "vdec",
+- [TEGRA_POWERGATE_PCIE] = "pcie",
+- [TEGRA_POWERGATE_L2] = "l2",
+- [TEGRA_POWERGATE_MPE] = "mpe",
+-};
+-
+-static const char * const powergate_name_t30[] = {
+- [TEGRA_POWERGATE_CPU] = "cpu0",
+- [TEGRA_POWERGATE_3D] = "3d0",
+- [TEGRA_POWERGATE_VENC] = "venc",
+- [TEGRA_POWERGATE_VDEC] = "vdec",
+- [TEGRA_POWERGATE_PCIE] = "pcie",
+- [TEGRA_POWERGATE_L2] = "l2",
+- [TEGRA_POWERGATE_MPE] = "mpe",
+- [TEGRA_POWERGATE_HEG] = "heg",
+- [TEGRA_POWERGATE_SATA] = "sata",
+- [TEGRA_POWERGATE_CPU1] = "cpu1",
+- [TEGRA_POWERGATE_CPU2] = "cpu2",
+- [TEGRA_POWERGATE_CPU3] = "cpu3",
+- [TEGRA_POWERGATE_CELP] = "celp",
+- [TEGRA_POWERGATE_3D1] = "3d1",
+-};
+-
+-static const char * const powergate_name_t114[] = {
+- [TEGRA_POWERGATE_CPU] = "crail",
+- [TEGRA_POWERGATE_3D] = "3d",
+- [TEGRA_POWERGATE_VENC] = "venc",
+- [TEGRA_POWERGATE_VDEC] = "vdec",
+- [TEGRA_POWERGATE_MPE] = "mpe",
+- [TEGRA_POWERGATE_HEG] = "heg",
+- [TEGRA_POWERGATE_CPU1] = "cpu1",
+- [TEGRA_POWERGATE_CPU2] = "cpu2",
+- [TEGRA_POWERGATE_CPU3] = "cpu3",
+- [TEGRA_POWERGATE_CELP] = "celp",
+- [TEGRA_POWERGATE_CPU0] = "cpu0",
+- [TEGRA_POWERGATE_C0NC] = "c0nc",
+- [TEGRA_POWERGATE_C1NC] = "c1nc",
+- [TEGRA_POWERGATE_DIS] = "dis",
+- [TEGRA_POWERGATE_DISB] = "disb",
+- [TEGRA_POWERGATE_XUSBA] = "xusba",
+- [TEGRA_POWERGATE_XUSBB] = "xusbb",
+- [TEGRA_POWERGATE_XUSBC] = "xusbc",
+-};
+-
+-static const char * const powergate_name_t124[] = {
+- [TEGRA_POWERGATE_CPU] = "crail",
+- [TEGRA_POWERGATE_3D] = "3d",
+- [TEGRA_POWERGATE_VENC] = "venc",
+- [TEGRA_POWERGATE_PCIE] = "pcie",
+- [TEGRA_POWERGATE_VDEC] = "vdec",
+- [TEGRA_POWERGATE_L2] = "l2",
+- [TEGRA_POWERGATE_MPE] = "mpe",
+- [TEGRA_POWERGATE_HEG] = "heg",
+- [TEGRA_POWERGATE_SATA] = "sata",
+- [TEGRA_POWERGATE_CPU1] = "cpu1",
+- [TEGRA_POWERGATE_CPU2] = "cpu2",
+- [TEGRA_POWERGATE_CPU3] = "cpu3",
+- [TEGRA_POWERGATE_CELP] = "celp",
+- [TEGRA_POWERGATE_CPU0] = "cpu0",
+- [TEGRA_POWERGATE_C0NC] = "c0nc",
+- [TEGRA_POWERGATE_C1NC] = "c1nc",
+- [TEGRA_POWERGATE_SOR] = "sor",
+- [TEGRA_POWERGATE_DIS] = "dis",
+- [TEGRA_POWERGATE_DISB] = "disb",
+- [TEGRA_POWERGATE_XUSBA] = "xusba",
+- [TEGRA_POWERGATE_XUSBB] = "xusbb",
+- [TEGRA_POWERGATE_XUSBC] = "xusbc",
+- [TEGRA_POWERGATE_VIC] = "vic",
+- [TEGRA_POWERGATE_IRAM] = "iram",
+-};
+-
+-static int powergate_show(struct seq_file *s, void *data)
+-{
+- int i;
+-
+- seq_printf(s, " powergate powered\n");
+- seq_printf(s, "------------------\n");
+-
+- for (i = 0; i < tegra_num_powerdomains; i++) {
+- if (!powergate_name[i])
+- continue;
+-
+- seq_printf(s, " %9s %7s\n", powergate_name[i],
+- tegra_powergate_is_powered(i) ? "yes" : "no");
+- }
+-
+- return 0;
+-}
+-
+-static int powergate_open(struct inode *inode, struct file *file)
+-{
+- return single_open(file, powergate_show, inode->i_private);
+-}
+-
+-static const struct file_operations powergate_fops = {
+- .open = powergate_open,
+- .read = seq_read,
+- .llseek = seq_lseek,
+- .release = single_release,
+-};
+-
+-int __init tegra_powergate_debugfs_init(void)
+-{
+- struct dentry *d;
+-
+- switch (tegra_chip_id) {
+- case TEGRA20:
+- powergate_name = powergate_name_t20;
+- break;
+- case TEGRA30:
+- powergate_name = powergate_name_t30;
+- break;
+- case TEGRA114:
+- powergate_name = powergate_name_t114;
+- break;
+- case TEGRA124:
+- powergate_name = powergate_name_t124;
+- break;
+- }
+-
+- if (powergate_name) {
+- d = debugfs_create_file("powergate", S_IRUGO, NULL, NULL,
+- &powergate_fops);
+- if (!d)
+- return -ENOMEM;
+- }
+-
+- return 0;
+-}
+-
+-#endif
+-
+-static int tegra_io_rail_prepare(int id, unsigned long *request,
+- unsigned long *status, unsigned int *bit)
+-{
+- unsigned long rate, value;
+- struct clk *clk;
+-
+- *bit = id % 32;
+-
+- /*
+- * There are two sets of 30 bits to select IO rails, but bits 30 and
+- * 31 are control bits rather than IO rail selection bits.
+- */
+- if (id > 63 || *bit == 30 || *bit == 31)
+- return -EINVAL;
+-
+- if (id < 32) {
+- *status = IO_DPD_STATUS;
+- *request = IO_DPD_REQ;
+- } else {
+- *status = IO_DPD2_STATUS;
+- *request = IO_DPD2_REQ;
+- }
+-
+- clk = clk_get_sys(NULL, "pclk");
+- if (IS_ERR(clk))
+- return PTR_ERR(clk);
+-
+- rate = clk_get_rate(clk);
+- clk_put(clk);
+-
- pmc_write(DPD_SAMPLE_ENABLE, DPD_SAMPLE);
-+ tegra_pmc_writel(DPD_SAMPLE_ENABLE, DPD_SAMPLE);
-
- /* must be at least 200 ns, in APB (PCLK) clock cycles */
- value = DIV_ROUND_UP(1000000000, rate);
- value = DIV_ROUND_UP(200, value);
+-
+- /* must be at least 200 ns, in APB (PCLK) clock cycles */
+- value = DIV_ROUND_UP(1000000000, rate);
+- value = DIV_ROUND_UP(200, value);
- pmc_write(value, SEL_DPD_TIM);
-+ tegra_pmc_writel(value, SEL_DPD_TIM);
-
- return 0;
- }
-@@ -443,7 +431,7 @@ static int tegra_io_rail_poll(unsigned long offset, unsigned long mask,
- timeout = jiffies + msecs_to_jiffies(timeout);
-
- while (time_after(timeout, jiffies)) {
+-
+- return 0;
+-}
+-
+-static int tegra_io_rail_poll(unsigned long offset, unsigned long mask,
+- unsigned long val, unsigned long timeout)
+-{
+- unsigned long value;
+-
+- timeout = jiffies + msecs_to_jiffies(timeout);
+-
+- while (time_after(timeout, jiffies)) {
- value = pmc_read(offset);
-+ value = tegra_pmc_readl(offset);
- if ((value & mask) == val)
- return 0;
-
-@@ -455,7 +443,7 @@ static int tegra_io_rail_poll(unsigned long offset, unsigned long mask,
-
- static void tegra_io_rail_unprepare(void)
- {
+- if ((value & mask) == val)
+- return 0;
+-
+- usleep_range(250, 1000);
+- }
+-
+- return -ETIMEDOUT;
+-}
+-
+-static void tegra_io_rail_unprepare(void)
+-{
- pmc_write(DPD_SAMPLE_DISABLE, DPD_SAMPLE);
-+ tegra_pmc_writel(DPD_SAMPLE_DISABLE, DPD_SAMPLE);
- }
-
- int tegra_io_rail_power_on(int id)
-@@ -470,11 +458,11 @@ int tegra_io_rail_power_on(int id)
-
- mask = 1 << bit;
-
+-}
+-
+-int tegra_io_rail_power_on(int id)
+-{
+- unsigned long request, status, value;
+- unsigned int bit, mask;
+- int err;
+-
+- err = tegra_io_rail_prepare(id, &request, &status, &bit);
+- if (err < 0)
+- return err;
+-
+- mask = 1 << bit;
+-
- value = pmc_read(request);
-+ value = tegra_pmc_readl(request);
- value |= mask;
- value &= ~IO_DPD_REQ_CODE_MASK;
- value |= IO_DPD_REQ_CODE_OFF;
+- value |= mask;
+- value &= ~IO_DPD_REQ_CODE_MASK;
+- value |= IO_DPD_REQ_CODE_OFF;
- pmc_write(value, request);
-+ tegra_pmc_writel(value, request);
-
- err = tegra_io_rail_poll(status, mask, 0, 250);
- if (err < 0)
-@@ -498,11 +486,11 @@ int tegra_io_rail_power_off(int id)
-
- mask = 1 << bit;
-
+-
+- err = tegra_io_rail_poll(status, mask, 0, 250);
+- if (err < 0)
+- return err;
+-
+- tegra_io_rail_unprepare();
+-
+- return 0;
+-}
+-EXPORT_SYMBOL(tegra_io_rail_power_on);
+-
+-int tegra_io_rail_power_off(int id)
+-{
+- unsigned long request, status, value;
+- unsigned int bit, mask;
+- int err;
+-
+- err = tegra_io_rail_prepare(id, &request, &status, &bit);
+- if (err < 0)
+- return err;
+-
+- mask = 1 << bit;
+-
- value = pmc_read(request);
-+ value = tegra_pmc_readl(request);
- value |= mask;
- value &= ~IO_DPD_REQ_CODE_MASK;
- value |= IO_DPD_REQ_CODE_ON;
+- value |= mask;
+- value &= ~IO_DPD_REQ_CODE_MASK;
+- value |= IO_DPD_REQ_CODE_ON;
- pmc_write(value, request);
-+ tegra_pmc_writel(value, request);
-
- err = tegra_io_rail_poll(status, mask, mask, 250);
- if (err < 0)
+-
+- err = tegra_io_rail_poll(status, mask, mask, 250);
+- if (err < 0)
+- return err;
+-
+- tegra_io_rail_unprepare();
+-
+- return 0;
+-}
+-EXPORT_SYMBOL(tegra_io_rail_power_off);
diff --git a/arch/arm/mach-tegra/reset-handler.S b/arch/arm/mach-tegra/reset-handler.S
-index 578d4d1..b9ff929 100644
+index 578d4d1..be2eaa8 100644
--- a/arch/arm/mach-tegra/reset-handler.S
+++ b/arch/arm/mach-tegra/reset-handler.S
-@@ -19,9 +19,9 @@
+@@ -14,14 +14,14 @@
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
- #include <asm/cache.h>
- #include <asm/asm-offsets.h>
+-#include <linux/linkage.h>
+ #include <linux/init.h>
++#include <linux/linkage.h>
+#include <linux/tegra-soc.h>
+-#include <asm/cache.h>
+ #include <asm/asm-offsets.h>
++#include <asm/cache.h>
+
#include "flowctrl.h"
-#include "fuse.h"
#include "iomap.h"
#include "reset.h"
#include "sleep.h"
diff --git a/arch/arm/mach-tegra/reset.c b/arch/arm/mach-tegra/reset.c
-index 146fe8e..203bac5 100644
+index 146fe8e..96cafc4 100644
--- a/arch/arm/mach-tegra/reset.c
+++ b/arch/arm/mach-tegra/reset.c
-@@ -22,12 +22,12 @@
+@@ -14,20 +14,20 @@
+ *
+ */
+
++#include <linux/bitops.h>
++#include <linux/cpumask.h>
+ #include <linux/init.h>
+ #include <linux/io.h>
+-#include <linux/cpumask.h>
+-#include <linux/bitops.h>
++#include <linux/tegra-soc.h>
+
#include <asm/cacheflush.h>
- #include <asm/hardware/cache-l2x0.h>
+-#include <asm/hardware/cache-l2x0.h>
#include <asm/firmware.h>
-+#include <linux/tegra-soc.h>
++#include <asm/hardware/cache-l2x0.h>
#include "iomap.h"
#include "irammap.h"
@@ -3033,38 +4775,1055 @@ index 146fe8e..203bac5 100644
#define TEGRA_IRAM_RESET_BASE (TEGRA_IRAM_BASE + \
TEGRA_IRAM_RESET_HANDLER_OFFSET)
+@@ -53,12 +53,10 @@ static void __init tegra_cpu_reset_handler_set(const u32 reset_address)
+ * Prevent further modifications to the physical reset vector.
+ * NOTE: Has no effect on chips prior to Tegra30.
+ */
+- if (tegra_chip_id != TEGRA20) {
+- reg = readl(sb_ctrl);
+- reg |= 2;
+- writel(reg, sb_ctrl);
+- wmb();
+- }
++ reg = readl(sb_ctrl);
++ reg |= 2;
++ writel(reg, sb_ctrl);
++ wmb();
+ }
+
+ static void __init tegra_cpu_reset_handler_enable(void)
diff --git a/arch/arm/mach-tegra/sleep-tegra30.S b/arch/arm/mach-tegra/sleep-tegra30.S
-index b16d4a57..f808c2c 100644
+index b16d4a57..3700fe9 100644
--- a/arch/arm/mach-tegra/sleep-tegra30.S
+++ b/arch/arm/mach-tegra/sleep-tegra30.S
-@@ -15,13 +15,13 @@
+@@ -15,15 +15,15 @@
*/
#include <linux/linkage.h>
+#include <linux/tegra-soc.h>
- #include <asm/assembler.h>
+-#include <asm/assembler.h>
#include <asm/asm-offsets.h>
++#include <asm/assembler.h>
#include <asm/cache.h>
++#include "flowctrl.h"
#include "irammap.h"
-#include "fuse.h"
#include "sleep.h"
- #include "flowctrl.h"
+-#include "flowctrl.h"
+
+ #define EMC_CFG 0xc
+ #define EMC_ADR_CFG 0x10
+diff --git a/arch/arm/mach-tegra/sleep.h b/arch/arm/mach-tegra/sleep.h
+index 339fe42..92d46ec 100644
+--- a/arch/arm/mach-tegra/sleep.h
++++ b/arch/arm/mach-tegra/sleep.h
+@@ -130,9 +130,6 @@ void tegra_disable_clean_inv_dcache(u32 flag);
+ #ifdef CONFIG_HOTPLUG_CPU
+ void tegra20_hotplug_shutdown(void);
+ void tegra30_hotplug_shutdown(void);
+-void tegra_hotplug_init(void);
+-#else
+-static inline void tegra_hotplug_init(void) {}
+ #endif
+ void tegra20_cpu_shutdown(int cpu);
+diff --git a/arch/arm/mach-tegra/tegra-pmc.c b/arch/arm/mach-tegra/tegra-pmc.c
+new file mode 100644
+index 0000000..b6bc758
+--- /dev/null
++++ b/arch/arm/mach-tegra/tegra-pmc.c
+@@ -0,0 +1,948 @@
++/*
++ * drivers/soc/tegra/pmc.c
++ *
++ * Copyright (c) 2010 Google, Inc
++ *
++ * Author:
++ * Colin Cross <ccross@google.com>
++ *
++ * 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/kernel.h>
++#include <linux/clk.h>
++#include <linux/clk/tegra.h>
++#include <linux/debugfs.h>
++#include <linux/delay.h>
++#include <linux/err.h>
++#include <linux/export.h>
++#include <linux/init.h>
++#include <linux/io.h>
++#include <linux/of.h>
++#include <linux/of_address.h>
++#include <linux/platform_device.h>
++#include <linux/reboot.h>
++#include <linux/reset.h>
++#include <linux/seq_file.h>
++#include <linux/spinlock.h>
++#include <linux/tegra-powergate.h>
++#include <linux/tegra-soc.h>
++
++#define PMC_CNTRL 0x0
++#define PMC_CNTRL_SYSCLK_POLARITY (1 << 10) /* sys clk polarity */
++#define PMC_CNTRL_SYSCLK_OE (1 << 11) /* system clock enable */
++#define PMC_CNTRL_SIDE_EFFECT_LP0 (1 << 14) /* LP0 when CPU pwr gated */
++#define PMC_CNTRL_CPU_PWRREQ_POLARITY (1 << 15) /* CPU pwr req polarity */
++#define PMC_CNTRL_CPU_PWRREQ_OE (1 << 16) /* CPU pwr req enable */
++#define PMC_CNTRL_INTR_POLARITY (1 << 17) /* inverts INTR polarity */
++
++#define DPD_SAMPLE 0x020
++#define DPD_SAMPLE_ENABLE (1 << 0)
++#define DPD_SAMPLE_DISABLE (0 << 0)
++
++#define PWRGATE_TOGGLE 0x30
++#define PWRGATE_TOGGLE_START (1 << 8)
++
++#define REMOVE_CLAMPING 0x34
++
++#define PWRGATE_STATUS 0x38
++
++#define PMC_SCRATCH0 0x50
++#define PMC_SCRATCH0_MODE_RECOVERY (1 << 31)
++#define PMC_SCRATCH0_MODE_BOOTLOADER (1 << 30)
++#define PMC_SCRATCH0_MODE_RCM (1 << 1)
++#define PMC_SCRATCH0_MODE_MASK (PMC_SCRATCH0_MODE_RECOVERY | \
++ PMC_SCRATCH0_MODE_BOOTLOADER | \
++ PMC_SCRATCH0_MODE_RCM)
++
++#define PMC_CPUPWRGOOD_TIMER 0xc8
++#define PMC_CPUPWROFF_TIMER 0xcc
++
++#define PMC_SCRATCH41 0x140
++
++#define IO_DPD_REQ 0x1b8
++#define IO_DPD_REQ_CODE_IDLE (0 << 30)
++#define IO_DPD_REQ_CODE_OFF (1 << 30)
++#define IO_DPD_REQ_CODE_ON (2 << 30)
++#define IO_DPD_REQ_CODE_MASK (3 << 30)
++
++#define IO_DPD_STATUS 0x1bc
++#define IO_DPD2_REQ 0x1c0
++#define IO_DPD2_STATUS 0x1c4
++#define SEL_DPD_TIM 0x1c8
++
++#define GPU_RG_CNTRL 0x2d4
++
++struct tegra_pmc_soc {
++ unsigned int num_powergates;
++ const char *const *powergates;
++ unsigned int num_cpu_powergates;
++ const u8 *cpu_powergates;
++};
++
++/**
++ * struct tegra_pmc - NVIDIA Tegra PMC
++ * @base: pointer to I/O remapped register region
++ * @clk: pointer to pclk clock
++ * @rate: currently configured rate of pclk
++ * @suspend_mode: lowest suspend mode available
++ * @cpu_good_time: CPU power good time (in microseconds)
++ * @cpu_off_time: CPU power off time (in microsecends)
++ * @core_osc_time: core power good OSC time (in microseconds)
++ * @core_pmu_time: core power good PMU time (in microseconds)
++ * @core_off_time: core power off time (in microseconds)
++ * @corereq_high: core power request is active-high
++ * @sysclkreq_high: system clock request is active-high
++ * @combined_req: combined power request for CPU & core
++ * @cpu_pwr_good_en: CPU power good signal is enabled
++ * @lp0_vec_phys: physical base address of the LP0 warm boot code
++ * @lp0_vec_size: size of the LP0 warm boot code
++ * @powergates_lock: mutex for power gate register access
++ */
++struct tegra_pmc {
++ void __iomem *base;
++ struct clk *clk;
++
++ const struct tegra_pmc_soc *soc;
++
++ unsigned long rate;
++
++ enum tegra_suspend_mode suspend_mode;
++ u32 cpu_good_time;
++ u32 cpu_off_time;
++ u32 core_osc_time;
++ u32 core_pmu_time;
++ u32 core_off_time;
++ bool corereq_high;
++ bool sysclkreq_high;
++ bool combined_req;
++ bool cpu_pwr_good_en;
++ u32 lp0_vec_phys;
++ u32 lp0_vec_size;
++
++ struct mutex powergates_lock;
++};
++
++static struct tegra_pmc *pmc = &(struct tegra_pmc) {
++ .base = NULL,
++ .suspend_mode = TEGRA_SUSPEND_NONE,
++};
++
++static u32 tegra_pmc_readl(unsigned long offset)
++{
++ return readl(pmc->base + offset);
++}
++
++static void tegra_pmc_writel(u32 value, unsigned long offset)
++{
++ writel(value, pmc->base + offset);
++}
++
++/**
++ * tegra_powergate_set() - set the state of a partition
++ * @id: partition ID
++ * @new_state: new state of the partition
++ */
++static int tegra_powergate_set(int id, bool new_state)
++{
++ bool status;
++
++ mutex_lock(&pmc->powergates_lock);
++
++ status = tegra_pmc_readl(PWRGATE_STATUS) & (1 << id);
++
++ if (status == new_state) {
++ mutex_unlock(&pmc->powergates_lock);
++ return 0;
++ }
++
++ tegra_pmc_writel(PWRGATE_TOGGLE_START | id, PWRGATE_TOGGLE);
++
++ mutex_unlock(&pmc->powergates_lock);
++
++ return 0;
++}
++
++/**
++ * tegra_powergate_power_on() - power on partition
++ * @id: partition ID
++ */
++int tegra_powergate_power_on(int id)
++{
++ if (!pmc->soc || id < 0 || id >= pmc->soc->num_powergates)
++ return -EINVAL;
++
++ return tegra_powergate_set(id, true);
++}
++
++/**
++ * tegra_powergate_power_off() - power off partition
++ * @id: partition ID
++ */
++int tegra_powergate_power_off(int id)
++{
++ if (!pmc->soc || id < 0 || id >= pmc->soc->num_powergates)
++ return -EINVAL;
++
++ return tegra_powergate_set(id, false);
++}
++EXPORT_SYMBOL(tegra_powergate_power_off);
++
++/**
++ * tegra_powergate_is_powered() - check if partition is powered
++ * @id: partition ID
++ */
++int tegra_powergate_is_powered(int id)
++{
++ u32 status;
++
++ if (!pmc->soc || id < 0 || id >= pmc->soc->num_powergates)
++ return -EINVAL;
++
++ status = tegra_pmc_readl(PWRGATE_STATUS) & (1 << id);
++ return !!status;
++}
++
++/**
++ * tegra_powergate_remove_clamping() - remove power clamps for partition
++ * @id: partition ID
++ */
++int tegra_powergate_remove_clamping(int id)
++{
++ u32 mask;
++
++ if (!pmc->soc || id < 0 || id >= pmc->soc->num_powergates)
++ return -EINVAL;
++
++ /*
++ * The Tegra124 GPU has a separate register (with different semantics)
++ * to remove clamps.
++ */
++ if (tegra_get_chip_id() == TEGRA124) {
++ if (id == TEGRA_POWERGATE_3D) {
++ tegra_pmc_writel(0, GPU_RG_CNTRL);
++ return 0;
++ }
++ }
++
++ /*
++ * Tegra 2 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, REMOVE_CLAMPING);
++
++ return 0;
++}
++EXPORT_SYMBOL(tegra_powergate_remove_clamping);
++
++/**
++ * tegra_powergate_sequence_power_up() - power up partition
++ * @id: partition ID
++ * @clk: clock for partition
++ * @rst: reset for partition
++ *
++ * Must be called with clk disabled, and returns with clk enabled.
++ */
++int tegra_powergate_sequence_power_up(int id, struct clk *clk,
++ struct reset_control *rst)
++{
++ int ret;
++
++ reset_control_assert(rst);
++
++ ret = tegra_powergate_power_on(id);
++ if (ret)
++ goto err_power;
++
++ ret = clk_prepare_enable(clk);
++ if (ret)
++ goto err_clk;
++
++ usleep_range(10, 20);
++
++ ret = tegra_powergate_remove_clamping(id);
++ if (ret)
++ goto err_clamp;
++
++ usleep_range(10, 20);
++ reset_control_deassert(rst);
++
++ return 0;
++
++err_clamp:
++ clk_disable_unprepare(clk);
++err_clk:
++ tegra_powergate_power_off(id);
++err_power:
++ return ret;
++}
++EXPORT_SYMBOL(tegra_powergate_sequence_power_up);
++
++/**
++ * tegra_get_cpu_powergate_id() - convert from CPU ID to partition ID
++ * @cpuid: CPU partition ID
++ *
++ * Returns the partition ID corresponding to the CPU partition ID or a
++ * negative error code on failure.
++ */
++static int tegra_get_cpu_powergate_id(int cpuid)
++{
++ if (pmc->soc && cpuid > 0 && cpuid < pmc->soc->num_cpu_powergates)
++ return pmc->soc->cpu_powergates[cpuid];
++
++ return -EINVAL;
++}
++
++/**
++ * tegra_pmc_cpu_is_powered() - check if CPU partition is powered
++ * @cpuid: CPU partition ID
++ */
++bool tegra_pmc_cpu_is_powered(int cpuid)
++{
++ int id;
++
++ id = tegra_get_cpu_powergate_id(cpuid);
++ if (id < 0)
++ return false;
++
++ return tegra_powergate_is_powered(id);
++}
++
++/**
++ * tegra_pmc_cpu_power_on() - power on CPU partition
++ * @cpuid: CPU partition ID
++ */
++int tegra_pmc_cpu_power_on(int cpuid)
++{
++ int id;
++
++ id = tegra_get_cpu_powergate_id(cpuid);
++ if (id < 0)
++ return id;
++
++ return tegra_powergate_set(id, true);
++}
++
++/**
++ * tegra_pmc_cpu_remove_clamping() - remove power clamps for CPU partition
++ * @cpuid: CPU partition ID
++ */
++int tegra_pmc_cpu_remove_clamping(int cpuid)
++{
++ int id;
++
++ id = tegra_get_cpu_powergate_id(cpuid);
++ if (id < 0)
++ return id;
++
++ return tegra_powergate_remove_clamping(id);
++}
++
++/**
++ * tegra_pmc_restart() - reboot the system
++ * @mode: which mode to reboot in
++ * @cmd: reboot command
++ */
++void tegra_pmc_restart(enum reboot_mode mode, const char *cmd)
++{
++ u32 value;
++
++ value = tegra_pmc_readl(PMC_SCRATCH0);
++ value &= ~PMC_SCRATCH0_MODE_MASK;
++
++ if (cmd) {
++ if (strcmp(cmd, "recovery") == 0)
++ value |= PMC_SCRATCH0_MODE_RECOVERY;
++
++ if (strcmp(cmd, "bootloader") == 0)
++ value |= PMC_SCRATCH0_MODE_BOOTLOADER;
++
++ if (strcmp(cmd, "forced-recovery") == 0)
++ value |= PMC_SCRATCH0_MODE_RCM;
++ }
++
++ tegra_pmc_writel(value, PMC_SCRATCH0);
++
++ value = tegra_pmc_readl(0);
++ value |= 0x10;
++ tegra_pmc_writel(value, 0);
++}
++
++static int powergate_show(struct seq_file *s, void *data)
++{
++ unsigned int i;
++
++ seq_printf(s, " powergate powered\n");
++ seq_printf(s, "------------------\n");
++
++ for (i = 0; i < pmc->soc->num_powergates; i++) {
++ if (!pmc->soc->powergates[i])
++ continue;
++
++ seq_printf(s, " %9s %7s\n", pmc->soc->powergates[i],
++ tegra_powergate_is_powered(i) ? "yes" : "no");
++ }
++
++ return 0;
++}
++
++static int powergate_open(struct inode *inode, struct file *file)
++{
++ return single_open(file, powergate_show, inode->i_private);
++}
++
++static const struct file_operations powergate_fops = {
++ .open = powergate_open,
++ .read = seq_read,
++ .llseek = seq_lseek,
++ .release = single_release,
++};
++
++static int tegra_powergate_debugfs_init(void)
++{
++ struct dentry *d;
++
++ d = debugfs_create_file("powergate", S_IRUGO, NULL, NULL,
++ &powergate_fops);
++ if (!d)
++ return -ENOMEM;
++
++ return 0;
++}
++
++static int tegra_io_rail_prepare(int id, unsigned long *request,
++ unsigned long *status, unsigned int *bit)
++{
++ unsigned long rate, value;
++ struct clk *clk;
++
++ *bit = id % 32;
++
++ /*
++ * There are two sets of 30 bits to select IO rails, but bits 30 and
++ * 31 are control bits rather than IO rail selection bits.
++ */
++ if (id > 63 || *bit == 30 || *bit == 31)
++ return -EINVAL;
++
++ if (id < 32) {
++ *status = IO_DPD_STATUS;
++ *request = IO_DPD_REQ;
++ } else {
++ *status = IO_DPD2_STATUS;
++ *request = IO_DPD2_REQ;
++ }
++
++ clk = clk_get_sys(NULL, "pclk");
++ if (IS_ERR(clk))
++ return PTR_ERR(clk);
++
++ rate = clk_get_rate(clk);
++ clk_put(clk);
++
++ tegra_pmc_writel(DPD_SAMPLE_ENABLE, DPD_SAMPLE);
++
++ /* must be at least 200 ns, in APB (PCLK) clock cycles */
++ value = DIV_ROUND_UP(1000000000, rate);
++ value = DIV_ROUND_UP(200, value);
++ tegra_pmc_writel(value, SEL_DPD_TIM);
++
++ return 0;
++}
++
++static int tegra_io_rail_poll(unsigned long offset, unsigned long mask,
++ unsigned long val, unsigned long timeout)
++{
++ unsigned long value;
++
++ timeout = jiffies + msecs_to_jiffies(timeout);
++
++ while (time_after(timeout, jiffies)) {
++ value = tegra_pmc_readl(offset);
++ if ((value & mask) == val)
++ return 0;
++
++ usleep_range(250, 1000);
++ }
++
++ return -ETIMEDOUT;
++}
++
++static void tegra_io_rail_unprepare(void)
++{
++ tegra_pmc_writel(DPD_SAMPLE_DISABLE, DPD_SAMPLE);
++}
++
++int tegra_io_rail_power_on(int id)
++{
++ unsigned long request, status, value;
++ unsigned int bit, mask;
++ int err;
++
++ err = tegra_io_rail_prepare(id, &request, &status, &bit);
++ if (err < 0)
++ return err;
++
++ mask = 1 << bit;
++
++ value = tegra_pmc_readl(request);
++ value |= mask;
++ value &= ~IO_DPD_REQ_CODE_MASK;
++ value |= IO_DPD_REQ_CODE_OFF;
++ tegra_pmc_writel(value, request);
++
++ err = tegra_io_rail_poll(status, mask, 0, 250);
++ if (err < 0)
++ return err;
++
++ tegra_io_rail_unprepare();
++
++ return 0;
++}
++EXPORT_SYMBOL(tegra_io_rail_power_on);
++
++int tegra_io_rail_power_off(int id)
++{
++ unsigned long request, status, value;
++ unsigned int bit, mask;
++ int err;
++
++ err = tegra_io_rail_prepare(id, &request, &status, &bit);
++ if (err < 0)
++ return err;
++
++ mask = 1 << bit;
++
++ value = tegra_pmc_readl(request);
++ value |= mask;
++ value &= ~IO_DPD_REQ_CODE_MASK;
++ value |= IO_DPD_REQ_CODE_ON;
++ tegra_pmc_writel(value, request);
++
++ err = tegra_io_rail_poll(status, mask, mask, 250);
++ if (err < 0)
++ return err;
++
++ tegra_io_rail_unprepare();
++
++ return 0;
++}
++EXPORT_SYMBOL(tegra_io_rail_power_off);
++
++enum tegra_suspend_mode tegra_pmc_get_suspend_mode(void)
++{
++ return pmc->suspend_mode;
++}
++
++void tegra_pmc_set_suspend_mode(enum tegra_suspend_mode mode)
++{
++ if (mode < TEGRA_SUSPEND_NONE || mode >= TEGRA_MAX_SUSPEND_MODE)
++ return;
++
++ pmc->suspend_mode = mode;
++}
++
++void tegra_pmc_enter_suspend_mode(enum tegra_suspend_mode mode)
++{
++ unsigned long long rate = 0;
++ u32 value;
++
++ switch (mode) {
++ case TEGRA_SUSPEND_LP1:
++ rate = 32768;
++ break;
++
++ case TEGRA_SUSPEND_LP2:
++ rate = clk_get_rate(pmc->clk);
++ break;
++
++ default:
++ break;
++ }
++
++ if (WARN_ON_ONCE(rate == 0))
++ rate = 100000000;
++
++ if (rate != pmc->rate) {
++ u64 ticks;
++
++ ticks = pmc->cpu_good_time * rate + USEC_PER_SEC - 1;
++ do_div(ticks, USEC_PER_SEC);
++ tegra_pmc_writel(ticks, PMC_CPUPWRGOOD_TIMER);
++
++ ticks = pmc->cpu_off_time * rate + USEC_PER_SEC - 1;
++ do_div(ticks, USEC_PER_SEC);
++ tegra_pmc_writel(ticks, PMC_CPUPWROFF_TIMER);
++
++ wmb();
++
++ pmc->rate = rate;
++ }
++
++ value = tegra_pmc_readl(PMC_CNTRL);
++ value &= ~PMC_CNTRL_SIDE_EFFECT_LP0;
++ value |= PMC_CNTRL_CPU_PWRREQ_OE;
++ tegra_pmc_writel(value, PMC_CNTRL);
++}
++
++static int tegra_pmc_parse_dt(struct tegra_pmc *pmc, struct device_node *np)
++{
++ u32 value, values[2];
++
++ if (of_property_read_u32(np, "nvidia,suspend-mode", &value)) {
++ } else {
++ switch (value) {
++ case 0:
++ pmc->suspend_mode = TEGRA_SUSPEND_LP0;
++ break;
++
++ case 1:
++ pmc->suspend_mode = TEGRA_SUSPEND_LP1;
++ break;
++
++ case 2:
++ pmc->suspend_mode = TEGRA_SUSPEND_LP2;
++ break;
++
++ default:
++ pmc->suspend_mode = TEGRA_SUSPEND_NONE;
++ break;
++ }
++ }
++
++ pmc->suspend_mode = tegra_pm_validate_suspend_mode(pmc->suspend_mode);
++
++ if (of_property_read_u32(np, "nvidia,cpu-pwr-good-time", &value))
++ pmc->suspend_mode = TEGRA_SUSPEND_NONE;
++
++ pmc->cpu_good_time = value;
++
++ if (of_property_read_u32(np, "nvidia,cpu-pwr-off-time", &value))
++ pmc->suspend_mode = TEGRA_SUSPEND_NONE;
++
++ pmc->cpu_off_time = value;
++
++ if (of_property_read_u32_array(np, "nvidia,core-pwr-good-time",
++ values, ARRAY_SIZE(values)))
++ pmc->suspend_mode = TEGRA_SUSPEND_NONE;
++
++ pmc->core_osc_time = values[0];
++ pmc->core_pmu_time = values[1];
++
++ if (of_property_read_u32(np, "nvidia,core-pwr-off-time", &value))
++ pmc->suspend_mode = TEGRA_SUSPEND_NONE;
++
++ pmc->core_off_time = value;
++
++ pmc->corereq_high = of_property_read_bool(np,
++ "nvidia,core-power-req-active-high");
++
++ pmc->sysclkreq_high = of_property_read_bool(np,
++ "nvidia,sys-clock-req-active-high");
++
++ pmc->combined_req = of_property_read_bool(np,
++ "nvidia,combined-power-req");
++
++ pmc->cpu_pwr_good_en = of_property_read_bool(np,
++ "nvidia,cpu-pwr-good-en");
++
++ if (of_property_read_u32_array(np, "nvidia,lp0-vec", values,
++ ARRAY_SIZE(values)))
++ if (pmc->suspend_mode == TEGRA_SUSPEND_LP0)
++ pmc->suspend_mode = TEGRA_SUSPEND_LP1;
++
++ pmc->lp0_vec_phys = values[0];
++ pmc->lp0_vec_size = values[1];
++
++ return 0;
++}
++
++static void tegra_pmc_init(struct tegra_pmc *pmc)
++{
++ u32 value;
++
++ /* Always enable CPU power request */
++ value = tegra_pmc_readl(PMC_CNTRL);
++ value |= PMC_CNTRL_CPU_PWRREQ_OE;
++ tegra_pmc_writel(value, PMC_CNTRL);
++
++ value = tegra_pmc_readl(PMC_CNTRL);
++
++ if (pmc->sysclkreq_high)
++ value &= ~PMC_CNTRL_SYSCLK_POLARITY;
++ else
++ value |= PMC_CNTRL_SYSCLK_POLARITY;
++
++ /* configure the output polarity while the request is tristated */
++ tegra_pmc_writel(value, PMC_CNTRL);
++
++ /* now enable the request */
++ value = tegra_pmc_readl(PMC_CNTRL);
++ value |= PMC_CNTRL_SYSCLK_OE;
++ tegra_pmc_writel(value, PMC_CNTRL);
++}
++
++static int tegra_pmc_probe(struct platform_device *pdev)
++{
++ void __iomem *base = pmc->base;
++ struct resource *res;
++ int err;
++
++ err = tegra_pmc_parse_dt(pmc, pdev->dev.of_node);
++ if (err < 0)
++ return err;
++
++ /* take over the memory region from the early initialization */
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ pmc->base = devm_ioremap_resource(&pdev->dev, res);
++ if (IS_ERR(pmc->base))
++ return PTR_ERR(pmc->base);
++
++ iounmap(base);
++
++ pmc->clk = devm_clk_get(&pdev->dev, "pclk");
++ if (IS_ERR(pmc->clk)) {
++ err = PTR_ERR(pmc->clk);
++ dev_err(&pdev->dev, "failed to get pclk: %d\n", err);
++ return err;
++ }
++
++ tegra_pmc_init(pmc);
++
++ if (IS_ENABLED(CONFIG_DEBUG_FS)) {
++ err = tegra_powergate_debugfs_init();
++ if (err < 0)
++ return err;
++ }
++
++ return 0;
++}
++
++#ifdef CONFIG_PM_SLEEP
++static int tegra_pmc_suspend(struct device *dev)
++{
++ tegra_pmc_writel(virt_to_phys(tegra_resume), PMC_SCRATCH41);
++
++ return 0;
++}
++
++static int tegra_pmc_resume(struct device *dev)
++{
++ tegra_pmc_writel(0x0, PMC_SCRATCH41);
++
++ return 0;
++}
++#endif
++
++static SIMPLE_DEV_PM_OPS(tegra_pmc_pm_ops, tegra_pmc_suspend, tegra_pmc_resume);
++
++static const char * const tegra20_powergates[] = {
++ [TEGRA_POWERGATE_CPU] = "cpu",
++ [TEGRA_POWERGATE_3D] = "3d",
++ [TEGRA_POWERGATE_VENC] = "venc",
++ [TEGRA_POWERGATE_VDEC] = "vdec",
++ [TEGRA_POWERGATE_PCIE] = "pcie",
++ [TEGRA_POWERGATE_L2] = "l2",
++ [TEGRA_POWERGATE_MPE] = "mpe",
++};
++
++static const struct tegra_pmc_soc tegra20_pmc_soc = {
++ .num_powergates = ARRAY_SIZE(tegra20_powergates),
++ .powergates = tegra20_powergates,
++ .num_cpu_powergates = 0,
++ .cpu_powergates = NULL,
++};
++
++static const char * const tegra30_powergates[] = {
++ [TEGRA_POWERGATE_CPU] = "cpu0",
++ [TEGRA_POWERGATE_3D] = "3d0",
++ [TEGRA_POWERGATE_VENC] = "venc",
++ [TEGRA_POWERGATE_VDEC] = "vdec",
++ [TEGRA_POWERGATE_PCIE] = "pcie",
++ [TEGRA_POWERGATE_L2] = "l2",
++ [TEGRA_POWERGATE_MPE] = "mpe",
++ [TEGRA_POWERGATE_HEG] = "heg",
++ [TEGRA_POWERGATE_SATA] = "sata",
++ [TEGRA_POWERGATE_CPU1] = "cpu1",
++ [TEGRA_POWERGATE_CPU2] = "cpu2",
++ [TEGRA_POWERGATE_CPU3] = "cpu3",
++ [TEGRA_POWERGATE_CELP] = "celp",
++ [TEGRA_POWERGATE_3D1] = "3d1",
++};
++
++static const u8 tegra30_cpu_powergates[] = {
++ TEGRA_POWERGATE_CPU,
++ TEGRA_POWERGATE_CPU1,
++ TEGRA_POWERGATE_CPU2,
++ TEGRA_POWERGATE_CPU3,
++};
++
++static const struct tegra_pmc_soc tegra30_pmc_soc = {
++ .num_powergates = ARRAY_SIZE(tegra30_powergates),
++ .powergates = tegra30_powergates,
++ .num_cpu_powergates = ARRAY_SIZE(tegra30_cpu_powergates),
++ .cpu_powergates = tegra30_cpu_powergates,
++};
++
++static const char * const tegra114_powergates[] = {
++ [TEGRA_POWERGATE_CPU] = "crail",
++ [TEGRA_POWERGATE_3D] = "3d",
++ [TEGRA_POWERGATE_VENC] = "venc",
++ [TEGRA_POWERGATE_VDEC] = "vdec",
++ [TEGRA_POWERGATE_MPE] = "mpe",
++ [TEGRA_POWERGATE_HEG] = "heg",
++ [TEGRA_POWERGATE_CPU1] = "cpu1",
++ [TEGRA_POWERGATE_CPU2] = "cpu2",
++ [TEGRA_POWERGATE_CPU3] = "cpu3",
++ [TEGRA_POWERGATE_CELP] = "celp",
++ [TEGRA_POWERGATE_CPU0] = "cpu0",
++ [TEGRA_POWERGATE_C0NC] = "c0nc",
++ [TEGRA_POWERGATE_C1NC] = "c1nc",
++ [TEGRA_POWERGATE_DIS] = "dis",
++ [TEGRA_POWERGATE_DISB] = "disb",
++ [TEGRA_POWERGATE_XUSBA] = "xusba",
++ [TEGRA_POWERGATE_XUSBB] = "xusbb",
++ [TEGRA_POWERGATE_XUSBC] = "xusbc",
++};
++
++static const u8 tegra114_cpu_powergates[] = {
++ TEGRA_POWERGATE_CPU0,
++ TEGRA_POWERGATE_CPU1,
++ TEGRA_POWERGATE_CPU2,
++ TEGRA_POWERGATE_CPU3,
++};
++
++static const struct tegra_pmc_soc tegra114_pmc_soc = {
++ .num_powergates = ARRAY_SIZE(tegra114_powergates),
++ .powergates = tegra114_powergates,
++ .num_cpu_powergates = ARRAY_SIZE(tegra114_cpu_powergates),
++ .cpu_powergates = tegra114_cpu_powergates,
++};
++
++static const char * const tegra124_powergates[] = {
++ [TEGRA_POWERGATE_CPU] = "crail",
++ [TEGRA_POWERGATE_3D] = "3d",
++ [TEGRA_POWERGATE_VENC] = "venc",
++ [TEGRA_POWERGATE_PCIE] = "pcie",
++ [TEGRA_POWERGATE_VDEC] = "vdec",
++ [TEGRA_POWERGATE_L2] = "l2",
++ [TEGRA_POWERGATE_MPE] = "mpe",
++ [TEGRA_POWERGATE_HEG] = "heg",
++ [TEGRA_POWERGATE_SATA] = "sata",
++ [TEGRA_POWERGATE_CPU1] = "cpu1",
++ [TEGRA_POWERGATE_CPU2] = "cpu2",
++ [TEGRA_POWERGATE_CPU3] = "cpu3",
++ [TEGRA_POWERGATE_CELP] = "celp",
++ [TEGRA_POWERGATE_CPU0] = "cpu0",
++ [TEGRA_POWERGATE_C0NC] = "c0nc",
++ [TEGRA_POWERGATE_C1NC] = "c1nc",
++ [TEGRA_POWERGATE_SOR] = "sor",
++ [TEGRA_POWERGATE_DIS] = "dis",
++ [TEGRA_POWERGATE_DISB] = "disb",
++ [TEGRA_POWERGATE_XUSBA] = "xusba",
++ [TEGRA_POWERGATE_XUSBB] = "xusbb",
++ [TEGRA_POWERGATE_XUSBC] = "xusbc",
++ [TEGRA_POWERGATE_VIC] = "vic",
++ [TEGRA_POWERGATE_IRAM] = "iram",
++};
++
++static const u8 tegra124_cpu_powergates[] = {
++ TEGRA_POWERGATE_CPU0,
++ TEGRA_POWERGATE_CPU1,
++ TEGRA_POWERGATE_CPU2,
++ TEGRA_POWERGATE_CPU3,
++};
++
++static const struct tegra_pmc_soc tegra124_pmc_soc = {
++ .num_powergates = ARRAY_SIZE(tegra124_powergates),
++ .powergates = tegra124_powergates,
++ .num_cpu_powergates = ARRAY_SIZE(tegra124_cpu_powergates),
++ .cpu_powergates = tegra124_cpu_powergates,
++};
++
++static const struct of_device_id tegra_pmc_match[] = {
++ { .compatible = "nvidia,tegra124-pmc", .data = &tegra124_pmc_soc },
++ { .compatible = "nvidia,tegra114-pmc", .data = &tegra114_pmc_soc },
++ { .compatible = "nvidia,tegra30-pmc", .data = &tegra30_pmc_soc },
++ { .compatible = "nvidia,tegra20-pmc", .data = &tegra20_pmc_soc },
++ { }
++};
++
++static struct platform_driver tegra_pmc_driver = {
++ .driver = {
++ .name = "tegra-pmc",
++ .suppress_bind_attrs = true,
++ .of_match_table = tegra_pmc_match,
++ .pm = &tegra_pmc_pm_ops,
++ },
++ .probe = tegra_pmc_probe,
++};
++module_platform_driver(tegra_pmc_driver);
++
++/*
++ * Early initialization to allow access to registers in the very early boot
++ * process.
++ */
++static int __init tegra_pmc_early_init(void)
++{
++ const struct of_device_id *match;
++ struct device_node *np;
++ struct resource regs;
++ bool invert;
++ u32 value;
++
++ np = of_find_matching_node_and_match(NULL, tegra_pmc_match, &match);
++ if (!np) {
++ pr_warn("PMC device node not found, disabling powergating\n");
++
++ regs.start = 0x7000e400;
++ regs.end = 0x7000e7ff;
++ regs.flags = IORESOURCE_MEM;
++
++ pr_warn("Using memory region %pR\n", &regs);
++ } else {
++ pmc->soc = match->data;
++ }
++
++ if (of_address_to_resource(np, 0, &regs) < 0) {
++ pr_err("failed to get PMC registers\n");
++ return -ENXIO;
++ }
++
++ pmc->base = ioremap_nocache(regs.start, resource_size(&regs));
++ if (!pmc->base) {
++ pr_err("failed to map PMC registers\n");
++ return -ENXIO;
++ }
++
++ mutex_init(&pmc->powergates_lock);
++
++ invert = of_property_read_bool(np, "nvidia,invert-interrupt");
++
++ value = tegra_pmc_readl(PMC_CNTRL);
++
++ if (invert)
++ value |= PMC_CNTRL_INTR_POLARITY;
++ else
++ value &= ~PMC_CNTRL_INTR_POLARITY;
++
++ tegra_pmc_writel(value, PMC_CNTRL);
++
++ return 0;
++}
++early_initcall(tegra_pmc_early_init);
diff --git a/arch/arm/mach-tegra/tegra.c b/arch/arm/mach-tegra/tegra.c
-index 15ac9fc..cf6a7ac 100644
+index 15ac9fc..4482ad8 100644
--- a/arch/arm/mach-tegra/tegra.c
+++ b/arch/arm/mach-tegra/tegra.c
-@@ -34,6 +34,7 @@
- #include <linux/usb/tegra_usb_phy.h>
- #include <linux/clk/tegra.h>
- #include <linux/irqchip.h>
+@@ -16,40 +16,38 @@
+ *
+ */
+
+-#include <linux/kernel.h>
+-#include <linux/init.h>
+-#include <linux/platform_device.h>
+-#include <linux/serial_8250.h>
+ #include <linux/clk.h>
++#include <linux/clk/tegra.h>
+ #include <linux/dma-mapping.h>
++#include <linux/init.h>
++#include <linux/io.h>
++#include <linux/irqchip.h>
+ #include <linux/irqdomain.h>
+-#include <linux/of.h>
++#include <linux/kernel.h>
+ #include <linux/of_address.h>
+ #include <linux/of_fdt.h>
++#include <linux/of.h>
+ #include <linux/of_platform.h>
+ #include <linux/pda_power.h>
+-#include <linux/io.h>
++#include <linux/platform_device.h>
++#include <linux/serial_8250.h>
+ #include <linux/slab.h>
+ #include <linux/sys_soc.h>
+#include <linux/tegra-soc.h>
+ #include <linux/usb/tegra_usb_phy.h>
+-#include <linux/clk/tegra.h>
+-#include <linux/irqchip.h>
#include <asm/hardware/cache-l2x0.h>
- #include <asm/mach-types.h>
-@@ -42,11 +43,9 @@
+-#include <asm/mach-types.h>
+ #include <asm/mach/arch.h>
+ #include <asm/mach/time.h>
++#include <asm/mach-types.h>
#include <asm/setup.h>
#include <asm/trusted_foundations.h>
@@ -3075,25 +5834,56 @@ index 15ac9fc..cf6a7ac 100644
-#include "fuse.h"
#include "iomap.h"
#include "irq.h"
- #include "pmc.h"
-@@ -73,7 +72,6 @@ u32 tegra_uart_config[3] = {
+-#include "pmc.h"
+ #include "pm.h"
+ #include "reset.h"
+ #include "sleep.h"
+@@ -73,16 +71,11 @@ u32 tegra_uart_config[3] = {
static void __init tegra_init_early(void)
{
of_register_trusted_foundations();
- tegra_apb_io_init();
- tegra_init_fuse();
+- tegra_init_fuse();
tegra_cpu_reset_handler_init();
- tegra_powergate_init();
-@@ -103,7 +101,8 @@ static void __init tegra_dt_init(void)
+- tegra_powergate_init();
+- tegra_hotplug_init();
+ }
+
+ static void __init tegra_dt_init_irq(void)
+ {
+- tegra_pmc_init_irq();
+ tegra_init_irq();
+ irqchip_init();
+ tegra_legacy_irq_syscore_init();
+@@ -94,8 +87,6 @@ static void __init tegra_dt_init(void)
+ struct soc_device *soc_dev;
+ struct device *parent = NULL;
+
+- tegra_pmc_init();
+-
+ tegra_clocks_apply_init_table();
+
+ soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
+@@ -103,8 +94,9 @@ static void __init tegra_dt_init(void)
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_attr->revision = kasprintf(GFP_KERNEL, "%d",
-+ tegra_sku_info.revision);
- soc_dev_attr->soc_id = kasprintf(GFP_KERNEL, "%d", tegra_chip_id);
++ tegra_sku_info.revision);
++ soc_dev_attr->soc_id = kasprintf(GFP_KERNEL, "%u", tegra_get_chip_id());
soc_dev = soc_device_register(soc_dev_attr);
+ if (IS_ERR(soc_dev)) {
+@@ -144,7 +136,6 @@ static void __init tegra_dt_init_late(void)
+
+ tegra_init_suspend();
+ tegra_cpuidle_init();
+- tegra_powergate_debugfs_init();
+
+ for (i = 0; i < ARRAY_SIZE(board_init_funcs); i++) {
+ if (of_machine_is_compatible(board_init_funcs[i].machine)) {
diff --git a/arch/arm/mach-tegra/tegra114_speedo.c b/arch/arm/mach-tegra/tegra114_speedo.c
deleted file mode 100644
index 5218d48..0000000
@@ -3662,15 +6452,6 @@ index d1869f0..d2616ef 100644
ret = setup_irq(tegra_timer_irq.irq, &tegra_timer_irq);
if (ret) {
pr_err("Failed to register timer IRQ: %d\n", ret);
-diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
-index d59ce12..f4ac83b 100644
---- a/drivers/misc/Makefile
-+++ b/drivers/misc/Makefile
-@@ -56,3 +56,4 @@ obj-y += mic/
- obj-$(CONFIG_GENWQE) += genwqe/
- obj-$(CONFIG_ECHO) += echo/
- obj-$(CONFIG_VEXPRESS_SYSCFG) += vexpress-syscfg.o
-+obj-y += fuse/
diff --git a/drivers/misc/fuse/Makefile b/drivers/misc/fuse/Makefile
new file mode 100644
index 0000000..0679c4f
@@ -3678,11 +6459,1273 @@ index 0000000..0679c4f
+++ b/drivers/misc/fuse/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_ARCH_TEGRA) += tegra/
-diff --git a/drivers/misc/fuse/tegra/Makefile b/drivers/misc/fuse/tegra/Makefile
+diff --git a/drivers/pci/host/pci-tegra.c b/drivers/pci/host/pci-tegra.c
+index 083cf37..7df5aaf 100644
+--- a/drivers/pci/host/pci-tegra.c
++++ b/drivers/pci/host/pci-tegra.c
+@@ -233,7 +233,6 @@ struct tegra_pcie_soc_data {
+ bool has_pex_clkreq_en;
+ bool has_pex_bias_ctrl;
+ bool has_intr_prsnt_sense;
+- bool has_avdd_supply;
+ bool has_cml_clk;
+ };
+
+@@ -272,9 +271,8 @@ struct tegra_pcie {
+ unsigned int num_ports;
+ u32 xbar_config;
+
+- struct regulator *pex_clk_supply;
+- struct regulator *vdd_supply;
+- struct regulator *avdd_supply;
++ struct regulator_bulk_data *supplies;
++ unsigned int num_supplies;
+
+ const struct tegra_pcie_soc_data *soc_data;
+ };
+@@ -894,7 +892,6 @@ static int tegra_pcie_enable_controller(struct tegra_pcie *pcie)
+
+ static void tegra_pcie_power_off(struct tegra_pcie *pcie)
+ {
+- const struct tegra_pcie_soc_data *soc = pcie->soc_data;
+ int err;
+
+ /* TODO: disable and unprepare clocks? */
+@@ -905,23 +902,9 @@ static void tegra_pcie_power_off(struct tegra_pcie *pcie)
+
+ tegra_powergate_power_off(TEGRA_POWERGATE_PCIE);
+
+- if (soc->has_avdd_supply) {
+- err = regulator_disable(pcie->avdd_supply);
+- if (err < 0)
+- dev_warn(pcie->dev,
+- "failed to disable AVDD regulator: %d\n",
+- err);
+- }
+-
+- err = regulator_disable(pcie->pex_clk_supply);
++ err = regulator_bulk_disable(pcie->num_supplies, pcie->supplies);
+ if (err < 0)
+- dev_warn(pcie->dev, "failed to disable pex-clk regulator: %d\n",
+- err);
+-
+- err = regulator_disable(pcie->vdd_supply);
+- if (err < 0)
+- dev_warn(pcie->dev, "failed to disable VDD regulator: %d\n",
+- err);
++ dev_warn(pcie->dev, "failed to disable regulators: %d\n", err);
+ }
+
+ static int tegra_pcie_power_on(struct tegra_pcie *pcie)
+@@ -936,28 +919,9 @@ static int tegra_pcie_power_on(struct tegra_pcie *pcie)
+ tegra_powergate_power_off(TEGRA_POWERGATE_PCIE);
+
+ /* enable regulators */
+- err = regulator_enable(pcie->vdd_supply);
+- if (err < 0) {
+- dev_err(pcie->dev, "failed to enable VDD regulator: %d\n", err);
+- return err;
+- }
+-
+- err = regulator_enable(pcie->pex_clk_supply);
+- if (err < 0) {
+- dev_err(pcie->dev, "failed to enable pex-clk regulator: %d\n",
+- err);
+- return err;
+- }
+-
+- if (soc->has_avdd_supply) {
+- err = regulator_enable(pcie->avdd_supply);
+- if (err < 0) {
+- dev_err(pcie->dev,
+- "failed to enable AVDD regulator: %d\n",
+- err);
+- return err;
+- }
+- }
++ err = regulator_bulk_enable(pcie->num_supplies, pcie->supplies);
++ if (err < 0)
++ dev_err(pcie->dev, "failed to enable regulators: %d\n", err);
+
+ err = tegra_powergate_sequence_power_up(TEGRA_POWERGATE_PCIE,
+ pcie->pex_clk,
+@@ -1394,14 +1358,83 @@ static int tegra_pcie_get_xbar_config(struct tegra_pcie *pcie, u32 lanes,
+ return -EINVAL;
+ }
+
++/*
++ * Obtains the list of regulators required for a particular generation of the
++ * IP block.
++ *
++ * This would've been nice to do simply by providing static tables for use
++ * with the regulator_bulk_*() API, but unfortunately Tegra30 is a bit quirky
++ * in that it has two pairs or AVDD_PEX and VDD_PEX supplies (PEXA and PEXB)
++ * and either seems to be optional depending on which ports are being used.
++ */
++static int tegra_pcie_get_regulators(struct tegra_pcie *pcie, u32 lane_mask)
++{
++ struct device_node *np = pcie->dev->of_node;
++ unsigned int i = 0;
++
++ if (of_device_is_compatible(np, "nvidia,tegra30-pcie")) {
++ bool need_pexa = false, need_pexb = false;
++
++ /* VDD_PEXA and AVDD_PEXA supply lanes 0 to 3 */
++ if (lane_mask & 0x0f)
++ need_pexa = true;
++
++ /* VDD_PEXB and AVDD_PEXB supply lanes 4 to 5 */
++ if (lane_mask & 0x30)
++ need_pexb = true;
++
++ pcie->num_supplies = 4 + (need_pexa ? 2 : 0) +
++ (need_pexb ? 2 : 0);
++
++ pcie->supplies = devm_kcalloc(pcie->dev, pcie->num_supplies,
++ sizeof(*pcie->supplies),
++ GFP_KERNEL);
++ if (!pcie->supplies)
++ return -ENOMEM;
++
++ pcie->supplies[i++].supply = "avdd-pex-pll";
++ pcie->supplies[i++].supply = "hvdd-pex";
++ pcie->supplies[i++].supply = "vddio-pex-ctl";
++ pcie->supplies[i++].supply = "avdd-plle";
++
++ if (need_pexa) {
++ pcie->supplies[i++].supply = "avdd-pexa";
++ pcie->supplies[i++].supply = "vdd-pexa";
++ }
++
++ if (need_pexb) {
++ pcie->supplies[i++].supply = "avdd-pexb";
++ pcie->supplies[i++].supply = "vdd-pexb";
++ }
++ } else if (of_device_is_compatible(np, "nvidia,tegra20-pcie")) {
++ pcie->num_supplies = 5;
++
++ pcie->supplies = devm_kcalloc(pcie->dev, pcie->num_supplies,
++ sizeof(*pcie->supplies),
++ GFP_KERNEL);
++ if (!pcie->supplies)
++ return -ENOMEM;
++
++ pcie->supplies[0].supply = "avdd-pex";
++ pcie->supplies[1].supply = "vdd-pex";
++ pcie->supplies[2].supply = "avdd-pex-pll";
++ pcie->supplies[3].supply = "avdd-plle";
++ pcie->supplies[4].supply = "vddio-pex-clk";
++ }
++
++ return devm_regulator_bulk_get(pcie->dev, pcie->num_supplies,
++ pcie->supplies);
++}
++
+ static int tegra_pcie_parse_dt(struct tegra_pcie *pcie)
+ {
+ const struct tegra_pcie_soc_data *soc = pcie->soc_data;
+ struct device_node *np = pcie->dev->of_node, *port;
+ struct of_pci_range_parser parser;
+ struct of_pci_range range;
++ u32 lanes = 0, mask = 0;
++ unsigned int lane = 0;
+ struct resource res;
+- u32 lanes = 0;
+ int err;
+
+ if (of_pci_range_parser_init(&parser, np)) {
+@@ -1409,20 +1442,6 @@ static int tegra_pcie_parse_dt(struct tegra_pcie *pcie)
+ return -EINVAL;
+ }
+
+- pcie->vdd_supply = devm_regulator_get(pcie->dev, "vdd");
+- if (IS_ERR(pcie->vdd_supply))
+- return PTR_ERR(pcie->vdd_supply);
+-
+- pcie->pex_clk_supply = devm_regulator_get(pcie->dev, "pex-clk");
+- if (IS_ERR(pcie->pex_clk_supply))
+- return PTR_ERR(pcie->pex_clk_supply);
+-
+- if (soc->has_avdd_supply) {
+- pcie->avdd_supply = devm_regulator_get(pcie->dev, "avdd");
+- if (IS_ERR(pcie->avdd_supply))
+- return PTR_ERR(pcie->avdd_supply);
+- }
+-
+ for_each_of_pci_range(&parser, &range) {
+ of_pci_range_to_resource(&range, np, &res);
+
+@@ -1490,8 +1509,13 @@ static int tegra_pcie_parse_dt(struct tegra_pcie *pcie)
+
+ lanes |= value << (index << 3);
+
+- if (!of_device_is_available(port))
++ if (!of_device_is_available(port)) {
++ lane += value;
+ continue;
++ }
++
++ mask |= ((1 << value) - 1) << lane;
++ lane += value;
+
+ rp = devm_kzalloc(pcie->dev, sizeof(*rp), GFP_KERNEL);
+ if (!rp)
+@@ -1522,6 +1546,10 @@ static int tegra_pcie_parse_dt(struct tegra_pcie *pcie)
+ return err;
+ }
+
++ err = tegra_pcie_get_regulators(pcie, mask);
++ if (err < 0)
++ return err;
++
+ return 0;
+ }
+
+@@ -1615,7 +1643,6 @@ static const struct tegra_pcie_soc_data tegra20_pcie_data = {
+ .has_pex_clkreq_en = false,
+ .has_pex_bias_ctrl = false,
+ .has_intr_prsnt_sense = false,
+- .has_avdd_supply = false,
+ .has_cml_clk = false,
+ };
+
+@@ -1627,7 +1654,6 @@ static const struct tegra_pcie_soc_data tegra30_pcie_data = {
+ .has_pex_clkreq_en = true,
+ .has_pex_bias_ctrl = true,
+ .has_intr_prsnt_sense = true,
+- .has_avdd_supply = true,
+ .has_cml_clk = true,
+ };
+
+diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
+index 0042ccb..0fa42be 100644
+--- a/drivers/pinctrl/Kconfig
++++ b/drivers/pinctrl/Kconfig
+@@ -328,6 +328,12 @@ config PINCTRL_TEGRA124
+ bool
+ select PINCTRL_TEGRA
+
++config PINCTRL_TEGRA_XUSB
++ def_bool y if ARCH_TEGRA
++ select GENERIC_PHY
++ select PINCONF
++ select PINMUX
++
+ config PINCTRL_TZ1090
+ bool "Toumaz Xenif TZ1090 pin control driver"
+ depends on SOC_TZ1090
+diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
+index c4b5d40..df88788 100644
+--- a/drivers/pinctrl/Makefile
++++ b/drivers/pinctrl/Makefile
+@@ -55,6 +55,7 @@ obj-$(CONFIG_PINCTRL_TEGRA20) += pinctrl-tegra20.o
+ obj-$(CONFIG_PINCTRL_TEGRA30) += pinctrl-tegra30.o
+ obj-$(CONFIG_PINCTRL_TEGRA114) += pinctrl-tegra114.o
+ obj-$(CONFIG_PINCTRL_TEGRA124) += pinctrl-tegra124.o
++obj-$(CONFIG_PINCTRL_TEGRA_XUSB) += pinctrl-tegra-xusb.o
+ obj-$(CONFIG_PINCTRL_TZ1090) += pinctrl-tz1090.o
+ obj-$(CONFIG_PINCTRL_TZ1090_PDC) += pinctrl-tz1090-pdc.o
+ obj-$(CONFIG_PINCTRL_U300) += pinctrl-u300.o
+diff --git a/drivers/pinctrl/pinctrl-tegra-xusb.c b/drivers/pinctrl/pinctrl-tegra-xusb.c
+new file mode 100644
+index 0000000..4a7daf5
+--- /dev/null
++++ b/drivers/pinctrl/pinctrl-tegra-xusb.c
+@@ -0,0 +1,973 @@
++/*
++ * Copyright (c) 2014, 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.
++ */
++
++#include <linux/delay.h>
++#include <linux/io.h>
++#include <linux/module.h>
++#include <linux/of.h>
++#include <linux/phy/phy.h>
++#include <linux/pinctrl/pinctrl.h>
++#include <linux/pinctrl/pinmux.h>
++#include <linux/platform_device.h>
++#include <linux/reset.h>
++
++#include <dt-bindings/pinctrl/pinctrl-tegra-xusb.h>
++
++#include "core.h"
++#include "pinctrl-utils.h"
++
++#define XUSB_PADCTL_ELPG_PROGRAM 0x01c
++#define XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN (1 << 26)
++#define XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY (1 << 25)
++#define XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN (1 << 24)
++
++#define XUSB_PADCTL_IOPHY_PLL_P0_CTL1 0x040
++#define XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL0_LOCKDET (1 << 19)
++#define XUSB_PADCTL_IOPHY_PLL_P0_CTL1_REFCLK_SEL_MASK (0xf << 12)
++#define XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL_RST (1 << 1)
++
++#define XUSB_PADCTL_IOPHY_PLL_P0_CTL2 0x044
++#define XUSB_PADCTL_IOPHY_PLL_P0_CTL2_REFCLKBUF_EN (1 << 6)
++#define XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_EN (1 << 5)
++#define XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_SEL (1 << 4)
++
++#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1 0x138
++#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_LOCKDET (1 << 27)
++#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_MODE (1 << 24)
++#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD (1 << 3)
++#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_RST (1 << 1)
++#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_IDDQ (1 << 0)
++
++#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1 0x148
++#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD (1 << 1)
++#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ (1 << 0)
++
++struct tegra_xusb_padctl_function {
++ const char *name;
++ const char * const *groups;
++ unsigned int num_groups;
++};
++
++struct tegra_xusb_padctl_group {
++ const unsigned int *funcs;
++ unsigned int num_funcs;
++};
++
++struct tegra_xusb_padctl_soc {
++ const struct pinctrl_pin_desc *pins;
++ unsigned int num_pins;
++
++ const struct tegra_xusb_padctl_function *functions;
++ unsigned int num_functions;
++
++ const struct tegra_xusb_padctl_lane *lanes;
++ unsigned int num_lanes;
++};
++
++struct tegra_xusb_padctl_lane {
++ const char *name;
++
++ unsigned int offset;
++ unsigned int shift;
++ unsigned int mask;
++ unsigned int iddq;
++
++ const unsigned int *funcs;
++ unsigned int num_funcs;
++};
++
++struct tegra_xusb_padctl {
++ struct device *dev;
++ void __iomem *regs;
++ struct mutex lock;
++ struct reset_control *rst;
++
++ const struct tegra_xusb_padctl_soc *soc;
++ struct pinctrl_dev *pinctrl;
++ struct pinctrl_desc desc;
++
++ struct phy_provider *provider;
++ struct phy *phys[2];
++
++ unsigned int enable;
++};
++
++static inline void padctl_writel(struct tegra_xusb_padctl *padctl, u32 value,
++ unsigned long offset)
++{
++ writel(value, padctl->regs + offset);
++}
++
++static inline u32 padctl_readl(struct tegra_xusb_padctl *padctl,
++ unsigned long offset)
++{
++ return readl(padctl->regs + offset);
++}
++
++static int tegra_xusb_padctl_get_groups_count(struct pinctrl_dev *pinctrl)
++{
++ struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl);
++
++ return padctl->soc->num_pins;
++}
++
++static const char *tegra_xusb_padctl_get_group_name(struct pinctrl_dev *pinctrl,
++ unsigned int group)
++{
++ struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl);
++
++ return padctl->soc->pins[group].name;
++}
++
++enum tegra_xusb_padctl_param {
++ TEGRA_XUSB_PADCTL_IDDQ,
++};
++
++static const struct tegra_xusb_padctl_property {
++ const char *name;
++ enum tegra_xusb_padctl_param param;
++} properties[] = {
++ { "nvidia,iddq", TEGRA_XUSB_PADCTL_IDDQ },
++};
++
++#define TEGRA_XUSB_PADCTL_PACK(param, value) ((param) << 16 | (value))
++#define TEGRA_XUSB_PADCTL_UNPACK_PARAM(config) ((config) >> 16)
++#define TEGRA_XUSB_PADCTL_UNPACK_VALUE(config) ((config) & 0xffff)
++
++static int tegra_xusb_padctl_parse_subnode(struct tegra_xusb_padctl *padctl,
++ struct device_node *np,
++ struct pinctrl_map **maps,
++ unsigned int *reserved_maps,
++ unsigned int *num_maps)
++{
++ unsigned int i, reserve = 0, num_configs = 0;
++ unsigned long config, *configs = NULL;
++ const char *function, *group;
++ struct property *prop;
++ int err = 0;
++ u32 value;
++
++ err = of_property_read_string(np, "nvidia,function", &function);
++ if (err < 0) {
++ if (err != -EINVAL)
++ return err;
++
++ function = NULL;
++ }
++
++ for (i = 0; i < ARRAY_SIZE(properties); i++) {
++ err = of_property_read_u32(np, properties[i].name, &value);
++ if (err < 0) {
++ if (err == -EINVAL)
++ continue;
++
++ return err;
++ }
++
++ config = TEGRA_XUSB_PADCTL_PACK(properties[i].param, value);
++
++ err = pinctrl_utils_add_config(padctl->pinctrl, &configs,
++ &num_configs, config);
++ if (err < 0)
++ return err;
++ }
++
++ if (function)
++ reserve++;
++
++ if (num_configs)
++ reserve++;
++
++ err = of_property_count_strings(np, "nvidia,lanes");
++ if (err < 0)
++ return err;
++
++ reserve *= err;
++
++ err = pinctrl_utils_reserve_map(padctl->pinctrl, maps, reserved_maps,
++ num_maps, reserve);
++ if (err < 0)
++ return err;
++
++ of_property_for_each_string(np, "nvidia,lanes", prop, group) {
++ if (function) {
++ err = pinctrl_utils_add_map_mux(padctl->pinctrl, maps,
++ reserved_maps, num_maps, group,
++ function);
++ if (err < 0)
++ return err;
++ }
++
++ if (num_configs) {
++ err = pinctrl_utils_add_map_configs(padctl->pinctrl,
++ maps, reserved_maps, num_maps, group,
++ configs, num_configs,
++ PIN_MAP_TYPE_CONFIGS_GROUP);
++ if (err < 0)
++ return err;
++ }
++ }
++
++ return 0;
++}
++
++static int tegra_xusb_padctl_dt_node_to_map(struct pinctrl_dev *pinctrl,
++ struct device_node *parent,
++ struct pinctrl_map **maps,
++ unsigned int *num_maps)
++{
++ struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl);
++ unsigned int reserved_maps = 0;
++ struct device_node *np;
++ int err;
++
++ *num_maps = 0;
++ *maps = NULL;
++
++ for_each_child_of_node(parent, np) {
++ err = tegra_xusb_padctl_parse_subnode(padctl, np, maps,
++ &reserved_maps,
++ num_maps);
++ if (err < 0)
++ return err;
++ }
++
++ return 0;
++}
++
++static const struct pinctrl_ops tegra_xusb_padctl_pinctrl_ops = {
++ .get_groups_count = tegra_xusb_padctl_get_groups_count,
++ .get_group_name = tegra_xusb_padctl_get_group_name,
++ .dt_node_to_map = tegra_xusb_padctl_dt_node_to_map,
++ .dt_free_map = pinctrl_utils_dt_free_map,
++};
++
++static int tegra_xusb_padctl_get_functions_count(struct pinctrl_dev *pinctrl)
++{
++ struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl);
++
++ return padctl->soc->num_functions;
++}
++
++static const char *
++tegra_xusb_padctl_get_function_name(struct pinctrl_dev *pinctrl,
++ unsigned int function)
++{
++ struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl);
++
++ return padctl->soc->functions[function].name;
++}
++
++static int tegra_xusb_padctl_get_function_groups(struct pinctrl_dev *pinctrl,
++ unsigned int function,
++ const char * const **groups,
++ unsigned * const num_groups)
++{
++ struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl);
++
++ *num_groups = padctl->soc->functions[function].num_groups;
++ *groups = padctl->soc->functions[function].groups;
++
++ return 0;
++}
++
++static int tegra_xusb_padctl_pinmux_enable(struct pinctrl_dev *pinctrl,
++ unsigned int function,
++ unsigned int group)
++{
++ struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl);
++ const struct tegra_xusb_padctl_lane *lane;
++ unsigned int i;
++ u32 value;
++
++ lane = &padctl->soc->lanes[group];
++
++ for (i = 0; i < lane->num_funcs; i++)
++ if (lane->funcs[i] == function)
++ break;
++
++ if (i >= lane->num_funcs)
++ return -EINVAL;
++
++ value = padctl_readl(padctl, lane->offset);
++ value &= ~(lane->mask << lane->shift);
++ value |= i << lane->shift;
++ padctl_writel(padctl, value, lane->offset);
++
++ return 0;
++}
++
++static const struct pinmux_ops tegra_xusb_padctl_pinmux_ops = {
++ .get_functions_count = tegra_xusb_padctl_get_functions_count,
++ .get_function_name = tegra_xusb_padctl_get_function_name,
++ .get_function_groups = tegra_xusb_padctl_get_function_groups,
++ .enable = tegra_xusb_padctl_pinmux_enable,
++};
++
++static int tegra_xusb_padctl_pinconf_group_get(struct pinctrl_dev *pinctrl,
++ unsigned int group,
++ unsigned long *config)
++{
++ struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl);
++ const struct tegra_xusb_padctl_lane *lane;
++ enum tegra_xusb_padctl_param param;
++ u32 value;
++
++ param = TEGRA_XUSB_PADCTL_UNPACK_PARAM(*config);
++ lane = &padctl->soc->lanes[group];
++
++ switch (param) {
++ case TEGRA_XUSB_PADCTL_IDDQ:
++ /* lanes with iddq == 0 don't support this parameter */
++ if (lane->iddq == 0)
++ return -EINVAL;
++
++ value = padctl_readl(padctl, lane->offset);
++
++ if (value & BIT(lane->iddq))
++ value = 0;
++ else
++ value = 1;
++
++ *config = TEGRA_XUSB_PADCTL_PACK(param, value);
++ break;
++
++ default:
++ dev_err(padctl->dev, "invalid configuration parameter: %04x\n",
++ param);
++ return -ENOTSUPP;
++ }
++
++ return 0;
++}
++
++static int tegra_xusb_padctl_pinconf_group_set(struct pinctrl_dev *pinctrl,
++ unsigned int group,
++ unsigned long *configs,
++ unsigned int num_configs)
++{
++ struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl);
++ const struct tegra_xusb_padctl_lane *lane;
++ enum tegra_xusb_padctl_param param;
++ unsigned long value;
++ unsigned int i;
++ u32 regval;
++
++ lane = &padctl->soc->lanes[group];
++
++ for (i = 0; i < num_configs; i++) {
++ param = TEGRA_XUSB_PADCTL_UNPACK_PARAM(configs[i]);
++ value = TEGRA_XUSB_PADCTL_UNPACK_VALUE(configs[i]);
++
++ switch (param) {
++ case TEGRA_XUSB_PADCTL_IDDQ:
++ /* lanes with iddq == 0 don't support this parameter */
++ if (lane->iddq == 0)
++ return -EINVAL;
++
++ regval = padctl_readl(padctl, lane->offset);
++
++ if (value)
++ regval &= ~BIT(lane->iddq);
++ else
++ regval |= BIT(lane->iddq);
++
++ padctl_writel(padctl, regval, lane->offset);
++ break;
++
++ default:
++ dev_err(padctl->dev,
++ "invalid configuration parameter: %04x\n",
++ param);
++ return -ENOTSUPP;
++ }
++ }
++
++ return 0;
++}
++
++#ifdef CONFIG_DEBUG_FS
++static const char *strip_prefix(const char *s)
++{
++ const char *comma = strchr(s, ',');
++ if (!comma)
++ return s;
++
++ return comma + 1;
++}
++
++static void
++tegra_xusb_padctl_pinconf_group_dbg_show(struct pinctrl_dev *pinctrl,
++ struct seq_file *s,
++ unsigned int group)
++{
++ unsigned int i;
++
++ for (i = 0; i < ARRAY_SIZE(properties); i++) {
++ unsigned long config, value;
++ int err;
++
++ config = TEGRA_XUSB_PADCTL_PACK(properties[i].param, 0);
++
++ err = tegra_xusb_padctl_pinconf_group_get(pinctrl, group,
++ &config);
++ if (err < 0)
++ continue;
++
++ value = TEGRA_XUSB_PADCTL_UNPACK_VALUE(config);
++
++ seq_printf(s, "\n\t%s=%lu\n", strip_prefix(properties[i].name),
++ value);
++ }
++}
++
++static void
++tegra_xusb_padctl_pinconf_config_dbg_show(struct pinctrl_dev *pinctrl,
++ struct seq_file *s,
++ unsigned long config)
++{
++ enum tegra_xusb_padctl_param param;
++ const char *name = "unknown";
++ unsigned long value;
++ unsigned int i;
++
++ param = TEGRA_XUSB_PADCTL_UNPACK_PARAM(config);
++ value = TEGRA_XUSB_PADCTL_UNPACK_VALUE(config);
++
++ for (i = 0; i < ARRAY_SIZE(properties); i++) {
++ if (properties[i].param == param) {
++ name = properties[i].name;
++ break;
++ }
++ }
++
++ seq_printf(s, "%s=%lu", strip_prefix(name), value);
++}
++#endif
++
++static const struct pinconf_ops tegra_xusb_padctl_pinconf_ops = {
++ .pin_config_group_get = tegra_xusb_padctl_pinconf_group_get,
++ .pin_config_group_set = tegra_xusb_padctl_pinconf_group_set,
++#ifdef CONFIG_DEBUG_FS
++ .pin_config_group_dbg_show = tegra_xusb_padctl_pinconf_group_dbg_show,
++ .pin_config_config_dbg_show = tegra_xusb_padctl_pinconf_config_dbg_show,
++#endif
++};
++
++static int tegra_xusb_padctl_enable(struct tegra_xusb_padctl *padctl)
++{
++ u32 value;
++
++ mutex_lock(&padctl->lock);
++
++ if (padctl->enable++ > 0)
++ goto out;
++
++ value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
++ value &= ~XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN;
++ padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
++
++ usleep_range(100, 200);
++
++ value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
++ value &= ~XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY;
++ padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
++
++ usleep_range(100, 200);
++
++ value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
++ value &= ~XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN;
++ padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
++
++out:
++ mutex_unlock(&padctl->lock);
++ return 0;
++}
++
++static int tegra_xusb_padctl_disable(struct tegra_xusb_padctl *padctl)
++{
++ u32 value;
++
++ mutex_lock(&padctl->lock);
++
++ if (WARN_ON(padctl->enable == 0))
++ goto out;
++
++ if (--padctl->enable > 0)
++ goto out;
++
++ value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
++ value |= XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN;
++ padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
++
++ usleep_range(100, 200);
++
++ value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
++ value |= XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY;
++ padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
++
++ usleep_range(100, 200);
++
++ value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
++ value |= XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN;
++ padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
++
++out:
++ mutex_unlock(&padctl->lock);
++ return 0;
++}
++
++static int tegra_xusb_phy_init(struct phy *phy)
++{
++ struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy);
++
++ return tegra_xusb_padctl_enable(padctl);
++}
++
++static int tegra_xusb_phy_exit(struct phy *phy)
++{
++ struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy);
++
++ return tegra_xusb_padctl_disable(padctl);
++}
++
++static int pcie_phy_power_on(struct phy *phy)
++{
++ struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy);
++ unsigned long timeout;
++ int err = -ETIMEDOUT;
++ u32 value;
++
++ value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
++ value &= ~XUSB_PADCTL_IOPHY_PLL_P0_CTL1_REFCLK_SEL_MASK;
++ padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
++
++ value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL2);
++ value |= XUSB_PADCTL_IOPHY_PLL_P0_CTL2_REFCLKBUF_EN |
++ XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_EN |
++ XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_SEL;
++ padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL2);
++
++ value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
++ value |= XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL_RST;
++ padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
++
++ timeout = jiffies + msecs_to_jiffies(50);
++
++ while (time_before(jiffies, timeout)) {
++ value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
++ if (value & XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL0_LOCKDET) {
++ err = 0;
++ break;
++ }
++
++ usleep_range(100, 200);
++ }
++
++ return err;
++}
++
++static int pcie_phy_power_off(struct phy *phy)
++{
++ struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy);
++ u32 value;
++
++ value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
++ value &= ~XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL_RST;
++ padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
++
++ return 0;
++}
++
++static const struct phy_ops pcie_phy_ops = {
++ .init = tegra_xusb_phy_init,
++ .exit = tegra_xusb_phy_exit,
++ .power_on = pcie_phy_power_on,
++ .power_off = pcie_phy_power_off,
++ .owner = THIS_MODULE,
++};
++
++static int sata_phy_power_on(struct phy *phy)
++{
++ struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy);
++ unsigned long timeout;
++ int err = -ETIMEDOUT;
++ u32 value;
++
++ value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1);
++ value &= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD;
++ value &= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ;
++ padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1);
++
++ value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
++ value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD;
++ value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_IDDQ;
++ padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
++
++ value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
++ value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_MODE;
++ padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
++
++ value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
++ value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_RST;
++ padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
++
++ timeout = jiffies + msecs_to_jiffies(50);
++
++ while (time_before(jiffies, timeout)) {
++ value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
++ if (value & XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_LOCKDET) {
++ err = 0;
++ break;
++ }
++
++ usleep_range(100, 200);
++ }
++
++ return err;
++}
++
++static int sata_phy_power_off(struct phy *phy)
++{
++ struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy);
++ u32 value;
++
++ value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
++ value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_RST;
++ padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
++
++ value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
++ value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_MODE;
++ padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
++
++ value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
++ value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD;
++ value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_IDDQ;
++ padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
++
++ value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1);
++ value |= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD;
++ value |= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ;
++ padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1);
++
++ return 0;
++}
++
++static const struct phy_ops sata_phy_ops = {
++ .init = tegra_xusb_phy_init,
++ .exit = tegra_xusb_phy_exit,
++ .power_on = sata_phy_power_on,
++ .power_off = sata_phy_power_off,
++ .owner = THIS_MODULE,
++};
++
++static struct phy *tegra_xusb_padctl_xlate(struct device *dev,
++ struct of_phandle_args *args)
++{
++ struct tegra_xusb_padctl *padctl = dev_get_drvdata(dev);
++ unsigned int index = args->args[0];
++
++ if (args->args_count <= 0)
++ return ERR_PTR(-EINVAL);
++
++ if (index > ARRAY_SIZE(padctl->phys))
++ return ERR_PTR(-EINVAL);
++
++ return padctl->phys[index];
++}
++
++#define PIN_OTG_0 0
++#define PIN_OTG_1 1
++#define PIN_OTG_2 2
++#define PIN_ULPI_0 3
++#define PIN_HSIC_0 4
++#define PIN_HSIC_1 5
++#define PIN_PCIE_0 6
++#define PIN_PCIE_1 7
++#define PIN_PCIE_2 8
++#define PIN_PCIE_3 9
++#define PIN_PCIE_4 10
++#define PIN_SATA_0 11
++
++static const struct pinctrl_pin_desc tegra124_pins[] = {
++ PINCTRL_PIN(PIN_OTG_0, "otg-0"),
++ PINCTRL_PIN(PIN_OTG_1, "otg-1"),
++ PINCTRL_PIN(PIN_OTG_2, "otg-2"),
++ PINCTRL_PIN(PIN_ULPI_0, "ulpi-0"),
++ PINCTRL_PIN(PIN_HSIC_0, "hsic-0"),
++ PINCTRL_PIN(PIN_HSIC_1, "hsic-1"),
++ PINCTRL_PIN(PIN_PCIE_0, "pcie-0"),
++ PINCTRL_PIN(PIN_PCIE_1, "pcie-1"),
++ PINCTRL_PIN(PIN_PCIE_2, "pcie-2"),
++ PINCTRL_PIN(PIN_PCIE_3, "pcie-3"),
++ PINCTRL_PIN(PIN_PCIE_4, "pcie-4"),
++ PINCTRL_PIN(PIN_SATA_0, "sata-0"),
++};
++
++static const char * const tegra124_snps_groups[] = {
++ "otg-0",
++ "otg-1",
++ "otg-2",
++ "ulpi-0",
++ "hsic-0",
++ "hsic-1",
++};
++
++static const char * const tegra124_xusb_groups[] = {
++ "otg-0",
++ "otg-1",
++ "otg-2",
++ "ulpi-0",
++ "hsic-0",
++ "hsic-1",
++};
++
++static const char * const tegra124_uart_groups[] = {
++ "otg-0",
++ "otg-1",
++ "otg-2",
++};
++
++static const char * const tegra124_pcie_groups[] = {
++ "pcie-0",
++ "pcie-1",
++ "pcie-2",
++ "pcie-3",
++ "pcie-4",
++ "sata-0",
++};
++
++static const char * const tegra124_usb3_groups[] = {
++ "pcie-0",
++ "pcie-1",
++ "pcie-2",
++ "pcie-3",
++ "pcie-4",
++ "sata-0",
++};
++
++static const char * const tegra124_sata_groups[] = {
++ "pcie-0",
++ "pcie-1",
++ "pcie-2",
++ "pcie-3",
++ "pcie-4",
++ "sata-0",
++};
++
++static const char * const tegra124_rsvd_groups[] = {
++ "otg-0",
++ "otg-1",
++ "otg-2",
++ "pcie-0",
++ "pcie-1",
++ "pcie-2",
++ "pcie-3",
++ "pcie-4",
++ "sata-0",
++};
++
++#define TEGRA124_FUNCTION(_name) \
++ { \
++ .name = #_name, \
++ .num_groups = ARRAY_SIZE(tegra124_##_name##_groups), \
++ .groups = tegra124_##_name##_groups, \
++ }
++
++static struct tegra_xusb_padctl_function tegra124_functions[] = {
++ TEGRA124_FUNCTION(snps),
++ TEGRA124_FUNCTION(xusb),
++ TEGRA124_FUNCTION(uart),
++ TEGRA124_FUNCTION(pcie),
++ TEGRA124_FUNCTION(usb3),
++ TEGRA124_FUNCTION(sata),
++ TEGRA124_FUNCTION(rsvd),
++};
++
++enum tegra124_function {
++ TEGRA124_FUNC_SNPS,
++ TEGRA124_FUNC_XUSB,
++ TEGRA124_FUNC_UART,
++ TEGRA124_FUNC_PCIE,
++ TEGRA124_FUNC_USB3,
++ TEGRA124_FUNC_SATA,
++ TEGRA124_FUNC_RSVD,
++};
++
++static const unsigned int tegra124_otg_functions[] = {
++ TEGRA124_FUNC_SNPS,
++ TEGRA124_FUNC_XUSB,
++ TEGRA124_FUNC_UART,
++ TEGRA124_FUNC_RSVD,
++};
++
++static const unsigned int tegra124_usb_functions[] = {
++ TEGRA124_FUNC_SNPS,
++ TEGRA124_FUNC_XUSB,
++};
++
++static const unsigned int tegra124_pci_functions[] = {
++ TEGRA124_FUNC_PCIE,
++ TEGRA124_FUNC_USB3,
++ TEGRA124_FUNC_SATA,
++ TEGRA124_FUNC_RSVD,
++};
++
++#define TEGRA124_LANE(_name, _offset, _shift, _mask, _iddq, _funcs) \
++ { \
++ .name = _name, \
++ .offset = _offset, \
++ .shift = _shift, \
++ .mask = _mask, \
++ .iddq = _iddq, \
++ .num_funcs = ARRAY_SIZE(tegra124_##_funcs##_functions), \
++ .funcs = tegra124_##_funcs##_functions, \
++ }
++
++static const struct tegra_xusb_padctl_lane tegra124_lanes[] = {
++ TEGRA124_LANE("otg-0", 0x004, 0, 0x3, 0, otg),
++ TEGRA124_LANE("otg-1", 0x004, 2, 0x3, 0, otg),
++ TEGRA124_LANE("otg-2", 0x004, 4, 0x3, 0, otg),
++ TEGRA124_LANE("ulpi-0", 0x004, 12, 0x1, 0, usb),
++ TEGRA124_LANE("hsic-0", 0x004, 14, 0x1, 0, usb),
++ TEGRA124_LANE("hsic-1", 0x004, 15, 0x1, 0, usb),
++ TEGRA124_LANE("pcie-0", 0x134, 16, 0x3, 1, pci),
++ TEGRA124_LANE("pcie-1", 0x134, 18, 0x3, 2, pci),
++ TEGRA124_LANE("pcie-2", 0x134, 20, 0x3, 3, pci),
++ TEGRA124_LANE("pcie-3", 0x134, 22, 0x3, 4, pci),
++ TEGRA124_LANE("pcie-4", 0x134, 24, 0x3, 5, pci),
++ TEGRA124_LANE("sata-0", 0x134, 26, 0x3, 6, pci),
++};
++
++static const struct tegra_xusb_padctl_soc tegra124_soc = {
++ .num_pins = ARRAY_SIZE(tegra124_pins),
++ .pins = tegra124_pins,
++ .num_functions = ARRAY_SIZE(tegra124_functions),
++ .functions = tegra124_functions,
++ .num_lanes = ARRAY_SIZE(tegra124_lanes),
++ .lanes = tegra124_lanes,
++};
++
++static const struct of_device_id tegra_xusb_padctl_of_match[] = {
++ { .compatible = "nvidia,tegra124-xusb-padctl", .data = &tegra124_soc },
++ { }
++};
++MODULE_DEVICE_TABLE(of, tegra_xusb_padctl_of_match);
++
++static int tegra_xusb_padctl_probe(struct platform_device *pdev)
++{
++ struct tegra_xusb_padctl *padctl;
++ const struct of_device_id *match;
++ struct resource *res;
++ struct phy *phy;
++ int err;
++
++ padctl = devm_kzalloc(&pdev->dev, sizeof(*padctl), GFP_KERNEL);
++ if (!padctl)
++ return -ENOMEM;
++
++ platform_set_drvdata(pdev, padctl);
++ mutex_init(&padctl->lock);
++ padctl->dev = &pdev->dev;
++
++ match = of_match_node(tegra_xusb_padctl_of_match, pdev->dev.of_node);
++ padctl->soc = match->data;
++
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ padctl->regs = devm_ioremap_resource(&pdev->dev, res);
++ if (IS_ERR(padctl->regs))
++ return PTR_ERR(padctl->regs);
++
++ padctl->rst = devm_reset_control_get(&pdev->dev, NULL);
++ if (IS_ERR(padctl->rst))
++ return PTR_ERR(padctl->rst);
++
++ err = reset_control_deassert(padctl->rst);
++ if (err < 0)
++ return err;
++
++ memset(&padctl->desc, 0, sizeof(padctl->desc));
++ padctl->desc.name = dev_name(padctl->dev);
++ padctl->desc.pctlops = &tegra_xusb_padctl_pinctrl_ops;
++ padctl->desc.pmxops = &tegra_xusb_padctl_pinmux_ops;
++ padctl->desc.confops = &tegra_xusb_padctl_pinconf_ops;
++ padctl->desc.owner = THIS_MODULE;
++
++ padctl->pinctrl = pinctrl_register(&padctl->desc, &pdev->dev, padctl);
++ if (!padctl->pinctrl) {
++ dev_err(&pdev->dev, "failed to register pincontrol\n");
++ err = -ENODEV;
++ goto reset;
++ }
++
++ phy = devm_phy_create(&pdev->dev, &pcie_phy_ops, NULL);
++ if (IS_ERR(phy)) {
++ err = PTR_ERR(phy);
++ goto unregister;
++ }
++
++ padctl->phys[TEGRA_XUSB_PADCTL_PCIE] = phy;
++ phy_set_drvdata(phy, padctl);
++
++ phy = devm_phy_create(&pdev->dev, &sata_phy_ops, NULL);
++ if (IS_ERR(phy)) {
++ err = PTR_ERR(phy);
++ goto unregister;
++ }
++
++ padctl->phys[TEGRA_XUSB_PADCTL_SATA] = phy;
++ phy_set_drvdata(phy, padctl);
++
++ padctl->provider = devm_of_phy_provider_register(&pdev->dev,
++ tegra_xusb_padctl_xlate);
++ if (err < 0) {
++ dev_err(&pdev->dev, "failed to register PHYs: %d\n", err);
++ goto unregister;
++ }
++
++ return 0;
++
++unregister:
++ pinctrl_unregister(padctl->pinctrl);
++reset:
++ reset_control_assert(padctl->rst);
++ return err;
++}
++
++static int tegra_xusb_padctl_remove(struct platform_device *pdev)
++{
++ struct tegra_xusb_padctl *padctl = platform_get_drvdata(pdev);
++ int err;
++
++ pinctrl_unregister(padctl->pinctrl);
++
++ err = reset_control_assert(padctl->rst);
++ if (err < 0)
++ dev_err(&pdev->dev, "failed to assert reset: %d\n", err);
++
++ return err;
++}
++
++static struct platform_driver tegra_xusb_padctl_driver = {
++ .driver = {
++ .name = "tegra-xusb-padctl",
++ .of_match_table = tegra_xusb_padctl_of_match,
++ },
++ .probe = tegra_xusb_padctl_probe,
++ .remove = tegra_xusb_padctl_remove,
++};
++module_platform_driver(tegra_xusb_padctl_driver);
++
++MODULE_AUTHOR("Thierry Reding <treding@nvidia.com>");
++MODULE_DESCRIPTION("Tegra 124 XUSB Pad Control driver");
++MODULE_LICENSE("GPL v2");
+diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile
+index 0f7c447..3b1b95d 100644
+--- a/drivers/soc/Makefile
++++ b/drivers/soc/Makefile
+@@ -3,3 +3,4 @@
+ #
+
+ obj-$(CONFIG_ARCH_QCOM) += qcom/
++obj-$(CONFIG_ARCH_TEGRA) += tegra/
+diff --git a/drivers/soc/tegra/Makefile b/drivers/soc/tegra/Makefile
+new file mode 100644
+index 0000000..236600f
+--- /dev/null
++++ b/drivers/soc/tegra/Makefile
+@@ -0,0 +1 @@
++obj-$(CONFIG_ARCH_TEGRA) += fuse/
+diff --git a/drivers/soc/tegra/fuse/Makefile b/drivers/soc/tegra/fuse/Makefile
new file mode 100644
index 0000000..3af357d
--- /dev/null
-+++ b/drivers/misc/fuse/tegra/Makefile
++++ b/drivers/soc/tegra/fuse/Makefile
@@ -0,0 +1,8 @@
+obj-y += fuse-tegra.o
+obj-y += fuse-tegra30.o
@@ -3692,12 +7735,12 @@ index 0000000..3af357d
+obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += speedo-tegra30.o
+obj-$(CONFIG_ARCH_TEGRA_114_SOC) += speedo-tegra114.o
+obj-$(CONFIG_ARCH_TEGRA_124_SOC) += speedo-tegra124.o
-diff --git a/drivers/misc/fuse/tegra/fuse-tegra.c b/drivers/misc/fuse/tegra/fuse-tegra.c
+diff --git a/drivers/soc/tegra/fuse/fuse-tegra.c b/drivers/soc/tegra/fuse/fuse-tegra.c
new file mode 100644
-index 0000000..934073e
+index 0000000..7cf83dd
--- /dev/null
-+++ b/drivers/misc/fuse/tegra/fuse-tegra.c
-@@ -0,0 +1,154 @@
++++ b/drivers/soc/tegra/fuse/fuse-tegra.c
+@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2013-2014, NVIDIA CORPORATION. All rights reserved.
+ *
@@ -3798,15 +7841,16 @@ index 0000000..934073e
+ writel(reg, base + 0x14);
+}
+
-+int tegra_fuse_readl(u32 offset, u32 *val)
++int tegra_fuse_readl(unsigned long offset, u32 *value)
+{
+ if (!fuse_readl)
+ return -EPROBE_DEFER;
+
-+ *val = fuse_readl(offset);
++ *value = fuse_readl(offset);
+
+ return 0;
+}
++EXPORT_SYMBOL(tegra_fuse_readl);
+
+int tegra_fuse_create_sysfs(struct device *dev, int size,
+ u32 (*readl)(const unsigned int offset))
@@ -3823,7 +7867,7 @@ index 0000000..934073e
+ return device_create_bin_file(dev, &fuse_bin_attr);
+}
+
-+void __init tegra_init_fuse(void)
++static int __init tegra_init_fuse(void)
+{
+ struct device_node *np;
+ void __iomem *car_base;
@@ -3837,10 +7881,10 @@ index 0000000..934073e
+ iounmap(car_base);
+ } else {
+ pr_err("Could not enable fuse clk. ioremap tegra car failed.\n");
-+ return;
++ return -ENXIO;
+ }
+
-+ if (tegra_chip_id == TEGRA20)
++ if (tegra_get_chip_id() == TEGRA20)
+ tegra20_init_fuse_early();
+ else
+ tegra30_init_fuse_early();
@@ -3851,12 +7895,15 @@ index 0000000..934073e
+ tegra_sku_info.core_process_id);
+ pr_debug("Tegra CPU Speedo ID %d, Soc Speedo ID %d\n",
+ tegra_sku_info.cpu_speedo_id, tegra_sku_info.soc_speedo_id);
++
++ return 0;
+}
-diff --git a/drivers/misc/fuse/tegra/fuse-tegra20.c b/drivers/misc/fuse/tegra/fuse-tegra20.c
++early_initcall(tegra_init_fuse);
+diff --git a/drivers/soc/tegra/fuse/fuse-tegra20.c b/drivers/soc/tegra/fuse/fuse-tegra20.c
new file mode 100644
index 0000000..c3dcf11
--- /dev/null
-+++ b/drivers/misc/fuse/tegra/fuse-tegra20.c
++++ b/drivers/soc/tegra/fuse/fuse-tegra20.c
@@ -0,0 +1,214 @@
+/*
+ * Copyright (c) 2013-2014, NVIDIA CORPORATION. All rights reserved.
@@ -4072,11 +8119,11 @@ index 0000000..c3dcf11
+
+ iounmap(fuse_base);
+}
-diff --git a/drivers/misc/fuse/tegra/fuse-tegra30.c b/drivers/misc/fuse/tegra/fuse-tegra30.c
+diff --git a/drivers/soc/tegra/fuse/fuse-tegra30.c b/drivers/soc/tegra/fuse/fuse-tegra30.c
new file mode 100644
-index 0000000..8aef5d0
+index 0000000..a4cfb11
--- /dev/null
-+++ b/drivers/misc/fuse/tegra/fuse-tegra30.c
++++ b/drivers/soc/tegra/fuse/fuse-tegra30.c
@@ -0,0 +1,223 @@
+/*
+ * Copyright (c) 2013-2014, NVIDIA CORPORATION. All rights reserved.
@@ -4254,7 +8301,7 @@ index 0000000..8aef5d0
+
+static void __init legacy_fuse_init(void)
+{
-+ switch (tegra_chip_id) {
++ switch (tegra_get_chip_id()) {
+ case TEGRA30:
+ fuse_info = &tegra30_info;
+ break;
@@ -4293,7 +8340,7 @@ index 0000000..8aef5d0
+
+ if (!fuse_base) {
+ pr_warn("fuse DT node missing and unknown chip id: 0x%02x\n",
-+ tegra_chip_id);
++ tegra_get_chip_id());
+ return;
+ }
+
@@ -4301,11 +8348,11 @@ index 0000000..8aef5d0
+ speedo_tbl[fuse_info->speedo_idx](&tegra_sku_info);
+ tegra30_fuse_add_randomness();
+}
-diff --git a/drivers/misc/fuse/tegra/fuse.h b/drivers/misc/fuse/tegra/fuse.h
+diff --git a/drivers/soc/tegra/fuse/fuse.h b/drivers/soc/tegra/fuse/fuse.h
new file mode 100644
index 0000000..3a398bf3
--- /dev/null
-+++ b/drivers/misc/fuse/tegra/fuse.h
++++ b/drivers/soc/tegra/fuse/fuse.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2010 Google, Inc.
@@ -4378,11 +8425,11 @@ index 0000000..3a398bf3
+#endif
+
+#endif
-diff --git a/drivers/misc/fuse/tegra/speedo-tegra114.c b/drivers/misc/fuse/tegra/speedo-tegra114.c
+diff --git a/drivers/soc/tegra/fuse/speedo-tegra114.c b/drivers/soc/tegra/fuse/speedo-tegra114.c
new file mode 100644
index 0000000..98d6cde
--- /dev/null
-+++ b/drivers/misc/fuse/tegra/speedo-tegra114.c
++++ b/drivers/soc/tegra/fuse/speedo-tegra114.c
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2013-2014, NVIDIA CORPORATION. All rights reserved.
@@ -4493,11 +8540,11 @@ index 0000000..98d6cde
+ break;
+ sku_info->core_process_id = i;
+}
-diff --git a/drivers/misc/fuse/tegra/speedo-tegra124.c b/drivers/misc/fuse/tegra/speedo-tegra124.c
+diff --git a/drivers/soc/tegra/fuse/speedo-tegra124.c b/drivers/soc/tegra/fuse/speedo-tegra124.c
new file mode 100644
index 0000000..a15dd53
--- /dev/null
-+++ b/drivers/misc/fuse/tegra/speedo-tegra124.c
++++ b/drivers/soc/tegra/fuse/speedo-tegra124.c
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2013-2014, NVIDIA CORPORATION. All rights reserved.
@@ -4666,11 +8713,11 @@ index 0000000..a15dd53
+ pr_debug("Tegra GPU Speedo ID=%d, Speedo Value=%d\n",
+ sku_info->gpu_speedo_id, sku_info->gpu_speedo_value);
+}
-diff --git a/drivers/misc/fuse/tegra/speedo-tegra20.c b/drivers/misc/fuse/tegra/speedo-tegra20.c
+diff --git a/drivers/soc/tegra/fuse/speedo-tegra20.c b/drivers/soc/tegra/fuse/speedo-tegra20.c
new file mode 100644
index 0000000..c951fa4
--- /dev/null
-+++ b/drivers/misc/fuse/tegra/speedo-tegra20.c
++++ b/drivers/soc/tegra/fuse/speedo-tegra20.c
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2012-2014, NVIDIA CORPORATION. All rights reserved.
@@ -4781,11 +8828,11 @@ index 0000000..c951fa4
+ }
+ sku_info->core_process_id = i;
+}
-diff --git a/drivers/misc/fuse/tegra/speedo-tegra30.c b/drivers/misc/fuse/tegra/speedo-tegra30.c
+diff --git a/drivers/soc/tegra/fuse/speedo-tegra30.c b/drivers/soc/tegra/fuse/speedo-tegra30.c
new file mode 100644
index 0000000..1a85ad8
--- /dev/null
-+++ b/drivers/misc/fuse/tegra/speedo-tegra30.c
++++ b/drivers/soc/tegra/fuse/speedo-tegra30.c
@@ -0,0 +1,287 @@
+/*
+ * Copyright (c) 2012-2014, NVIDIA CORPORATION. All rights reserved.
@@ -5074,12 +9121,12 @@ index 0000000..1a85ad8
+ sku_info->soc_speedo_id = 1;
+ }
+}
-diff --git a/drivers/misc/fuse/tegra/tegra-apbmisc.c b/drivers/misc/fuse/tegra/tegra-apbmisc.c
+diff --git a/drivers/soc/tegra/fuse/tegra-apbmisc.c b/drivers/soc/tegra/fuse/tegra-apbmisc.c
new file mode 100644
-index 0000000..43e5bd5
+index 0000000..30126e6
--- /dev/null
-+++ b/drivers/misc/fuse/tegra/tegra-apbmisc.c
-@@ -0,0 +1,110 @@
++++ b/drivers/soc/tegra/fuse/tegra-apbmisc.c
+@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved.
+ *
@@ -5109,8 +9156,6 @@ index 0000000..43e5bd5
+#define APBMISC_SIZE 0x64
+#define FUSE_SKU_INFO 0x10
+
-+int tegra_chip_id;
-+
+static void __iomem *apbmisc_base;
+static void __iomem *strapping_base;
+
@@ -5119,6 +9164,16 @@ index 0000000..43e5bd5
+ return readl_relaxed(apbmisc_base + 4);
+}
+
++u8 tegra_get_chip_id(void)
++{
++ if (!apbmisc_base) {
++ WARN(1, "Tegra Chip ID not yet available\n");
++ return 0;
++ }
++
++ return (tegra_read_chipid() >> 8) & 0xff;
++}
++
+u32 tegra_read_straps(void)
+{
+ if (strapping_base)
@@ -5134,10 +9189,11 @@ index 0000000..43e5bd5
+
+void __init tegra_init_revision(void)
+{
-+ u32 id, minor_rev;
++ u32 id, chip_id, minor_rev;
+ int rev;
+
+ id = tegra_read_chipid();
++ chip_id = (id >> 8) & 0xff;
+ minor_rev = (id >> 16) & 0xf;
+
+ switch (minor_rev) {
@@ -5148,9 +9204,8 @@ index 0000000..43e5bd5
+ rev = TEGRA_REVISION_A02;
+ break;
+ case 3:
-+ if (tegra_chip_id == TEGRA20 &&
-+ (tegra20_spare_fuse_early(18) ||
-+ tegra20_spare_fuse_early(19)))
++ if (chip_id == TEGRA20 && (tegra20_spare_fuse_early(18) ||
++ tegra20_spare_fuse_early(19)))
+ rev = TEGRA_REVISION_A03p;
+ else
+ rev = TEGRA_REVISION_A03;
@@ -5164,7 +9219,7 @@ index 0000000..43e5bd5
+
+ tegra_sku_info.revision = rev;
+
-+ if (tegra_chip_id == TEGRA20)
++ if (chip_id == TEGRA20)
+ tegra_sku_info.sku_id = tegra20_fuse_early(FUSE_SKU_INFO);
+ else
+ tegra_sku_info.sku_id = tegra30_fuse_readl(FUSE_SKU_INFO);
@@ -5173,7 +9228,6 @@ index 0000000..43e5bd5
+void __init tegra_init_apbmisc(void)
+{
+ struct device_node *np;
-+ u32 id;
+
+ np = of_find_matching_node(NULL, apbmisc_match);
+ apbmisc_base = of_iomap(np, 0);
@@ -5183,256 +9237,28 @@ index 0000000..43e5bd5
+ apbmisc_base = ioremap(APBMISC_BASE, APBMISC_SIZE);
+ }
+
-+ id = tegra_read_chipid();
-+ tegra_chip_id = (id >> 8) & 0xff;
-+
+ strapping_base = of_iomap(np, 1);
+ if (!strapping_base)
+ pr_err("ioremap tegra strapping_base failed\n");
+}
-diff --git a/drivers/pci/host/pci-tegra.c b/drivers/pci/host/pci-tegra.c
-index 083cf37..7df5aaf 100644
---- a/drivers/pci/host/pci-tegra.c
-+++ b/drivers/pci/host/pci-tegra.c
-@@ -233,7 +233,6 @@ struct tegra_pcie_soc_data {
- bool has_pex_clkreq_en;
- bool has_pex_bias_ctrl;
- bool has_intr_prsnt_sense;
-- bool has_avdd_supply;
- bool has_cml_clk;
- };
-
-@@ -272,9 +271,8 @@ struct tegra_pcie {
- unsigned int num_ports;
- u32 xbar_config;
-
-- struct regulator *pex_clk_supply;
-- struct regulator *vdd_supply;
-- struct regulator *avdd_supply;
-+ struct regulator_bulk_data *supplies;
-+ unsigned int num_supplies;
-
- const struct tegra_pcie_soc_data *soc_data;
- };
-@@ -894,7 +892,6 @@ static int tegra_pcie_enable_controller(struct tegra_pcie *pcie)
-
- static void tegra_pcie_power_off(struct tegra_pcie *pcie)
- {
-- const struct tegra_pcie_soc_data *soc = pcie->soc_data;
- int err;
-
- /* TODO: disable and unprepare clocks? */
-@@ -905,23 +902,9 @@ static void tegra_pcie_power_off(struct tegra_pcie *pcie)
-
- tegra_powergate_power_off(TEGRA_POWERGATE_PCIE);
-
-- if (soc->has_avdd_supply) {
-- err = regulator_disable(pcie->avdd_supply);
-- if (err < 0)
-- dev_warn(pcie->dev,
-- "failed to disable AVDD regulator: %d\n",
-- err);
-- }
--
-- err = regulator_disable(pcie->pex_clk_supply);
-+ err = regulator_bulk_disable(pcie->num_supplies, pcie->supplies);
- if (err < 0)
-- dev_warn(pcie->dev, "failed to disable pex-clk regulator: %d\n",
-- err);
--
-- err = regulator_disable(pcie->vdd_supply);
-- if (err < 0)
-- dev_warn(pcie->dev, "failed to disable VDD regulator: %d\n",
-- err);
-+ dev_warn(pcie->dev, "failed to disable regulators: %d\n", err);
- }
-
- static int tegra_pcie_power_on(struct tegra_pcie *pcie)
-@@ -936,28 +919,9 @@ static int tegra_pcie_power_on(struct tegra_pcie *pcie)
- tegra_powergate_power_off(TEGRA_POWERGATE_PCIE);
-
- /* enable regulators */
-- err = regulator_enable(pcie->vdd_supply);
-- if (err < 0) {
-- dev_err(pcie->dev, "failed to enable VDD regulator: %d\n", err);
-- return err;
-- }
--
-- err = regulator_enable(pcie->pex_clk_supply);
-- if (err < 0) {
-- dev_err(pcie->dev, "failed to enable pex-clk regulator: %d\n",
-- err);
-- return err;
-- }
--
-- if (soc->has_avdd_supply) {
-- err = regulator_enable(pcie->avdd_supply);
-- if (err < 0) {
-- dev_err(pcie->dev,
-- "failed to enable AVDD regulator: %d\n",
-- err);
-- return err;
-- }
-- }
-+ err = regulator_bulk_enable(pcie->num_supplies, pcie->supplies);
-+ if (err < 0)
-+ dev_err(pcie->dev, "failed to enable regulators: %d\n", err);
-
- err = tegra_powergate_sequence_power_up(TEGRA_POWERGATE_PCIE,
- pcie->pex_clk,
-@@ -1394,14 +1358,83 @@ static int tegra_pcie_get_xbar_config(struct tegra_pcie *pcie, u32 lanes,
- return -EINVAL;
- }
-
-+/*
-+ * Obtains the list of regulators required for a particular generation of the
-+ * IP block.
-+ *
-+ * This would've been nice to do simply by providing static tables for use
-+ * with the regulator_bulk_*() API, but unfortunately Tegra30 is a bit quirky
-+ * in that it has two pairs or AVDD_PEX and VDD_PEX supplies (PEXA and PEXB)
-+ * and either seems to be optional depending on which ports are being used.
-+ */
-+static int tegra_pcie_get_regulators(struct tegra_pcie *pcie, u32 lane_mask)
-+{
-+ struct device_node *np = pcie->dev->of_node;
-+ unsigned int i = 0;
-+
-+ if (of_device_is_compatible(np, "nvidia,tegra30-pcie")) {
-+ bool need_pexa = false, need_pexb = false;
-+
-+ /* VDD_PEXA and AVDD_PEXA supply lanes 0 to 3 */
-+ if (lane_mask & 0x0f)
-+ need_pexa = true;
-+
-+ /* VDD_PEXB and AVDD_PEXB supply lanes 4 to 5 */
-+ if (lane_mask & 0x30)
-+ need_pexb = true;
-+
-+ pcie->num_supplies = 4 + (need_pexa ? 2 : 0) +
-+ (need_pexb ? 2 : 0);
-+
-+ pcie->supplies = devm_kcalloc(pcie->dev, pcie->num_supplies,
-+ sizeof(*pcie->supplies),
-+ GFP_KERNEL);
-+ if (!pcie->supplies)
-+ return -ENOMEM;
-+
-+ pcie->supplies[i++].supply = "avdd-pex-pll";
-+ pcie->supplies[i++].supply = "hvdd-pex";
-+ pcie->supplies[i++].supply = "vddio-pex-ctl";
-+ pcie->supplies[i++].supply = "avdd-plle";
-+
-+ if (need_pexa) {
-+ pcie->supplies[i++].supply = "avdd-pexa";
-+ pcie->supplies[i++].supply = "vdd-pexa";
-+ }
-+
-+ if (need_pexb) {
-+ pcie->supplies[i++].supply = "avdd-pexb";
-+ pcie->supplies[i++].supply = "vdd-pexb";
-+ }
-+ } else if (of_device_is_compatible(np, "nvidia,tegra20-pcie")) {
-+ pcie->num_supplies = 5;
-+
-+ pcie->supplies = devm_kcalloc(pcie->dev, pcie->num_supplies,
-+ sizeof(*pcie->supplies),
-+ GFP_KERNEL);
-+ if (!pcie->supplies)
-+ return -ENOMEM;
-+
-+ pcie->supplies[0].supply = "avdd-pex";
-+ pcie->supplies[1].supply = "vdd-pex";
-+ pcie->supplies[2].supply = "avdd-pex-pll";
-+ pcie->supplies[3].supply = "avdd-plle";
-+ pcie->supplies[4].supply = "vddio-pex-clk";
-+ }
-+
-+ return devm_regulator_bulk_get(pcie->dev, pcie->num_supplies,
-+ pcie->supplies);
-+}
-+
- static int tegra_pcie_parse_dt(struct tegra_pcie *pcie)
- {
- const struct tegra_pcie_soc_data *soc = pcie->soc_data;
- struct device_node *np = pcie->dev->of_node, *port;
- struct of_pci_range_parser parser;
- struct of_pci_range range;
-+ u32 lanes = 0, mask = 0;
-+ unsigned int lane = 0;
- struct resource res;
-- u32 lanes = 0;
- int err;
-
- if (of_pci_range_parser_init(&parser, np)) {
-@@ -1409,20 +1442,6 @@ static int tegra_pcie_parse_dt(struct tegra_pcie *pcie)
- return -EINVAL;
- }
-
-- pcie->vdd_supply = devm_regulator_get(pcie->dev, "vdd");
-- if (IS_ERR(pcie->vdd_supply))
-- return PTR_ERR(pcie->vdd_supply);
--
-- pcie->pex_clk_supply = devm_regulator_get(pcie->dev, "pex-clk");
-- if (IS_ERR(pcie->pex_clk_supply))
-- return PTR_ERR(pcie->pex_clk_supply);
--
-- if (soc->has_avdd_supply) {
-- pcie->avdd_supply = devm_regulator_get(pcie->dev, "avdd");
-- if (IS_ERR(pcie->avdd_supply))
-- return PTR_ERR(pcie->avdd_supply);
-- }
--
- for_each_of_pci_range(&parser, &range) {
- of_pci_range_to_resource(&range, np, &res);
-
-@@ -1490,8 +1509,13 @@ static int tegra_pcie_parse_dt(struct tegra_pcie *pcie)
-
- lanes |= value << (index << 3);
-
-- if (!of_device_is_available(port))
-+ if (!of_device_is_available(port)) {
-+ lane += value;
- continue;
-+ }
+diff --git a/include/dt-bindings/pinctrl/pinctrl-tegra-xusb.h b/include/dt-bindings/pinctrl/pinctrl-tegra-xusb.h
+new file mode 100644
+index 0000000..914d56d
+--- /dev/null
++++ b/include/dt-bindings/pinctrl/pinctrl-tegra-xusb.h
+@@ -0,0 +1,7 @@
++#ifndef _DT_BINDINGS_PINCTRL_TEGRA_XUSB_H
++#define _DT_BINDINGS_PINCTRL_TEGRA_XUSB_H 1
+
-+ mask |= ((1 << value) - 1) << lane;
-+ lane += value;
-
- rp = devm_kzalloc(pcie->dev, sizeof(*rp), GFP_KERNEL);
- if (!rp)
-@@ -1522,6 +1546,10 @@ static int tegra_pcie_parse_dt(struct tegra_pcie *pcie)
- return err;
- }
-
-+ err = tegra_pcie_get_regulators(pcie, mask);
-+ if (err < 0)
-+ return err;
++#define TEGRA_XUSB_PADCTL_PCIE 0
++#define TEGRA_XUSB_PADCTL_SATA 1
+
- return 0;
- }
-
-@@ -1615,7 +1643,6 @@ static const struct tegra_pcie_soc_data tegra20_pcie_data = {
- .has_pex_clkreq_en = false,
- .has_pex_bias_ctrl = false,
- .has_intr_prsnt_sense = false,
-- .has_avdd_supply = false,
- .has_cml_clk = false,
- };
-
-@@ -1627,7 +1654,6 @@ static const struct tegra_pcie_soc_data tegra30_pcie_data = {
- .has_pex_clkreq_en = true,
- .has_pex_bias_ctrl = true,
- .has_intr_prsnt_sense = true,
-- .has_avdd_supply = true,
- .has_cml_clk = true,
- };
-
++#endif /* _DT_BINDINGS_PINCTRL_TEGRA_XUSB_H */
diff --git a/include/linux/tegra-soc.h b/include/linux/tegra-soc.h
-index 95f611d..fcf65ec 100644
+index 95f611d..70a6124 100644
--- a/include/linux/tegra-soc.h
+++ b/include/linux/tegra-soc.h
-@@ -17,6 +17,48 @@
+@@ -17,6 +17,95 @@
#ifndef __LINUX_TEGRA_SOC_H_
#define __LINUX_TEGRA_SOC_H_
@@ -5446,6 +9272,11 @@ index 95f611d..fcf65ec 100644
+
+#ifndef __ASSEMBLY__
+
++#include <linux/reboot.h>
++
+ u32 tegra_read_chipid(void);
++u8 tegra_get_chip_id(void);
++
+enum tegra_revision {
+ TEGRA_REVISION_UNKNOWN = 0,
+ TEGRA_REVISION_A01,
@@ -5471,13 +9302,55 @@ index 95f611d..fcf65ec 100644
+};
+
+u32 tegra_read_straps(void);
- u32 tegra_read_chipid(void);
-+void tegra_init_fuse(void);
-+int tegra_fuse_readl(u32 offset, u32 *val);
++u32 tegra_read_chipid(void);
++int tegra_fuse_readl(unsigned long offset, u32 *value);
+
-+extern int tegra_chip_id;
+extern struct tegra_sku_info tegra_sku_info;
+
++/*
++ * PMC
++ */
++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_set_suspend_mode(enum tegra_suspend_mode mode);
++void tegra_pmc_enter_suspend_mode(enum tegra_suspend_mode mode);
++
++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_restart(enum reboot_mode mode, const char *cmd);
++#endif
++
++/*
++ * PM
++ */
++#ifdef CONFIG_PM_SLEEP
++enum tegra_suspend_mode
++tegra_pm_validate_suspend_mode(enum tegra_suspend_mode mode);
++
++/* low-level resume entry point */
++void tegra_resume(void);
++#else
++static inline enum tegra_suspend_mode
++tegra_pm_validate_suspend_mode(enum tegra_suspend_mode mode)
++{
++ return TEGRA_SUSPEND_NONE;
++}
++
++static inline void tegra_resume(void)
++{
++}
++#endif /* CONFIG_PM_SLEEP */
++
+#endif /* __ASSEMBLY__ */
#endif /* __LINUX_TEGRA_SOC_H_ */