summaryrefslogtreecommitdiffstats
path: root/tegra-bp-next-3.17.patch
diff options
context:
space:
mode:
authorNicolas Chauvet <kwizart@gmail.com>2014-06-26 17:13:37 +0200
committerNicolas Chauvet <kwizart@gmail.com>2014-07-07 16:21:19 +0200
commita5fca2b83cd4dcf2d94c717aaa17897d85516be3 (patch)
tree8193bd815ccf8f233fe419a15a0ef24fe7e3d99b /tegra-bp-next-3.17.patch
parent93b95b9dfa283ccd1062a997d550b260bbb4a51d (diff)
downloadkernel-a5fca2b83cd4dcf2d94c717aaa17897d85516be3.tar.gz
kernel-a5fca2b83cd4dcf2d94c717aaa17897d85516be3.tar.xz
kernel-a5fca2b83cd4dcf2d94c717aaa17897d85516be3.zip
Add tegra-bp-next-3.17.patch
Diffstat (limited to 'tegra-bp-next-3.17.patch')
-rw-r--r--tegra-bp-next-3.17.patch5510
1 files changed, 5510 insertions, 0 deletions
diff --git a/tegra-bp-next-3.17.patch b/tegra-bp-next-3.17.patch
new file mode 100644
index 00000000..946f8707
--- /dev/null
+++ b/tegra-bp-next-3.17.patch
@@ -0,0 +1,5510 @@
+diff --git a/Documentation/ABI/testing/sysfs-driver-tegra-fuse b/Documentation/ABI/testing/sysfs-driver-tegra-fuse
+new file mode 100644
+index 0000000..69f5af6
+--- /dev/null
++++ b/Documentation/ABI/testing/sysfs-driver-tegra-fuse
+@@ -0,0 +1,11 @@
++What: /sys/devices/*/<our-device>/fuse
++Date: February 2014
++Contact: Peter De Schrijver <pdeschrijver@nvidia.com>
++Description: read-only access to the efuses on Tegra20, Tegra30, Tegra114
++ and Tegra124 SoC's from NVIDIA. The efuses contain write once
++ data programmed at the factory. The data is layed out in 32bit
++ words in LSB first format. Each bit represents a single value
++ as decoded from the fuse registers. Bits order/assignment
++ exactly matches the HW registers, including any unused bits.
++Users: any user space application which wants to read the efuses on
++ Tegra SoC's
+diff --git a/Documentation/devicetree/bindings/arm/tegra.txt b/Documentation/devicetree/bindings/arm/tegra.txt
+index 558ed4b..73278c6 100644
+--- a/Documentation/devicetree/bindings/arm/tegra.txt
++++ b/Documentation/devicetree/bindings/arm/tegra.txt
+@@ -30,6 +30,8 @@ board-specific compatible values:
+ nvidia,seaboard
+ nvidia,ventana
+ nvidia,whistler
++ toradex,apalis_t30
++ toradex,apalis_t30-eval
+ toradex,colibri_t20-512
+ toradex,iris
+
+diff --git a/Documentation/devicetree/bindings/fuse/nvidia,tegra20-fuse.txt b/Documentation/devicetree/bindings/fuse/nvidia,tegra20-fuse.txt
+new file mode 100644
+index 0000000..d8c98c7
+--- /dev/null
++++ b/Documentation/devicetree/bindings/fuse/nvidia,tegra20-fuse.txt
+@@ -0,0 +1,40 @@
++NVIDIA Tegra20/Tegra30/Tegr114/Tegra124 fuse block.
++
++Required properties:
++- compatible : should be:
++ "nvidia,tegra20-efuse"
++ "nvidia,tegra30-efuse"
++ "nvidia,tegra114-efuse"
++ "nvidia,tegra124-efuse"
++ Details:
++ nvidia,tegra20-efuse: Tegra20 requires using APB DMA to read the fuse data
++ due to a hardware bug. Tegra20 also lacks certain information which is
++ available in later generations such as fab code, lot code, wafer id,..
++ nvidia,tegra30-efuse, nvidia,tegra114-efuse and nvidia,tegra124-efuse:
++ The differences between these SoCs are the size of the efuse array,
++ the location of the spare (OEM programmable) bits and the location of
++ the speedo data.
++- reg: Should contain 1 entry: the entry gives the physical address and length
++ of the fuse registers.
++- 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:
++ - fuse
++- resets: Must contain an entry for each entry in reset-names.
++ See ../reset/reset.txt for details.
++- reset-names: Must include the following entries:
++ - fuse
++
++Example:
++
++ fuse@7000f800 {
++ compatible = "nvidia,tegra20-efuse";
++ reg = <0x7000F800 0x400>,
++ <0x70000000 0x400>;
++ clocks = <&tegra_car TEGRA20_CLK_FUSE>;
++ clock-names = "fuse";
++ resets = <&tegra_car 39>;
++ reset-names = "fuse";
++ };
++
++
+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
+--- /dev/null
++++ b/Documentation/devicetree/bindings/misc/nvidia,tegra20-apbmisc.txt
+@@ -0,0 +1,13 @@
++NVIDIA Tegra20/Tegra30/Tegr114/Tegra124 apbmisc block
++
++Required properties:
++- compatible : should be:
++ "nvidia,tegra20-apbmisc"
++ "nvidia,tegra30-apbmisc"
++ "nvidia,tegra114-apbmisc"
++ "nvidia,tegra124-apbmisc"
++- reg: Should contain 2 entries: the first entry gives the physical address
++ and length of the registers which contain revision and debug features.
++ The second entry gives the physical address and length of the
++ registers indicating the strapping options.
++
+diff --git a/Documentation/devicetree/bindings/pci/nvidia,tegra20-pcie.txt b/Documentation/devicetree/bindings/pci/nvidia,tegra20-pcie.txt
+index c300391..0823362 100644
+--- a/Documentation/devicetree/bindings/pci/nvidia,tegra20-pcie.txt
++++ b/Documentation/devicetree/bindings/pci/nvidia,tegra20-pcie.txt
+@@ -14,9 +14,6 @@ Required properties:
+ - interrupt-names: Must include the following entries:
+ "intr": The Tegra interrupt that is asserted for controller interrupts
+ "msi": The Tegra interrupt that is asserted when an MSI is received
+-- pex-clk-supply: Supply voltage for internal reference clock
+-- vdd-supply: Power supply for controller (1.05V)
+-- avdd-supply: Power supply for controller (1.05V) (not required for Tegra20)
+ - bus-range: Range of bus numbers associated with this controller
+ - #address-cells: Address representation for root ports (must be 3)
+ - cell 0 specifies the bus and device numbers of the root port:
+@@ -60,6 +57,33 @@ Required properties:
+ - afi
+ - pcie_x
+
++Power supplies for Tegra20:
++- avdd-pex-supply: Power supply for analog PCIe logic. Must supply 1.05 V.
++- vdd-pex-supply: Power supply for digital PCIe I/O. Must supply 1.05 V.
++- avdd-pex-pll-supply: Power supply for dedicated (internal) PCIe PLL. Must
++ supply 1.05 V.
++- avdd-plle-supply: Power supply for PLLE, which is shared with SATA. Must
++ supply 1.05 V.
++- vddio-pex-clk-supply: Power supply for PCIe clock. Must supply 3.3 V.
++
++Power supplies for Tegra30:
++- Required:
++ - avdd-pex-pll-supply: Power supply for dedicated (internal) PCIe PLL. Must
++ supply 1.05 V.
++ - avdd-plle-supply: Power supply for PLLE, which is shared with SATA. Must
++ supply 1.05 V.
++ - vddio-pex-ctl-supply: Power supply for PCIe control I/O partition. Must
++ supply 1.8 V.
++ - hvdd-pex-supply: High-voltage supply for PCIe I/O and PCIe output clocks.
++ Must supply 3.3 V.
++- Optional:
++ - If lanes 0 to 3 are used:
++ - avdd-pexa-supply: Power supply for analog PCIe logic. Must supply 1.05 V.
++ - vdd-pexa-supply: Power supply for digital PCIe I/O. Must supply 1.05 V.
++ - If lanes 4 or 5 are used:
++ - avdd-pexb-supply: Power supply for analog PCIe logic. Must supply 1.05 V.
++ - vdd-pexb-supply: Power supply for digital PCIe I/O. Must supply 1.05 V.
++
+ Root ports are defined as subnodes of the PCIe controller node.
+
+ Required properties:
+diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
+index 5986ff6..906fb67 100644
+--- a/arch/arm/boot/dts/Makefile
++++ b/arch/arm/boot/dts/Makefile
+@@ -390,6 +390,7 @@ dtb-$(CONFIG_ARCH_TEGRA) += tegra20-harmony.dtb \
+ tegra20-trimslice.dtb \
+ tegra20-ventana.dtb \
+ tegra20-whistler.dtb \
++ tegra30-apalis-eval.dtb \
+ tegra30-beaver.dtb \
+ tegra30-cardhu-a02.dtb \
+ tegra30-cardhu-a04.dtb \
+diff --git a/arch/arm/boot/dts/cros-ec-keyboard.dtsi b/arch/arm/boot/dts/cros-ec-keyboard.dtsi
+new file mode 100644
+index 0000000..9c7fb0a
+--- /dev/null
++++ b/arch/arm/boot/dts/cros-ec-keyboard.dtsi
+@@ -0,0 +1,105 @@
++/*
++ * Keyboard dts fragment for devices that use cros-ec-keyboard
++ *
++ * Copyright (c) 2014 Google, Inc
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++*/
++
++#include <dt-bindings/input/input.h>
++
++&cros_ec {
++ keyboard-controller {
++ compatible = "google,cros-ec-keyb";
++ keypad,num-rows = <8>;
++ keypad,num-columns = <13>;
++ google,needs-ghost-filter;
++
++ linux,keymap = <
++ MATRIX_KEY(0x00, 0x01, KEY_LEFTMETA)
++ MATRIX_KEY(0x00, 0x02, KEY_F1)
++ MATRIX_KEY(0x00, 0x03, KEY_B)
++ MATRIX_KEY(0x00, 0x04, KEY_F10)
++ MATRIX_KEY(0x00, 0x06, KEY_N)
++ MATRIX_KEY(0x00, 0x08, KEY_EQUAL)
++ MATRIX_KEY(0x00, 0x0a, KEY_RIGHTALT)
++
++ MATRIX_KEY(0x01, 0x01, KEY_ESC)
++ MATRIX_KEY(0x01, 0x02, KEY_F4)
++ MATRIX_KEY(0x01, 0x03, KEY_G)
++ MATRIX_KEY(0x01, 0x04, KEY_F7)
++ MATRIX_KEY(0x01, 0x06, KEY_H)
++ MATRIX_KEY(0x01, 0x08, KEY_APOSTROPHE)
++ MATRIX_KEY(0x01, 0x09, KEY_F9)
++ MATRIX_KEY(0x01, 0x0b, KEY_BACKSPACE)
++
++ MATRIX_KEY(0x02, 0x00, KEY_LEFTCTRL)
++ MATRIX_KEY(0x02, 0x01, KEY_TAB)
++ MATRIX_KEY(0x02, 0x02, KEY_F3)
++ MATRIX_KEY(0x02, 0x03, KEY_T)
++ MATRIX_KEY(0x02, 0x04, KEY_F6)
++ MATRIX_KEY(0x02, 0x05, KEY_RIGHTBRACE)
++ MATRIX_KEY(0x02, 0x06, KEY_Y)
++ MATRIX_KEY(0x02, 0x07, KEY_102ND)
++ MATRIX_KEY(0x02, 0x08, KEY_LEFTBRACE)
++ MATRIX_KEY(0x02, 0x09, KEY_F8)
++
++ MATRIX_KEY(0x03, 0x01, KEY_GRAVE)
++ MATRIX_KEY(0x03, 0x02, KEY_F2)
++ MATRIX_KEY(0x03, 0x03, KEY_5)
++ MATRIX_KEY(0x03, 0x04, KEY_F5)
++ MATRIX_KEY(0x03, 0x06, KEY_6)
++ MATRIX_KEY(0x03, 0x08, KEY_MINUS)
++ MATRIX_KEY(0x03, 0x0b, KEY_BACKSLASH)
++
++ MATRIX_KEY(0x04, 0x00, KEY_RIGHTCTRL)
++ MATRIX_KEY(0x04, 0x01, KEY_A)
++ MATRIX_KEY(0x04, 0x02, KEY_D)
++ MATRIX_KEY(0x04, 0x03, KEY_F)
++ MATRIX_KEY(0x04, 0x04, KEY_S)
++ MATRIX_KEY(0x04, 0x05, KEY_K)
++ MATRIX_KEY(0x04, 0x06, KEY_J)
++ MATRIX_KEY(0x04, 0x08, KEY_SEMICOLON)
++ MATRIX_KEY(0x04, 0x09, KEY_L)
++ MATRIX_KEY(0x04, 0x0a, KEY_BACKSLASH)
++ MATRIX_KEY(0x04, 0x0b, KEY_ENTER)
++
++ MATRIX_KEY(0x05, 0x01, KEY_Z)
++ MATRIX_KEY(0x05, 0x02, KEY_C)
++ MATRIX_KEY(0x05, 0x03, KEY_V)
++ MATRIX_KEY(0x05, 0x04, KEY_X)
++ MATRIX_KEY(0x05, 0x05, KEY_COMMA)
++ MATRIX_KEY(0x05, 0x06, KEY_M)
++ MATRIX_KEY(0x05, 0x07, KEY_LEFTSHIFT)
++ MATRIX_KEY(0x05, 0x08, KEY_SLASH)
++ MATRIX_KEY(0x05, 0x09, KEY_DOT)
++ MATRIX_KEY(0x05, 0x0b, KEY_SPACE)
++
++ MATRIX_KEY(0x06, 0x01, KEY_1)
++ MATRIX_KEY(0x06, 0x02, KEY_3)
++ MATRIX_KEY(0x06, 0x03, KEY_4)
++ MATRIX_KEY(0x06, 0x04, KEY_2)
++ MATRIX_KEY(0x06, 0x05, KEY_8)
++ MATRIX_KEY(0x06, 0x06, KEY_7)
++ MATRIX_KEY(0x06, 0x08, KEY_0)
++ MATRIX_KEY(0x06, 0x09, KEY_9)
++ MATRIX_KEY(0x06, 0x0a, KEY_LEFTALT)
++ MATRIX_KEY(0x06, 0x0b, KEY_DOWN)
++ MATRIX_KEY(0x06, 0x0c, KEY_RIGHT)
++
++ MATRIX_KEY(0x07, 0x01, KEY_Q)
++ MATRIX_KEY(0x07, 0x02, KEY_E)
++ MATRIX_KEY(0x07, 0x03, KEY_R)
++ MATRIX_KEY(0x07, 0x04, KEY_W)
++ MATRIX_KEY(0x07, 0x05, KEY_I)
++ MATRIX_KEY(0x07, 0x06, KEY_U)
++ MATRIX_KEY(0x07, 0x07, KEY_RIGHTSHIFT)
++ MATRIX_KEY(0x07, 0x08, KEY_P)
++ MATRIX_KEY(0x07, 0x09, KEY_O)
++ MATRIX_KEY(0x07, 0x0b, KEY_UP)
++ MATRIX_KEY(0x07, 0x0c, KEY_LEFT)
++ >;
++ };
++};
+diff --git a/arch/arm/boot/dts/exynos5250-snow.dts b/arch/arm/boot/dts/exynos5250-snow.dts
+index 079fdf9..7bd2df1 100644
+--- a/arch/arm/boot/dts/exynos5250-snow.dts
++++ b/arch/arm/boot/dts/exynos5250-snow.dts
+@@ -137,7 +137,7 @@
+ sbs,poll-retry-count = <1>;
+ };
+
+- ec: embedded-controller {
++ cros_ec: embedded-controller {
+ compatible = "google,cros-ec-i2c";
+ reg = <0x1e>;
+ interrupts = <6 0>;
+@@ -145,95 +145,6 @@
+ pinctrl-names = "default";
+ pinctrl-0 = <&ec_irq>;
+ wakeup-source;
+-
+- keyboard-controller {
+- compatible = "google,cros-ec-keyb";
+- keypad,num-rows = <8>;
+- keypad,num-columns = <13>;
+- google,needs-ghost-filter;
+- linux,keymap = <0x0001007d /* L_META */
+- 0x0002003b /* F1 */
+- 0x00030030 /* B */
+- 0x00040044 /* F10 */
+- 0x00060031 /* N */
+- 0x0008000d /* = */
+- 0x000a0064 /* R_ALT */
+-
+- 0x01010001 /* ESC */
+- 0x0102003e /* F4 */
+- 0x01030022 /* G */
+- 0x01040041 /* F7 */
+- 0x01060023 /* H */
+- 0x01080028 /* ' */
+- 0x01090043 /* F9 */
+- 0x010b000e /* BKSPACE */
+-
+- 0x0200001d /* L_CTRL */
+- 0x0201000f /* TAB */
+- 0x0202003d /* F3 */
+- 0x02030014 /* T */
+- 0x02040040 /* F6 */
+- 0x0205001b /* ] */
+- 0x02060015 /* Y */
+- 0x02070056 /* 102ND */
+- 0x0208001a /* [ */
+- 0x02090042 /* F8 */
+-
+- 0x03010029 /* GRAVE */
+- 0x0302003c /* F2 */
+- 0x03030006 /* 5 */
+- 0x0304003f /* F5 */
+- 0x03060007 /* 6 */
+- 0x0308000c /* - */
+- 0x030b002b /* \ */
+-
+- 0x04000061 /* R_CTRL */
+- 0x0401001e /* A */
+- 0x04020020 /* D */
+- 0x04030021 /* F */
+- 0x0404001f /* S */
+- 0x04050025 /* K */
+- 0x04060024 /* J */
+- 0x04080027 /* ; */
+- 0x04090026 /* L */
+- 0x040a002b /* \ */
+- 0x040b001c /* ENTER */
+-
+- 0x0501002c /* Z */
+- 0x0502002e /* C */
+- 0x0503002f /* V */
+- 0x0504002d /* X */
+- 0x05050033 /* , */
+- 0x05060032 /* M */
+- 0x0507002a /* L_SHIFT */
+- 0x05080035 /* / */
+- 0x05090034 /* . */
+- 0x050B0039 /* SPACE */
+-
+- 0x06010002 /* 1 */
+- 0x06020004 /* 3 */
+- 0x06030005 /* 4 */
+- 0x06040003 /* 2 */
+- 0x06050009 /* 8 */
+- 0x06060008 /* 7 */
+- 0x0608000b /* 0 */
+- 0x0609000a /* 9 */
+- 0x060a0038 /* L_ALT */
+- 0x060b006c /* DOWN */
+- 0x060c006a /* RIGHT */
+-
+- 0x07010010 /* Q */
+- 0x07020012 /* E */
+- 0x07030013 /* R */
+- 0x07040011 /* W */
+- 0x07050017 /* I */
+- 0x07060016 /* U */
+- 0x07070036 /* R_SHIFT */
+- 0x07080019 /* P */
+- 0x07090018 /* O */
+- 0x070b0067 /* UP */
+- 0x070c0069>; /* LEFT */
+- };
+ };
+
+ power-regulator {
+@@ -431,3 +342,5 @@
+ };
+ };
+ };
++
++#include "cros-ec-keyboard.dtsi"
+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
++++ b/arch/arm/boot/dts/tegra114.dtsi
+@@ -220,6 +220,12 @@
+ interrupt-controller;
+ };
+
++ apbmisc@70000800 {
++ compatible = "nvidia,tegra114-apbmisc", "nvidia,tegra20-apbmisc";
++ reg = <0x70000800 0x64 /* Chip revision */
++ 0x70000008 0x04>; /* Strapping options */
++ };
++
+ pinmux: pinmux@70000868 {
+ compatible = "nvidia,tegra114-pinmux";
+ reg = <0x70000868 0x148 /* Pad control registers */
+@@ -485,6 +491,15 @@
+ clock-names = "pclk", "clk32k_in";
+ };
+
++ fuse@7000f800 {
++ compatible = "nvidia,tegra114-efuse";
++ reg = <0x7000f800 0x400>;
++ clocks = <&tegra_car TEGRA114_CLK_FUSE>;
++ clock-names = "fuse";
++ resets = <&tegra_car 39>;
++ reset-names = "fuse";
++ };
++
+ iommu@70019010 {
+ 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
+--- a/arch/arm/boot/dts/tegra124-jetson-tk1.dts
++++ b/arch/arm/boot/dts/tegra124-jetson-tk1.dts
+@@ -1633,6 +1633,7 @@
+ sdhci@0,700b0600 {
+ status = "okay";
+ bus-width = <8>;
++ non-removable;
+ };
+
+ 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
+--- a/arch/arm/boot/dts/tegra124-venice2.dts
++++ b/arch/arm/boot/dts/tegra124-venice2.dts
+@@ -816,7 +816,7 @@
+ spi@0,7000d400 {
+ status = "okay";
+
+- cros-ec@0 {
++ cros_ec: cros-ec@0 {
+ compatible = "google,cros-ec-spi";
+ spi-max-frequency = <4000000>;
+ interrupt-parent = <&gpio>;
+@@ -825,96 +825,30 @@
+
+ google,cros-ec-spi-msg-delay = <2000>;
+
+- cros-ec-keyb {
+- compatible = "google,cros-ec-keyb";
+- keypad,num-rows = <8>;
+- keypad,num-columns = <13>;
+- google,needs-ghost-filter;
+-
+- linux,keymap = <
+- MATRIX_KEY(0x00, 0x01, KEY_LEFTMETA)
+- MATRIX_KEY(0x00, 0x02, KEY_F1)
+- MATRIX_KEY(0x00, 0x03, KEY_B)
+- MATRIX_KEY(0x00, 0x04, KEY_F10)
+- MATRIX_KEY(0x00, 0x06, KEY_N)
+- MATRIX_KEY(0x00, 0x08, KEY_EQUAL)
+- MATRIX_KEY(0x00, 0x0a, KEY_RIGHTALT)
+-
+- MATRIX_KEY(0x01, 0x01, KEY_ESC)
+- MATRIX_KEY(0x01, 0x02, KEY_F4)
+- MATRIX_KEY(0x01, 0x03, KEY_G)
+- MATRIX_KEY(0x01, 0x04, KEY_F7)
+- MATRIX_KEY(0x01, 0x06, KEY_H)
+- MATRIX_KEY(0x01, 0x08, KEY_APOSTROPHE)
+- MATRIX_KEY(0x01, 0x09, KEY_F9)
+- MATRIX_KEY(0x01, 0x0b, KEY_BACKSPACE)
+-
+- MATRIX_KEY(0x02, 0x00, KEY_LEFTCTRL)
+- MATRIX_KEY(0x02, 0x01, KEY_TAB)
+- MATRIX_KEY(0x02, 0x02, KEY_F3)
+- MATRIX_KEY(0x02, 0x03, KEY_T)
+- MATRIX_KEY(0x02, 0x04, KEY_F6)
+- MATRIX_KEY(0x02, 0x05, KEY_RIGHTBRACE)
+- MATRIX_KEY(0x02, 0x06, KEY_Y)
+- MATRIX_KEY(0x02, 0x07, KEY_102ND)
+- MATRIX_KEY(0x02, 0x08, KEY_LEFTBRACE)
+- MATRIX_KEY(0x02, 0x09, KEY_F8)
+-
+- MATRIX_KEY(0x03, 0x01, KEY_GRAVE)
+- MATRIX_KEY(0x03, 0x02, KEY_F2)
+- MATRIX_KEY(0x03, 0x03, KEY_5)
+- MATRIX_KEY(0x03, 0x04, KEY_F5)
+- MATRIX_KEY(0x03, 0x06, KEY_6)
+- MATRIX_KEY(0x03, 0x08, KEY_MINUS)
+- MATRIX_KEY(0x03, 0x0b, KEY_BACKSLASH)
+-
+- MATRIX_KEY(0x04, 0x00, KEY_RIGHTCTRL)
+- MATRIX_KEY(0x04, 0x01, KEY_A)
+- MATRIX_KEY(0x04, 0x02, KEY_D)
+- MATRIX_KEY(0x04, 0x03, KEY_F)
+- MATRIX_KEY(0x04, 0x04, KEY_S)
+- MATRIX_KEY(0x04, 0x05, KEY_K)
+- MATRIX_KEY(0x04, 0x06, KEY_J)
+- MATRIX_KEY(0x04, 0x08, KEY_SEMICOLON)
+- MATRIX_KEY(0x04, 0x09, KEY_L)
+- MATRIX_KEY(0x04, 0x0a, KEY_BACKSLASH)
+- MATRIX_KEY(0x04, 0x0b, KEY_ENTER)
+-
+- MATRIX_KEY(0x05, 0x01, KEY_Z)
+- MATRIX_KEY(0x05, 0x02, KEY_C)
+- MATRIX_KEY(0x05, 0x03, KEY_V)
+- MATRIX_KEY(0x05, 0x04, KEY_X)
+- MATRIX_KEY(0x05, 0x05, KEY_COMMA)
+- MATRIX_KEY(0x05, 0x06, KEY_M)
+- MATRIX_KEY(0x05, 0x07, KEY_LEFTSHIFT)
+- MATRIX_KEY(0x05, 0x08, KEY_SLASH)
+- MATRIX_KEY(0x05, 0x09, KEY_DOT)
+- MATRIX_KEY(0x05, 0x0b, KEY_SPACE)
+-
+- MATRIX_KEY(0x06, 0x01, KEY_1)
+- MATRIX_KEY(0x06, 0x02, KEY_3)
+- MATRIX_KEY(0x06, 0x03, KEY_4)
+- MATRIX_KEY(0x06, 0x04, KEY_2)
+- MATRIX_KEY(0x06, 0x05, KEY_8)
+- MATRIX_KEY(0x06, 0x06, KEY_7)
+- MATRIX_KEY(0x06, 0x08, KEY_0)
+- MATRIX_KEY(0x06, 0x09, KEY_9)
+- MATRIX_KEY(0x06, 0x0a, KEY_LEFTALT)
+- MATRIX_KEY(0x06, 0x0b, KEY_DOWN)
+- MATRIX_KEY(0x06, 0x0c, KEY_RIGHT)
+-
+- MATRIX_KEY(0x07, 0x01, KEY_Q)
+- MATRIX_KEY(0x07, 0x02, KEY_E)
+- MATRIX_KEY(0x07, 0x03, KEY_R)
+- MATRIX_KEY(0x07, 0x04, KEY_W)
+- MATRIX_KEY(0x07, 0x05, KEY_I)
+- MATRIX_KEY(0x07, 0x06, KEY_U)
+- MATRIX_KEY(0x07, 0x07, KEY_RIGHTSHIFT)
+- MATRIX_KEY(0x07, 0x08, KEY_P)
+- MATRIX_KEY(0x07, 0x09, KEY_O)
+- MATRIX_KEY(0x07, 0x0b, KEY_UP)
+- MATRIX_KEY(0x07, 0x0c, KEY_LEFT)
+- >;
++ i2c-tunnel {
++ compatible = "google,cros-ec-i2c-tunnel";
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ google,remote-bus = <0>;
++
++ charger: bq24735@9 {
++ compatible = "ti,bq24735";
++ reg = <0x9>;
++ interrupt-parent = <&gpio>;
++ interrupts = <TEGRA_GPIO(J, 0)
++ GPIO_ACTIVE_HIGH>;
++ ti,ac-detect-gpios = <&gpio
++ TEGRA_GPIO(J, 0)
++ GPIO_ACTIVE_HIGH>;
++ };
++
++ battery: sbs-battery@b {
++ compatible = "sbs,sbs-battery";
++ reg = <0xb>;
++ sbs,i2c-retry-count = <2>;
++ sbs,poll-retry-count = <1>;
++ };
+ };
+ };
+ };
+@@ -940,6 +874,10 @@
+ nvidia,sys-clock-req-active-high;
+ };
+
++ hda@0,70030000 {
++ status = "okay";
++ };
++
+ sdhci@0,700b0400 {
+ cd-gpios = <&gpio TEGRA_GPIO(V, 2) GPIO_ACTIVE_HIGH>;
+ power-gpios = <&gpio TEGRA_GPIO(R, 0) GPIO_ACTIVE_HIGH>;
+@@ -1205,3 +1143,5 @@
+ clock-names = "pll_a", "pll_a_out0", "mclk";
+ };
+ };
++
++#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
+--- a/arch/arm/boot/dts/tegra124.dtsi
++++ b/arch/arm/boot/dts/tegra124.dtsi
+@@ -179,6 +179,12 @@
+ #dma-cells = <1>;
+ };
+
++ apbmisc@0,70000800 {
++ compatible = "nvidia,tegra124-apbmisc", "nvidia,tegra20-apbmisc";
++ reg = <0x0 0x70000800 0x0 0x64>, /* Chip revision */
++ <0x0 0x7000E864 0x0 0x04>; /* Strapping options */
++ };
++
+ pinmux: pinmux@0,70000868 {
+ compatible = "nvidia,tegra124-pinmux";
+ reg = <0x0 0x70000868 0x0 0x164>, /* Pad control registers */
+@@ -449,6 +455,30 @@
+ clock-names = "pclk", "clk32k_in";
+ };
+
++ fuse@0,7000f800 {
++ compatible = "nvidia,tegra124-efuse";
++ reg = <0x0 0x7000f800 0x0 0x400>;
++ clocks = <&tegra_car TEGRA124_CLK_FUSE>;
++ clock-names = "fuse";
++ resets = <&tegra_car 39>;
++ reset-names = "fuse";
++ };
++
++ hda@0,70030000 {
++ compatible = "nvidia,tegra124-hda", "nvidia,tegra30-hda";
++ reg = <0x0 0x70030000 0x0 0x10000>;
++ interrupts = <GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH>;
++ clocks = <&tegra_car TEGRA124_CLK_HDA>,
++ <&tegra_car TEGRA124_CLK_HDA2HDMI>,
++ <&tegra_car TEGRA124_CLK_HDA2CODEC_2X>;
++ clock-names = "hda", "hda2hdmi", "hdacodec_2x";
++ resets = <&tegra_car 125>, /* hda */
++ <&tegra_car 128>, /* hda2hdmi */
++ <&tegra_car 111>; /* hda2codec_2x */
++ reset-names = "hda", "hda2hdmi", "hdacodec_2x";
++ status = "disabled";
++ };
++
+ sdhci@0,700b0000 {
+ compatible = "nvidia,tegra124-sdhci";
+ reg = <0x0 0x700b0000 0x0 0x200>;
+diff --git a/arch/arm/boot/dts/tegra20-harmony.dts b/arch/arm/boot/dts/tegra20-harmony.dts
+index f45aad6..a37279a 100644
+--- a/arch/arm/boot/dts/tegra20-harmony.dts
++++ b/arch/arm/boot/dts/tegra20-harmony.dts
+@@ -562,10 +562,14 @@
+ };
+
+ pcie-controller@80003000 {
+- pex-clk-supply = <&pci_clk_reg>;
+- vdd-supply = <&pci_vdd_reg>;
+ status = "okay";
+
++ avdd-pex-supply = <&pci_vdd_reg>;
++ vdd-pex-supply = <&pci_vdd_reg>;
++ avdd-pex-pll-supply = <&pci_vdd_reg>;
++ avdd-plle-supply = <&pci_vdd_reg>;
++ vddio-pex-clk-supply = <&pci_clk_reg>;
++
+ pci@1,0 {
+ status = "okay";
+ };
+diff --git a/arch/arm/boot/dts/tegra20-medcom-wide.dts b/arch/arm/boot/dts/tegra20-medcom-wide.dts
+index 6d3a4cb..1b7c56b 100644
+--- a/arch/arm/boot/dts/tegra20-medcom-wide.dts
++++ b/arch/arm/boot/dts/tegra20-medcom-wide.dts
+@@ -10,6 +10,15 @@
+ status = "okay";
+ };
+
++ host1x@50000000 {
++ dc@54200000 {
++ rgb {
++ status = "okay";
++ nvidia,panel = <&panel>;
++ };
++ };
++ };
++
+ i2c@7000c000 {
+ wm8903: wm8903@1a {
+ compatible = "wlf,wm8903";
+@@ -30,7 +39,7 @@
+ };
+ };
+
+- backlight {
++ backlight: backlight {
+ compatible = "pwm-backlight";
+ pwms = <&pwm 0 5000000>;
+
+@@ -38,6 +47,15 @@
+ default-brightness-level = <6>;
+ };
+
++ panel: panel {
++ compatible = "innolux,n156bge-l21", "simple-panel";
++
++ power-supply = <&vdd_1v8_reg>, <&vdd_3v3_reg>;
++ enable-gpios = <&gpio TEGRA_GPIO(B, 2) GPIO_ACTIVE_HIGH>;
++
++ backlight = <&backlight>;
++ };
++
+ sound {
+ compatible = "ad,tegra-audio-wm8903-medcom-wide",
+ "nvidia,tegra-audio-wm8903";
+@@ -64,4 +82,45 @@
+ <&tegra_car TEGRA20_CLK_CDEV1>;
+ clock-names = "pll_a", "pll_a_out0", "mclk";
+ };
++
++ regulators {
++ vcc_24v_reg: regulator@100 {
++ compatible = "regulator-fixed";
++ reg = <100>;
++ regulator-name = "vcc_24v";
++ regulator-min-microvolt = <24000000>;
++ regulator-max-microvolt = <24000000>;
++ regulator-always-on;
++ };
++
++ vdd_5v0_reg: regulator@101 {
++ compatible = "regulator-fixed";
++ reg = <101>;
++ regulator-name = "vdd_5v0";
++ vin-supply = <&vcc_24v_reg>;
++ regulator-min-microvolt = <5000000>;
++ regulator-max-microvolt = <5000000>;
++ regulator-always-on;
++ };
++
++ vdd_3v3_reg: regulator@102 {
++ compatible = "regulator-fixed";
++ reg = <102>;
++ regulator-name = "vdd_3v3";
++ vin-supply = <&vcc_24v_reg>;
++ regulator-min-microvolt = <3300000>;
++ regulator-max-microvolt = <3300000>;
++ regulator-always-on;
++ };
++
++ vdd_1v8_reg: regulator@103 {
++ compatible = "regulator-fixed";
++ reg = <103>;
++ regulator-name = "vdd_1v8";
++ vin-supply = <&vdd_3v3_reg>;
++ regulator-min-microvolt = <1800000>;
++ regulator-max-microvolt = <1800000>;
++ regulator-always-on;
++ };
++ };
+ };
+diff --git a/arch/arm/boot/dts/tegra20-plutux.dts b/arch/arm/boot/dts/tegra20-plutux.dts
+index 29051a2..a10b415 100644
+--- a/arch/arm/boot/dts/tegra20-plutux.dts
++++ b/arch/arm/boot/dts/tegra20-plutux.dts
+@@ -58,4 +58,45 @@
+ <&tegra_car TEGRA20_CLK_CDEV1>;
+ clock-names = "pll_a", "pll_a_out0", "mclk";
+ };
++
++ regulators {
++ vcc_24v_reg: regulator@100 {
++ compatible = "regulator-fixed";
++ reg = <100>;
++ regulator-name = "vcc_24v";
++ regulator-min-microvolt = <24000000>;
++ regulator-max-microvolt = <24000000>;
++ regulator-always-on;
++ };
++
++ vdd_5v0_reg: regulator@101 {
++ compatible = "regulator-fixed";
++ reg = <101>;
++ regulator-name = "vdd_5v0";
++ vin-supply = <&vcc_24v_reg>;
++ regulator-min-microvolt = <5000000>;
++ regulator-max-microvolt = <5000000>;
++ regulator-always-on;
++ };
++
++ vdd_3v3_reg: regulator@102 {
++ compatible = "regulator-fixed";
++ reg = <102>;
++ regulator-name = "vdd_3v3";
++ vin-supply = <&vcc_24v_reg>;
++ regulator-min-microvolt = <3300000>;
++ regulator-max-microvolt = <3300000>;
++ regulator-always-on;
++ };
++
++ vdd_1v8_reg: regulator@103 {
++ compatible = "regulator-fixed";
++ reg = <103>;
++ regulator-name = "vdd_1v8";
++ vin-supply = <&vdd_3v3_reg>;
++ regulator-min-microvolt = <1800000>;
++ regulator-max-microvolt = <1800000>;
++ regulator-always-on;
++ };
++ };
+ };
+diff --git a/arch/arm/boot/dts/tegra20-tamonten.dtsi b/arch/arm/boot/dts/tegra20-tamonten.dtsi
+index a1b0d96..80e7d38 100644
+--- a/arch/arm/boot/dts/tegra20-tamonten.dtsi
++++ b/arch/arm/boot/dts/tegra20-tamonten.dtsi
+@@ -334,6 +334,7 @@
+ #gpio-cells = <2>;
+ gpio-controller;
+
++ /* vdd_5v0_reg must be provided by the base board */
+ sys-supply = <&vdd_5v0_reg>;
+ vin-sm0-supply = <&sys_reg>;
+ vin-sm1-supply = <&sys_reg>;
+@@ -473,8 +474,11 @@
+ };
+
+ pcie-controller@80003000 {
+- pex-clk-supply = <&pci_clk_reg>;
+- vdd-supply = <&pci_vdd_reg>;
++ avdd-pex-supply = <&pci_vdd_reg>;
++ vdd-pex-supply = <&pci_vdd_reg>;
++ avdd-pex-pll-supply = <&pci_vdd_reg>;
++ avdd-plle-supply = <&pci_vdd_reg>;
++ vddio-pex-clk-supply = <&pci_clk_reg>;
+ };
+
+ usb@c5008000 {
+@@ -511,15 +515,6 @@
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+- vdd_5v0_reg: regulator@0 {
+- compatible = "regulator-fixed";
+- reg = <0>;
+- regulator-name = "vdd_5v0";
+- regulator-min-microvolt = <5000000>;
+- regulator-max-microvolt = <5000000>;
+- regulator-always-on;
+- };
+-
+ pci_vdd_reg: regulator@1 {
+ compatible = "regulator-fixed";
+ reg = <1>;
+diff --git a/arch/arm/boot/dts/tegra20-tec.dts b/arch/arm/boot/dts/tegra20-tec.dts
+index 890562c..c12d8be 100644
+--- a/arch/arm/boot/dts/tegra20-tec.dts
++++ b/arch/arm/boot/dts/tegra20-tec.dts
+@@ -67,4 +67,45 @@
+ <&tegra_car TEGRA20_CLK_CDEV1>;
+ clock-names = "pll_a", "pll_a_out0", "mclk";
+ };
++
++ regulators {
++ vcc_24v_reg: regulator@100 {
++ compatible = "regulator-fixed";
++ reg = <100>;
++ regulator-name = "vcc_24v";
++ regulator-min-microvolt = <24000000>;
++ regulator-max-microvolt = <24000000>;
++ regulator-always-on;
++ };
++
++ vdd_5v0_reg: regulator@101 {
++ compatible = "regulator-fixed";
++ reg = <101>;
++ regulator-name = "vdd_5v0";
++ vin-supply = <&vcc_24v_reg>;
++ regulator-min-microvolt = <5000000>;
++ regulator-max-microvolt = <5000000>;
++ regulator-always-on;
++ };
++
++ vdd_3v3_reg: regulator@102 {
++ compatible = "regulator-fixed";
++ reg = <102>;
++ regulator-name = "vdd_3v3";
++ vin-supply = <&vcc_24v_reg>;
++ regulator-min-microvolt = <3300000>;
++ regulator-max-microvolt = <3300000>;
++ regulator-always-on;
++ };
++
++ vdd_1v8_reg: regulator@103 {
++ compatible = "regulator-fixed";
++ reg = <103>;
++ regulator-name = "vdd_1v8";
++ vin-supply = <&vdd_3v3_reg>;
++ regulator-min-microvolt = <1800000>;
++ regulator-max-microvolt = <1800000>;
++ regulator-always-on;
++ };
++ };
+ };
+diff --git a/arch/arm/boot/dts/tegra20-trimslice.dts b/arch/arm/boot/dts/tegra20-trimslice.dts
+index 216fa6d..5ad8797 100644
+--- a/arch/arm/boot/dts/tegra20-trimslice.dts
++++ b/arch/arm/boot/dts/tegra20-trimslice.dts
+@@ -318,8 +318,12 @@
+
+ pcie-controller@80003000 {
+ status = "okay";
+- pex-clk-supply = <&pci_clk_reg>;
+- vdd-supply = <&pci_vdd_reg>;
++
++ avdd-pex-supply = <&pci_vdd_reg>;
++ vdd-pex-supply = <&pci_vdd_reg>;
++ avdd-pex-pll-supply = <&pci_vdd_reg>;
++ avdd-plle-supply = <&pci_vdd_reg>;
++ vddio-pex-clk-supply = <&pci_clk_reg>;
+
+ pci@1,0 {
+ status = "okay";
+diff --git a/arch/arm/boot/dts/tegra20.dtsi b/arch/arm/boot/dts/tegra20.dtsi
+index a7ddf70..243d84c 100644
+--- a/arch/arm/boot/dts/tegra20.dtsi
++++ b/arch/arm/boot/dts/tegra20.dtsi
+@@ -236,6 +236,12 @@
+ interrupt-controller;
+ };
+
++ apbmisc@70000800 {
++ compatible = "nvidia,tegra20-apbmisc";
++ reg = <0x70000800 0x64 /* Chip revision */
++ 0x70000008 0x04>; /* Strapping options */
++ };
++
+ pinmux: pinmux@70000014 {
+ compatible = "nvidia,tegra20-pinmux";
+ reg = <0x70000014 0x10 /* Tri-state registers */
+@@ -545,6 +551,15 @@
+ #size-cells = <0>;
+ };
+
++ fuse@7000f800 {
++ compatible = "nvidia,tegra20-efuse";
++ reg = <0x7000F800 0x400>;
++ clocks = <&tegra_car TEGRA20_CLK_FUSE>;
++ clock-names = "fuse";
++ resets = <&tegra_car 39>;
++ reset-names = "fuse";
++ };
++
+ pcie-controller@80003000 {
+ compatible = "nvidia,tegra20-pcie";
+ device_type = "pci";
+diff --git a/arch/arm/boot/dts/tegra30-apalis-eval.dts b/arch/arm/boot/dts/tegra30-apalis-eval.dts
+new file mode 100644
+index 0000000..9921433
+--- /dev/null
++++ b/arch/arm/boot/dts/tegra30-apalis-eval.dts
+@@ -0,0 +1,260 @@
++/dts-v1/;
++
++#include <dt-bindings/input/input.h>
++#include "tegra30-apalis.dtsi"
++
++/ {
++ model = "Toradex Apalis T30 on Apalis Evaluation Board";
++ compatible = "toradex,apalis_t30-eval", "nvidia,tegra30";
++
++ aliases {
++ rtc0 = "/i2c@7000c000/rtc@68";
++ rtc1 = "/i2c@7000d000/tps65911@2d";
++ rtc2 = "/rtc@7000e000";
++ };
++
++ pcie-controller@00003000 {
++ status = "okay";
++
++ pci@1,0 {
++ status = "okay";
++ };
++
++ pci@2,0 {
++ status = "okay";
++ };
++
++ pci@3,0 {
++ status = "okay";
++ };
++ };
++
++ host1x@50000000 {
++ dc@54200000 {
++ rgb {
++ status = "okay";
++ nvidia,panel = <&panel>;
++ };
++ };
++ hdmi@54280000 {
++ status = "okay";
++ };
++ };
++
++ serial@70006000 {
++ status = "okay";
++ };
++
++ serial@70006040 {
++ compatible = "nvidia,tegra30-hsuart";
++ status = "okay";
++ };
++
++ serial@70006200 {
++ compatible = "nvidia,tegra30-hsuart";
++ status = "okay";
++ };
++
++ serial@70006300 {
++ compatible = "nvidia,tegra30-hsuart";
++ status = "okay";
++ };
++
++ pwm@7000a000 {
++ status = "okay";
++ };
++
++ /*
++ * GEN1_I2C: I2C1_SDA/SCL on MXM3 pin 209/211 (e.g. RTC on carrier
++ * board)
++ */
++ i2c@7000c000 {
++ status = "okay";
++ clock-frequency = <100000>;
++
++ pcie-switch@58 {
++ compatible = "plx,pex8605";
++ reg = <0x58>;
++ };
++
++ /* M41T0M6 real time clock on carrier board */
++ rtc@68 {
++ compatible = "st,m41t00";
++ reg = <0x68>;
++ };
++ };
++
++ /* GEN2_I2C: unused */
++
++ /*
++ * CAM_I2C: I2C3_SDA/SCL on MXM3 pin 201/203 (e.g. camera sensor on
++ * carrier board)
++ */
++ cami2c: i2c@7000c500 {
++ status = "okay";
++ clock-frequency = <400000>;
++ };
++
++ /* DDC: I2C2_SDA/SCL on MXM3 pin 205/207 (e.g. display EDID) */
++ hdmiddc: i2c@7000c700 {
++ status = "okay";
++ };
++
++ /* SPI1: Apalis SPI1 */
++ spi@7000d400 {
++ status = "okay";
++ spi-max-frequency = <25000000>;
++ spidev0: spidev@1 {
++ compatible = "spidev";
++ reg = <1>;
++ spi-max-frequency = <25000000>;
++ };
++ };
++
++ /* SPI5: Apalis SPI2 */
++ spi@7000dc00 {
++ status = "okay";
++ spi-max-frequency = <25000000>;
++ spidev1: spidev@2 {
++ compatible = "spidev";
++ reg = <2>;
++ spi-max-frequency = <25000000>;
++ };
++ };
++
++ sd1: sdhci@78000000 {
++ status = "okay";
++ bus-width = <4>;
++ /* SD1_CD# */
++ cd-gpios = <&gpio TEGRA_GPIO(CC, 5) GPIO_ACTIVE_LOW>;
++ no-1-8-v;
++ };
++
++ mmc1: sdhci@78000400 {
++ status = "okay";
++ bus-width = <8>;
++ /* MMC1_CD# */
++ cd-gpios = <&gpio TEGRA_GPIO(V, 3) GPIO_ACTIVE_LOW>;
++ no-1-8-v;
++ };
++
++ /* EHCI instance 0: USB1_DP/N -> USBO1_DP/N */
++ usb@7d000000 {
++ status = "okay";
++ };
++
++ usb-phy@7d000000 {
++ status = "okay";
++ vbus-supply = <&usbo1_vbus_reg>;
++ };
++
++ /* EHCI instance 1: USB2_DP/N -> USBH2_DP/N */
++ usb@7d004000 {
++ status = "okay";
++ };
++
++ usb-phy@7d004000 {
++ status = "okay";
++ vbus-supply = <&usbh_vbus_reg>;
++ };
++
++ /* EHCI instance 2: USB3_DP/N -> USBH3_DP/N */
++ usb@7d008000 {
++ status = "okay";
++ };
++
++ usb-phy@7d008000 {
++ status = "okay";
++ vbus-supply = <&usbh_vbus_reg>;
++ };
++
++ backlight: backlight {
++ compatible = "pwm-backlight";
++
++ /* PWM0 */
++ pwms = <&pwm 0 5000000>;
++ brightness-levels = <255 231 223 207 191 159 127 0>;
++ default-brightness-level = <6>;
++ /* BKL1_ON */
++ enable-gpios = <&gpio TEGRA_GPIO(V, 2) GPIO_ACTIVE_HIGH>;
++ };
++
++ gpio-keys {
++ compatible = "gpio-keys";
++
++ power {
++ label = "Power";
++ gpios = <&gpio TEGRA_GPIO(V, 1) GPIO_ACTIVE_LOW>;
++ linux,code = <KEY_POWER>;
++ debounce-interval = <10>;
++ gpio-key,wakeup;
++ };
++ };
++
++ panel: panel {
++ /*
++ * edt,et057090dhu: EDT 5.7" LCD TFT
++ * edt,et070080dh6: EDT 7.0" LCD TFT
++ */
++ compatible = "edt,et057090dhu", "simple-panel";
++
++ backlight = <&backlight>;
++ };
++
++ pwmleds {
++ compatible = "pwm-leds";
++
++ pwm1 {
++ label = "PWM1";
++ pwms = <&pwm 3 19600>;
++ max-brightness = <255>;
++ };
++
++ pwm2 {
++ label = "PWM2";
++ pwms = <&pwm 2 19600>;
++ max-brightness = <255>;
++ };
++
++ pwm3 {
++ label = "PWM3";
++ pwms = <&pwm 1 19600>;
++ max-brightness = <255>;
++ };
++ };
++
++ regulators {
++ sys_5v0_reg: regulator@1 {
++ compatible = "regulator-fixed";
++ reg = <1>;
++ regulator-name = "5v0";
++ regulator-min-microvolt = <5000000>;
++ regulator-max-microvolt = <5000000>;
++ regulator-always-on;
++ };
++
++ /* USBO1_EN */
++ usbo1_vbus_reg: regulator@2 {
++ compatible = "regulator-fixed";
++ reg = <2>;
++ regulator-name = "usbo1_vbus";
++ regulator-min-microvolt = <5000000>;
++ regulator-max-microvolt = <5000000>;
++ gpio = <&gpio TEGRA_GPIO(T, 5) GPIO_ACTIVE_HIGH>;
++ enable-active-high;
++ vin-supply = <&sys_5v0_reg>;
++ };
++
++ /* USBH_EN */
++ usbh_vbus_reg: regulator@3 {
++ compatible = "regulator-fixed";
++ reg = <3>;
++ regulator-name = "usbh_vbus";
++ regulator-min-microvolt = <5000000>;
++ regulator-max-microvolt = <5000000>;
++ gpio = <&gpio TEGRA_GPIO(DD, 1) GPIO_ACTIVE_HIGH>;
++ enable-active-high;
++ vin-supply = <&sys_5v0_reg>;
++ };
++ };
++};
+diff --git a/arch/arm/boot/dts/tegra30-apalis.dtsi b/arch/arm/boot/dts/tegra30-apalis.dtsi
+new file mode 100644
+index 0000000..8adaa78
+--- /dev/null
++++ b/arch/arm/boot/dts/tegra30-apalis.dtsi
+@@ -0,0 +1,678 @@
++#include "tegra30.dtsi"
++
++/*
++ * Toradex Apalis T30 Device Tree
++ * Compatible for Revisions 1GB: V1.0A; 2GB: V1.0B, V1.0C
++ */
++/ {
++ model = "Toradex Apalis T30";
++ compatible = "toradex,apalis_t30", "nvidia,tegra30";
++
++ pcie-controller@00003000 {
++ avdd-pexa-supply = <&vdd2_reg>;
++ vdd-pexa-supply = <&vdd2_reg>;
++ avdd-pexb-supply = <&vdd2_reg>;
++ vdd-pexb-supply = <&vdd2_reg>;
++ avdd-pex-pll-supply = <&vdd2_reg>;
++ avdd-plle-supply = <&ldo6_reg>;
++ vddio-pex-ctl-supply = <&sys_3v3_reg>;
++ hvdd-pex-supply = <&sys_3v3_reg>;
++
++ pci@1,0 {
++ nvidia,num-lanes = <4>;
++ };
++
++ pci@2,0 {
++ nvidia,num-lanes = <1>;
++ };
++
++ pci@3,0 {
++ nvidia,num-lanes = <1>;
++ };
++ };
++
++ host1x@50000000 {
++ hdmi@54280000 {
++ vdd-supply = <&sys_3v3_reg>;
++ pll-supply = <&vio_reg>;
++
++ nvidia,hpd-gpio =
++ <&gpio TEGRA_GPIO(N, 7) GPIO_ACTIVE_HIGH>;
++ nvidia,ddc-i2c-bus = <&hdmiddc>;
++ };
++ };
++
++ pinmux@70000868 {
++ pinctrl-names = "default";
++ pinctrl-0 = <&state_default>;
++
++ state_default: pinmux {
++ /* Apalis BKL1_ON */
++ pv2 {
++ nvidia,pins = "pv2";
++ nvidia,function = "rsvd4";
++ nvidia,pull = <TEGRA_PIN_PULL_NONE>;
++ nvidia,tristate = <TEGRA_PIN_DISABLE>;
++ };
++
++ /* Apalis BKL1_PWM */
++ uart3_rts_n_pc0 {
++ nvidia,pins = "uart3_rts_n_pc0";
++ nvidia,function = "pwm0";
++ nvidia,pull = <TEGRA_PIN_PULL_NONE>;
++ nvidia,tristate = <TEGRA_PIN_DISABLE>;
++ };
++ /* BKL1_PWM_EN#, disable TPS65911 PMIC PWM backlight */
++ uart3_cts_n_pa1 {
++ nvidia,pins = "uart3_cts_n_pa1";
++ nvidia,function = "rsvd1";
++ nvidia,pull = <TEGRA_PIN_PULL_UP>;
++ nvidia,tristate = <TEGRA_PIN_DISABLE>;
++ };
++
++ /* Apalis CAN1 on SPI6 */
++ spi2_cs0_n_px3 {
++ nvidia,pins = "spi2_cs0_n_px3",
++ "spi2_miso_px1",
++ "spi2_mosi_px0",
++ "spi2_sck_px2";
++ nvidia,function = "spi6";
++ nvidia,pull = <TEGRA_PIN_PULL_NONE>;
++ nvidia,tristate = <TEGRA_PIN_DISABLE>;
++ };
++ /* CAN_INT1 */
++ spi2_cs1_n_pw2 {
++ nvidia,pins = "spi2_cs1_n_pw2";
++ nvidia,function = "spi3";
++ nvidia,pull = <TEGRA_PIN_PULL_NONE>;
++ nvidia,tristate = <TEGRA_PIN_DISABLE>;
++ nvidia,enable-input = <TEGRA_PIN_ENABLE>;
++ };
++
++ /* Apalis CAN2 on SPI4 */
++ gmi_a16_pj7 {
++ nvidia,pins = "gmi_a16_pj7",
++ "gmi_a17_pb0",
++ "gmi_a18_pb1",
++ "gmi_a19_pk7";
++ nvidia,function = "spi4";
++ nvidia,pull = <TEGRA_PIN_PULL_NONE>;
++ nvidia,tristate = <TEGRA_PIN_DISABLE>;
++ };
++ /* CAN_INT2 */
++ spi2_cs2_n_pw3 {
++ nvidia,pins = "spi2_cs2_n_pw3";
++ nvidia,function = "spi3";
++ nvidia,pull = <TEGRA_PIN_PULL_NONE>;
++ nvidia,tristate = <TEGRA_PIN_DISABLE>;
++ nvidia,enable-input = <TEGRA_PIN_ENABLE>;
++ };
++
++ /* Apalis I2C3 */
++ cam_i2c_scl_pbb1 {
++ nvidia,pins = "cam_i2c_scl_pbb1",
++ "cam_i2c_sda_pbb2";
++ nvidia,function = "i2c3";
++ nvidia,pull = <TEGRA_PIN_PULL_NONE>;
++ nvidia,tristate = <TEGRA_PIN_DISABLE>;
++ nvidia,enable-input = <TEGRA_PIN_ENABLE>;
++ nvidia,lock = <TEGRA_PIN_DISABLE>;
++ nvidia,open-drain = <TEGRA_PIN_ENABLE>;
++ };
++
++ /* Apalis MMC1 */
++ sdmmc3_clk_pa6 {
++ nvidia,pins = "sdmmc3_clk_pa6",
++ "sdmmc3_cmd_pa7";
++ nvidia,function = "sdmmc3";
++ nvidia,pull = <TEGRA_PIN_PULL_NONE>;
++ nvidia,tristate = <TEGRA_PIN_DISABLE>;
++ };
++ sdmmc3_dat0_pb7 {
++ nvidia,pins = "sdmmc3_dat0_pb7",
++ "sdmmc3_dat1_pb6",
++ "sdmmc3_dat2_pb5",
++ "sdmmc3_dat3_pb4",
++ "sdmmc3_dat4_pd1",
++ "sdmmc3_dat5_pd0",
++ "sdmmc3_dat6_pd3",
++ "sdmmc3_dat7_pd4";
++ nvidia,function = "sdmmc3";
++ nvidia,pull = <TEGRA_PIN_PULL_UP>;
++ nvidia,tristate = <TEGRA_PIN_DISABLE>;
++ };
++ /* Apalis MMC1_CD# */
++ pv3 {
++ nvidia,pins = "pv3";
++ nvidia,function = "rsvd2";
++ nvidia,pull = <TEGRA_PIN_PULL_NONE>;
++ nvidia,tristate = <TEGRA_PIN_DISABLE>;
++ nvidia,enable-input = <TEGRA_PIN_ENABLE>;
++ };
++
++ /* Apalis PWM1 */
++ gpio_pu6 {
++ nvidia,pins = "gpio_pu6";
++ nvidia,function = "pwm3";
++ nvidia,pull = <TEGRA_PIN_PULL_NONE>;
++ nvidia,tristate = <TEGRA_PIN_DISABLE>;
++ };
++
++ /* Apalis PWM2 */
++ gpio_pu5 {
++ nvidia,pins = "gpio_pu5";
++ nvidia,function = "pwm2";
++ nvidia,pull = <TEGRA_PIN_PULL_NONE>;
++ nvidia,tristate = <TEGRA_PIN_DISABLE>;
++ };
++
++ /* Apalis PWM3 */
++ gpio_pu4 {
++ nvidia,pins = "gpio_pu4";
++ nvidia,function = "pwm1";
++ nvidia,pull = <TEGRA_PIN_PULL_NONE>;
++ nvidia,tristate = <TEGRA_PIN_DISABLE>;
++ };
++
++ /* Apalis PWM4 */
++ gpio_pu3 {
++ nvidia,pins = "gpio_pu3";
++ nvidia,function = "pwm0";
++ nvidia,pull = <TEGRA_PIN_PULL_NONE>;
++ nvidia,tristate = <TEGRA_PIN_DISABLE>;
++ };
++
++ /* Apalis RESET_MOCI# */
++ gmi_rst_n_pi4 {
++ nvidia,pins = "gmi_rst_n_pi4";
++ nvidia,function = "gmi";
++ nvidia,pull = <TEGRA_PIN_PULL_NONE>;
++ nvidia,tristate = <TEGRA_PIN_DISABLE>;
++ };
++
++ /* Apalis SD1 */
++ sdmmc1_clk_pz0 {
++ nvidia,pins = "sdmmc1_clk_pz0";
++ nvidia,function = "sdmmc1";
++ nvidia,pull = <TEGRA_PIN_PULL_NONE>;
++ nvidia,tristate = <TEGRA_PIN_DISABLE>;
++ };
++ sdmmc1_cmd_pz1 {
++ nvidia,pins = "sdmmc1_cmd_pz1",
++ "sdmmc1_dat0_py7",
++ "sdmmc1_dat1_py6",
++ "sdmmc1_dat2_py5",
++ "sdmmc1_dat3_py4";
++ nvidia,function = "sdmmc1";
++ nvidia,pull = <TEGRA_PIN_PULL_UP>;
++ nvidia,tristate = <TEGRA_PIN_DISABLE>;
++ };
++ /* Apalis SD1_CD# */
++ clk2_req_pcc5 {
++ nvidia,pins = "clk2_req_pcc5";
++ nvidia,function = "rsvd2";
++ nvidia,pull = <TEGRA_PIN_PULL_NONE>;
++ nvidia,tristate = <TEGRA_PIN_DISABLE>;
++ nvidia,enable-input = <TEGRA_PIN_ENABLE>;
++ };
++
++ /* Apalis SPI1 */
++ spi1_sck_px5 {
++ nvidia,pins = "spi1_sck_px5",
++ "spi1_mosi_px4",
++ "spi1_miso_px7",
++ "spi1_cs0_n_px6";
++ nvidia,function = "spi1";
++ nvidia,pull = <TEGRA_PIN_PULL_NONE>;
++ nvidia,tristate = <TEGRA_PIN_DISABLE>;
++ };
++
++ /* Apalis SPI2 */
++ lcd_sck_pz4 {
++ nvidia,pins = "lcd_sck_pz4",
++ "lcd_sdout_pn5",
++ "lcd_sdin_pz2",
++ "lcd_cs0_n_pn4";
++ nvidia,function = "spi5";
++ nvidia,pull = <TEGRA_PIN_PULL_NONE>;
++ nvidia,tristate = <TEGRA_PIN_DISABLE>;
++ };
++
++ /* Apalis UART1 */
++ ulpi_data0 {
++ nvidia,pins = "ulpi_data0_po1",
++ "ulpi_data1_po2",
++ "ulpi_data2_po3",
++ "ulpi_data3_po4",
++ "ulpi_data4_po5",
++ "ulpi_data5_po6",
++ "ulpi_data6_po7",
++ "ulpi_data7_po0";
++ nvidia,function = "uarta";
++ nvidia,pull = <TEGRA_PIN_PULL_NONE>;
++ nvidia,tristate = <TEGRA_PIN_DISABLE>;
++ };
++
++ /* Apalis UART2 */
++ ulpi_clk_py0 {
++ nvidia,pins = "ulpi_clk_py0",
++ "ulpi_dir_py1",
++ "ulpi_nxt_py2",
++ "ulpi_stp_py3";
++ nvidia,function = "uartd";
++ nvidia,pull = <TEGRA_PIN_PULL_NONE>;
++ nvidia,tristate = <TEGRA_PIN_DISABLE>;
++ };
++
++ /* Apalis UART3 */
++ uart2_rxd_pc3 {
++ nvidia,pins = "uart2_rxd_pc3",
++ "uart2_txd_pc2";
++ nvidia,function = "uartb";
++ nvidia,pull = <TEGRA_PIN_PULL_NONE>;
++ nvidia,tristate = <TEGRA_PIN_DISABLE>;
++ };
++
++ /* Apalis UART4 */
++ uart3_rxd_pw7 {
++ nvidia,pins = "uart3_rxd_pw7",
++ "uart3_txd_pw6";
++ nvidia,function = "uartc";
++ nvidia,pull = <TEGRA_PIN_PULL_NONE>;
++ nvidia,tristate = <TEGRA_PIN_DISABLE>;
++ };
++
++ /* Apalis USBO1_EN */
++ gen2_i2c_scl_pt5 {
++ nvidia,pins = "gen2_i2c_scl_pt5";
++ nvidia,function = "rsvd4";
++ nvidia,open-drain = <TEGRA_PIN_DISABLE>;
++ nvidia,pull = <TEGRA_PIN_PULL_NONE>;
++ nvidia,tristate = <TEGRA_PIN_DISABLE>;
++ };
++
++ /* Apalis USBO1_OC# */
++ gen2_i2c_sda_pt6 {
++ nvidia,pins = "gen2_i2c_sda_pt6";
++ nvidia,function = "rsvd4";
++ nvidia,open-drain = <TEGRA_PIN_DISABLE>;
++ nvidia,pull = <TEGRA_PIN_PULL_NONE>;
++ nvidia,tristate = <TEGRA_PIN_DISABLE>;
++ nvidia,enable-input = <TEGRA_PIN_ENABLE>;
++ };
++
++ /* Apalis WAKE1_MICO */
++ pv1 {
++ nvidia,pins = "pv1";
++ nvidia,function = "rsvd1";
++ nvidia,pull = <TEGRA_PIN_PULL_NONE>;
++ nvidia,tristate = <TEGRA_PIN_DISABLE>;
++ nvidia,enable-input = <TEGRA_PIN_ENABLE>;
++ };
++
++ /* eMMC (On-module) */
++ sdmmc4_clk_pcc4 {
++ nvidia,pins = "sdmmc4_clk_pcc4",
++ "sdmmc4_rst_n_pcc3";
++ nvidia,function = "sdmmc4";
++ nvidia,pull = <TEGRA_PIN_PULL_NONE>;
++ nvidia,tristate = <TEGRA_PIN_DISABLE>;
++ };
++ sdmmc4_dat0_paa0 {
++ nvidia,pins = "sdmmc4_dat0_paa0",
++ "sdmmc4_dat1_paa1",
++ "sdmmc4_dat2_paa2",
++ "sdmmc4_dat3_paa3",
++ "sdmmc4_dat4_paa4",
++ "sdmmc4_dat5_paa5",
++ "sdmmc4_dat6_paa6",
++ "sdmmc4_dat7_paa7";
++ nvidia,function = "sdmmc4";
++ nvidia,pull = <TEGRA_PIN_PULL_UP>;
++ nvidia,tristate = <TEGRA_PIN_DISABLE>;
++ };
++
++ /* LVDS Transceiver Configuration */
++ pbb0 {
++ nvidia,pins = "pbb0",
++ "pbb7",
++ "pcc1",
++ "pcc2";
++ nvidia,function = "rsvd2";
++ nvidia,pull = <TEGRA_PIN_PULL_NONE>;
++ nvidia,tristate = <TEGRA_PIN_DISABLE>;
++ nvidia,enable-input = <TEGRA_PIN_DISABLE>;
++ nvidia,lock = <TEGRA_PIN_DISABLE>;
++ };
++ pbb3 {
++ nvidia,pins = "pbb3",
++ "pbb4",
++ "pbb5",
++ "pbb6";
++ nvidia,function = "displayb";
++ nvidia,pull = <TEGRA_PIN_PULL_NONE>;
++ nvidia,tristate = <TEGRA_PIN_DISABLE>;
++ nvidia,enable-input = <TEGRA_PIN_DISABLE>;
++ nvidia,lock = <TEGRA_PIN_DISABLE>;
++ };
++
++ /* Power I2C (On-module) */
++ pwr_i2c_scl_pz6 {
++ nvidia,pins = "pwr_i2c_scl_pz6",
++ "pwr_i2c_sda_pz7";
++ nvidia,function = "i2cpwr";
++ nvidia,pull = <TEGRA_PIN_PULL_NONE>;
++ nvidia,tristate = <TEGRA_PIN_DISABLE>;
++ nvidia,enable-input = <TEGRA_PIN_ENABLE>;
++ nvidia,lock = <TEGRA_PIN_DISABLE>;
++ nvidia,open-drain = <TEGRA_PIN_ENABLE>;
++ };
++
++ /*
++ * THERMD_ALERT#, unlatched I2C address pin of LM95245
++ * temperature sensor therefore requires disabling for
++ * now
++ */
++ lcd_dc1_pd2 {
++ nvidia,pins = "lcd_dc1_pd2";
++ nvidia,function = "rsvd3";
++ nvidia,pull = <TEGRA_PIN_PULL_NONE>;
++ nvidia,tristate = <TEGRA_PIN_DISABLE>;
++ nvidia,enable-input = <TEGRA_PIN_ENABLE>;
++ };
++
++ /* TOUCH_PEN_INT# */
++ pv0 {
++ nvidia,pins = "pv0";
++ nvidia,function = "rsvd1";
++ nvidia,pull = <TEGRA_PIN_PULL_NONE>;
++ nvidia,tristate = <TEGRA_PIN_DISABLE>;
++ nvidia,enable-input = <TEGRA_PIN_ENABLE>;
++ };
++ };
++ };
++
++ hdmiddc: i2c@7000c700 {
++ clock-frequency = <100000>;
++ };
++
++ /*
++ * PWR_I2C: power I2C to audio codec, PMIC, temperature sensor and
++ * touch screen controller
++ */
++ i2c@7000d000 {
++ status = "okay";
++ clock-frequency = <100000>;
++
++ pmic: tps65911@2d {
++ compatible = "ti,tps65911";
++ reg = <0x2d>;
++
++ interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
++ #interrupt-cells = <2>;
++ interrupt-controller;
++
++ ti,system-power-controller;
++
++ #gpio-cells = <2>;
++ gpio-controller;
++
++ vcc1-supply = <&sys_3v3_reg>;
++ vcc2-supply = <&sys_3v3_reg>;
++ vcc3-supply = <&vio_reg>;
++ vcc4-supply = <&sys_3v3_reg>;
++ vcc5-supply = <&sys_3v3_reg>;
++ vcc6-supply = <&vio_reg>;
++ vcc7-supply = <&sys_5v0_reg>;
++ vccio-supply = <&sys_3v3_reg>;
++
++ regulators {
++ /* SW1: +V1.35_VDDIO_DDR */
++ vdd1_reg: vdd1 {
++ regulator-name = "vddio_ddr_1v35";
++ regulator-min-microvolt = <1350000>;
++ regulator-max-microvolt = <1350000>;
++ regulator-always-on;
++ };
++
++ /* SW2: +V1.05 */
++ vdd2_reg: vdd2 {
++ regulator-name =
++ "vdd_pexa,vdd_pexb,vdd_sata";
++ regulator-min-microvolt = <1050000>;
++ regulator-max-microvolt = <1050000>;
++ };
++
++ /* SW CTRL: +V1.0_VDD_CPU */
++ vddctrl_reg: vddctrl {
++ regulator-name = "vdd_cpu,vdd_sys";
++ regulator-min-microvolt = <1150000>;
++ regulator-max-microvolt = <1150000>;
++ regulator-always-on;
++ };
++
++ /* SWIO: +V1.8 */
++ vio_reg: vio {
++ regulator-name = "vdd_1v8_gen";
++ regulator-min-microvolt = <1800000>;
++ regulator-max-microvolt = <1800000>;
++ regulator-always-on;
++ };
++
++ /* LDO1: unused */
++
++ /*
++ * EN_+V3.3 switching via FET:
++ * +V3.3_AUDIO_AVDD_S, +V3.3 and +V1.8_VDD_LAN
++ * see also v3_3 fixed supply
++ */
++ ldo2_reg: ldo2 {
++ regulator-name = "en_3v3";
++ regulator-min-microvolt = <3300000>;
++ regulator-max-microvolt = <3300000>;
++ regulator-always-on;
++ };
++
++ /* +V1.2_CSI */
++ ldo3_reg: ldo3 {
++ regulator-name =
++ "avdd_dsi_csi,pwrdet_mipi";
++ regulator-min-microvolt = <1200000>;
++ regulator-max-microvolt = <1200000>;
++ };
++
++ /* +V1.2_VDD_RTC */
++ ldo4_reg: ldo4 {
++ regulator-name = "vdd_rtc";
++ regulator-min-microvolt = <1200000>;
++ regulator-max-microvolt = <1200000>;
++ regulator-always-on;
++ };
++
++ /*
++ * +V2.8_AVDD_VDAC:
++ * only required for analog RGB
++ */
++ ldo5_reg: ldo5 {
++ regulator-name = "avdd_vdac";
++ regulator-min-microvolt = <2800000>;
++ regulator-max-microvolt = <2800000>;
++ regulator-always-on;
++ };
++
++ /*
++ * +V1.05_AVDD_PLLE: avdd_plle should be 1.05V
++ * but LDO6 can't set voltage in 50mV
++ * granularity
++ */
++ ldo6_reg: ldo6 {
++ regulator-name = "avdd_plle";
++ regulator-min-microvolt = <1100000>;
++ regulator-max-microvolt = <1100000>;
++ };
++
++ /* +V1.2_AVDD_PLL */
++ ldo7_reg: ldo7 {
++ regulator-name = "avdd_pll";
++ regulator-min-microvolt = <1200000>;
++ regulator-max-microvolt = <1200000>;
++ regulator-always-on;
++ };
++
++ /* +V1.0_VDD_DDR_HS */
++ ldo8_reg: ldo8 {
++ regulator-name = "vdd_ddr_hs";
++ regulator-min-microvolt = <1000000>;
++ regulator-max-microvolt = <1000000>;
++ regulator-always-on;
++ };
++ };
++ };
++
++ /* STMPE811 touch screen controller */
++ stmpe811@41 {
++ compatible = "st,stmpe811";
++ #address-cells = <1>;
++ #size-cells = <0>;
++ reg = <0x41>;
++ interrupts = <TEGRA_GPIO(V, 0) IRQ_TYPE_LEVEL_LOW>;
++ interrupt-parent = <&gpio>;
++ interrupt-controller;
++ id = <0>;
++ blocks = <0x5>;
++ irq-trigger = <0x1>;
++
++ stmpe_touchscreen {
++ compatible = "st,stmpe-ts";
++ reg = <0>;
++ /* 3.25 MHz ADC clock speed */
++ st,adc-freq = <1>;
++ /* 8 sample average control */
++ st,ave-ctrl = <3>;
++ /* 7 length fractional part in z */
++ st,fraction-z = <7>;
++ /*
++ * 50 mA typical 80 mA max touchscreen drivers
++ * current limit value
++ */
++ st,i-drive = <1>;
++ /* 12-bit ADC */
++ st,mod-12b = <1>;
++ /* internal ADC reference */
++ st,ref-sel = <0>;
++ /* ADC converstion time: 80 clocks */
++ st,sample-time = <4>;
++ /* 1 ms panel driver settling time */
++ st,settling = <3>;
++ /* 5 ms touch detect interrupt delay */
++ st,touch-det-delay = <5>;
++ };
++ };
++
++ /*
++ * LM95245 temperature sensor
++ * Note: OVERT_N directly connected to PMIC PWRDN
++ */
++ temp-sensor@4c {
++ compatible = "national,lm95245";
++ reg = <0x4c>;
++ };
++
++ /* SW: +V1.2_VDD_CORE */
++ tps62362@60 {
++ compatible = "ti,tps62362";
++ reg = <0x60>;
++
++ regulator-name = "tps62362-vout";
++ regulator-min-microvolt = <900000>;
++ regulator-max-microvolt = <1400000>;
++ regulator-boot-on;
++ regulator-always-on;
++ ti,vsel0-state-low;
++ /* VSEL1: EN_CORE_DVFS_N low for DVFS */
++ ti,vsel1-state-low;
++ };
++ };
++
++ /* SPI4: CAN2 */
++ spi@7000da00 {
++ status = "okay";
++ spi-max-frequency = <10000000>;
++
++ can@1 {
++ compatible = "microchip,mcp2515";
++ reg = <1>;
++ clocks = <&clk16m>;
++ interrupt-parent = <&gpio>;
++ interrupts = <TEGRA_GPIO(W, 3) GPIO_ACTIVE_LOW>;
++ spi-max-frequency = <10000000>;
++ };
++ };
++
++ /* SPI6: CAN1 */
++ spi@7000de00 {
++ status = "okay";
++ spi-max-frequency = <10000000>;
++
++ can@0 {
++ compatible = "microchip,mcp2515";
++ reg = <0>;
++ clocks = <&clk16m>;
++ interrupt-parent = <&gpio>;
++ interrupts = <TEGRA_GPIO(W, 2) GPIO_ACTIVE_LOW>;
++ spi-max-frequency = <10000000>;
++ };
++ };
++
++ pmc@7000e400 {
++ nvidia,invert-interrupt;
++ nvidia,suspend-mode = <1>;
++ nvidia,cpu-pwr-good-time = <5000>;
++ nvidia,cpu-pwr-off-time = <5000>;
++ nvidia,core-pwr-good-time = <3845 3845>;
++ nvidia,core-pwr-off-time = <0>;
++ nvidia,core-power-req-active-high;
++ nvidia,sys-clock-req-active-high;
++ };
++
++ sdhci@78000600 {
++ status = "okay";
++ bus-width = <8>;
++ non-removable;
++ };
++
++ clocks {
++ compatible = "simple-bus";
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ clk32k_in: clk@0 {
++ compatible = "fixed-clock";
++ reg=<0>;
++ #clock-cells = <0>;
++ clock-frequency = <32768>;
++ };
++ clk16m: clk@1 {
++ compatible = "fixed-clock";
++ reg=<1>;
++ #clock-cells = <0>;
++ clock-frequency = <16000000>;
++ clock-output-names = "clk16m";
++ };
++ };
++
++ regulators {
++ compatible = "simple-bus";
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ sys_3v3_reg: regulator@100 {
++ compatible = "regulator-fixed";
++ reg = <100>;
++ regulator-name = "3v3";
++ regulator-min-microvolt = <3300000>;
++ regulator-max-microvolt = <3300000>;
++ regulator-always-on;
++ };
++ };
++};
+diff --git a/arch/arm/boot/dts/tegra30-beaver.dts b/arch/arm/boot/dts/tegra30-beaver.dts
+index 3189791..cee8f22 100644
+--- a/arch/arm/boot/dts/tegra30-beaver.dts
++++ b/arch/arm/boot/dts/tegra30-beaver.dts
+@@ -17,9 +17,15 @@
+
+ pcie-controller@00003000 {
+ status = "okay";
+- pex-clk-supply = <&sys_3v3_pexs_reg>;
+- vdd-supply = <&ldo1_reg>;
+- avdd-supply = <&ldo2_reg>;
++
++ avdd-pexa-supply = <&ldo1_reg>;
++ vdd-pexa-supply = <&ldo1_reg>;
++ avdd-pexb-supply = <&ldo1_reg>;
++ vdd-pexb-supply = <&ldo1_reg>;
++ avdd-pex-pll-supply = <&ldo1_reg>;
++ avdd-plle-supply = <&ldo1_reg>;
++ vddio-pex-ctl-supply = <&sys_3v3_reg>;
++ hvdd-pex-supply = <&sys_3v3_pexs_reg>;
+
+ pci@1,0 {
+ status = "okay";
+diff --git a/arch/arm/boot/dts/tegra30-cardhu.dtsi b/arch/arm/boot/dts/tegra30-cardhu.dtsi
+index 0cf0848..2063795 100644
+--- a/arch/arm/boot/dts/tegra30-cardhu.dtsi
++++ b/arch/arm/boot/dts/tegra30-cardhu.dtsi
+@@ -38,9 +38,14 @@
+
+ pcie-controller@00003000 {
+ status = "okay";
+- pex-clk-supply = <&pex_hvdd_3v3_reg>;
+- vdd-supply = <&ldo1_reg>;
+- avdd-supply = <&ldo2_reg>;
++
++ /* AVDD_PEXA and VDD_PEXA inputs are grounded on Cardhu. */
++ avdd-pexb-supply = <&ldo1_reg>;
++ vdd-pexb-supply = <&ldo1_reg>;
++ avdd-pex-pll-supply = <&ldo1_reg>;
++ hvdd-pex-supply = <&pex_hvdd_3v3_reg>;
++ vddio-pex-ctl-supply = <&sys_3v3_reg>;
++ avdd-plle-supply = <&ldo2_reg>;
+
+ pci@1,0 {
+ nvidia,num-lanes = <4>;
+diff --git a/arch/arm/boot/dts/tegra30.dtsi b/arch/arm/boot/dts/tegra30.dtsi
+index dec4fc8..0b1ede9 100644
+--- a/arch/arm/boot/dts/tegra30.dtsi
++++ b/arch/arm/boot/dts/tegra30.dtsi
+@@ -335,6 +335,12 @@
+ interrupt-controller;
+ };
+
++ apbmisc@70000800 {
++ compatible = "nvidia,tegra30-apbmisc", "nvidia,tegra20-apbmisc";
++ reg = <0x70000800 0x64 /* Chip revision */
++ 0x70000008 0x04>; /* Strapping options */
++ };
++
+ pinmux: pinmux@70000868 {
+ compatible = "nvidia,tegra30-pinmux";
+ reg = <0x70000868 0xd4 /* Pad control registers */
+@@ -631,6 +637,15 @@
+ nvidia,ahb = <&ahb>;
+ };
+
++ fuse@7000f800 {
++ compatible = "nvidia,tegra30-efuse";
++ reg = <0x7000f800 0x400>;
++ clocks = <&tegra_car TEGRA30_CLK_FUSE>;
++ clock-names = "fuse";
++ resets = <&tegra_car 39>;
++ reset-names = "fuse";
++ };
++
+ ahub@70080000 {
+ 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
+--- a/arch/arm/configs/tegra_defconfig
++++ b/arch/arm/configs/tegra_defconfig
+@@ -104,6 +104,7 @@ CONFIG_SCSI_MULTI_LUN=y
+ # CONFIG_SCSI_LOWLEVEL is not set
+ CONFIG_NETDEVICES=y
+ CONFIG_DUMMY=y
++CONFIG_IGB=y
+ CONFIG_R8169=y
+ CONFIG_USB_PEGASUS=y
+ CONFIG_USB_USBNET=y
+@@ -118,6 +119,8 @@ CONFIG_KEYBOARD_GPIO=y
+ CONFIG_KEYBOARD_TEGRA=y
+ CONFIG_KEYBOARD_CROS_EC=y
+ CONFIG_MOUSE_PS2_ELANTECH=y
++CONFIG_INPUT_TOUCHSCREEN=y
++CONFIG_TOUCHSCREEN_STMPE=y
+ CONFIG_INPUT_MISC=y
+ CONFIG_INPUT_MPU3050=y
+ # CONFIG_LEGACY_PTYS is not set
+@@ -128,6 +131,7 @@ CONFIG_SERIAL_TEGRA=y
+ CONFIG_SERIAL_OF_PLATFORM=y
+ # CONFIG_HW_RANDOM is not set
+ # CONFIG_I2C_COMPAT is not set
++CONFIG_I2C_CHARDEV=y
+ CONFIG_I2C_MUX_PCA954x=y
+ CONFIG_I2C_MUX_PINCTRL=y
+ CONFIG_I2C_TEGRA=y
+@@ -149,10 +153,12 @@ CONFIG_POWER_RESET=y
+ CONFIG_POWER_RESET_AS3722=y
+ CONFIG_POWER_RESET_GPIO=y
+ CONFIG_SENSORS_LM90=y
++CONFIG_SENSORS_LM95245=y
+ CONFIG_MFD_AS3722=y
+ CONFIG_MFD_CROS_EC=y
+ CONFIG_MFD_CROS_EC_SPI=y
+ CONFIG_MFD_MAX8907=y
++CONFIG_MFD_STMPE=y
+ CONFIG_MFD_PALMAS=y
+ CONFIG_MFD_TPS65090=y
+ CONFIG_MFD_TPS6586X=y
+@@ -215,6 +221,7 @@ CONFIG_MMC_SDHCI_TEGRA=y
+ CONFIG_NEW_LEDS=y
+ CONFIG_LEDS_CLASS=y
+ CONFIG_LEDS_GPIO=y
++CONFIG_LEDS_PWM=y
+ CONFIG_LEDS_TRIGGERS=y
+ CONFIG_LEDS_TRIGGER_TIMER=y
+ CONFIG_LEDS_TRIGGER_ONESHOT=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
++++ b/arch/arm/lib/delay.c
+@@ -19,6 +19,7 @@
+ * Author: Will Deacon <will.deacon@arm.com>
+ */
+
++#include <linux/clocksource.h>
+ #include <linux/delay.h>
+ #include <linux/init.h>
+ #include <linux/kernel.h>
+@@ -36,6 +37,7 @@ struct arm_delay_ops arm_delay_ops = {
+
+ static const struct delay_timer *delay_timer;
+ static bool delay_calibrated;
++static u64 delay_res;
+
+ int read_current_timer(unsigned long *timer_val)
+ {
+@@ -47,6 +49,11 @@ int read_current_timer(unsigned long *timer_val)
+ }
+ EXPORT_SYMBOL_GPL(read_current_timer);
+
++static inline u64 cyc_to_ns(u64 cyc, u32 mult, u32 shift)
++{
++ return (cyc * mult) >> shift;
++}
++
+ static void __timer_delay(unsigned long cycles)
+ {
+ cycles_t start = get_cycles();
+@@ -69,18 +76,24 @@ static void __timer_udelay(unsigned long usecs)
+
+ void __init register_current_timer_delay(const struct delay_timer *timer)
+ {
+- if (!delay_calibrated) {
+- pr_info("Switching to timer-based delay loop\n");
++ u32 new_mult, new_shift;
++ u64 res;
++
++ clocks_calc_mult_shift(&new_mult, &new_shift, timer->freq,
++ NSEC_PER_SEC, 3600);
++ res = cyc_to_ns(1ULL, new_mult, new_shift);
++
++ if (!delay_calibrated && (!delay_res || (res < delay_res))) {
++ pr_info("Switching to timer-based delay loop, resolution %lluns\n", res);
+ delay_timer = timer;
+ lpj_fine = timer->freq / HZ;
++ delay_res = res;
+
+ /* cpufreq may scale loops_per_jiffy, so keep a private copy */
+ arm_delay_ops.ticks_per_jiffy = lpj_fine;
+ arm_delay_ops.delay = __timer_delay;
+ arm_delay_ops.const_udelay = __timer_const_udelay;
+ arm_delay_ops.udelay = __timer_udelay;
+-
+- delay_calibrated = true;
+ } else {
+ pr_info("Ignoring duplicate/late registration of read_current_timer delay\n");
+ }
+@@ -91,3 +104,8 @@ unsigned long calibrate_delay_is_known(void)
+ delay_calibrated = true;
+ return lpj_fine;
+ }
++
++void calibration_delay_done(void)
++{
++ delay_calibrated = true;
++}
+diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile
+index 6fbfbb7..c303b55 100644
+--- a/arch/arm/mach-tegra/Makefile
++++ b/arch/arm/mach-tegra/Makefile
+@@ -2,24 +2,20 @@ asflags-y += -march=armv7-a
+
+ obj-y += io.o
+ obj-y += irq.o
+-obj-y += fuse.o
+ obj-y += pmc.o
+ obj-y += flowctrl.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-$(CONFIG_CPU_IDLE) += cpuidle.o
+-obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra20_speedo.o
+ obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += sleep-tegra20.o
+ obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += pm-tegra20.o
+ ifeq ($(CONFIG_CPU_IDLE),y)
+ obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += cpuidle-tegra20.o
+ endif
+-obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += tegra30_speedo.o
+ 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
+ obj-$(CONFIG_SMP) += platsmp.o headsmp.o
+ obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
+
+-obj-$(CONFIG_ARCH_TEGRA_114_SOC) += tegra114_speedo.o
+ obj-$(CONFIG_ARCH_TEGRA_114_SOC) += sleep-tegra30.o
+ obj-$(CONFIG_ARCH_TEGRA_114_SOC) += pm-tegra30.o
+ ifeq ($(CONFIG_CPU_IDLE),y)
+diff --git a/arch/arm/mach-tegra/apbio.c b/arch/arm/mach-tegra/apbio.c
+deleted file mode 100644
+index bc47197..0000000
+--- a/arch/arm/mach-tegra/apbio.c
++++ /dev/null
+@@ -1,206 +0,0 @@
+-/*
+- * Copyright (C) 2010 NVIDIA Corporation.
+- * Copyright (C) 2010 Google, Inc.
+- *
+- * This software is licensed under the terms of the GNU General Public
+- * License version 2, as published by the Free Software Foundation, and
+- * may be copied, distributed, and modified under those terms.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- */
+-
+-#include <linux/kernel.h>
+-#include <linux/io.h>
+-#include <linux/of.h>
+-#include <linux/dmaengine.h>
+-#include <linux/dma-mapping.h>
+-#include <linux/spinlock.h>
+-#include <linux/completion.h>
+-#include <linux/sched.h>
+-#include <linux/mutex.h>
+-
+-#include "apbio.h"
+-#include "iomap.h"
+-
+-#if defined(CONFIG_TEGRA20_APB_DMA)
+-static DEFINE_MUTEX(tegra_apb_dma_lock);
+-static u32 *tegra_apb_bb;
+-static dma_addr_t tegra_apb_bb_phys;
+-static DECLARE_COMPLETION(tegra_apb_wait);
+-
+-static u32 tegra_apb_readl_direct(unsigned long offset);
+-static void tegra_apb_writel_direct(u32 value, unsigned long offset);
+-
+-static struct dma_chan *tegra_apb_dma_chan;
+-static struct dma_slave_config dma_sconfig;
+-
+-static bool tegra_apb_dma_init(void)
+-{
+- dma_cap_mask_t mask;
+-
+- mutex_lock(&tegra_apb_dma_lock);
+-
+- /* Check to see if we raced to setup */
+- if (tegra_apb_dma_chan)
+- goto skip_init;
+-
+- dma_cap_zero(mask);
+- dma_cap_set(DMA_SLAVE, mask);
+- tegra_apb_dma_chan = dma_request_channel(mask, NULL, NULL);
+- if (!tegra_apb_dma_chan) {
+- /*
+- * This is common until the device is probed, so don't
+- * shout about it.
+- */
+- pr_debug("%s: can not allocate dma channel\n", __func__);
+- goto err_dma_alloc;
+- }
+-
+- tegra_apb_bb = dma_alloc_coherent(NULL, sizeof(u32),
+- &tegra_apb_bb_phys, GFP_KERNEL);
+- if (!tegra_apb_bb) {
+- pr_err("%s: can not allocate bounce buffer\n", __func__);
+- goto err_buff_alloc;
+- }
+-
+- dma_sconfig.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+- dma_sconfig.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+- dma_sconfig.src_maxburst = 1;
+- dma_sconfig.dst_maxburst = 1;
+-
+-skip_init:
+- mutex_unlock(&tegra_apb_dma_lock);
+- return true;
+-
+-err_buff_alloc:
+- dma_release_channel(tegra_apb_dma_chan);
+- tegra_apb_dma_chan = NULL;
+-
+-err_dma_alloc:
+- mutex_unlock(&tegra_apb_dma_lock);
+- return false;
+-}
+-
+-static void apb_dma_complete(void *args)
+-{
+- complete(&tegra_apb_wait);
+-}
+-
+-static int do_dma_transfer(unsigned long apb_add,
+- enum dma_transfer_direction dir)
+-{
+- struct dma_async_tx_descriptor *dma_desc;
+- int ret;
+-
+- if (dir == DMA_DEV_TO_MEM)
+- dma_sconfig.src_addr = apb_add;
+- else
+- dma_sconfig.dst_addr = apb_add;
+-
+- ret = dmaengine_slave_config(tegra_apb_dma_chan, &dma_sconfig);
+- if (ret)
+- return ret;
+-
+- dma_desc = dmaengine_prep_slave_single(tegra_apb_dma_chan,
+- tegra_apb_bb_phys, sizeof(u32), dir,
+- DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+- if (!dma_desc)
+- return -EINVAL;
+-
+- dma_desc->callback = apb_dma_complete;
+- dma_desc->callback_param = NULL;
+-
+- reinit_completion(&tegra_apb_wait);
+-
+- dmaengine_submit(dma_desc);
+- dma_async_issue_pending(tegra_apb_dma_chan);
+- ret = wait_for_completion_timeout(&tegra_apb_wait,
+- msecs_to_jiffies(50));
+-
+- if (WARN(ret == 0, "apb read dma timed out")) {
+- dmaengine_terminate_all(tegra_apb_dma_chan);
+- return -EFAULT;
+- }
+- return 0;
+-}
+-
+-static u32 tegra_apb_readl_using_dma(unsigned long offset)
+-{
+- int ret;
+-
+- if (!tegra_apb_dma_chan && !tegra_apb_dma_init())
+- return tegra_apb_readl_direct(offset);
+-
+- mutex_lock(&tegra_apb_dma_lock);
+- ret = do_dma_transfer(offset, DMA_DEV_TO_MEM);
+- if (ret < 0) {
+- pr_err("error in reading offset 0x%08lx using dma\n", offset);
+- *(u32 *)tegra_apb_bb = 0;
+- }
+- mutex_unlock(&tegra_apb_dma_lock);
+- return *((u32 *)tegra_apb_bb);
+-}
+-
+-static void tegra_apb_writel_using_dma(u32 value, unsigned long offset)
+-{
+- int ret;
+-
+- if (!tegra_apb_dma_chan && !tegra_apb_dma_init()) {
+- tegra_apb_writel_direct(value, offset);
+- return;
+- }
+-
+- mutex_lock(&tegra_apb_dma_lock);
+- *((u32 *)tegra_apb_bb) = value;
+- ret = do_dma_transfer(offset, DMA_MEM_TO_DEV);
+- if (ret < 0)
+- pr_err("error in writing offset 0x%08lx using dma\n", offset);
+- mutex_unlock(&tegra_apb_dma_lock);
+-}
+-#else
+-#define tegra_apb_readl_using_dma tegra_apb_readl_direct
+-#define tegra_apb_writel_using_dma tegra_apb_writel_direct
+-#endif
+-
+-typedef u32 (*apbio_read_fptr)(unsigned long offset);
+-typedef void (*apbio_write_fptr)(u32 value, unsigned long offset);
+-
+-static apbio_read_fptr apbio_read;
+-static apbio_write_fptr apbio_write;
+-
+-static u32 tegra_apb_readl_direct(unsigned long offset)
+-{
+- return readl(IO_ADDRESS(offset));
+-}
+-
+-static void tegra_apb_writel_direct(u32 value, unsigned long offset)
+-{
+- writel(value, IO_ADDRESS(offset));
+-}
+-
+-void tegra_apb_io_init(void)
+-{
+- /* Need to use dma only when it is Tegra20 based platform */
+- if (of_machine_is_compatible("nvidia,tegra20") ||
+- !of_have_populated_dt()) {
+- apbio_read = tegra_apb_readl_using_dma;
+- apbio_write = tegra_apb_writel_using_dma;
+- } else {
+- apbio_read = tegra_apb_readl_direct;
+- apbio_write = tegra_apb_writel_direct;
+- }
+-}
+-
+-u32 tegra_apb_readl(unsigned long offset)
+-{
+- return apbio_read(offset);
+-}
+-
+-void tegra_apb_writel(u32 value, unsigned long offset)
+-{
+- apbio_write(value, offset);
+-}
+diff --git a/arch/arm/mach-tegra/apbio.h b/arch/arm/mach-tegra/apbio.h
+deleted file mode 100644
+index f05d71c..0000000
+--- a/arch/arm/mach-tegra/apbio.h
++++ /dev/null
+@@ -1,22 +0,0 @@
+-/*
+- * Copyright (C) 2010 NVIDIA Corporation.
+- * Copyright (C) 2010 Google, Inc.
+- *
+- * This software is licensed under the terms of the GNU General Public
+- * License version 2, as published by the Free Software Foundation, and
+- * may be copied, distributed, and modified under those terms.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- */
+-
+-#ifndef __MACH_TEGRA_APBIO_H
+-#define __MACH_TEGRA_APBIO_H
+-
+-void tegra_apb_io_init(void);
+-u32 tegra_apb_readl(unsigned long offset);
+-void tegra_apb_writel(u32 value, unsigned long offset);
+-#endif
+diff --git a/arch/arm/mach-tegra/cpuidle.c b/arch/arm/mach-tegra/cpuidle.c
+index 7bc5d8d..ff0a10b 100644
+--- a/arch/arm/mach-tegra/cpuidle.c
++++ b/arch/arm/mach-tegra/cpuidle.c
+@@ -23,8 +23,8 @@
+
+ #include <linux/kernel.h>
+ #include <linux/module.h>
++#include <linux/tegra-soc.h>
+
+-#include "fuse.h"
+ #include "cpuidle.h"
+
+ void __init tegra_cpuidle_init(void)
+diff --git a/arch/arm/mach-tegra/flowctrl.c b/arch/arm/mach-tegra/flowctrl.c
+index ce8ab8a..4b31091 100644
+--- a/arch/arm/mach-tegra/flowctrl.c
++++ b/arch/arm/mach-tegra/flowctrl.c
+@@ -22,10 +22,10 @@
+ #include <linux/kernel.h>
+ #include <linux/io.h>
+ #include <linux/cpumask.h>
++#include <linux/tegra-soc.h>
+
+ #include "flowctrl.h"
+ #include "iomap.h"
+-#include "fuse.h"
+
+ static u8 flowctrl_offset_halt_cpu[] = {
+ FLOW_CTRL_HALT_CPU0_EVENTS,
+diff --git a/arch/arm/mach-tegra/fuse.c b/arch/arm/mach-tegra/fuse.c
+deleted file mode 100644
+index c9ac23b..0000000
+--- a/arch/arm/mach-tegra/fuse.c
++++ /dev/null
+@@ -1,252 +0,0 @@
+-/*
+- * arch/arm/mach-tegra/fuse.c
+- *
+- * Copyright (C) 2010 Google, Inc.
+- * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved.
+- *
+- * Author:
+- * Colin Cross <ccross@android.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/io.h>
+-#include <linux/export.h>
+-#include <linux/random.h>
+-#include <linux/clk.h>
+-#include <linux/tegra-soc.h>
+-
+-#include "fuse.h"
+-#include "iomap.h"
+-#include "apbio.h"
+-
+-/* Tegra20 only */
+-#define FUSE_UID_LOW 0x108
+-#define FUSE_UID_HIGH 0x10c
+-
+-/* Tegra30 and later */
+-#define FUSE_VENDOR_CODE 0x200
+-#define FUSE_FAB_CODE 0x204
+-#define FUSE_LOT_CODE_0 0x208
+-#define FUSE_LOT_CODE_1 0x20c
+-#define FUSE_WAFER_ID 0x210
+-#define FUSE_X_COORDINATE 0x214
+-#define FUSE_Y_COORDINATE 0x218
+-
+-#define FUSE_SKU_INFO 0x110
+-
+-#define TEGRA20_FUSE_SPARE_BIT 0x200
+-#define TEGRA30_FUSE_SPARE_BIT 0x244
+-
+-int tegra_sku_id;
+-int tegra_cpu_process_id;
+-int tegra_core_process_id;
+-int tegra_chip_id;
+-int tegra_cpu_speedo_id; /* only exist in Tegra30 and later */
+-int tegra_soc_speedo_id;
+-enum tegra_revision tegra_revision;
+-
+-static struct clk *fuse_clk;
+-static int tegra_fuse_spare_bit;
+-static void (*tegra_init_speedo_data)(void);
+-
+-/* The BCT to use at boot is specified by board straps that can be read
+- * through a APB misc register and decoded. 2 bits, i.e. 4 possible BCTs.
+- */
+-int tegra_bct_strapping;
+-
+-#define STRAP_OPT 0x008
+-#define GMI_AD0 (1 << 4)
+-#define GMI_AD1 (1 << 5)
+-#define RAM_ID_MASK (GMI_AD0 | GMI_AD1)
+-#define RAM_CODE_SHIFT 4
+-
+-static const char *tegra_revision_name[TEGRA_REVISION_MAX] = {
+- [TEGRA_REVISION_UNKNOWN] = "unknown",
+- [TEGRA_REVISION_A01] = "A01",
+- [TEGRA_REVISION_A02] = "A02",
+- [TEGRA_REVISION_A03] = "A03",
+- [TEGRA_REVISION_A03p] = "A03 prime",
+- [TEGRA_REVISION_A04] = "A04",
+-};
+-
+-static void tegra_fuse_enable_clk(void)
+-{
+- if (IS_ERR(fuse_clk))
+- fuse_clk = clk_get_sys(NULL, "fuse");
+- if (IS_ERR(fuse_clk))
+- return;
+- clk_prepare_enable(fuse_clk);
+-}
+-
+-static void tegra_fuse_disable_clk(void)
+-{
+- if (IS_ERR(fuse_clk))
+- return;
+- clk_disable_unprepare(fuse_clk);
+-}
+-
+-u32 tegra_fuse_readl(unsigned long offset)
+-{
+- return tegra_apb_readl(TEGRA_FUSE_BASE + offset);
+-}
+-
+-bool tegra_spare_fuse(int bit)
+-{
+- bool ret;
+-
+- tegra_fuse_enable_clk();
+-
+- ret = tegra_fuse_readl(tegra_fuse_spare_bit + bit * 4);
+-
+- tegra_fuse_disable_clk();
+-
+- return ret;
+-}
+-
+-static enum tegra_revision tegra_get_revision(u32 id)
+-{
+- u32 minor_rev = (id >> 16) & 0xf;
+-
+- switch (minor_rev) {
+- case 1:
+- return TEGRA_REVISION_A01;
+- case 2:
+- return TEGRA_REVISION_A02;
+- case 3:
+- if (tegra_chip_id == TEGRA20 &&
+- (tegra_spare_fuse(18) || tegra_spare_fuse(19)))
+- return TEGRA_REVISION_A03p;
+- else
+- return TEGRA_REVISION_A03;
+- case 4:
+- return TEGRA_REVISION_A04;
+- default:
+- return TEGRA_REVISION_UNKNOWN;
+- }
+-}
+-
+-static void tegra_get_process_id(void)
+-{
+- u32 reg;
+-
+- tegra_fuse_enable_clk();
+-
+- reg = tegra_fuse_readl(tegra_fuse_spare_bit);
+- tegra_cpu_process_id = (reg >> 6) & 3;
+- reg = tegra_fuse_readl(tegra_fuse_spare_bit);
+- tegra_core_process_id = (reg >> 12) & 3;
+-
+- tegra_fuse_disable_clk();
+-}
+-
+-u32 tegra_read_chipid(void)
+-{
+- return readl_relaxed(IO_ADDRESS(TEGRA_APB_MISC_BASE) + 0x804);
+-}
+-
+-static void __init tegra20_fuse_init_randomness(void)
+-{
+- u32 randomness[2];
+-
+- randomness[0] = tegra_fuse_readl(FUSE_UID_LOW);
+- randomness[1] = tegra_fuse_readl(FUSE_UID_HIGH);
+-
+- add_device_randomness(randomness, sizeof(randomness));
+-}
+-
+-/* Applies to Tegra30 or later */
+-static void __init tegra30_fuse_init_randomness(void)
+-{
+- u32 randomness[7];
+-
+- randomness[0] = tegra_fuse_readl(FUSE_VENDOR_CODE);
+- randomness[1] = tegra_fuse_readl(FUSE_FAB_CODE);
+- randomness[2] = tegra_fuse_readl(FUSE_LOT_CODE_0);
+- randomness[3] = tegra_fuse_readl(FUSE_LOT_CODE_1);
+- randomness[4] = tegra_fuse_readl(FUSE_WAFER_ID);
+- randomness[5] = tegra_fuse_readl(FUSE_X_COORDINATE);
+- randomness[6] = tegra_fuse_readl(FUSE_Y_COORDINATE);
+-
+- add_device_randomness(randomness, sizeof(randomness));
+-}
+-
+-void __init tegra_init_fuse(void)
+-{
+- u32 id;
+- u32 randomness[5];
+-
+- u32 reg = readl(IO_ADDRESS(TEGRA_CLK_RESET_BASE + 0x48));
+- reg |= 1 << 28;
+- writel(reg, IO_ADDRESS(TEGRA_CLK_RESET_BASE + 0x48));
+-
+- /*
+- * Enable FUSE clock. This needs to be hardcoded because the clock
+- * subsystem is not active during early boot.
+- */
+- reg = readl(IO_ADDRESS(TEGRA_CLK_RESET_BASE + 0x14));
+- reg |= 1 << 7;
+- writel(reg, IO_ADDRESS(TEGRA_CLK_RESET_BASE + 0x14));
+- fuse_clk = ERR_PTR(-EINVAL);
+-
+- reg = tegra_fuse_readl(FUSE_SKU_INFO);
+- randomness[0] = reg;
+- tegra_sku_id = reg & 0xFF;
+-
+- reg = tegra_apb_readl(TEGRA_APB_MISC_BASE + STRAP_OPT);
+- randomness[1] = reg;
+- tegra_bct_strapping = (reg & RAM_ID_MASK) >> RAM_CODE_SHIFT;
+-
+- id = tegra_read_chipid();
+- randomness[2] = id;
+- tegra_chip_id = (id >> 8) & 0xff;
+-
+- switch (tegra_chip_id) {
+- case TEGRA20:
+- tegra_fuse_spare_bit = TEGRA20_FUSE_SPARE_BIT;
+- tegra_init_speedo_data = &tegra20_init_speedo_data;
+- break;
+- case TEGRA30:
+- tegra_fuse_spare_bit = TEGRA30_FUSE_SPARE_BIT;
+- tegra_init_speedo_data = &tegra30_init_speedo_data;
+- break;
+- case TEGRA114:
+- tegra_init_speedo_data = &tegra114_init_speedo_data;
+- break;
+- default:
+- pr_warn("Tegra: unknown chip id %d\n", tegra_chip_id);
+- tegra_fuse_spare_bit = TEGRA20_FUSE_SPARE_BIT;
+- tegra_init_speedo_data = &tegra_get_process_id;
+- }
+-
+- tegra_revision = tegra_get_revision(id);
+- tegra_init_speedo_data();
+- randomness[3] = (tegra_cpu_process_id << 16) | tegra_core_process_id;
+- randomness[4] = (tegra_cpu_speedo_id << 16) | tegra_soc_speedo_id;
+-
+- add_device_randomness(randomness, sizeof(randomness));
+- switch (tegra_chip_id) {
+- case TEGRA20:
+- tegra20_fuse_init_randomness();
+- break;
+- case TEGRA30:
+- case TEGRA114:
+- default:
+- tegra30_fuse_init_randomness();
+- break;
+- }
+-
+- pr_info("Tegra Revision: %s SKU: %d CPU Process: %d Core Process: %d\n",
+- tegra_revision_name[tegra_revision],
+- tegra_sku_id, tegra_cpu_process_id,
+- tegra_core_process_id);
+-}
+diff --git a/arch/arm/mach-tegra/fuse.h b/arch/arm/mach-tegra/fuse.h
+deleted file mode 100644
+index c01d047..0000000
+--- a/arch/arm/mach-tegra/fuse.h
++++ /dev/null
+@@ -1,79 +0,0 @@
+-/*
+- * Copyright (C) 2010 Google, Inc.
+- * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved.
+- *
+- * Author:
+- * Colin Cross <ccross@android.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.
+- *
+- */
+-
+-#ifndef __MACH_TEGRA_FUSE_H
+-#define __MACH_TEGRA_FUSE_H
+-
+-#define SKU_ID_T20 8
+-#define SKU_ID_T25SE 20
+-#define SKU_ID_AP25 23
+-#define SKU_ID_T25 24
+-#define SKU_ID_AP25E 27
+-#define SKU_ID_T25E 28
+-
+-#define TEGRA20 0x20
+-#define TEGRA30 0x30
+-#define TEGRA114 0x35
+-#define TEGRA124 0x40
+-
+-#ifndef __ASSEMBLY__
+-enum tegra_revision {
+- TEGRA_REVISION_UNKNOWN = 0,
+- TEGRA_REVISION_A01,
+- TEGRA_REVISION_A02,
+- TEGRA_REVISION_A03,
+- TEGRA_REVISION_A03p,
+- TEGRA_REVISION_A04,
+- TEGRA_REVISION_MAX,
+-};
+-
+-extern int tegra_sku_id;
+-extern int tegra_cpu_process_id;
+-extern int tegra_core_process_id;
+-extern int tegra_chip_id;
+-extern int tegra_cpu_speedo_id; /* only exist in Tegra30 and later */
+-extern int tegra_soc_speedo_id;
+-extern enum tegra_revision tegra_revision;
+-
+-extern int tegra_bct_strapping;
+-
+-unsigned long long tegra_chip_uid(void);
+-void tegra_init_fuse(void);
+-bool tegra_spare_fuse(int bit);
+-u32 tegra_fuse_readl(unsigned long offset);
+-
+-#ifdef CONFIG_ARCH_TEGRA_2x_SOC
+-void tegra20_init_speedo_data(void);
+-#else
+-static inline void tegra20_init_speedo_data(void) {}
+-#endif
+-
+-#ifdef CONFIG_ARCH_TEGRA_3x_SOC
+-void tegra30_init_speedo_data(void);
+-#else
+-static inline void tegra30_init_speedo_data(void) {}
+-#endif
+-
+-#ifdef CONFIG_ARCH_TEGRA_114_SOC
+-void tegra114_init_speedo_data(void);
+-#else
+-static inline void tegra114_init_speedo_data(void) {}
+-#endif
+-#endif /* __ASSEMBLY__ */
+-
+-#endif
+diff --git a/arch/arm/mach-tegra/hotplug.c b/arch/arm/mach-tegra/hotplug.c
+index ff26af2..38c5170 100644
+--- a/arch/arm/mach-tegra/hotplug.c
++++ b/arch/arm/mach-tegra/hotplug.c
+@@ -10,10 +10,10 @@
+ #include <linux/kernel.h>
+ #include <linux/smp.h>
+ #include <linux/clk/tegra.h>
++#include <linux/tegra-soc.h>
+
+ #include <asm/smp_plat.h>
+
+-#include "fuse.h"
+ #include "sleep.h"
+
+ static void (*tegra_hotplug_shutdown)(void);
+diff --git a/arch/arm/mach-tegra/platsmp.c b/arch/arm/mach-tegra/platsmp.c
+index 929d104..d9878ac 100644
+--- a/arch/arm/mach-tegra/platsmp.c
++++ b/arch/arm/mach-tegra/platsmp.c
+@@ -19,13 +19,13 @@
+ #include <linux/smp.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_plat.h>
+
+-#include "fuse.h"
+ #include "flowctrl.h"
+ #include "reset.h"
+ #include "pmc.h"
+diff --git a/arch/arm/mach-tegra/pm.c b/arch/arm/mach-tegra/pm.c
+index f55b05a..d7e6370 100644
+--- a/arch/arm/mach-tegra/pm.c
++++ b/arch/arm/mach-tegra/pm.c
+@@ -26,6 +26,7 @@
+ #include <linux/err.h>
+ #include <linux/slab.h>
+ #include <linux/clk/tegra.h>
++#include <linux/tegra-soc.h>
+
+ #include <asm/smp_plat.h>
+ #include <asm/cacheflush.h>
+@@ -37,7 +38,6 @@
+ #include "iomap.h"
+ #include "reset.h"
+ #include "flowctrl.h"
+-#include "fuse.h"
+ #include "pm.h"
+ #include "pmc.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>
+
+ #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 __iomem *tegra_pmc_base;
+ static bool tegra_pmc_invert_interrupt;
+ static struct clk *tegra_pclk;
++void __iomem *tegra_pmc_base;
+
+ struct pmc_pm_data {
+ u32 cpu_good_time; /* CPU power good time in uS */
+@@ -80,16 +79,6 @@ struct pmc_pm_data {
+ };
+ static struct pmc_pm_data pmc_pm_data;
+
+-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);
+-}
+-
+ static int tegra_pmc_get_cpu_powerdomain_id(int cpuid)
+ {
+ if (cpuid <= 0 || cpuid >= num_possible_cpus())
+diff --git a/arch/arm/mach-tegra/pmc.h b/arch/arm/mach-tegra/pmc.h
+index 59e19c34..139a3086 100644
+--- 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);
+diff --git a/arch/arm/mach-tegra/powergate.c b/arch/arm/mach-tegra/powergate.c
+index 4cefc5c..c90f303 100644
+--- 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>
+
+-#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);
+
+-static void __iomem *pmc = IO_ADDRESS(TEGRA_PMC_BASE);
+-
+-static u32 pmc_read(unsigned long reg)
+-{
+- return readl(pmc + reg);
+-}
+-
+-static void pmc_write(u32 val, unsigned long reg)
+-{
+- 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);
+
+- 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;
+ }
+
+- 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;
+
+- 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) {
+- 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);
+
+- 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);
+
+- 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);
+- 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)) {
+- 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)
+ {
+- 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;
+
+- value = pmc_read(request);
++ value = tegra_pmc_readl(request);
+ 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;
+
+- value = pmc_read(request);
++ value = tegra_pmc_readl(request);
+ 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)
+diff --git a/arch/arm/mach-tegra/reset-handler.S b/arch/arm/mach-tegra/reset-handler.S
+index 578d4d1..b9ff929 100644
+--- a/arch/arm/mach-tegra/reset-handler.S
++++ b/arch/arm/mach-tegra/reset-handler.S
+@@ -19,9 +19,9 @@
+
+ #include <asm/cache.h>
+ #include <asm/asm-offsets.h>
++#include <linux/tegra-soc.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
+--- a/arch/arm/mach-tegra/reset.c
++++ b/arch/arm/mach-tegra/reset.c
+@@ -22,12 +22,12 @@
+ #include <asm/cacheflush.h>
+ #include <asm/hardware/cache-l2x0.h>
+ #include <asm/firmware.h>
++#include <linux/tegra-soc.h>
+
+ #include "iomap.h"
+ #include "irammap.h"
+ #include "reset.h"
+ #include "sleep.h"
+-#include "fuse.h"
+
+ #define TEGRA_IRAM_RESET_BASE (TEGRA_IRAM_BASE + \
+ TEGRA_IRAM_RESET_HANDLER_OFFSET)
+diff --git a/arch/arm/mach-tegra/sleep-tegra30.S b/arch/arm/mach-tegra/sleep-tegra30.S
+index b16d4a57..f808c2c 100644
+--- a/arch/arm/mach-tegra/sleep-tegra30.S
++++ b/arch/arm/mach-tegra/sleep-tegra30.S
+@@ -15,13 +15,13 @@
+ */
+
+ #include <linux/linkage.h>
++#include <linux/tegra-soc.h>
+
+ #include <asm/assembler.h>
+ #include <asm/asm-offsets.h>
+ #include <asm/cache.h>
+
+ #include "irammap.h"
+-#include "fuse.h"
+ #include "sleep.h"
+ #include "flowctrl.h"
+
+diff --git a/arch/arm/mach-tegra/tegra.c b/arch/arm/mach-tegra/tegra.c
+index 15ac9fc..cf6a7ac 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>
++#include <linux/tegra-soc.h>
+
+ #include <asm/hardware/cache-l2x0.h>
+ #include <asm/mach-types.h>
+@@ -42,11 +43,9 @@
+ #include <asm/setup.h>
+ #include <asm/trusted_foundations.h>
+
+-#include "apbio.h"
+ #include "board.h"
+ #include "common.h"
+ #include "cpuidle.h"
+-#include "fuse.h"
+ #include "iomap.h"
+ #include "irq.h"
+ #include "pmc.h"
+@@ -73,7 +72,6 @@ u32 tegra_uart_config[3] = {
+ static void __init tegra_init_early(void)
+ {
+ of_register_trusted_foundations();
+- tegra_apb_io_init();
+ tegra_init_fuse();
+ tegra_cpu_reset_handler_init();
+ tegra_powergate_init();
+@@ -103,7 +101,8 @@ 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->revision = kasprintf(GFP_KERNEL, "%d",
++ tegra_sku_info.revision);
+ soc_dev_attr->soc_id = kasprintf(GFP_KERNEL, "%d", tegra_chip_id);
+
+ soc_dev = soc_device_register(soc_dev_attr);
+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
+--- a/arch/arm/mach-tegra/tegra114_speedo.c
++++ /dev/null
+@@ -1,104 +0,0 @@
+-/*
+- * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved.
+- *
+- * This program is free software; you can redistribute it and/or modify it
+- * under the terms and conditions of the GNU General Public License,
+- * version 2, as published by the Free Software Foundation.
+- *
+- * This program is distributed in the hope it will be useful, but WITHOUT
+- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+- * more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program. If not, see <http://www.gnu.org/licenses/>.
+- */
+-
+-#include <linux/kernel.h>
+-#include <linux/bug.h>
+-
+-#include "fuse.h"
+-
+-#define CORE_PROCESS_CORNERS_NUM 2
+-#define CPU_PROCESS_CORNERS_NUM 2
+-
+-enum {
+- THRESHOLD_INDEX_0,
+- THRESHOLD_INDEX_1,
+- THRESHOLD_INDEX_COUNT,
+-};
+-
+-static const u32 core_process_speedos[][CORE_PROCESS_CORNERS_NUM] = {
+- {1123, UINT_MAX},
+- {0, UINT_MAX},
+-};
+-
+-static const u32 cpu_process_speedos[][CPU_PROCESS_CORNERS_NUM] = {
+- {1695, UINT_MAX},
+- {0, UINT_MAX},
+-};
+-
+-static void rev_sku_to_speedo_ids(int rev, int sku, int *threshold)
+-{
+- u32 tmp;
+-
+- switch (sku) {
+- case 0x00:
+- case 0x10:
+- case 0x05:
+- case 0x06:
+- tegra_cpu_speedo_id = 1;
+- tegra_soc_speedo_id = 0;
+- *threshold = THRESHOLD_INDEX_0;
+- break;
+-
+- case 0x03:
+- case 0x04:
+- tegra_cpu_speedo_id = 2;
+- tegra_soc_speedo_id = 1;
+- *threshold = THRESHOLD_INDEX_1;
+- break;
+-
+- default:
+- pr_err("Tegra114 Unknown SKU %d\n", sku);
+- tegra_cpu_speedo_id = 0;
+- tegra_soc_speedo_id = 0;
+- *threshold = THRESHOLD_INDEX_0;
+- break;
+- }
+-
+- if (rev == TEGRA_REVISION_A01) {
+- tmp = tegra_fuse_readl(0x270) << 1;
+- tmp |= tegra_fuse_readl(0x26c);
+- if (!tmp)
+- tegra_cpu_speedo_id = 0;
+- }
+-}
+-
+-void tegra114_init_speedo_data(void)
+-{
+- u32 cpu_speedo_val;
+- u32 core_speedo_val;
+- int threshold;
+- int i;
+-
+- BUILD_BUG_ON(ARRAY_SIZE(cpu_process_speedos) !=
+- THRESHOLD_INDEX_COUNT);
+- BUILD_BUG_ON(ARRAY_SIZE(core_process_speedos) !=
+- THRESHOLD_INDEX_COUNT);
+-
+- rev_sku_to_speedo_ids(tegra_revision, tegra_sku_id, &threshold);
+-
+- cpu_speedo_val = tegra_fuse_readl(0x12c) + 1024;
+- core_speedo_val = tegra_fuse_readl(0x134);
+-
+- for (i = 0; i < CPU_PROCESS_CORNERS_NUM; i++)
+- if (cpu_speedo_val < cpu_process_speedos[threshold][i])
+- break;
+- tegra_cpu_process_id = i;
+-
+- for (i = 0; i < CORE_PROCESS_CORNERS_NUM; i++)
+- if (core_speedo_val < core_process_speedos[threshold][i])
+- break;
+- tegra_core_process_id = i;
+-}
+diff --git a/arch/arm/mach-tegra/tegra20_speedo.c b/arch/arm/mach-tegra/tegra20_speedo.c
+deleted file mode 100644
+index fa6eb57..0000000
+--- a/arch/arm/mach-tegra/tegra20_speedo.c
++++ /dev/null
+@@ -1,109 +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/>.
+- */
+-
+-#include <linux/kernel.h>
+-#include <linux/bug.h>
+-
+-#include "fuse.h"
+-
+-#define CPU_SPEEDO_LSBIT 20
+-#define CPU_SPEEDO_MSBIT 29
+-#define CPU_SPEEDO_REDUND_LSBIT 30
+-#define CPU_SPEEDO_REDUND_MSBIT 39
+-#define CPU_SPEEDO_REDUND_OFFS (CPU_SPEEDO_REDUND_MSBIT - CPU_SPEEDO_MSBIT)
+-
+-#define CORE_SPEEDO_LSBIT 40
+-#define CORE_SPEEDO_MSBIT 47
+-#define CORE_SPEEDO_REDUND_LSBIT 48
+-#define CORE_SPEEDO_REDUND_MSBIT 55
+-#define CORE_SPEEDO_REDUND_OFFS (CORE_SPEEDO_REDUND_MSBIT - CORE_SPEEDO_MSBIT)
+-
+-#define SPEEDO_MULT 4
+-
+-#define PROCESS_CORNERS_NUM 4
+-
+-#define SPEEDO_ID_SELECT_0(rev) ((rev) <= 2)
+-#define SPEEDO_ID_SELECT_1(sku) \
+- (((sku) != 20) && ((sku) != 23) && ((sku) != 24) && \
+- ((sku) != 27) && ((sku) != 28))
+-
+-enum {
+- SPEEDO_ID_0,
+- SPEEDO_ID_1,
+- SPEEDO_ID_2,
+- SPEEDO_ID_COUNT,
+-};
+-
+-static const u32 cpu_process_speedos[][PROCESS_CORNERS_NUM] = {
+- {315, 366, 420, UINT_MAX},
+- {303, 368, 419, UINT_MAX},
+- {316, 331, 383, UINT_MAX},
+-};
+-
+-static const u32 core_process_speedos[][PROCESS_CORNERS_NUM] = {
+- {165, 195, 224, UINT_MAX},
+- {165, 195, 224, UINT_MAX},
+- {165, 195, 224, UINT_MAX},
+-};
+-
+-void tegra20_init_speedo_data(void)
+-{
+- u32 reg;
+- u32 val;
+- int i;
+-
+- BUILD_BUG_ON(ARRAY_SIZE(cpu_process_speedos) != SPEEDO_ID_COUNT);
+- BUILD_BUG_ON(ARRAY_SIZE(core_process_speedos) != SPEEDO_ID_COUNT);
+-
+- if (SPEEDO_ID_SELECT_0(tegra_revision))
+- tegra_soc_speedo_id = SPEEDO_ID_0;
+- else if (SPEEDO_ID_SELECT_1(tegra_sku_id))
+- tegra_soc_speedo_id = SPEEDO_ID_1;
+- else
+- tegra_soc_speedo_id = SPEEDO_ID_2;
+-
+- val = 0;
+- for (i = CPU_SPEEDO_MSBIT; i >= CPU_SPEEDO_LSBIT; i--) {
+- reg = tegra_spare_fuse(i) |
+- tegra_spare_fuse(i + CPU_SPEEDO_REDUND_OFFS);
+- val = (val << 1) | (reg & 0x1);
+- }
+- val = val * SPEEDO_MULT;
+- pr_debug("%s CPU speedo value %u\n", __func__, val);
+-
+- for (i = 0; i < (PROCESS_CORNERS_NUM - 1); i++) {
+- if (val <= cpu_process_speedos[tegra_soc_speedo_id][i])
+- break;
+- }
+- tegra_cpu_process_id = i;
+-
+- val = 0;
+- for (i = CORE_SPEEDO_MSBIT; i >= CORE_SPEEDO_LSBIT; i--) {
+- reg = tegra_spare_fuse(i) |
+- tegra_spare_fuse(i + CORE_SPEEDO_REDUND_OFFS);
+- val = (val << 1) | (reg & 0x1);
+- }
+- val = val * SPEEDO_MULT;
+- pr_debug("%s Core speedo value %u\n", __func__, val);
+-
+- for (i = 0; i < (PROCESS_CORNERS_NUM - 1); i++) {
+- if (val <= core_process_speedos[tegra_soc_speedo_id][i])
+- break;
+- }
+- tegra_core_process_id = i;
+-
+- pr_info("Tegra20 Soc Speedo ID %d", tegra_soc_speedo_id);
+-}
+diff --git a/arch/arm/mach-tegra/tegra30_speedo.c b/arch/arm/mach-tegra/tegra30_speedo.c
+deleted file mode 100644
+index 125cb16..0000000
+--- a/arch/arm/mach-tegra/tegra30_speedo.c
++++ /dev/null
+@@ -1,292 +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/>.
+- */
+-
+-#include <linux/kernel.h>
+-#include <linux/bug.h>
+-
+-#include "fuse.h"
+-
+-#define CORE_PROCESS_CORNERS_NUM 1
+-#define CPU_PROCESS_CORNERS_NUM 6
+-
+-#define FUSE_SPEEDO_CALIB_0 0x114
+-#define FUSE_PACKAGE_INFO 0X1FC
+-#define FUSE_TEST_PROG_VER 0X128
+-
+-#define G_SPEEDO_BIT_MINUS1 58
+-#define G_SPEEDO_BIT_MINUS1_R 59
+-#define G_SPEEDO_BIT_MINUS2 60
+-#define G_SPEEDO_BIT_MINUS2_R 61
+-#define LP_SPEEDO_BIT_MINUS1 62
+-#define LP_SPEEDO_BIT_MINUS1_R 63
+-#define LP_SPEEDO_BIT_MINUS2 64
+-#define LP_SPEEDO_BIT_MINUS2_R 65
+-
+-enum {
+- THRESHOLD_INDEX_0,
+- THRESHOLD_INDEX_1,
+- THRESHOLD_INDEX_2,
+- THRESHOLD_INDEX_3,
+- THRESHOLD_INDEX_4,
+- THRESHOLD_INDEX_5,
+- THRESHOLD_INDEX_6,
+- THRESHOLD_INDEX_7,
+- THRESHOLD_INDEX_8,
+- THRESHOLD_INDEX_9,
+- THRESHOLD_INDEX_10,
+- THRESHOLD_INDEX_11,
+- THRESHOLD_INDEX_COUNT,
+-};
+-
+-static const u32 core_process_speedos[][CORE_PROCESS_CORNERS_NUM] = {
+- {180},
+- {170},
+- {195},
+- {180},
+- {168},
+- {192},
+- {180},
+- {170},
+- {195},
+- {180},
+- {180},
+- {180},
+-};
+-
+-static const u32 cpu_process_speedos[][CPU_PROCESS_CORNERS_NUM] = {
+- {306, 338, 360, 376, UINT_MAX},
+- {295, 336, 358, 375, UINT_MAX},
+- {325, 325, 358, 375, UINT_MAX},
+- {325, 325, 358, 375, UINT_MAX},
+- {292, 324, 348, 364, UINT_MAX},
+- {324, 324, 348, 364, UINT_MAX},
+- {324, 324, 348, 364, UINT_MAX},
+- {295, 336, 358, 375, UINT_MAX},
+- {358, 358, 358, 358, 397, UINT_MAX},
+- {364, 364, 364, 364, 397, UINT_MAX},
+- {295, 336, 358, 375, 391, UINT_MAX},
+- {295, 336, 358, 375, 391, UINT_MAX},
+-};
+-
+-static int threshold_index;
+-static int package_id;
+-
+-static void fuse_speedo_calib(u32 *speedo_g, u32 *speedo_lp)
+-{
+- u32 reg;
+- int ate_ver;
+- int bit_minus1;
+- int bit_minus2;
+-
+- reg = tegra_fuse_readl(FUSE_SPEEDO_CALIB_0);
+-
+- *speedo_lp = (reg & 0xFFFF) * 4;
+- *speedo_g = ((reg >> 16) & 0xFFFF) * 4;
+-
+- ate_ver = tegra_fuse_readl(FUSE_TEST_PROG_VER);
+- pr_info("%s: ATE prog ver %d.%d\n", __func__, ate_ver/10, ate_ver%10);
+-
+- if (ate_ver >= 26) {
+- bit_minus1 = tegra_spare_fuse(LP_SPEEDO_BIT_MINUS1);
+- bit_minus1 |= tegra_spare_fuse(LP_SPEEDO_BIT_MINUS1_R);
+- bit_minus2 = tegra_spare_fuse(LP_SPEEDO_BIT_MINUS2);
+- bit_minus2 |= tegra_spare_fuse(LP_SPEEDO_BIT_MINUS2_R);
+- *speedo_lp |= (bit_minus1 << 1) | bit_minus2;
+-
+- bit_minus1 = tegra_spare_fuse(G_SPEEDO_BIT_MINUS1);
+- bit_minus1 |= tegra_spare_fuse(G_SPEEDO_BIT_MINUS1_R);
+- bit_minus2 = tegra_spare_fuse(G_SPEEDO_BIT_MINUS2);
+- bit_minus2 |= tegra_spare_fuse(G_SPEEDO_BIT_MINUS2_R);
+- *speedo_g |= (bit_minus1 << 1) | bit_minus2;
+- } else {
+- *speedo_lp |= 0x3;
+- *speedo_g |= 0x3;
+- }
+-}
+-
+-static void rev_sku_to_speedo_ids(int rev, int sku)
+-{
+- switch (rev) {
+- case TEGRA_REVISION_A01:
+- tegra_cpu_speedo_id = 0;
+- tegra_soc_speedo_id = 0;
+- threshold_index = THRESHOLD_INDEX_0;
+- break;
+- case TEGRA_REVISION_A02:
+- case TEGRA_REVISION_A03:
+- switch (sku) {
+- case 0x87:
+- case 0x82:
+- tegra_cpu_speedo_id = 1;
+- tegra_soc_speedo_id = 1;
+- threshold_index = THRESHOLD_INDEX_1;
+- break;
+- case 0x81:
+- switch (package_id) {
+- case 1:
+- tegra_cpu_speedo_id = 2;
+- tegra_soc_speedo_id = 2;
+- threshold_index = THRESHOLD_INDEX_2;
+- break;
+- case 2:
+- tegra_cpu_speedo_id = 4;
+- tegra_soc_speedo_id = 1;
+- threshold_index = THRESHOLD_INDEX_7;
+- break;
+- default:
+- pr_err("Tegra30: Unknown pkg %d\n", package_id);
+- BUG();
+- break;
+- }
+- break;
+- case 0x80:
+- switch (package_id) {
+- case 1:
+- tegra_cpu_speedo_id = 5;
+- tegra_soc_speedo_id = 2;
+- threshold_index = THRESHOLD_INDEX_8;
+- break;
+- case 2:
+- tegra_cpu_speedo_id = 6;
+- tegra_soc_speedo_id = 2;
+- threshold_index = THRESHOLD_INDEX_9;
+- break;
+- default:
+- pr_err("Tegra30: Unknown pkg %d\n", package_id);
+- BUG();
+- break;
+- }
+- break;
+- case 0x83:
+- switch (package_id) {
+- case 1:
+- tegra_cpu_speedo_id = 7;
+- tegra_soc_speedo_id = 1;
+- threshold_index = THRESHOLD_INDEX_10;
+- break;
+- case 2:
+- tegra_cpu_speedo_id = 3;
+- tegra_soc_speedo_id = 2;
+- threshold_index = THRESHOLD_INDEX_3;
+- break;
+- default:
+- pr_err("Tegra30: Unknown pkg %d\n", package_id);
+- BUG();
+- break;
+- }
+- break;
+- case 0x8F:
+- tegra_cpu_speedo_id = 8;
+- tegra_soc_speedo_id = 1;
+- threshold_index = THRESHOLD_INDEX_11;
+- break;
+- case 0x08:
+- tegra_cpu_speedo_id = 1;
+- tegra_soc_speedo_id = 1;
+- threshold_index = THRESHOLD_INDEX_4;
+- break;
+- case 0x02:
+- tegra_cpu_speedo_id = 2;
+- tegra_soc_speedo_id = 2;
+- threshold_index = THRESHOLD_INDEX_5;
+- break;
+- case 0x04:
+- tegra_cpu_speedo_id = 3;
+- tegra_soc_speedo_id = 2;
+- threshold_index = THRESHOLD_INDEX_6;
+- break;
+- case 0:
+- switch (package_id) {
+- case 1:
+- tegra_cpu_speedo_id = 2;
+- tegra_soc_speedo_id = 2;
+- threshold_index = THRESHOLD_INDEX_2;
+- break;
+- case 2:
+- tegra_cpu_speedo_id = 3;
+- tegra_soc_speedo_id = 2;
+- threshold_index = THRESHOLD_INDEX_3;
+- break;
+- default:
+- pr_err("Tegra30: Unknown pkg %d\n", package_id);
+- BUG();
+- break;
+- }
+- break;
+- default:
+- pr_warn("Tegra30: Unknown SKU %d\n", sku);
+- tegra_cpu_speedo_id = 0;
+- tegra_soc_speedo_id = 0;
+- threshold_index = THRESHOLD_INDEX_0;
+- break;
+- }
+- break;
+- default:
+- pr_warn("Tegra30: Unknown chip rev %d\n", rev);
+- tegra_cpu_speedo_id = 0;
+- tegra_soc_speedo_id = 0;
+- threshold_index = THRESHOLD_INDEX_0;
+- break;
+- }
+-}
+-
+-void tegra30_init_speedo_data(void)
+-{
+- u32 cpu_speedo_val;
+- u32 core_speedo_val;
+- int i;
+-
+- BUILD_BUG_ON(ARRAY_SIZE(cpu_process_speedos) !=
+- THRESHOLD_INDEX_COUNT);
+- BUILD_BUG_ON(ARRAY_SIZE(core_process_speedos) !=
+- THRESHOLD_INDEX_COUNT);
+-
+- package_id = tegra_fuse_readl(FUSE_PACKAGE_INFO) & 0x0F;
+-
+- rev_sku_to_speedo_ids(tegra_revision, tegra_sku_id);
+- fuse_speedo_calib(&cpu_speedo_val, &core_speedo_val);
+- pr_debug("%s CPU speedo value %u\n", __func__, cpu_speedo_val);
+- pr_debug("%s Core speedo value %u\n", __func__, core_speedo_val);
+-
+- for (i = 0; i < CPU_PROCESS_CORNERS_NUM; i++) {
+- if (cpu_speedo_val < cpu_process_speedos[threshold_index][i])
+- break;
+- }
+- tegra_cpu_process_id = i - 1;
+-
+- if (tegra_cpu_process_id == -1) {
+- pr_warn("Tegra30: CPU speedo value %3d out of range",
+- cpu_speedo_val);
+- tegra_cpu_process_id = 0;
+- tegra_cpu_speedo_id = 1;
+- }
+-
+- for (i = 0; i < CORE_PROCESS_CORNERS_NUM; i++) {
+- if (core_speedo_val < core_process_speedos[threshold_index][i])
+- break;
+- }
+- tegra_core_process_id = i - 1;
+-
+- if (tegra_core_process_id == -1) {
+- pr_warn("Tegra30: CORE speedo value %3d out of range",
+- core_speedo_val);
+- tegra_core_process_id = 0;
+- tegra_soc_speedo_id = 1;
+- }
+-
+- pr_info("Tegra30: CPU Speedo ID %d, Soc Speedo ID %d",
+- tegra_cpu_speedo_id, tegra_soc_speedo_id);
+-}
+diff --git a/drivers/clocksource/tegra20_timer.c b/drivers/clocksource/tegra20_timer.c
+index d1869f0..d2616ef 100644
+--- a/drivers/clocksource/tegra20_timer.c
++++ b/drivers/clocksource/tegra20_timer.c
+@@ -27,6 +27,7 @@
+ #include <linux/of_address.h>
+ #include <linux/of_irq.h>
+ #include <linux/sched_clock.h>
++#include <linux/delay.h>
+
+ #include <asm/mach/time.h>
+ #include <asm/smp_twd.h>
+@@ -53,6 +54,8 @@ static void __iomem *rtc_base;
+ static struct timespec persistent_ts;
+ static u64 persistent_ms, last_persistent_ms;
+
++static struct delay_timer tegra_delay_timer;
++
+ #define timer_writel(value, reg) \
+ __raw_writel(value, timer_reg_base + (reg))
+ #define timer_readl(reg) \
+@@ -139,6 +142,11 @@ static void tegra_read_persistent_clock(struct timespec *ts)
+ *ts = *tsp;
+ }
+
++static unsigned long tegra_delay_timer_read_counter_long(void)
++{
++ return readl(timer_reg_base + TIMERUS_CNTR_1US);
++}
++
+ static irqreturn_t tegra_timer_interrupt(int irq, void *dev_id)
+ {
+ struct clock_event_device *evt = (struct clock_event_device *)dev_id;
+@@ -206,6 +214,11 @@ static void __init tegra20_init_timer(struct device_node *np)
+ BUG();
+ }
+
++ tegra_delay_timer.read_current_timer =
++ tegra_delay_timer_read_counter_long;
++ tegra_delay_timer.freq = 1000000;
++ register_current_timer_delay(&tegra_delay_timer);
++
+ 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
+--- /dev/null
++++ 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
+new file mode 100644
+index 0000000..3af357d
+--- /dev/null
++++ b/drivers/misc/fuse/tegra/Makefile
+@@ -0,0 +1,8 @@
++obj-y += fuse-tegra.o
++obj-y += fuse-tegra30.o
++obj-y += tegra-apbmisc.o
++obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += fuse-tegra20.o
++obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += speedo-tegra20.o
++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
+new file mode 100644
+index 0000000..934073e
+--- /dev/null
++++ b/drivers/misc/fuse/tegra/fuse-tegra.c
+@@ -0,0 +1,154 @@
++/*
++ * Copyright (c) 2013-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.
++ *
++ * 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/device.h>
++#include <linux/kobject.h>
++#include <linux/kernel.h>
++#include <linux/platform_device.h>
++#include <linux/of.h>
++#include <linux/of_address.h>
++#include <linux/io.h>
++#include <linux/tegra-soc.h>
++
++#include "fuse.h"
++
++static u32 (*fuse_readl)(const unsigned int offset);
++static int fuse_size;
++struct tegra_sku_info tegra_sku_info;
++
++static const char *tegra_revision_name[TEGRA_REVISION_MAX] = {
++ [TEGRA_REVISION_UNKNOWN] = "unknown",
++ [TEGRA_REVISION_A01] = "A01",
++ [TEGRA_REVISION_A02] = "A02",
++ [TEGRA_REVISION_A03] = "A03",
++ [TEGRA_REVISION_A03p] = "A03 prime",
++ [TEGRA_REVISION_A04] = "A04",
++};
++
++static u8 fuse_readb(const unsigned int offset)
++{
++ u32 val;
++
++ val = fuse_readl(round_down(offset, 4));
++ val >>= (offset % 4) * 8;
++ val &= 0xff;
++
++ return val;
++}
++
++static ssize_t fuse_read(struct file *fd, struct kobject *kobj,
++ struct bin_attribute *attr, char *buf,
++ loff_t pos, size_t size)
++{
++ int i;
++
++ if (pos < 0 || pos >= fuse_size)
++ return 0;
++
++ if (size > fuse_size - pos)
++ size = fuse_size - pos;
++
++ for (i = 0; i < size; i++)
++ buf[i] = fuse_readb(pos + i);
++
++ return i;
++}
++
++static struct bin_attribute fuse_bin_attr = {
++ .attr = { .name = "fuse", .mode = S_IRUGO, },
++ .read = fuse_read,
++};
++
++static const struct of_device_id car_match[] __initconst = {
++ { .compatible = "nvidia,tegra20-car", },
++ { .compatible = "nvidia,tegra30-car", },
++ { .compatible = "nvidia,tegra114-car", },
++ { .compatible = "nvidia,tegra124-car", },
++ {},
++};
++
++static void tegra_enable_fuse_clk(void __iomem *base)
++{
++ u32 reg;
++
++ reg = readl_relaxed(base + 0x48);
++ reg |= 1 << 28;
++ writel(reg, base + 0x48);
++
++ /*
++ * Enable FUSE clock. This needs to be hardcoded because the clock
++ * subsystem is not active during early boot.
++ */
++ reg = readl(base + 0x14);
++ reg |= 1 << 7;
++ writel(reg, base + 0x14);
++}
++
++int tegra_fuse_readl(u32 offset, u32 *val)
++{
++ if (!fuse_readl)
++ return -EPROBE_DEFER;
++
++ *val = fuse_readl(offset);
++
++ return 0;
++}
++
++int tegra_fuse_create_sysfs(struct device *dev, int size,
++ u32 (*readl)(const unsigned int offset))
++{
++ if (fuse_size)
++ return -ENODEV;
++
++ fuse_bin_attr.size = size;
++ fuse_bin_attr.read = fuse_read;
++
++ fuse_size = size;
++ fuse_readl = readl;
++
++ return device_create_bin_file(dev, &fuse_bin_attr);
++}
++
++void __init tegra_init_fuse(void)
++{
++ struct device_node *np;
++ void __iomem *car_base;
++
++ tegra_init_apbmisc();
++
++ np = of_find_matching_node(NULL, car_match);
++ car_base = of_iomap(np, 0);
++ if (car_base) {
++ tegra_enable_fuse_clk(car_base);
++ iounmap(car_base);
++ } else {
++ pr_err("Could not enable fuse clk. ioremap tegra car failed.\n");
++ return;
++ }
++
++ if (tegra_chip_id == TEGRA20)
++ tegra20_init_fuse_early();
++ else
++ tegra30_init_fuse_early();
++
++ pr_info("Tegra Revision: %s SKU: %d CPU Process: %d Core Process: %d\n",
++ tegra_revision_name[tegra_sku_info.revision],
++ tegra_sku_info.sku_id, tegra_sku_info.cpu_process_id,
++ 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);
++}
+diff --git a/drivers/misc/fuse/tegra/fuse-tegra20.c b/drivers/misc/fuse/tegra/fuse-tegra20.c
+new file mode 100644
+index 0000000..c3dcf11
+--- /dev/null
++++ b/drivers/misc/fuse/tegra/fuse-tegra20.c
+@@ -0,0 +1,214 @@
++/*
++ * Copyright (c) 2013-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.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program. If not, see <http://www.gnu.org/licenses/>.
++ *
++ * Based on drivers/misc/eeprom/sunxi_sid.c
++ */
++
++#include <linux/device.h>
++#include <linux/clk.h>
++#include <linux/completion.h>
++#include <linux/dmaengine.h>
++#include <linux/dma-mapping.h>
++#include <linux/err.h>
++#include <linux/io.h>
++#include <linux/kernel.h>
++#include <linux/kobject.h>
++#include <linux/of_device.h>
++#include <linux/platform_device.h>
++#include <linux/random.h>
++#include <linux/tegra-soc.h>
++
++#include "fuse.h"
++
++#define FUSE_BEGIN 0x100
++#define FUSE_SIZE 0x1f8
++#define FUSE_UID_LOW 0x08
++#define FUSE_UID_HIGH 0x0c
++
++static phys_addr_t fuse_phys;
++static struct clk *fuse_clk;
++static void __iomem __initdata *fuse_base;
++
++static DEFINE_MUTEX(apb_dma_lock);
++static DECLARE_COMPLETION(apb_dma_wait);
++static struct dma_chan *apb_dma_chan;
++static struct dma_slave_config dma_sconfig;
++static u32 *apb_buffer;
++static dma_addr_t apb_buffer_phys;
++
++static void apb_dma_complete(void *args)
++{
++ complete(&apb_dma_wait);
++}
++
++static u32 tegra20_fuse_readl(const unsigned int offset)
++{
++ int ret;
++ u32 val = 0;
++ struct dma_async_tx_descriptor *dma_desc;
++
++ mutex_lock(&apb_dma_lock);
++
++ dma_sconfig.src_addr = fuse_phys + FUSE_BEGIN + offset;
++ ret = dmaengine_slave_config(apb_dma_chan, &dma_sconfig);
++ if (ret)
++ goto out;
++
++ dma_desc = dmaengine_prep_slave_single(apb_dma_chan, apb_buffer_phys,
++ sizeof(u32), DMA_DEV_TO_MEM,
++ DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
++ if (!dma_desc)
++ goto out;
++
++ dma_desc->callback = apb_dma_complete;
++ dma_desc->callback_param = NULL;
++
++ reinit_completion(&apb_dma_wait);
++
++ clk_prepare_enable(fuse_clk);
++
++ dmaengine_submit(dma_desc);
++ dma_async_issue_pending(apb_dma_chan);
++ ret = wait_for_completion_timeout(&apb_dma_wait, msecs_to_jiffies(50));
++
++ if (WARN(ret == 0, "apb read dma timed out"))
++ dmaengine_terminate_all(apb_dma_chan);
++ else
++ val = *apb_buffer;
++
++ clk_disable_unprepare(fuse_clk);
++out:
++ mutex_unlock(&apb_dma_lock);
++
++ return val;
++}
++
++static const struct of_device_id tegra20_fuse_of_match[] = {
++ { .compatible = "nvidia,tegra20-efuse" },
++ {},
++};
++
++static int apb_dma_init(void)
++{
++ dma_cap_mask_t mask;
++
++ dma_cap_zero(mask);
++ dma_cap_set(DMA_SLAVE, mask);
++ apb_dma_chan = dma_request_channel(mask, NULL, NULL);
++ if (!apb_dma_chan)
++ return -EPROBE_DEFER;
++
++ apb_buffer = dma_alloc_coherent(NULL, sizeof(u32), &apb_buffer_phys,
++ GFP_KERNEL);
++ if (!apb_buffer) {
++ dma_release_channel(apb_dma_chan);
++ return -ENOMEM;
++ }
++
++ dma_sconfig.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
++ dma_sconfig.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
++ dma_sconfig.src_maxburst = 1;
++ dma_sconfig.dst_maxburst = 1;
++
++ return 0;
++}
++
++static int tegra20_fuse_probe(struct platform_device *pdev)
++{
++ struct resource *res;
++ int err;
++
++ fuse_clk = devm_clk_get(&pdev->dev, NULL);
++ if (IS_ERR(fuse_clk)) {
++ dev_err(&pdev->dev, "missing clock");
++ return PTR_ERR(fuse_clk);
++ }
++
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ if (!res)
++ return -EINVAL;
++ fuse_phys = res->start;
++
++ err = apb_dma_init();
++ if (err)
++ return err;
++
++ if (tegra_fuse_create_sysfs(&pdev->dev, FUSE_SIZE, tegra20_fuse_readl))
++ return -ENODEV;
++
++ dev_dbg(&pdev->dev, "loaded\n");
++
++ return 0;
++}
++
++static struct platform_driver tegra20_fuse_driver = {
++ .probe = tegra20_fuse_probe,
++ .driver = {
++ .name = "tegra20_fuse",
++ .owner = THIS_MODULE,
++ .of_match_table = tegra20_fuse_of_match,
++ }
++};
++
++static int __init tegra20_fuse_init(void)
++{
++ return platform_driver_register(&tegra20_fuse_driver);
++}
++postcore_initcall(tegra20_fuse_init);
++
++/* Early boot code. This code is called before the devices are created */
++
++u32 __init tegra20_fuse_early(const unsigned int offset)
++{
++ return readl_relaxed(fuse_base + FUSE_BEGIN + offset);
++}
++
++bool __init tegra20_spare_fuse_early(int spare_bit)
++{
++ u32 offset = spare_bit * 4;
++ bool value;
++
++ value = tegra20_fuse_early(offset + 0x100);
++
++ return value;
++}
++
++static void __init tegra20_fuse_add_randomness(void)
++{
++ u32 randomness[7];
++
++ randomness[0] = tegra_sku_info.sku_id;
++ randomness[1] = tegra_read_straps();
++ randomness[2] = tegra_read_chipid();
++ randomness[3] = tegra_sku_info.cpu_process_id << 16;
++ randomness[3] |= tegra_sku_info.core_process_id;
++ randomness[4] = tegra_sku_info.cpu_speedo_id << 16;
++ randomness[4] |= tegra_sku_info.soc_speedo_id;
++ randomness[5] = tegra20_fuse_early(FUSE_UID_LOW);
++ randomness[6] = tegra20_fuse_early(FUSE_UID_HIGH);
++
++ add_device_randomness(randomness, sizeof(randomness));
++}
++
++void __init tegra20_init_fuse_early(void)
++{
++ fuse_base = ioremap(TEGRA_FUSE_BASE, TEGRA_FUSE_SIZE);
++
++ tegra_init_revision();
++ tegra20_init_speedo_data(&tegra_sku_info);
++ tegra20_fuse_add_randomness();
++
++ iounmap(fuse_base);
++}
+diff --git a/drivers/misc/fuse/tegra/fuse-tegra30.c b/drivers/misc/fuse/tegra/fuse-tegra30.c
+new file mode 100644
+index 0000000..8aef5d0
+--- /dev/null
++++ b/drivers/misc/fuse/tegra/fuse-tegra30.c
+@@ -0,0 +1,223 @@
++/*
++ * Copyright (c) 2013-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.
++ *
++ * 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/device.h>
++#include <linux/clk.h>
++#include <linux/err.h>
++#include <linux/io.h>
++#include <linux/kernel.h>
++#include <linux/of_device.h>
++#include <linux/of_address.h>
++#include <linux/platform_device.h>
++#include <linux/random.h>
++#include <linux/tegra-soc.h>
++
++#include "fuse.h"
++
++#define FUSE_BEGIN 0x100
++
++/* Tegra30 and later */
++#define FUSE_VENDOR_CODE 0x100
++#define FUSE_FAB_CODE 0x104
++#define FUSE_LOT_CODE_0 0x108
++#define FUSE_LOT_CODE_1 0x10c
++#define FUSE_WAFER_ID 0x110
++#define FUSE_X_COORDINATE 0x114
++#define FUSE_Y_COORDINATE 0x118
++
++#define FUSE_HAS_REVISION_INFO BIT(0)
++
++enum speedo_idx {
++ SPEEDO_TEGRA30 = 0,
++ SPEEDO_TEGRA114,
++ SPEEDO_TEGRA124,
++};
++
++struct tegra_fuse_info {
++ int size;
++ int spare_bit;
++ enum speedo_idx speedo_idx;
++};
++
++static void __iomem *fuse_base;
++static struct clk *fuse_clk;
++static struct tegra_fuse_info *fuse_info;
++
++u32 tegra30_fuse_readl(const unsigned int offset)
++{
++ u32 val;
++
++ /*
++ * early in the boot, the fuse clock will be enabled by
++ * tegra_init_fuse()
++ */
++
++ if (fuse_clk)
++ clk_prepare_enable(fuse_clk);
++
++ val = readl_relaxed(fuse_base + FUSE_BEGIN + offset);
++
++ if (fuse_clk)
++ clk_disable_unprepare(fuse_clk);
++
++ return val;
++}
++
++static struct tegra_fuse_info tegra30_info = {
++ .size = 0x2a4,
++ .spare_bit = 0x144,
++ .speedo_idx = SPEEDO_TEGRA30,
++};
++
++static struct tegra_fuse_info tegra114_info = {
++ .size = 0x2a0,
++ .speedo_idx = SPEEDO_TEGRA114,
++};
++
++static struct tegra_fuse_info tegra124_info = {
++ .size = 0x300,
++ .speedo_idx = SPEEDO_TEGRA124,
++};
++
++static const struct of_device_id tegra30_fuse_of_match[] = {
++ { .compatible = "nvidia,tegra30-efuse", .data = &tegra30_info },
++ { .compatible = "nvidia,tegra114-efuse", .data = &tegra114_info },
++ { .compatible = "nvidia,tegra124-efuse", .data = &tegra124_info },
++ {},
++};
++
++static int tegra30_fuse_probe(struct platform_device *pdev)
++{
++ const struct of_device_id *of_dev_id;
++
++ of_dev_id = of_match_device(tegra30_fuse_of_match, &pdev->dev);
++ if (!of_dev_id)
++ return -ENODEV;
++
++ fuse_clk = devm_clk_get(&pdev->dev, NULL);
++ if (IS_ERR(fuse_clk)) {
++ dev_err(&pdev->dev, "missing clock");
++ return PTR_ERR(fuse_clk);
++ }
++
++ platform_set_drvdata(pdev, NULL);
++
++ if (tegra_fuse_create_sysfs(&pdev->dev, fuse_info->size,
++ tegra30_fuse_readl))
++ return -ENODEV;
++
++ dev_dbg(&pdev->dev, "loaded\n");
++
++ return 0;
++}
++
++static struct platform_driver tegra30_fuse_driver = {
++ .probe = tegra30_fuse_probe,
++ .driver = {
++ .name = "tegra_fuse",
++ .owner = THIS_MODULE,
++ .of_match_table = tegra30_fuse_of_match,
++ }
++};
++
++static int __init tegra30_fuse_init(void)
++{
++ return platform_driver_register(&tegra30_fuse_driver);
++}
++postcore_initcall(tegra30_fuse_init);
++
++/* Early boot code. This code is called before the devices are created */
++
++typedef void (*speedo_f)(struct tegra_sku_info *sku_info);
++
++static speedo_f __initdata speedo_tbl[] = {
++ [SPEEDO_TEGRA30] = tegra30_init_speedo_data,
++ [SPEEDO_TEGRA114] = tegra114_init_speedo_data,
++ [SPEEDO_TEGRA124] = tegra124_init_speedo_data,
++};
++
++static void __init tegra30_fuse_add_randomness(void)
++{
++ u32 randomness[12];
++
++ randomness[0] = tegra_sku_info.sku_id;
++ randomness[1] = tegra_read_straps();
++ randomness[2] = tegra_read_chipid();
++ randomness[3] = tegra_sku_info.cpu_process_id << 16;
++ randomness[3] |= tegra_sku_info.core_process_id;
++ randomness[4] = tegra_sku_info.cpu_speedo_id << 16;
++ randomness[4] |= tegra_sku_info.soc_speedo_id;
++ randomness[5] = tegra30_fuse_readl(FUSE_VENDOR_CODE);
++ randomness[6] = tegra30_fuse_readl(FUSE_FAB_CODE);
++ randomness[7] = tegra30_fuse_readl(FUSE_LOT_CODE_0);
++ randomness[8] = tegra30_fuse_readl(FUSE_LOT_CODE_1);
++ randomness[9] = tegra30_fuse_readl(FUSE_WAFER_ID);
++ randomness[10] = tegra30_fuse_readl(FUSE_X_COORDINATE);
++ randomness[11] = tegra30_fuse_readl(FUSE_Y_COORDINATE);
++
++ add_device_randomness(randomness, sizeof(randomness));
++}
++
++static void __init legacy_fuse_init(void)
++{
++ switch (tegra_chip_id) {
++ case TEGRA30:
++ fuse_info = &tegra30_info;
++ break;
++ case TEGRA114:
++ fuse_info = &tegra114_info;
++ break;
++ case TEGRA124:
++ fuse_info = &tegra124_info;
++ break;
++ default:
++ return;
++ }
++
++ fuse_base = ioremap(TEGRA_FUSE_BASE, TEGRA_FUSE_SIZE);
++}
++
++bool __init tegra30_spare_fuse(int spare_bit)
++{
++ u32 offset = fuse_info->spare_bit + spare_bit * 4;
++
++ return tegra30_fuse_readl(offset) & 1;
++}
++
++void __init tegra30_init_fuse_early(void)
++{
++ struct device_node *np;
++ const struct of_device_id *of_match;
++
++ np = of_find_matching_node_and_match(NULL, tegra30_fuse_of_match,
++ &of_match);
++ if (np) {
++ fuse_base = of_iomap(np, 0);
++ fuse_info = (struct tegra_fuse_info *)of_match->data;
++ } else
++ legacy_fuse_init();
++
++ if (!fuse_base) {
++ pr_warn("fuse DT node missing and unknown chip id: 0x%02x\n",
++ tegra_chip_id);
++ return;
++ }
++
++ tegra_init_revision();
++ 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
+new file mode 100644
+index 0000000..3a398bf3
+--- /dev/null
++++ b/drivers/misc/fuse/tegra/fuse.h
+@@ -0,0 +1,71 @@
++/*
++ * Copyright (C) 2010 Google, Inc.
++ * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved.
++ *
++ * Author:
++ * Colin Cross <ccross@android.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.
++ *
++ */
++
++#ifndef __DRIVERS_MISC_TEGRA_FUSE_H
++#define __DRIVERS_MISC_TEGRA_FUSE_H
++
++#define TEGRA_FUSE_BASE 0x7000f800
++#define TEGRA_FUSE_SIZE 0x400
++
++int tegra_fuse_create_sysfs(struct device *dev, int size,
++ u32 (*readl)(const unsigned int offset));
++
++bool tegra30_spare_fuse(int bit);
++u32 tegra30_fuse_readl(const unsigned int offset);
++void tegra30_init_fuse_early(void);
++void tegra_init_revision(void);
++void tegra_init_apbmisc(void);
++
++#ifdef CONFIG_ARCH_TEGRA_2x_SOC
++void tegra20_init_speedo_data(struct tegra_sku_info *sku_info);
++bool tegra20_spare_fuse_early(int spare_bit);
++void tegra20_init_fuse_early(void);
++u32 tegra20_fuse_early(const unsigned int offset);
++#else
++static inline void tegra20_init_speedo_data(struct tegra_sku_info *sku_info) {}
++static inline bool tegra20_spare_fuse_early(int spare_bit)
++{
++ return false;
++}
++static inline void tegra20_init_fuse_early(void) {}
++static inline u32 tegra20_fuse_early(const unsigned int offset)
++{
++ return 0;
++}
++#endif
++
++
++#ifdef CONFIG_ARCH_TEGRA_3x_SOC
++void tegra30_init_speedo_data(struct tegra_sku_info *sku_info);
++#else
++static inline void tegra30_init_speedo_data(struct tegra_sku_info *sku_info) {}
++#endif
++
++#ifdef CONFIG_ARCH_TEGRA_114_SOC
++void tegra114_init_speedo_data(struct tegra_sku_info *sku_info);
++#else
++static inline void tegra114_init_speedo_data(struct tegra_sku_info *sku_info) {}
++#endif
++
++#ifdef CONFIG_ARCH_TEGRA_124_SOC
++void tegra124_init_speedo_data(struct tegra_sku_info *sku_info);
++#else
++static inline void tegra124_init_speedo_data(struct tegra_sku_info *sku_info) {}
++#endif
++
++#endif
+diff --git a/drivers/misc/fuse/tegra/speedo-tegra114.c b/drivers/misc/fuse/tegra/speedo-tegra114.c
+new file mode 100644
+index 0000000..98d6cde
+--- /dev/null
++++ b/drivers/misc/fuse/tegra/speedo-tegra114.c
+@@ -0,0 +1,109 @@
++/*
++ * Copyright (c) 2013-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.
++ *
++ * 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/device.h>
++#include <linux/kernel.h>
++#include <linux/bug.h>
++#include <linux/tegra-soc.h>
++
++#include "fuse.h"
++
++#define CORE_PROCESS_CORNERS 2
++#define CPU_PROCESS_CORNERS 2
++
++enum {
++ THRESHOLD_INDEX_0,
++ THRESHOLD_INDEX_1,
++ THRESHOLD_INDEX_COUNT,
++};
++
++static const u32 __initconst core_process_speedos[][CORE_PROCESS_CORNERS] = {
++ {1123, UINT_MAX},
++ {0, UINT_MAX},
++};
++
++static const u32 __initconst cpu_process_speedos[][CPU_PROCESS_CORNERS] = {
++ {1695, UINT_MAX},
++ {0, UINT_MAX},
++};
++
++static void __init rev_sku_to_speedo_ids(struct tegra_sku_info *sku_info,
++ int *threshold)
++{
++ u32 tmp;
++ u32 sku = sku_info->sku_id;
++ enum tegra_revision rev = sku_info->revision;
++
++ switch (sku) {
++ case 0x00:
++ case 0x10:
++ case 0x05:
++ case 0x06:
++ sku_info->cpu_speedo_id = 1;
++ sku_info->soc_speedo_id = 0;
++ *threshold = THRESHOLD_INDEX_0;
++ break;
++
++ case 0x03:
++ case 0x04:
++ sku_info->cpu_speedo_id = 2;
++ sku_info->soc_speedo_id = 1;
++ *threshold = THRESHOLD_INDEX_1;
++ break;
++
++ default:
++ pr_err("Tegra Unknown SKU %d\n", sku);
++ sku_info->cpu_speedo_id = 0;
++ sku_info->soc_speedo_id = 0;
++ *threshold = THRESHOLD_INDEX_0;
++ break;
++ }
++
++ if (rev == TEGRA_REVISION_A01) {
++ tmp = tegra30_fuse_readl(0x270) << 1;
++ tmp |= tegra30_fuse_readl(0x26c);
++ if (!tmp)
++ sku_info->cpu_speedo_id = 0;
++ }
++}
++
++void __init tegra114_init_speedo_data(struct tegra_sku_info *sku_info)
++{
++ u32 cpu_speedo_val;
++ u32 core_speedo_val;
++ int threshold;
++ int i;
++
++ BUILD_BUG_ON(ARRAY_SIZE(cpu_process_speedos) !=
++ THRESHOLD_INDEX_COUNT);
++ BUILD_BUG_ON(ARRAY_SIZE(core_process_speedos) !=
++ THRESHOLD_INDEX_COUNT);
++
++ rev_sku_to_speedo_ids(sku_info, &threshold);
++
++ cpu_speedo_val = tegra30_fuse_readl(0x12c) + 1024;
++ core_speedo_val = tegra30_fuse_readl(0x134);
++
++ for (i = 0; i < CPU_PROCESS_CORNERS; i++)
++ if (cpu_speedo_val < cpu_process_speedos[threshold][i])
++ break;
++ sku_info->cpu_process_id = i;
++
++ for (i = 0; i < CORE_PROCESS_CORNERS; i++)
++ if (core_speedo_val < core_process_speedos[threshold][i])
++ 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
+new file mode 100644
+index 0000000..a15dd53
+--- /dev/null
++++ b/drivers/misc/fuse/tegra/speedo-tegra124.c
+@@ -0,0 +1,167 @@
++/*
++ * Copyright (c) 2013-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.
++ *
++ * 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/device.h>
++#include <linux/kernel.h>
++#include <linux/bug.h>
++#include <linux/tegra-soc.h>
++
++#include "fuse.h"
++
++#define CPU_PROCESS_CORNERS 2
++#define GPU_PROCESS_CORNERS 2
++#define CORE_PROCESS_CORNERS 2
++
++#define FUSE_CPU_SPEEDO_0 0x14
++#define FUSE_CPU_SPEEDO_1 0x2c
++#define FUSE_CPU_SPEEDO_2 0x30
++#define FUSE_SOC_SPEEDO_0 0x34
++#define FUSE_SOC_SPEEDO_1 0x38
++#define FUSE_SOC_SPEEDO_2 0x3c
++#define FUSE_CPU_IDDQ 0x18
++#define FUSE_SOC_IDDQ 0x40
++#define FUSE_GPU_IDDQ 0x128
++#define FUSE_FT_REV 0x28
++
++enum {
++ THRESHOLD_INDEX_0,
++ THRESHOLD_INDEX_1,
++ THRESHOLD_INDEX_COUNT,
++};
++
++static const u32 __initconst cpu_process_speedos[][CPU_PROCESS_CORNERS] = {
++ {2190, UINT_MAX},
++ {0, UINT_MAX},
++};
++
++static const u32 __initconst gpu_process_speedos[][GPU_PROCESS_CORNERS] = {
++ {1965, UINT_MAX},
++ {0, UINT_MAX},
++};
++
++static const u32 __initconst core_process_speedos[][CORE_PROCESS_CORNERS] = {
++ {2101, UINT_MAX},
++ {0, UINT_MAX},
++};
++
++static void __init rev_sku_to_speedo_ids(struct tegra_sku_info *sku_info,
++ int *threshold)
++{
++ int sku = sku_info->sku_id;
++
++ /* Assign to default */
++ sku_info->cpu_speedo_id = 0;
++ sku_info->soc_speedo_id = 0;
++ sku_info->gpu_speedo_id = 0;
++ *threshold = THRESHOLD_INDEX_0;
++
++ switch (sku) {
++ case 0x00: /* Eng sku */
++ case 0x0F:
++ case 0x23:
++ /* Using the default */
++ break;
++ case 0x83:
++ sku_info->cpu_speedo_id = 2;
++ break;
++
++ case 0x1F:
++ case 0x87:
++ case 0x27:
++ sku_info->cpu_speedo_id = 2;
++ sku_info->soc_speedo_id = 0;
++ sku_info->gpu_speedo_id = 1;
++ *threshold = THRESHOLD_INDEX_0;
++ break;
++ case 0x81:
++ case 0x21:
++ case 0x07:
++ sku_info->cpu_speedo_id = 1;
++ sku_info->soc_speedo_id = 1;
++ sku_info->gpu_speedo_id = 1;
++ *threshold = THRESHOLD_INDEX_1;
++ break;
++ case 0x49:
++ case 0x4A:
++ case 0x48:
++ sku_info->cpu_speedo_id = 4;
++ sku_info->soc_speedo_id = 2;
++ sku_info->gpu_speedo_id = 3;
++ *threshold = THRESHOLD_INDEX_1;
++ break;
++ default:
++ pr_err("Tegra Unknown SKU %d\n", sku);
++ /* Using the default for the error case */
++ break;
++ }
++}
++
++void __init tegra124_init_speedo_data(struct tegra_sku_info *sku_info)
++{
++ int i, threshold, cpu_speedo_0_value, soc_speedo_0_value;
++ int cpu_iddq_value, gpu_iddq_value, soc_iddq_value;
++
++ BUILD_BUG_ON(ARRAY_SIZE(cpu_process_speedos) !=
++ THRESHOLD_INDEX_COUNT);
++ BUILD_BUG_ON(ARRAY_SIZE(gpu_process_speedos) !=
++ THRESHOLD_INDEX_COUNT);
++ BUILD_BUG_ON(ARRAY_SIZE(core_process_speedos) !=
++ THRESHOLD_INDEX_COUNT);
++
++ cpu_speedo_0_value = tegra30_fuse_readl(FUSE_CPU_SPEEDO_0);
++
++ /* GPU Speedo is stored in CPU_SPEEDO_2 */
++ sku_info->gpu_speedo_value = tegra30_fuse_readl(FUSE_CPU_SPEEDO_2);
++
++ soc_speedo_0_value = tegra30_fuse_readl(FUSE_SOC_SPEEDO_0);
++
++ cpu_iddq_value = tegra30_fuse_readl(FUSE_CPU_IDDQ);
++ soc_iddq_value = tegra30_fuse_readl(FUSE_SOC_IDDQ);
++ gpu_iddq_value = tegra30_fuse_readl(FUSE_GPU_IDDQ);
++
++ sku_info->cpu_speedo_value = cpu_speedo_0_value;
++
++ if (sku_info->cpu_speedo_value == 0) {
++ pr_warn("Tegra Warning: Speedo value not fused.\n");
++ WARN_ON(1);
++ return;
++ }
++
++ rev_sku_to_speedo_ids(sku_info, &threshold);
++
++ sku_info->cpu_iddq_value = tegra30_fuse_readl(FUSE_CPU_IDDQ);
++
++ for (i = 0; i < GPU_PROCESS_CORNERS; i++)
++ if (sku_info->gpu_speedo_value <
++ gpu_process_speedos[threshold][i])
++ break;
++ sku_info->gpu_process_id = i;
++
++ for (i = 0; i < CPU_PROCESS_CORNERS; i++)
++ if (sku_info->cpu_speedo_value <
++ cpu_process_speedos[threshold][i])
++ break;
++ sku_info->cpu_process_id = i;
++
++ for (i = 0; i < CORE_PROCESS_CORNERS; i++)
++ if (soc_speedo_0_value <
++ core_process_speedos[threshold][i])
++ break;
++ sku_info->core_process_id = i;
++
++ 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
+new file mode 100644
+index 0000000..c951fa4
+--- /dev/null
++++ b/drivers/misc/fuse/tegra/speedo-tegra20.c
+@@ -0,0 +1,109 @@
++/*
++ * Copyright (c) 2012-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.
++ *
++ * 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/device.h>
++#include <linux/bug.h>
++#include <linux/tegra-soc.h>
++
++#include "fuse.h"
++
++#define CPU_SPEEDO_LSBIT 20
++#define CPU_SPEEDO_MSBIT 29
++#define CPU_SPEEDO_REDUND_LSBIT 30
++#define CPU_SPEEDO_REDUND_MSBIT 39
++#define CPU_SPEEDO_REDUND_OFFS (CPU_SPEEDO_REDUND_MSBIT - CPU_SPEEDO_MSBIT)
++
++#define CORE_SPEEDO_LSBIT 40
++#define CORE_SPEEDO_MSBIT 47
++#define CORE_SPEEDO_REDUND_LSBIT 48
++#define CORE_SPEEDO_REDUND_MSBIT 55
++#define CORE_SPEEDO_REDUND_OFFS (CORE_SPEEDO_REDUND_MSBIT - CORE_SPEEDO_MSBIT)
++
++#define SPEEDO_MULT 4
++
++#define PROCESS_CORNERS_NUM 4
++
++#define SPEEDO_ID_SELECT_0(rev) ((rev) <= 2)
++#define SPEEDO_ID_SELECT_1(sku) \
++ (((sku) != 20) && ((sku) != 23) && ((sku) != 24) && \
++ ((sku) != 27) && ((sku) != 28))
++
++enum {
++ SPEEDO_ID_0,
++ SPEEDO_ID_1,
++ SPEEDO_ID_2,
++ SPEEDO_ID_COUNT,
++};
++
++static const u32 __initconst cpu_process_speedos[][PROCESS_CORNERS_NUM] = {
++ {315, 366, 420, UINT_MAX},
++ {303, 368, 419, UINT_MAX},
++ {316, 331, 383, UINT_MAX},
++};
++
++static const u32 __initconst core_process_speedos[][PROCESS_CORNERS_NUM] = {
++ {165, 195, 224, UINT_MAX},
++ {165, 195, 224, UINT_MAX},
++ {165, 195, 224, UINT_MAX},
++};
++
++void __init tegra20_init_speedo_data(struct tegra_sku_info *sku_info)
++{
++ u32 reg;
++ u32 val;
++ int i;
++
++ BUILD_BUG_ON(ARRAY_SIZE(cpu_process_speedos) != SPEEDO_ID_COUNT);
++ BUILD_BUG_ON(ARRAY_SIZE(core_process_speedos) != SPEEDO_ID_COUNT);
++
++ if (SPEEDO_ID_SELECT_0(sku_info->revision))
++ sku_info->soc_speedo_id = SPEEDO_ID_0;
++ else if (SPEEDO_ID_SELECT_1(sku_info->sku_id))
++ sku_info->soc_speedo_id = SPEEDO_ID_1;
++ else
++ sku_info->soc_speedo_id = SPEEDO_ID_2;
++
++ val = 0;
++ for (i = CPU_SPEEDO_MSBIT; i >= CPU_SPEEDO_LSBIT; i--) {
++ reg = tegra20_spare_fuse_early(i) |
++ tegra20_spare_fuse_early(i + CPU_SPEEDO_REDUND_OFFS);
++ val = (val << 1) | (reg & 0x1);
++ }
++ val = val * SPEEDO_MULT;
++ pr_debug("Tegra CPU speedo value %u\n", val);
++
++ for (i = 0; i < (PROCESS_CORNERS_NUM - 1); i++) {
++ if (val <= cpu_process_speedos[sku_info->soc_speedo_id][i])
++ break;
++ }
++ sku_info->cpu_process_id = i;
++
++ val = 0;
++ for (i = CORE_SPEEDO_MSBIT; i >= CORE_SPEEDO_LSBIT; i--) {
++ reg = tegra20_spare_fuse_early(i) |
++ tegra20_spare_fuse_early(i + CORE_SPEEDO_REDUND_OFFS);
++ val = (val << 1) | (reg & 0x1);
++ }
++ val = val * SPEEDO_MULT;
++ pr_debug("Core speedo value %u\n", val);
++
++ for (i = 0; i < (PROCESS_CORNERS_NUM - 1); i++) {
++ if (val <= core_process_speedos[sku_info->soc_speedo_id][i])
++ break;
++ }
++ sku_info->core_process_id = i;
++}
+diff --git a/drivers/misc/fuse/tegra/speedo-tegra30.c b/drivers/misc/fuse/tegra/speedo-tegra30.c
+new file mode 100644
+index 0000000..1a85ad8
+--- /dev/null
++++ b/drivers/misc/fuse/tegra/speedo-tegra30.c
+@@ -0,0 +1,287 @@
++/*
++ * Copyright (c) 2012-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.
++ *
++ * 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/device.h>
++#include <linux/kernel.h>
++#include <linux/bug.h>
++#include <linux/tegra-soc.h>
++
++#include "fuse.h"
++
++#define CORE_PROCESS_CORNERS 1
++#define CPU_PROCESS_CORNERS 6
++
++#define FUSE_SPEEDO_CALIB_0 0x14
++#define FUSE_PACKAGE_INFO 0XFC
++#define FUSE_TEST_PROG_VER 0X28
++
++#define G_SPEEDO_BIT_MINUS1 58
++#define G_SPEEDO_BIT_MINUS1_R 59
++#define G_SPEEDO_BIT_MINUS2 60
++#define G_SPEEDO_BIT_MINUS2_R 61
++#define LP_SPEEDO_BIT_MINUS1 62
++#define LP_SPEEDO_BIT_MINUS1_R 63
++#define LP_SPEEDO_BIT_MINUS2 64
++#define LP_SPEEDO_BIT_MINUS2_R 65
++
++enum {
++ THRESHOLD_INDEX_0,
++ THRESHOLD_INDEX_1,
++ THRESHOLD_INDEX_2,
++ THRESHOLD_INDEX_3,
++ THRESHOLD_INDEX_4,
++ THRESHOLD_INDEX_5,
++ THRESHOLD_INDEX_6,
++ THRESHOLD_INDEX_7,
++ THRESHOLD_INDEX_8,
++ THRESHOLD_INDEX_9,
++ THRESHOLD_INDEX_10,
++ THRESHOLD_INDEX_11,
++ THRESHOLD_INDEX_COUNT,
++};
++
++static const u32 __initconst core_process_speedos[][CORE_PROCESS_CORNERS] = {
++ {180},
++ {170},
++ {195},
++ {180},
++ {168},
++ {192},
++ {180},
++ {170},
++ {195},
++ {180},
++ {180},
++ {180},
++};
++
++static const u32 __initconst cpu_process_speedos[][CPU_PROCESS_CORNERS] = {
++ {306, 338, 360, 376, UINT_MAX},
++ {295, 336, 358, 375, UINT_MAX},
++ {325, 325, 358, 375, UINT_MAX},
++ {325, 325, 358, 375, UINT_MAX},
++ {292, 324, 348, 364, UINT_MAX},
++ {324, 324, 348, 364, UINT_MAX},
++ {324, 324, 348, 364, UINT_MAX},
++ {295, 336, 358, 375, UINT_MAX},
++ {358, 358, 358, 358, 397, UINT_MAX},
++ {364, 364, 364, 364, 397, UINT_MAX},
++ {295, 336, 358, 375, 391, UINT_MAX},
++ {295, 336, 358, 375, 391, UINT_MAX},
++};
++
++static int threshold_index __initdata;
++
++static void __init fuse_speedo_calib(u32 *speedo_g, u32 *speedo_lp)
++{
++ u32 reg;
++ int ate_ver;
++ int bit_minus1;
++ int bit_minus2;
++
++ reg = tegra30_fuse_readl(FUSE_SPEEDO_CALIB_0);
++
++ *speedo_lp = (reg & 0xFFFF) * 4;
++ *speedo_g = ((reg >> 16) & 0xFFFF) * 4;
++
++ ate_ver = tegra30_fuse_readl(FUSE_TEST_PROG_VER);
++ pr_debug("Tegra ATE prog ver %d.%d\n", ate_ver/10, ate_ver%10);
++
++ if (ate_ver >= 26) {
++ bit_minus1 = tegra30_spare_fuse(LP_SPEEDO_BIT_MINUS1);
++ bit_minus1 |= tegra30_spare_fuse(LP_SPEEDO_BIT_MINUS1_R);
++ bit_minus2 = tegra30_spare_fuse(LP_SPEEDO_BIT_MINUS2);
++ bit_minus2 |= tegra30_spare_fuse(LP_SPEEDO_BIT_MINUS2_R);
++ *speedo_lp |= (bit_minus1 << 1) | bit_minus2;
++
++ bit_minus1 = tegra30_spare_fuse(G_SPEEDO_BIT_MINUS1);
++ bit_minus1 |= tegra30_spare_fuse(G_SPEEDO_BIT_MINUS1_R);
++ bit_minus2 = tegra30_spare_fuse(G_SPEEDO_BIT_MINUS2);
++ bit_minus2 |= tegra30_spare_fuse(G_SPEEDO_BIT_MINUS2_R);
++ *speedo_g |= (bit_minus1 << 1) | bit_minus2;
++ } else {
++ *speedo_lp |= 0x3;
++ *speedo_g |= 0x3;
++ }
++}
++
++static void __init rev_sku_to_speedo_ids(struct tegra_sku_info *sku_info)
++{
++ int package_id = tegra30_fuse_readl(FUSE_PACKAGE_INFO) & 0x0F;
++
++ switch (sku_info->revision) {
++ case TEGRA_REVISION_A01:
++ sku_info->cpu_speedo_id = 0;
++ sku_info->soc_speedo_id = 0;
++ threshold_index = THRESHOLD_INDEX_0;
++ break;
++ case TEGRA_REVISION_A02:
++ case TEGRA_REVISION_A03:
++ switch (sku_info->sku_id) {
++ case 0x87:
++ case 0x82:
++ sku_info->cpu_speedo_id = 1;
++ sku_info->soc_speedo_id = 1;
++ threshold_index = THRESHOLD_INDEX_1;
++ break;
++ case 0x81:
++ switch (package_id) {
++ case 1:
++ sku_info->cpu_speedo_id = 2;
++ sku_info->soc_speedo_id = 2;
++ threshold_index = THRESHOLD_INDEX_2;
++ break;
++ case 2:
++ sku_info->cpu_speedo_id = 4;
++ sku_info->soc_speedo_id = 1;
++ threshold_index = THRESHOLD_INDEX_7;
++ break;
++ default:
++ pr_err("Tegra Unknown pkg %d\n", package_id);
++ break;
++ }
++ break;
++ case 0x80:
++ switch (package_id) {
++ case 1:
++ sku_info->cpu_speedo_id = 5;
++ sku_info->soc_speedo_id = 2;
++ threshold_index = THRESHOLD_INDEX_8;
++ break;
++ case 2:
++ sku_info->cpu_speedo_id = 6;
++ sku_info->soc_speedo_id = 2;
++ threshold_index = THRESHOLD_INDEX_9;
++ break;
++ default:
++ pr_err("Tegra Unknown pkg %d\n", package_id);
++ break;
++ }
++ break;
++ case 0x83:
++ switch (package_id) {
++ case 1:
++ sku_info->cpu_speedo_id = 7;
++ sku_info->soc_speedo_id = 1;
++ threshold_index = THRESHOLD_INDEX_10;
++ break;
++ case 2:
++ sku_info->cpu_speedo_id = 3;
++ sku_info->soc_speedo_id = 2;
++ threshold_index = THRESHOLD_INDEX_3;
++ break;
++ default:
++ pr_err("Tegra Unknown pkg %d\n", package_id);
++ break;
++ }
++ break;
++ case 0x8F:
++ sku_info->cpu_speedo_id = 8;
++ sku_info->soc_speedo_id = 1;
++ threshold_index = THRESHOLD_INDEX_11;
++ break;
++ case 0x08:
++ sku_info->cpu_speedo_id = 1;
++ sku_info->soc_speedo_id = 1;
++ threshold_index = THRESHOLD_INDEX_4;
++ break;
++ case 0x02:
++ sku_info->cpu_speedo_id = 2;
++ sku_info->soc_speedo_id = 2;
++ threshold_index = THRESHOLD_INDEX_5;
++ break;
++ case 0x04:
++ sku_info->cpu_speedo_id = 3;
++ sku_info->soc_speedo_id = 2;
++ threshold_index = THRESHOLD_INDEX_6;
++ break;
++ case 0:
++ switch (package_id) {
++ case 1:
++ sku_info->cpu_speedo_id = 2;
++ sku_info->soc_speedo_id = 2;
++ threshold_index = THRESHOLD_INDEX_2;
++ break;
++ case 2:
++ sku_info->cpu_speedo_id = 3;
++ sku_info->soc_speedo_id = 2;
++ threshold_index = THRESHOLD_INDEX_3;
++ break;
++ default:
++ pr_err("Tegra Unknown pkg %d\n", package_id);
++ break;
++ }
++ break;
++ default:
++ pr_warn("Tegra Unknown SKU %d\n", sku_info->sku_id);
++ sku_info->cpu_speedo_id = 0;
++ sku_info->soc_speedo_id = 0;
++ threshold_index = THRESHOLD_INDEX_0;
++ break;
++ }
++ break;
++ default:
++ pr_warn("Tegra Unknown chip rev %d\n", sku_info->revision);
++ sku_info->cpu_speedo_id = 0;
++ sku_info->soc_speedo_id = 0;
++ threshold_index = THRESHOLD_INDEX_0;
++ break;
++ }
++}
++
++void __init tegra30_init_speedo_data(struct tegra_sku_info *sku_info)
++{
++ u32 cpu_speedo_val;
++ u32 core_speedo_val;
++ int i;
++
++ BUILD_BUG_ON(ARRAY_SIZE(cpu_process_speedos) !=
++ THRESHOLD_INDEX_COUNT);
++ BUILD_BUG_ON(ARRAY_SIZE(core_process_speedos) !=
++ THRESHOLD_INDEX_COUNT);
++
++
++ rev_sku_to_speedo_ids(sku_info);
++ fuse_speedo_calib(&cpu_speedo_val, &core_speedo_val);
++ pr_debug("Tegra CPU speedo value %u\n", cpu_speedo_val);
++ pr_debug("Tegra Core speedo value %u\n", core_speedo_val);
++
++ for (i = 0; i < CPU_PROCESS_CORNERS; i++) {
++ if (cpu_speedo_val < cpu_process_speedos[threshold_index][i])
++ break;
++ }
++ sku_info->cpu_process_id = i - 1;
++
++ if (sku_info->cpu_process_id == -1) {
++ pr_warn("Tegra CPU speedo value %3d out of range",
++ cpu_speedo_val);
++ sku_info->cpu_process_id = 0;
++ sku_info->cpu_speedo_id = 1;
++ }
++
++ for (i = 0; i < CORE_PROCESS_CORNERS; i++) {
++ if (core_speedo_val < core_process_speedos[threshold_index][i])
++ break;
++ }
++ sku_info->core_process_id = i - 1;
++
++ if (sku_info->core_process_id == -1) {
++ pr_warn("Tegra CORE speedo value %3d out of range",
++ core_speedo_val);
++ sku_info->core_process_id = 0;
++ sku_info->soc_speedo_id = 1;
++ }
++}
+diff --git a/drivers/misc/fuse/tegra/tegra-apbmisc.c b/drivers/misc/fuse/tegra/tegra-apbmisc.c
+new file mode 100644
+index 0000000..43e5bd5
+--- /dev/null
++++ b/drivers/misc/fuse/tegra/tegra-apbmisc.c
+@@ -0,0 +1,110 @@
++/*
++ * 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.
++ *
++ * 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/of.h>
++#include <linux/of_address.h>
++#include <linux/io.h>
++#include <linux/tegra-soc.h>
++
++#include "fuse.h"
++
++#define APBMISC_BASE 0x70000800
++#define APBMISC_SIZE 0x64
++#define FUSE_SKU_INFO 0x10
++
++int tegra_chip_id;
++
++static void __iomem *apbmisc_base;
++static void __iomem *strapping_base;
++
++u32 tegra_read_chipid(void)
++{
++ return readl_relaxed(apbmisc_base + 4);
++}
++
++u32 tegra_read_straps(void)
++{
++ if (strapping_base)
++ return readl_relaxed(strapping_base);
++ else
++ return 0;
++}
++
++static const struct of_device_id apbmisc_match[] __initconst = {
++ { .compatible = "nvidia,tegra20-apbmisc", },
++ {},
++};
++
++void __init tegra_init_revision(void)
++{
++ u32 id, minor_rev;
++ int rev;
++
++ id = tegra_read_chipid();
++ minor_rev = (id >> 16) & 0xf;
++
++ switch (minor_rev) {
++ case 1:
++ rev = TEGRA_REVISION_A01;
++ break;
++ case 2:
++ rev = TEGRA_REVISION_A02;
++ break;
++ case 3:
++ if (tegra_chip_id == TEGRA20 &&
++ (tegra20_spare_fuse_early(18) ||
++ tegra20_spare_fuse_early(19)))
++ rev = TEGRA_REVISION_A03p;
++ else
++ rev = TEGRA_REVISION_A03;
++ break;
++ case 4:
++ rev = TEGRA_REVISION_A04;
++ break;
++ default:
++ rev = TEGRA_REVISION_UNKNOWN;
++ }
++
++ tegra_sku_info.revision = rev;
++
++ if (tegra_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);
++}
++
++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);
++ if (!apbmisc_base) {
++ pr_warn("ioremap tegra apbmisc failed. using %08x instead\n",
++ APBMISC_BASE);
++ 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;
++ }
++
++ 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/include/linux/tegra-soc.h b/include/linux/tegra-soc.h
+index 95f611d..fcf65ec 100644
+--- a/include/linux/tegra-soc.h
++++ b/include/linux/tegra-soc.h
+@@ -17,6 +17,48 @@
+ #ifndef __LINUX_TEGRA_SOC_H_
+ #define __LINUX_TEGRA_SOC_H_
+
++#define TEGRA20 0x20
++#define TEGRA30 0x30
++#define TEGRA114 0x35
++#define TEGRA124 0x40
++
++#define TEGRA_FUSE_SKU_CALIB_0 0xf0
++#define TEGRA30_FUSE_SATA_CALIB 0x124
++
++#ifndef __ASSEMBLY__
++
++enum tegra_revision {
++ TEGRA_REVISION_UNKNOWN = 0,
++ TEGRA_REVISION_A01,
++ TEGRA_REVISION_A02,
++ TEGRA_REVISION_A03,
++ TEGRA_REVISION_A03p,
++ TEGRA_REVISION_A04,
++ TEGRA_REVISION_MAX,
++};
++
++struct tegra_sku_info {
++ int sku_id;
++ int cpu_process_id;
++ int cpu_speedo_id;
++ int cpu_speedo_value;
++ int cpu_iddq_value;
++ int core_process_id;
++ int soc_speedo_id;
++ int gpu_speedo_id;
++ int gpu_process_id;
++ int gpu_speedo_value;
++ enum tegra_revision revision;
++};
++
++u32 tegra_read_straps(void);
+ u32 tegra_read_chipid(void);
++void tegra_init_fuse(void);
++int tegra_fuse_readl(u32 offset, u32 *val);
++
++extern int tegra_chip_id;
++extern struct tegra_sku_info tegra_sku_info;
++
++#endif /* __ASSEMBLY__ */
+
+ #endif /* __LINUX_TEGRA_SOC_H_ */
+diff --git a/init/calibrate.c b/init/calibrate.c
+index 520702d..ce635dc 100644
+--- a/init/calibrate.c
++++ b/init/calibrate.c
+@@ -262,6 +262,15 @@ unsigned long __attribute__((weak)) calibrate_delay_is_known(void)
+ return 0;
+ }
+
++/*
++ * Indicate the cpu delay calibration is done. This can be used by
++ * architectures to stop accepting delay timer registrations after this point.
++ */
++
++void __attribute__((weak)) calibration_delay_done(void)
++{
++}
++
+ void calibrate_delay(void)
+ {
+ unsigned long lpj;
+@@ -301,4 +310,6 @@ void calibrate_delay(void)
+
+ loops_per_jiffy = lpj;
+ printed = true;
++
++ calibration_delay_done();
+ }