public inbox for linux-arm-kernel@lists.infradead.org
 help / color / mirror / Atom feed
* [PATCH v3 0/6] efuse driver for Tegra
@ 2014-01-28 23:36 Peter De Schrijver
  2014-01-28 23:36 ` [PATCH v3 1/6] ARM: tegra: export apb dma readl/writel Peter De Schrijver
                   ` (7 more replies)
  0 siblings, 8 replies; 21+ messages in thread
From: Peter De Schrijver @ 2014-01-28 23:36 UTC (permalink / raw)
  To: linux-arm-kernel

This driver allows userspace to read the raw efuse data. Its userspace
interface is modelled after the sunxi_sid driver which provides similar
functionality for some Allwinner SoCs. It has been tested on
Tegra20 (ventana), Tegra30 (beaverboard) and Tegra114 (dalmore).

Changes since v1:

* Add documentation for sysfs interface
* Cleanup messages

Changes since v2:

* Incorporate early fuse code
* Remove module support
* Make driver always build when Tegra platform is selected
* Add DT binding document
* Address comments on v2

TODO:
* test on Tegra124 (venice2) 

Peter De Schrijver (6):
  ARM: tegra: export apb dma readl/writel
  ARM: tegra: Add chipid, revision and fuse init
  misc: fuse: Add efuse driver for Tegra
  ARM: tegra: Add efuse bindings
  misc: enable fuse drivers
  ARM: tegra: remove fuse files from mach-tegra

 Documentation/ABI/testing/sysfs-driver-tegra-fuse  |    8 +
 .../devicetree/bindings/fuse/fuse-tegra.txt        |   32 +++
 arch/arm/boot/dts/tegra114.dtsi                    |    7 +
 arch/arm/boot/dts/tegra124.dtsi                    |    7 +
 arch/arm/boot/dts/tegra20.dtsi                     |    7 +
 arch/arm/boot/dts/tegra30.dtsi                     |    7 +
 arch/arm/mach-tegra/Makefile                       |    4 -
 arch/arm/mach-tegra/apbio.c                        |   51 ++--
 arch/arm/mach-tegra/cpuidle.c                      |    2 +-
 arch/arm/mach-tegra/flowctrl.c                     |    2 +-
 arch/arm/mach-tegra/fuse.c                         |  252 -----------------
 arch/arm/mach-tegra/fuse.h                         |   79 ------
 arch/arm/mach-tegra/hotplug.c                      |    2 +-
 arch/arm/mach-tegra/platsmp.c                      |    2 +-
 arch/arm/mach-tegra/pm.c                           |    2 +-
 arch/arm/mach-tegra/pmc.c                          |    2 +-
 arch/arm/mach-tegra/powergate.c                    |    2 +-
 arch/arm/mach-tegra/reset-handler.S                |    2 +-
 arch/arm/mach-tegra/reset.c                        |    2 +-
 arch/arm/mach-tegra/sleep-tegra30.S                |    2 +-
 arch/arm/mach-tegra/tegra.c                        |    2 +-
 arch/arm/mach-tegra/tegra114_speedo.c              |  104 -------
 arch/arm/mach-tegra/tegra20_speedo.c               |  109 --------
 arch/arm/mach-tegra/tegra2_emc.c                   |    2 +-
 arch/arm/mach-tegra/tegra30_speedo.c               |  292 -------------------
 drivers/misc/Makefile                              |    1 +
 drivers/misc/fuse/Makefile                         |    1 +
 drivers/misc/fuse/tegra/Makefile                   |    7 +
 drivers/misc/fuse/tegra/fuse-tegra.c               |  228 +++++++++++++++
 drivers/misc/fuse/tegra/fuse-tegra20.c             |  136 +++++++++
 drivers/misc/fuse/tegra/fuse-tegra30.c             |  178 ++++++++++++
 drivers/misc/fuse/tegra/fuse.h                     |   82 ++++++
 drivers/misc/fuse/tegra/tegra114_speedo.c          |  110 ++++++++
 drivers/misc/fuse/tegra/tegra124_speedo.c          |  164 +++++++++++
 drivers/misc/fuse/tegra/tegra20_speedo.c           |  110 ++++++++
 drivers/misc/fuse/tegra/tegra30_speedo.c           |  294 ++++++++++++++++++++
 include/linux/tegra-soc.h                          |   39 +++
 37 files changed, 1461 insertions(+), 872 deletions(-)
 create mode 100644 Documentation/ABI/testing/sysfs-driver-tegra-fuse
 create mode 100644 Documentation/devicetree/bindings/fuse/fuse-tegra.txt
 delete mode 100644 arch/arm/mach-tegra/fuse.c
 delete mode 100644 arch/arm/mach-tegra/fuse.h
 delete mode 100644 arch/arm/mach-tegra/tegra114_speedo.c
 delete mode 100644 arch/arm/mach-tegra/tegra20_speedo.c
 delete mode 100644 arch/arm/mach-tegra/tegra30_speedo.c
 create mode 100644 drivers/misc/fuse/Makefile
 create mode 100644 drivers/misc/fuse/tegra/Makefile
 create mode 100644 drivers/misc/fuse/tegra/fuse-tegra.c
 create mode 100644 drivers/misc/fuse/tegra/fuse-tegra20.c
 create mode 100644 drivers/misc/fuse/tegra/fuse-tegra30.c
 create mode 100644 drivers/misc/fuse/tegra/fuse.h
 create mode 100644 drivers/misc/fuse/tegra/tegra114_speedo.c
 create mode 100644 drivers/misc/fuse/tegra/tegra124_speedo.c
 create mode 100644 drivers/misc/fuse/tegra/tegra20_speedo.c
 create mode 100644 drivers/misc/fuse/tegra/tegra30_speedo.c

-- 
1.7.7.rc0.72.g4b5ea.dirty

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH v3 1/6] ARM: tegra: export apb dma readl/writel
  2014-01-28 23:36 [PATCH v3 0/6] efuse driver for Tegra Peter De Schrijver
@ 2014-01-28 23:36 ` Peter De Schrijver
  2014-01-28 23:36 ` [PATCH v3 2/6] ARM: tegra: Add chipid, revision and fuse init Peter De Schrijver
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 21+ messages in thread
From: Peter De Schrijver @ 2014-01-28 23:36 UTC (permalink / raw)
  To: linux-arm-kernel

Export APB DMA readl and writel. These are needed because we can't access
the fuses directly on Tegra20 without potentially causing a system hang.
Also have the APB DMA readl and writel return an error in case of a read
failure instead of just returning zero or ignore write failures.

Signed-off-by: Peter De Schrijver <pdeschrijver@nvidia.com>
---
 arch/arm/mach-tegra/apbio.c |   51 ++++++++++++++++++++++++++----------------
 include/linux/tegra-soc.h   |   14 +++++++++++
 2 files changed, 45 insertions(+), 20 deletions(-)

diff --git a/arch/arm/mach-tegra/apbio.c b/arch/arm/mach-tegra/apbio.c
index bc47197..e0bf49d 100644
--- a/arch/arm/mach-tegra/apbio.c
+++ b/arch/arm/mach-tegra/apbio.c
@@ -32,8 +32,8 @@ 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 int tegra_apb_readl_direct(unsigned long offset, u32 *value);
+static int tegra_apb_writel_direct(u32 value, unsigned long offset);
 
 static struct dma_chan *tegra_apb_dma_chan;
 static struct dma_slave_config dma_sconfig;
@@ -128,58 +128,64 @@ static int do_dma_transfer(unsigned long apb_add,
 	return 0;
 }
 
-static u32 tegra_apb_readl_using_dma(unsigned long offset)
+int tegra_apb_readl_using_dma(unsigned long offset, u32 *value)
 {
 	int ret;
 
 	if (!tegra_apb_dma_chan && !tegra_apb_dma_init())
-		return tegra_apb_readl_direct(offset);
+		return tegra_apb_readl_direct(offset, value);
 
 	mutex_lock(&tegra_apb_dma_lock);
 	ret = do_dma_transfer(offset, DMA_DEV_TO_MEM);
-	if (ret < 0) {
+	if (ret < 0)
 		pr_err("error in reading offset 0x%08lx using dma\n", offset);
-		*(u32 *)tegra_apb_bb = 0;
-	}
+	else
+		*value = *tegra_apb_bb;
+
 	mutex_unlock(&tegra_apb_dma_lock);
-	return *((u32 *)tegra_apb_bb);
+
+	return ret;
 }
 
-static void tegra_apb_writel_using_dma(u32 value, unsigned long offset)
+int 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;
-	}
+	if (!tegra_apb_dma_chan && !tegra_apb_dma_init())
+		return tegra_apb_writel_direct(value, offset);
 
 	mutex_lock(&tegra_apb_dma_lock);
 	*((u32 *)tegra_apb_bb) = value;
 	ret = do_dma_transfer(offset, DMA_MEM_TO_DEV);
+	mutex_unlock(&tegra_apb_dma_lock);
 	if (ret < 0)
 		pr_err("error in writing offset 0x%08lx using dma\n", offset);
-	mutex_unlock(&tegra_apb_dma_lock);
+
+	return ret;
 }
 #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);
+typedef int (*apbio_read_fptr)(unsigned long offset, u32 *value);
+typedef int (*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)
+static int tegra_apb_readl_direct(unsigned long offset, u32 *value)
 {
-	return readl(IO_ADDRESS(offset));
+	*value = readl(IO_ADDRESS(offset));
+
+	return 0;
 }
 
-static void tegra_apb_writel_direct(u32 value, unsigned long offset)
+static int tegra_apb_writel_direct(u32 value, unsigned long offset)
 {
 	writel(value, IO_ADDRESS(offset));
+
+	return 0;
 }
 
 void tegra_apb_io_init(void)
@@ -197,7 +203,12 @@ void tegra_apb_io_init(void)
 
 u32 tegra_apb_readl(unsigned long offset)
 {
-	return apbio_read(offset);
+	u32 val;
+
+	if (apbio_read(offset, &val) < 0)
+		return 0;
+	else
+		return val;
 }
 
 void tegra_apb_writel(u32 value, unsigned long offset)
diff --git a/include/linux/tegra-soc.h b/include/linux/tegra-soc.h
index 95f611d..b02d73b 100644
--- a/include/linux/tegra-soc.h
+++ b/include/linux/tegra-soc.h
@@ -19,4 +19,18 @@
 
 u32 tegra_read_chipid(void);
 
+
+#if defined(CONFIG_TEGRA20_APB_DMA)
+int tegra_apb_readl_using_dma(unsigned long offset, u32 *value);
+int tegra_apb_writel_using_dma(u32 value, unsigned long offset);
+#else
+static inline int tegra_apb_readl_using_dma(unsigned long offset, u32 *value)
+{
+	return -EINVAL;
+}
+static inline int tegra_apb_writel_using_dma(u32 value, unsigned long offset)
+{
+	return -EINVAL;
+}
+#endif
 #endif /* __LINUX_TEGRA_SOC_H_ */
-- 
1.7.7.rc0.72.g4b5ea.dirty

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH v3 2/6] ARM: tegra: Add chipid, revision and fuse init
  2014-01-28 23:36 [PATCH v3 0/6] efuse driver for Tegra Peter De Schrijver
  2014-01-28 23:36 ` [PATCH v3 1/6] ARM: tegra: export apb dma readl/writel Peter De Schrijver
@ 2014-01-28 23:36 ` Peter De Schrijver
  2014-02-05 18:40   ` Stephen Warren
  2014-01-28 23:36 ` [PATCH v3 3/6] misc: fuse: Add efuse driver for Tegra Peter De Schrijver
                   ` (5 subsequent siblings)
  7 siblings, 1 reply; 21+ messages in thread
From: Peter De Schrijver @ 2014-01-28 23:36 UTC (permalink / raw)
  To: linux-arm-kernel

All fuse related functionality will move to a driver in the following patches.
To prepare for this, export all the required functionality in a global header
file and move all users of fuse.h to tegra-soc.h

Signed-off-by: Peter De Schrijver <pdeschrijver@nvidia.com>
---
 arch/arm/mach-tegra/cpuidle.c         |    2 +-
 arch/arm/mach-tegra/flowctrl.c        |    2 +-
 arch/arm/mach-tegra/fuse.h            |   18 ------------------
 arch/arm/mach-tegra/hotplug.c         |    2 +-
 arch/arm/mach-tegra/platsmp.c         |    2 +-
 arch/arm/mach-tegra/pm.c              |    2 +-
 arch/arm/mach-tegra/pmc.c             |    2 +-
 arch/arm/mach-tegra/powergate.c       |    2 +-
 arch/arm/mach-tegra/reset-handler.S   |    2 +-
 arch/arm/mach-tegra/reset.c           |    2 +-
 arch/arm/mach-tegra/sleep-tegra30.S   |    2 +-
 arch/arm/mach-tegra/tegra.c           |    2 +-
 arch/arm/mach-tegra/tegra114_speedo.c |    1 +
 arch/arm/mach-tegra/tegra20_speedo.c  |    1 +
 arch/arm/mach-tegra/tegra2_emc.c      |    2 +-
 arch/arm/mach-tegra/tegra30_speedo.c  |    1 +
 include/linux/tegra-soc.h             |   25 +++++++++++++++++++++++++
 17 files changed, 40 insertions(+), 30 deletions(-)

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 43ae750..d2e0197 100644
--- a/arch/arm/mach-tegra/flowctrl.c
+++ b/arch/arm/mach-tegra/flowctrl.c
@@ -21,10 +21,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.h b/arch/arm/mach-tegra/fuse.h
index c01d047..b17c4ba 100644
--- a/arch/arm/mach-tegra/fuse.h
+++ b/arch/arm/mach-tegra/fuse.h
@@ -26,21 +26,7 @@
 #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;
@@ -48,12 +34,8 @@ 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);
 
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 eb72ae7..44409fd 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 4ae0286..b444ce7 100644
--- a/arch/arm/mach-tegra/pm.c
+++ b/arch/arm/mach-tegra/pm.c
@@ -25,6 +25,7 @@
 #include <linux/suspend.h>
 #include <linux/err.h>
 #include <linux/clk/tegra.h>
+#include <linux/tegra-soc.h>
 
 #include <asm/smp_plat.h>
 #include <asm/cacheflush.h>
@@ -36,7 +37,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 fb79202..d8fe587 100644
--- a/arch/arm/mach-tegra/pmc.c
+++ b/arch/arm/mach-tegra/pmc.c
@@ -21,9 +21,9 @@
 #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"
diff --git a/arch/arm/mach-tegra/powergate.c b/arch/arm/mach-tegra/powergate.c
index 3d0c537..e5c6d0f 100644
--- a/arch/arm/mach-tegra/powergate.c
+++ b/arch/arm/mach-tegra/powergate.c
@@ -30,8 +30,8 @@
 #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"
 
 #define DPD_SAMPLE		0x020
diff --git a/arch/arm/mach-tegra/reset-handler.S b/arch/arm/mach-tegra/reset-handler.S
index 9aa6cd3..f427466 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 <asm/hardware/cache-l2x0.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 303a285..3cfca20 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>
@@ -46,7 +47,6 @@
 #include "board.h"
 #include "common.h"
 #include "cpuidle.h"
-#include "fuse.h"
 #include "iomap.h"
 #include "irq.h"
 #include "pmc.h"
diff --git a/arch/arm/mach-tegra/tegra114_speedo.c b/arch/arm/mach-tegra/tegra114_speedo.c
index 5218d48..7c73716 100644
--- a/arch/arm/mach-tegra/tegra114_speedo.c
+++ b/arch/arm/mach-tegra/tegra114_speedo.c
@@ -16,6 +16,7 @@
 
 #include <linux/kernel.h>
 #include <linux/bug.h>
+#include <linux/tegra-soc.h>
 
 #include "fuse.h"
 
diff --git a/arch/arm/mach-tegra/tegra20_speedo.c b/arch/arm/mach-tegra/tegra20_speedo.c
index fa6eb57..3b1bb53 100644
--- a/arch/arm/mach-tegra/tegra20_speedo.c
+++ b/arch/arm/mach-tegra/tegra20_speedo.c
@@ -16,6 +16,7 @@
 
 #include <linux/kernel.h>
 #include <linux/bug.h>
+#include <linux/tegra-soc.h>
 
 #include "fuse.h"
 
diff --git a/arch/arm/mach-tegra/tegra2_emc.c b/arch/arm/mach-tegra/tegra2_emc.c
index 3ae4a7f..26e4edb 100644
--- a/arch/arm/mach-tegra/tegra2_emc.c
+++ b/arch/arm/mach-tegra/tegra2_emc.c
@@ -24,9 +24,9 @@
 #include <linux/of.h>
 #include <linux/platform_device.h>
 #include <linux/platform_data/tegra_emc.h>
+#include <linux/tegra-soc.h>
 
 #include "tegra2_emc.h"
-#include "fuse.h"
 
 #ifdef CONFIG_TEGRA_EMC_SCALING_ENABLE
 static bool emc_enable = true;
diff --git a/arch/arm/mach-tegra/tegra30_speedo.c b/arch/arm/mach-tegra/tegra30_speedo.c
index 125cb16..81a958d 100644
--- a/arch/arm/mach-tegra/tegra30_speedo.c
+++ b/arch/arm/mach-tegra/tegra30_speedo.c
@@ -16,6 +16,7 @@
 
 #include <linux/kernel.h>
 #include <linux/bug.h>
+#include <linux/tegra-soc.h>
 
 #include "fuse.h"
 
diff --git a/include/linux/tegra-soc.h b/include/linux/tegra-soc.h
index b02d73b..ccf42ee 100644
--- a/include/linux/tegra-soc.h
+++ b/include/linux/tegra-soc.h
@@ -17,8 +17,30 @@
 #ifndef __LINUX_TEGRA_SOC_H_
 #define __LINUX_TEGRA_SOC_H_
 
+#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,
+};
+
+u32 tegra_read_straps(void);
 u32 tegra_read_chipid(void);
+void tegra_init_fuse(void);
 
+extern int tegra_chip_id;
+extern enum tegra_revision tegra_revision;
+extern int tegra_bct_strapping;
 
 #if defined(CONFIG_TEGRA20_APB_DMA)
 int tegra_apb_readl_using_dma(unsigned long offset, u32 *value);
@@ -33,4 +55,7 @@ static inline int tegra_apb_writel_using_dma(u32 value, unsigned long offset)
 	return -EINVAL;
 }
 #endif
+
+#endif /* __ASSEMBLY__ */
+
 #endif /* __LINUX_TEGRA_SOC_H_ */
-- 
1.7.7.rc0.72.g4b5ea.dirty

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH v3 3/6] misc: fuse: Add efuse driver for Tegra
  2014-01-28 23:36 [PATCH v3 0/6] efuse driver for Tegra Peter De Schrijver
  2014-01-28 23:36 ` [PATCH v3 1/6] ARM: tegra: export apb dma readl/writel Peter De Schrijver
  2014-01-28 23:36 ` [PATCH v3 2/6] ARM: tegra: Add chipid, revision and fuse init Peter De Schrijver
@ 2014-01-28 23:36 ` Peter De Schrijver
  2014-01-29  2:26   ` Jim Lin
  2014-02-05 19:15   ` Stephen Warren
  2014-01-28 23:36 ` [PATCH v3 4/6] ARM: tegra: Add efuse bindings Peter De Schrijver
                   ` (4 subsequent siblings)
  7 siblings, 2 replies; 21+ messages in thread
From: Peter De Schrijver @ 2014-01-28 23:36 UTC (permalink / raw)
  To: linux-arm-kernel

Implement fuse driver for Tegra20, Tegra30, Tegra114 and Tegra124.

Signed-off-by: Peter De Schrijver <pdeschrijver@nvidia.com>
---
 Documentation/ABI/testing/sysfs-driver-tegra-fuse |    8 +
 drivers/misc/fuse/Makefile                        |    1 +
 drivers/misc/fuse/tegra/Makefile                  |    7 +
 drivers/misc/fuse/tegra/fuse-tegra.c              |  228 ++++++++++++++++
 drivers/misc/fuse/tegra/fuse-tegra20.c            |  136 ++++++++++
 drivers/misc/fuse/tegra/fuse-tegra30.c            |  178 +++++++++++++
 drivers/misc/fuse/tegra/fuse.h                    |   82 ++++++
 drivers/misc/fuse/tegra/tegra114_speedo.c         |  110 ++++++++
 drivers/misc/fuse/tegra/tegra124_speedo.c         |  164 ++++++++++++
 drivers/misc/fuse/tegra/tegra20_speedo.c          |  110 ++++++++
 drivers/misc/fuse/tegra/tegra30_speedo.c          |  294 +++++++++++++++++++++
 11 files changed, 1318 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/ABI/testing/sysfs-driver-tegra-fuse
 create mode 100644 drivers/misc/fuse/Makefile
 create mode 100644 drivers/misc/fuse/tegra/Makefile
 create mode 100644 drivers/misc/fuse/tegra/fuse-tegra.c
 create mode 100644 drivers/misc/fuse/tegra/fuse-tegra20.c
 create mode 100644 drivers/misc/fuse/tegra/fuse-tegra30.c
 create mode 100644 drivers/misc/fuse/tegra/fuse.h
 create mode 100644 drivers/misc/fuse/tegra/tegra114_speedo.c
 create mode 100644 drivers/misc/fuse/tegra/tegra124_speedo.c
 create mode 100644 drivers/misc/fuse/tegra/tegra20_speedo.c
 create mode 100644 drivers/misc/fuse/tegra/tegra30_speedo.c

diff --git a/Documentation/ABI/testing/sysfs-driver-tegra-fuse b/Documentation/ABI/testing/sysfs-driver-tegra-fuse
new file mode 100644
index 0000000..3b5e1ea
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-driver-tegra-fuse
@@ -0,0 +1,8 @@
+What:		/sys/devices/*/<our-device>/fuse
+Date:		December 2013
+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.
+Users:		any user space application which wants to read the efuses on
+		Tegra SoC's
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..42829b3
--- /dev/null
+++ b/drivers/misc/fuse/tegra/Makefile
@@ -0,0 +1,7 @@
+obj-y					+= fuse-tegra.o
+obj-y					+= fuse-tegra30.o
+obj-$(CONFIG_ARCH_TEGRA_2x_SOC)		+= fuse-tegra20.o
+obj-$(CONFIG_ARCH_TEGRA_2x_SOC)		+= tegra20_speedo.o
+obj-$(CONFIG_ARCH_TEGRA_3x_SOC)		+= tegra30_speedo.o
+obj-$(CONFIG_ARCH_TEGRA_114_SOC)	+= tegra114_speedo.o
+obj-$(CONFIG_ARCH_TEGRA_124_SOC)	+= tegra124_speedo.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..aeecbcd
--- /dev/null
+++ b/drivers/misc/fuse/tegra/fuse-tegra.c
@@ -0,0 +1,228 @@
+/*
+ * 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"
+
+int tegra_chip_id;
+enum tegra_revision tegra_revision;
+
+/*
+ * 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 TEGRA_STRAP_OPT		0x8
+#define TEGRA_RAM_ID_SHIFT	4
+#define TEGRA_RAM_ID_MASK	3
+
+static u32 (*fuse_readl)(const unsigned int offset);
+static int fuse_size;
+static void __iomem *fuse_base;
+static void __iomem *apbmisc_base;
+static void __iomem *car_base;
+
+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 tegra_fuse_match[] __initconst = {
+	{ .compatible = "nvidia,tegra20-efuse", },
+	{ .compatible = "nvidia,tegra30-efuse", },
+	{ .compatible = "nvidia,tegra114-efuse", },
+	{ .compatible = "nvidia,tegra124-efuse", },
+	{},
+};
+
+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_read_bct_strapping(void)
+{
+	tegra_bct_strapping = readl_relaxed(apbmisc_base +
+					    TEGRA_STRAP_OPT);
+	tegra_bct_strapping >>= TEGRA_RAM_ID_SHIFT;
+	tegra_bct_strapping &= TEGRA_RAM_ID_MASK;
+}
+
+static void tegra_get_revision(u32 id)
+{
+	u32 minor_rev = (id >> 16) & 0xf;
+
+	switch (minor_rev) {
+	case 1:
+		tegra_revision = TEGRA_REVISION_A01;
+		break;
+	case 2:
+		tegra_revision = TEGRA_REVISION_A02;
+		break;
+	case 3:
+		if (tegra_chip_id == TEGRA20 &&
+			(tegra20_spare_fuse_early(18, fuse_base) ||
+			 tegra20_spare_fuse_early(19, fuse_base)))
+			tegra_revision = TEGRA_REVISION_A03p;
+		else
+			tegra_revision = TEGRA_REVISION_A03;
+		break;
+	case 4:
+		tegra_revision = TEGRA_REVISION_A04;
+		break;
+	default:
+		tegra_revision = TEGRA_REVISION_UNKNOWN;
+	}
+}
+
+u32 tegra_read_straps(void)
+{
+	return readl(apbmisc_base + TEGRA_STRAP_OPT);
+}
+
+u32 tegra_read_chipid(void)
+{
+	return readl_relaxed(apbmisc_base + 0x804);
+}
+
+int tegra_fuse_create_sysfs(struct device *dev, int size,
+		     u32 (*readl)(const unsigned int offset),
+		     struct tegra_sku_info *sku_info)
+{
+	int err;
+
+	if (fuse_size)
+		return -ENODEV;
+
+	fuse_bin_attr.size = size;
+	fuse_bin_attr.read = fuse_read;
+
+	fuse_size = size;
+	fuse_readl = readl;
+
+	err = device_create_bin_file(dev, &fuse_bin_attr);
+	if (err)
+		return err;
+
+	dev_info(dev,
+		"Tegra Revision: %s SKU: %d CPU Process: %d Core Process: %d\n",
+		tegra_revision_name[sku_info->revision],
+		sku_info->sku_id, sku_info->cpu_process_id,
+		sku_info->core_process_id);
+
+	return 0;
+}
+
+void __init tegra_init_fuse(void)
+{
+	struct device_node *np;
+	u32 id, reg;
+
+	np = of_find_matching_node(NULL, tegra_fuse_match);
+	fuse_base = of_iomap(np, 0);
+	if (!fuse_base) {
+		pr_err("ioremap tegra fuse failed\n");
+		return;
+	}
+
+	apbmisc_base = of_iomap(np, 1);
+	if (!apbmisc_base) {
+		pr_err("ioremap tegra apbmisc failed\n");
+		iounmap(fuse_base);
+		return;
+	}
+
+	np = of_find_matching_node(NULL, car_match);
+	car_base = of_iomap(np, 0);
+	if (!car_base) {
+		pr_err("ioremap tegra car failed\n");
+		iounmap(fuse_base);
+		iounmap(apbmisc_base);
+		return;
+	}
+
+	reg = readl_relaxed(car_base + 0x48);
+	reg |= 1 << 28;
+	writel(reg, car_base + 0x48);
+
+	/*
+	 * Enable FUSE clock. This needs to be hardcoded because the clock
+	 * subsystem is not active during early boot.
+	 */
+	reg = readl(car_base + 0x14);
+	reg |= 1 << 7;
+	writel(reg, car_base + 0x14);
+
+	iounmap(car_base);
+
+	id = tegra_read_chipid();
+	tegra_chip_id = (id >> 8) & 0xff;
+
+	tegra_read_bct_strapping();
+
+	tegra_get_revision(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..45bdfb8
--- /dev/null
+++ b/drivers/misc/fuse/tegra/fuse-tegra20.c
@@ -0,0 +1,136 @@
+/*
+ * 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/err.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/kobject.h>
+#include <linux/module.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_SKU_INFO	0x10
+#define FUSE_UID_LOW	0x08
+#define FUSE_UID_HIGH	0x0c
+
+static phys_addr_t fuse_phys;
+static struct clk *fuse_clk;
+static struct tegra_sku_info sku_info;
+
+static u32 tegra20_fuse_readl(const unsigned int offset)
+{
+	int ret;
+	u32 val;
+
+	clk_prepare_enable(fuse_clk);
+
+	ret = tegra_apb_readl_using_dma(fuse_phys + FUSE_BEGIN + offset, &val);
+
+	clk_disable_unprepare(fuse_clk);
+
+	return (ret < 0) ? 0 : val;
+}
+
+static void tegra20_fuse_add_randomness(void)
+{
+	u32 randomness[7];
+
+	randomness[0] = tegra20_fuse_readl(FUSE_SKU_INFO);
+	randomness[1] = tegra_read_straps();
+	randomness[2] = tegra_read_chipid();
+	randomness[3] = sku_info.cpu_process_id << 16;
+	randomness[3] |= sku_info.core_process_id;
+	randomness[4] = sku_info.cpu_speedo_id << 16 | sku_info.soc_speedo_id;
+	randomness[5] = tegra20_fuse_readl(FUSE_UID_LOW);
+	randomness[6] = tegra20_fuse_readl(FUSE_UID_HIGH);
+
+	add_device_randomness(randomness, sizeof(randomness));
+}
+
+bool tegra20_spare_fuse(int spare_bit)
+{
+	u32 offset = spare_bit * 4 + 0x100;
+
+	return tegra20_fuse_readl(offset) & 1;
+}
+
+bool tegra20_spare_fuse_early(int spare_bit, void *fuse_base)
+{
+	u32 offset = spare_bit * 4 + 0x100;
+
+	return readl_relaxed(fuse_base + FUSE_BEGIN + offset);
+}
+
+static const struct of_device_id tegra20_fuse_of_match[] = {
+	{ .compatible = "nvidia,tegra20-efuse" },
+	{},
+}
+MODULE_DEVICE_TABLE(of, tegra20_fuse_of_match);
+
+static int tegra20_fuse_probe(struct platform_device *pdev)
+{
+	struct resource *res;
+
+	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;
+
+	sku_info.revision = tegra_revision;
+	tegra20_init_speedo_data(&sku_info, &pdev->dev);
+	dev_dbg(&pdev->dev, "Soc Speedo ID %d", sku_info.soc_speedo_id);
+
+	tegra20_fuse_add_randomness();
+
+	if (tegra_fuse_create_sysfs(&pdev->dev, FUSE_SIZE, tegra20_fuse_readl,
+			     &sku_info))
+		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);
diff --git a/drivers/misc/fuse/tegra/fuse-tegra30.c b/drivers/misc/fuse/tegra/fuse-tegra30.c
new file mode 100644
index 0000000..6133b77
--- /dev/null
+++ b/drivers/misc/fuse/tegra/fuse-tegra30.c
@@ -0,0 +1,178 @@
+/*
+ * 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/module.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_SKU_INFO		0x10
+
+/* 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)
+
+struct tegra_fuse_info {
+	int	size;
+	int	spare_bit;
+	void	(*init_speedo_data)(struct tegra_sku_info *sku_info,
+				    struct device *dev);
+};
+
+static void __iomem *fuse_base;
+static struct clk *fuse_clk;
+static struct tegra_fuse_info *fuse_info;
+static struct tegra_sku_info sku_info;
+
+u32 tegra30_fuse_readl(const unsigned int offset)
+{
+	u32 val;
+
+	clk_prepare_enable(fuse_clk);
+
+	val = readl_relaxed(fuse_base + FUSE_BEGIN + offset);
+
+	clk_disable_unprepare(fuse_clk);
+
+	return val;
+}
+
+bool tegra30_spare_fuse(int spare_bit)
+{
+	u32 offset = fuse_info->spare_bit + spare_bit * 4;
+
+	return tegra30_fuse_readl(offset) & 1;
+}
+
+static void tegra30_fuse_add_randomness(void)
+{
+	u32 randomness[12];
+
+	randomness[0] = tegra30_fuse_readl(FUSE_SKU_INFO);
+	randomness[1] = tegra_read_straps();
+	randomness[2] = tegra_read_chipid();
+	randomness[3] = sku_info.cpu_process_id << 16;
+	randomness[3] |= sku_info.core_process_id;
+	randomness[4] = sku_info.cpu_speedo_id << 16;
+	randomness[4] |= 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 struct tegra_fuse_info tegra30_info = {
+	.size			= 0x2a4,
+	.spare_bit		= 0x144,
+	.init_speedo_data	= tegra30_init_speedo_data,
+};
+
+static struct tegra_fuse_info tegra114_info = {
+	.size			= 0x2a0,
+	.init_speedo_data	= tegra114_init_speedo_data,
+};
+
+static struct tegra_fuse_info tegra124_info = {
+	.size			= 0x300,
+	.init_speedo_data	= tegra124_init_speedo_data,
+};
+
+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;
+	struct resource *res;
+
+	of_dev_id = of_match_device(tegra30_fuse_of_match, &pdev->dev);
+	if (!of_dev_id)
+		return -ENODEV;
+	fuse_info = (struct tegra_fuse_info *)of_dev_id->data;
+
+	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);
+	fuse_base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(fuse_base)) {
+		dev_err(&pdev->dev, "unable to map base address");
+		return PTR_ERR(fuse_base);
+	}
+
+	sku_info.revision = tegra_revision;
+	fuse_info->init_speedo_data(&sku_info, &pdev->dev);
+	dev_dbg(&pdev->dev, "CPU Speedo ID %d, Soc Speedo ID %d",
+		sku_info.cpu_speedo_id, sku_info.soc_speedo_id);
+
+	tegra30_fuse_add_randomness();
+
+	platform_set_drvdata(pdev, NULL);
+
+	if (tegra_fuse_create_sysfs(&pdev->dev, fuse_info->size,
+				    tegra30_fuse_readl, &sku_info))
+		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);
+
diff --git a/drivers/misc/fuse/tegra/fuse.h b/drivers/misc/fuse/tegra/fuse.h
new file mode 100644
index 0000000..0baf82b
--- /dev/null
+++ b/drivers/misc/fuse/tegra/fuse.h
@@ -0,0 +1,82 @@
+/*
+ * 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
+
+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;
+};
+
+int tegra_fuse_create_sysfs(struct device *dev, int size,
+		     u32 (*readl)(const unsigned int offset),
+		     struct tegra_sku_info *sku_info);
+
+bool tegra30_spare_fuse(int bit);
+u32 tegra30_fuse_readl(const unsigned int offset);
+
+#ifdef CONFIG_ARCH_TEGRA_2x_SOC
+void tegra20_init_speedo_data(struct tegra_sku_info *sku_info,
+			      struct device *dev);
+bool tegra20_spare_fuse(int bit);
+bool tegra20_spare_fuse_early(int spare_bit, void *fuse_base);
+#else
+static inline void tegra20_init_speedo_data(struct tegra_sku_info *sku_info,
+					    struct device *dev) {}
+static inline bool tegra20_spare_fuse(int bit) { return false; }
+static inline bool tegra20_spare_fuse_early(int spare_bit, void *fuse_base)
+{
+			return false;
+}
+#endif
+
+#ifdef CONFIG_ARCH_TEGRA_3x_SOC
+void tegra30_init_speedo_data(struct tegra_sku_info *sku_info,
+			      struct device *dev);
+#else
+static inline void tegra30_init_speedo_data(struct tegra_sku_info *sku_info,
+					    struct device *dev) {}
+#endif
+
+#ifdef CONFIG_ARCH_TEGRA_114_SOC
+void tegra114_init_speedo_data(struct tegra_sku_info *sku_info,
+			       struct device *dev);
+#else
+static inline void tegra114_init_speedo_data(struct tegra_sku_info *sku_info,
+					     struct device *dev) {}
+#endif
+
+#ifdef CONFIG_ARCH_TEGRA_124_SOC
+void tegra124_init_speedo_data(struct tegra_sku_info *sku_info,
+			       struct device *dev);
+#else
+static inline void tegra124_init_speedo_data(struct tegra_sku_info *sku_info,
+					     struct device *dev) {}
+#endif
+
+#endif
diff --git a/drivers/misc/fuse/tegra/tegra114_speedo.c b/drivers/misc/fuse/tegra/tegra114_speedo.c
new file mode 100644
index 0000000..7be8ba5
--- /dev/null
+++ b/drivers/misc/fuse/tegra/tegra114_speedo.c
@@ -0,0 +1,110 @@
+/*
+ * 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_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(struct tegra_sku_info *sku_info,
+				  int *threshold, struct device *dev)
+{
+	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:
+		dev_err(dev, "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 tegra114_init_speedo_data(struct tegra_sku_info *sku_info,
+			       struct device *dev)
+{
+	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, dev);
+
+	cpu_speedo_val = tegra30_fuse_readl(0x12c) + 1024;
+	core_speedo_val = tegra30_fuse_readl(0x134);
+
+	for (i = 0; i < CPU_PROCESS_CORNERS_NUM; i++)
+		if (cpu_speedo_val < cpu_process_speedos[threshold][i])
+			break;
+	sku_info->cpu_process_id = i;
+
+	for (i = 0; i < CORE_PROCESS_CORNERS_NUM; i++)
+		if (core_speedo_val < core_process_speedos[threshold][i])
+			break;
+	sku_info->core_process_id = i;
+}
diff --git a/drivers/misc/fuse/tegra/tegra124_speedo.c b/drivers/misc/fuse/tegra/tegra124_speedo.c
new file mode 100644
index 0000000..70edb2d
--- /dev/null
+++ b/drivers/misc/fuse/tegra/tegra124_speedo.c
@@ -0,0 +1,164 @@
+/*
+ * 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_NUM	2
+#define GPU_PROCESS_CORNERS_NUM	2
+#define CORE_PROCESS_CORNERS_NUM	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 int cpu_speedo_0_value;
+static int cpu_speedo_1_value;
+static int soc_speedo_0_value;
+static int soc_speedo_1_value;
+static int soc_speedo_2_value;
+static int cpu_iddq_value;
+static int gpu_iddq_value;
+static int soc_iddq_value;
+
+static const u32 cpu_process_speedos[][CPU_PROCESS_CORNERS_NUM] = {
+	{2190,	UINT_MAX},
+	{0,	UINT_MAX},
+};
+
+static const u32 gpu_process_speedos[][GPU_PROCESS_CORNERS_NUM] = {
+	{1965,	UINT_MAX},
+	{0,	UINT_MAX},
+};
+
+static const u32 core_process_speedos[][CORE_PROCESS_CORNERS_NUM] = {
+	{2101,	UINT_MAX},
+	{0,	UINT_MAX},
+};
+
+static void rev_sku_to_speedo_ids(struct tegra_sku_info *sku_info,
+				  int *threshold, struct device *dev)
+{
+	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:
+		/* Using the default */
+		break;
+
+	case 0x81:
+	case 0x83:
+		sku_info->cpu_speedo_id = 2;
+		break;
+
+	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;
+
+	default:
+		dev_err(dev, "Unknown SKU %d\n", sku);
+		/* Using the default for the error case */
+		break;
+	}
+}
+
+void tegra124_init_speedo_data(struct tegra_sku_info *sku_info,
+			       struct device *dev)
+{
+	int i;
+	int threshold;
+
+	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);
+	cpu_speedo_1_value = tegra30_fuse_readl(FUSE_CPU_SPEEDO_1);
+
+	/* 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);
+	soc_speedo_1_value = tegra30_fuse_readl(FUSE_SOC_SPEEDO_1);
+	soc_speedo_2_value = tegra30_fuse_readl(FUSE_SOC_SPEEDO_2);
+
+	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) {
+		dev_warn(dev, "Warning: Speedo value not fused.\n");
+		WARN_ON(1);
+		return;
+	}
+
+	rev_sku_to_speedo_ids(sku_info, &threshold, dev);
+
+	sku_info->cpu_iddq_value = tegra30_fuse_readl(FUSE_CPU_IDDQ);
+
+	for (i = 0; i < GPU_PROCESS_CORNERS_NUM; 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_NUM; 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_NUM; i++)
+		if (soc_speedo_0_value <
+			core_process_speedos[threshold][i])
+			break;
+	sku_info->core_process_id = i;
+
+	dev_dbg(dev, "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/tegra20_speedo.c b/drivers/misc/fuse/tegra/tegra20_speedo.c
new file mode 100644
index 0000000..af8e86a
--- /dev/null
+++ b/drivers/misc/fuse/tegra/tegra20_speedo.c
@@ -0,0 +1,110 @@
+/*
+ * 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 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(struct tegra_sku_info *sku_info,
+			      struct device *dev)
+{
+	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(i) |
+			tegra20_spare_fuse(i + CPU_SPEEDO_REDUND_OFFS);
+		val = (val << 1) | (reg & 0x1);
+	}
+	val = val * SPEEDO_MULT;
+	dev_dbg(dev, "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(i) |
+			tegra20_spare_fuse(i + CORE_SPEEDO_REDUND_OFFS);
+		val = (val << 1) | (reg & 0x1);
+	}
+	val = val * SPEEDO_MULT;
+	dev_dbg(dev, "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/tegra30_speedo.c b/drivers/misc/fuse/tegra/tegra30_speedo.c
new file mode 100644
index 0000000..11cf0cd
--- /dev/null
+++ b/drivers/misc/fuse/tegra/tegra30_speedo.c
@@ -0,0 +1,294 @@
+/*
+ * 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_NUM	1
+#define CPU_PROCESS_CORNERS_NUM		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 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,
+			      struct device *dev)
+{
+	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);
+	dev_dbg(dev, "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 rev_sku_to_speedo_ids(struct tegra_sku_info *sku_info,
+				  struct device *dev)
+{
+	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:
+				dev_err(dev, "Unknown pkg %d\n", package_id);
+				BUG();
+				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:
+				dev_err(dev, "Unknown pkg %d\n", package_id);
+				BUG();
+				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:
+				dev_err(dev, "Unknown pkg %d\n", package_id);
+				BUG();
+				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:
+				dev_err(dev, "Unknown pkg %d\n", package_id);
+				BUG();
+				break;
+			}
+			break;
+		default:
+			dev_warn(dev, "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:
+		dev_warn(dev, "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 tegra30_init_speedo_data(struct tegra_sku_info *sku_info,
+			      struct device *dev)
+{
+	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 = tegra30_fuse_readl(FUSE_PACKAGE_INFO) & 0x0F;
+
+	rev_sku_to_speedo_ids(sku_info, dev);
+	fuse_speedo_calib(&cpu_speedo_val, &core_speedo_val, dev);
+	dev_dbg(dev, "CPU speedo value %u\n", cpu_speedo_val);
+	dev_dbg(dev, "Core speedo value %u\n", core_speedo_val);
+
+	for (i = 0; i < CPU_PROCESS_CORNERS_NUM; 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) {
+		dev_warn(dev, "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_NUM; 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) {
+		dev_warn(dev, "CORE speedo value %3d out of range",
+		       core_speedo_val);
+		sku_info->core_process_id = 0;
+		sku_info->soc_speedo_id = 1;
+	}
+}
-- 
1.7.7.rc0.72.g4b5ea.dirty

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH v3 4/6] ARM: tegra: Add efuse bindings
  2014-01-28 23:36 [PATCH v3 0/6] efuse driver for Tegra Peter De Schrijver
                   ` (2 preceding siblings ...)
  2014-01-28 23:36 ` [PATCH v3 3/6] misc: fuse: Add efuse driver for Tegra Peter De Schrijver
@ 2014-01-28 23:36 ` Peter De Schrijver
  2014-01-29 17:18   ` Rob Herring
  2014-02-05 18:42   ` Stephen Warren
  2014-01-28 23:36 ` [PATCH v3 5/6] misc: enable fuse drivers Peter De Schrijver
                   ` (3 subsequent siblings)
  7 siblings, 2 replies; 21+ messages in thread
From: Peter De Schrijver @ 2014-01-28 23:36 UTC (permalink / raw)
  To: linux-arm-kernel

Add efuse bindings for Tegra20, Tegra30, Tegra114 and Tegra124.

Signed-off-by: Peter De Schrijver <pdeschrijver@nvidia.com>
---
 .../devicetree/bindings/fuse/fuse-tegra.txt        |   32 ++++++++++++++++++++
 arch/arm/boot/dts/tegra114.dtsi                    |    7 ++++
 arch/arm/boot/dts/tegra124.dtsi                    |    7 ++++
 arch/arm/boot/dts/tegra20.dtsi                     |    7 ++++
 arch/arm/boot/dts/tegra30.dtsi                     |    7 ++++
 5 files changed, 60 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/fuse/fuse-tegra.txt

diff --git a/Documentation/devicetree/bindings/fuse/fuse-tegra.txt b/Documentation/devicetree/bindings/fuse/fuse-tegra.txt
new file mode 100644
index 0000000..8a566a1
--- /dev/null
+++ b/Documentation/devicetree/bindings/fuse/fuse-tegra.txt
@@ -0,0 +1,32 @@
+NVIDIA Tegra20/Tegra30/Tegr114/Tegra124 fuse driver.
+
+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 2 entries: the first entry gives the physical address
+       and length of the fuse registers, the second entry gives the physical
+       address and length of the apbmisc registers. These are used to provide
+       the chipid, chip revision and strapping options.
+- clocks: Should contain a pointer to the fuse clock.
+
+Example:
+
+        fuse at 7000f800 {
+                compatible = "nvidia,tegra20-efuse";
+                reg = <0x7000F800 0x400>,
+                      <0x70000000 0x400>;
+                clocks = <&tegra_car TEGRA20_CLK_FUSE>;
+        };
+
+
diff --git a/arch/arm/boot/dts/tegra114.dtsi b/arch/arm/boot/dts/tegra114.dtsi
index 389e987..05ca90b 100644
--- a/arch/arm/boot/dts/tegra114.dtsi
+++ b/arch/arm/boot/dts/tegra114.dtsi
@@ -481,6 +481,13 @@
 		clock-names = "pclk", "clk32k_in";
 	};
 
+	fuse at 7000f800 {
+		compatible = "nvidia,tegra114-efuse";
+		reg = <0x7000f800 0x400>,
+		      <0x70000000 0x400>;
+		clocks = <&tegra_car TEGRA114_CLK_FUSE>;
+	};
+
 	iommu at 70019010 {
 		compatible = "nvidia,tegra114-smmu", "nvidia,tegra30-smmu";
 		reg = <0x70019010 0x02c
diff --git a/arch/arm/boot/dts/tegra124.dtsi b/arch/arm/boot/dts/tegra124.dtsi
index ec0698a..30faa73 100644
--- a/arch/arm/boot/dts/tegra124.dtsi
+++ b/arch/arm/boot/dts/tegra124.dtsi
@@ -381,6 +381,13 @@
 		clock-names = "pclk", "clk32k_in";
 	};
 
+	fuse@7000f800 {
+		compatible = "nvidia,tegra124-efuse";
+		reg = <0x7000f800 0x400>,
+		      <0x70000000 0x400>;
+		clocks = <&tegra_car TEGRA124_CLK_FUSE>;
+	};
+
 	sdhci at 700b0000 {
 		compatible = "nvidia,tegra124-sdhci";
 		reg = <0x700b0000 0x200>;
diff --git a/arch/arm/boot/dts/tegra20.dtsi b/arch/arm/boot/dts/tegra20.dtsi
index 480ecda..a1a15d7 100644
--- a/arch/arm/boot/dts/tegra20.dtsi
+++ b/arch/arm/boot/dts/tegra20.dtsi
@@ -541,6 +541,13 @@
 		#size-cells = <0>;
 	};
 
+	fuse at 7000f800 {
+		compatible = "nvidia,tegra20-efuse";
+		reg = <0x7000F800 0x400>,
+		      <0x70000000 0x400>;
+		clocks = <&tegra_car TEGRA20_CLK_FUSE>;
+	};
+
 	pcie-controller at 80003000 {
 		compatible = "nvidia,tegra20-pcie";
 		device_type = "pci";
diff --git a/arch/arm/boot/dts/tegra30.dtsi b/arch/arm/boot/dts/tegra30.dtsi
index ed8e770..1ec80fa 100644
--- a/arch/arm/boot/dts/tegra30.dtsi
+++ b/arch/arm/boot/dts/tegra30.dtsi
@@ -623,6 +623,13 @@
 		nvidia,ahb = <&ahb>;
 	};
 
+	fuse at 7000f800 {
+		compatible = "nvidia,tegra30-efuse";
+		reg = <0x7000f800 0x400>,
+		      <0x70000000 0x400>;
+		clocks = <&tegra_car TEGRA30_CLK_FUSE>;
+	};
+
 	ahub at 70080000 {
 		compatible = "nvidia,tegra30-ahub";
 		reg = <0x70080000 0x200
-- 
1.7.7.rc0.72.g4b5ea.dirty

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH v3 5/6] misc: enable fuse drivers
  2014-01-28 23:36 [PATCH v3 0/6] efuse driver for Tegra Peter De Schrijver
                   ` (3 preceding siblings ...)
  2014-01-28 23:36 ` [PATCH v3 4/6] ARM: tegra: Add efuse bindings Peter De Schrijver
@ 2014-01-28 23:36 ` Peter De Schrijver
  2014-02-05 18:44   ` Stephen Warren
  2014-01-28 23:36 ` [PATCH v3 6/6] ARM: tegra: remove fuse files from mach-tegra Peter De Schrijver
                   ` (2 subsequent siblings)
  7 siblings, 1 reply; 21+ messages in thread
From: Peter De Schrijver @ 2014-01-28 23:36 UTC (permalink / raw)
  To: linux-arm-kernel

Enable building the fuse drivers.

Signed-off-by: Peter De Schrijver <pdeschrijver@nvidia.com>
---
 arch/arm/mach-tegra/Makefile |    4 ----
 drivers/misc/Makefile        |    1 +
 2 files changed, 1 insertions(+), 4 deletions(-)

diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile
index 019bb17..92f8ab2 100644
--- a/arch/arm/mach-tegra/Makefile
+++ b/arch/arm/mach-tegra/Makefile
@@ -2,7 +2,6 @@ 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
@@ -13,14 +12,12 @@ 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)		+= tegra2_emc.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)
@@ -29,7 +26,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/drivers/misc/Makefile b/drivers/misc/Makefile
index 99b9424..e243a8b 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -54,3 +54,4 @@ obj-$(CONFIG_LATTICE_ECP3_CONFIG)	+= lattice-ecp3-config.o
 obj-$(CONFIG_SRAM)		+= sram.o
 obj-y				+= mic/
 obj-$(CONFIG_GENWQE)		+= genwqe/
+obj-y				+= fuse/
-- 
1.7.7.rc0.72.g4b5ea.dirty

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH v3 6/6] ARM: tegra: remove fuse files from mach-tegra
  2014-01-28 23:36 [PATCH v3 0/6] efuse driver for Tegra Peter De Schrijver
                   ` (4 preceding siblings ...)
  2014-01-28 23:36 ` [PATCH v3 5/6] misc: enable fuse drivers Peter De Schrijver
@ 2014-01-28 23:36 ` Peter De Schrijver
  2014-02-05 18:45   ` Stephen Warren
  2014-01-29 15:00 ` [PATCH v3 0/6] efuse driver for Tegra Paul Gortmaker
  2014-02-05 18:49 ` Stephen Warren
  7 siblings, 1 reply; 21+ messages in thread
From: Peter De Schrijver @ 2014-01-28 23:36 UTC (permalink / raw)
  To: linux-arm-kernel

All fuse related functionality is now provided by the tegra fuse driver.
Hence all the fuse related files in mach-tegra can be removed.

Signed-off-by: Peter De Schrijver <pdeschrijver@nvidia.com>
---
 arch/arm/mach-tegra/fuse.c            |  252 ----------------------------
 arch/arm/mach-tegra/fuse.h            |   61 -------
 arch/arm/mach-tegra/tegra114_speedo.c |  105 ------------
 arch/arm/mach-tegra/tegra20_speedo.c  |  110 ------------
 arch/arm/mach-tegra/tegra30_speedo.c  |  293 ---------------------------------
 5 files changed, 0 insertions(+), 821 deletions(-)
 delete mode 100644 arch/arm/mach-tegra/fuse.c
 delete mode 100644 arch/arm/mach-tegra/fuse.h
 delete mode 100644 arch/arm/mach-tegra/tegra114_speedo.c
 delete mode 100644 arch/arm/mach-tegra/tegra20_speedo.c
 delete mode 100644 arch/arm/mach-tegra/tegra30_speedo.c

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 b17c4ba..0000000
--- a/arch/arm/mach-tegra/fuse.h
+++ /dev/null
@@ -1,61 +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
-
-#ifndef __ASSEMBLY__
-
-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;
-
-unsigned long long tegra_chip_uid(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/tegra114_speedo.c b/arch/arm/mach-tegra/tegra114_speedo.c
deleted file mode 100644
index 7c73716..0000000
--- a/arch/arm/mach-tegra/tegra114_speedo.c
+++ /dev/null
@@ -1,105 +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 <linux/tegra-soc.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 3b1bb53..0000000
--- a/arch/arm/mach-tegra/tegra20_speedo.c
+++ /dev/null
@@ -1,110 +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 <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 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 81a958d..0000000
--- a/arch/arm/mach-tegra/tegra30_speedo.c
+++ /dev/null
@@ -1,293 +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 <linux/tegra-soc.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);
-}
-- 
1.7.7.rc0.72.g4b5ea.dirty

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH v3 3/6] misc: fuse: Add efuse driver for Tegra
  2014-01-28 23:36 ` [PATCH v3 3/6] misc: fuse: Add efuse driver for Tegra Peter De Schrijver
@ 2014-01-29  2:26   ` Jim Lin
  2014-02-03 14:15     ` Peter De Schrijver
  2014-02-05 19:15   ` Stephen Warren
  1 sibling, 1 reply; 21+ messages in thread
From: Jim Lin @ 2014-01-29  2:26 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, 2014-01-29 at 07:36 +0800, Peter De Schrijver wrote:
> Implement fuse driver for Tegra20, Tegra30, Tegra114 and Tegra124.
> 
> Signed-off-by: Peter De Schrijver <pdeschrijver@nvidia.com>
> ---
>  Documentation/ABI/testing/sysfs-driver-tegra-fuse |    8 +
>  drivers/misc/fuse/Makefile                        |    1 +
>  drivers/misc/fuse/tegra/Makefile                  |    7 +
>  drivers/misc/fuse/tegra/fuse-tegra.c              |  228 ++++++++++++++++
>  drivers/misc/fuse/tegra/fuse-tegra20.c            |  136 ++++++++++
>  drivers/misc/fuse/tegra/fuse-tegra30.c            |  178 +++++++++++++
>  drivers/misc/fuse/tegra/fuse.h                    |   82 ++++++
Could we move this fuse.h to other folder under /include/linux
(like /include/linux/platform_data)
for other driver to include?
So other driver can invoke function to read fuse data if needed.

--nvpublic

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH v3 0/6] efuse driver for Tegra
  2014-01-28 23:36 [PATCH v3 0/6] efuse driver for Tegra Peter De Schrijver
                   ` (5 preceding siblings ...)
  2014-01-28 23:36 ` [PATCH v3 6/6] ARM: tegra: remove fuse files from mach-tegra Peter De Schrijver
@ 2014-01-29 15:00 ` Paul Gortmaker
  2014-01-30  9:45   ` Peter De Schrijver
  2014-02-05 18:49 ` Stephen Warren
  7 siblings, 1 reply; 21+ messages in thread
From: Paul Gortmaker @ 2014-01-29 15:00 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Jan 28, 2014 at 6:36 PM, Peter De Schrijver
<pdeschrijver@nvidia.com> wrote:
> This driver allows userspace to read the raw efuse data. Its userspace
> interface is modelled after the sunxi_sid driver which provides similar
> functionality for some Allwinner SoCs. It has been tested on
> Tegra20 (ventana), Tegra30 (beaverboard) and Tegra114 (dalmore).
>
> Changes since v1:
>
> * Add documentation for sysfs interface
> * Cleanup messages
>
> Changes since v2:
>
> * Incorporate early fuse code
> * Remove module support
> * Make driver always build when Tegra platform is selected

Given the above, you should be able to remove #include <linux/module.h>
and MODULE_DEVICE_TABLE, etc.

Paul.
--

> * Add DT binding document
> * Address comments on v2
>
> TODO:
> * test on Tegra124 (venice2)
>
> Peter De Schrijver (6):
>   ARM: tegra: export apb dma readl/writel
>   ARM: tegra: Add chipid, revision and fuse init
>   misc: fuse: Add efuse driver for Tegra
>   ARM: tegra: Add efuse bindings
>   misc: enable fuse drivers
>   ARM: tegra: remove fuse files from mach-tegra
>
>  Documentation/ABI/testing/sysfs-driver-tegra-fuse  |    8 +
>  .../devicetree/bindings/fuse/fuse-tegra.txt        |   32 +++
>  arch/arm/boot/dts/tegra114.dtsi                    |    7 +
>  arch/arm/boot/dts/tegra124.dtsi                    |    7 +
>  arch/arm/boot/dts/tegra20.dtsi                     |    7 +
>  arch/arm/boot/dts/tegra30.dtsi                     |    7 +
>  arch/arm/mach-tegra/Makefile                       |    4 -
>  arch/arm/mach-tegra/apbio.c                        |   51 ++--
>  arch/arm/mach-tegra/cpuidle.c                      |    2 +-
>  arch/arm/mach-tegra/flowctrl.c                     |    2 +-
>  arch/arm/mach-tegra/fuse.c                         |  252 -----------------
>  arch/arm/mach-tegra/fuse.h                         |   79 ------
>  arch/arm/mach-tegra/hotplug.c                      |    2 +-
>  arch/arm/mach-tegra/platsmp.c                      |    2 +-
>  arch/arm/mach-tegra/pm.c                           |    2 +-
>  arch/arm/mach-tegra/pmc.c                          |    2 +-
>  arch/arm/mach-tegra/powergate.c                    |    2 +-
>  arch/arm/mach-tegra/reset-handler.S                |    2 +-
>  arch/arm/mach-tegra/reset.c                        |    2 +-
>  arch/arm/mach-tegra/sleep-tegra30.S                |    2 +-
>  arch/arm/mach-tegra/tegra.c                        |    2 +-
>  arch/arm/mach-tegra/tegra114_speedo.c              |  104 -------
>  arch/arm/mach-tegra/tegra20_speedo.c               |  109 --------
>  arch/arm/mach-tegra/tegra2_emc.c                   |    2 +-
>  arch/arm/mach-tegra/tegra30_speedo.c               |  292 -------------------
>  drivers/misc/Makefile                              |    1 +
>  drivers/misc/fuse/Makefile                         |    1 +
>  drivers/misc/fuse/tegra/Makefile                   |    7 +
>  drivers/misc/fuse/tegra/fuse-tegra.c               |  228 +++++++++++++++
>  drivers/misc/fuse/tegra/fuse-tegra20.c             |  136 +++++++++
>  drivers/misc/fuse/tegra/fuse-tegra30.c             |  178 ++++++++++++
>  drivers/misc/fuse/tegra/fuse.h                     |   82 ++++++
>  drivers/misc/fuse/tegra/tegra114_speedo.c          |  110 ++++++++
>  drivers/misc/fuse/tegra/tegra124_speedo.c          |  164 +++++++++++
>  drivers/misc/fuse/tegra/tegra20_speedo.c           |  110 ++++++++
>  drivers/misc/fuse/tegra/tegra30_speedo.c           |  294 ++++++++++++++++++++
>  include/linux/tegra-soc.h                          |   39 +++
>  37 files changed, 1461 insertions(+), 872 deletions(-)
>  create mode 100644 Documentation/ABI/testing/sysfs-driver-tegra-fuse
>  create mode 100644 Documentation/devicetree/bindings/fuse/fuse-tegra.txt
>  delete mode 100644 arch/arm/mach-tegra/fuse.c
>  delete mode 100644 arch/arm/mach-tegra/fuse.h
>  delete mode 100644 arch/arm/mach-tegra/tegra114_speedo.c
>  delete mode 100644 arch/arm/mach-tegra/tegra20_speedo.c
>  delete mode 100644 arch/arm/mach-tegra/tegra30_speedo.c
>  create mode 100644 drivers/misc/fuse/Makefile
>  create mode 100644 drivers/misc/fuse/tegra/Makefile
>  create mode 100644 drivers/misc/fuse/tegra/fuse-tegra.c
>  create mode 100644 drivers/misc/fuse/tegra/fuse-tegra20.c
>  create mode 100644 drivers/misc/fuse/tegra/fuse-tegra30.c
>  create mode 100644 drivers/misc/fuse/tegra/fuse.h
>  create mode 100644 drivers/misc/fuse/tegra/tegra114_speedo.c
>  create mode 100644 drivers/misc/fuse/tegra/tegra124_speedo.c
>  create mode 100644 drivers/misc/fuse/tegra/tegra20_speedo.c
>  create mode 100644 drivers/misc/fuse/tegra/tegra30_speedo.c
>
> --
> 1.7.7.rc0.72.g4b5ea.dirty
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH v3 4/6] ARM: tegra: Add efuse bindings
  2014-01-28 23:36 ` [PATCH v3 4/6] ARM: tegra: Add efuse bindings Peter De Schrijver
@ 2014-01-29 17:18   ` Rob Herring
  2014-02-05 18:42   ` Stephen Warren
  1 sibling, 0 replies; 21+ messages in thread
From: Rob Herring @ 2014-01-29 17:18 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Jan 28, 2014 at 5:36 PM, Peter De Schrijver
<pdeschrijver@nvidia.com> wrote:
> Add efuse bindings for Tegra20, Tegra30, Tegra114 and Tegra124.
>
> Signed-off-by: Peter De Schrijver <pdeschrijver@nvidia.com>

Acked-by: Rob Herring <robh@kernel.org>

Rob

> ---
>  .../devicetree/bindings/fuse/fuse-tegra.txt        |   32 ++++++++++++++++++++
>  arch/arm/boot/dts/tegra114.dtsi                    |    7 ++++
>  arch/arm/boot/dts/tegra124.dtsi                    |    7 ++++
>  arch/arm/boot/dts/tegra20.dtsi                     |    7 ++++
>  arch/arm/boot/dts/tegra30.dtsi                     |    7 ++++
>  5 files changed, 60 insertions(+), 0 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/fuse/fuse-tegra.txt
>
> diff --git a/Documentation/devicetree/bindings/fuse/fuse-tegra.txt b/Documentation/devicetree/bindings/fuse/fuse-tegra.txt
> new file mode 100644
> index 0000000..8a566a1
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/fuse/fuse-tegra.txt
> @@ -0,0 +1,32 @@
> +NVIDIA Tegra20/Tegra30/Tegr114/Tegra124 fuse driver.
> +
> +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 2 entries: the first entry gives the physical address
> +       and length of the fuse registers, the second entry gives the physical
> +       address and length of the apbmisc registers. These are used to provide
> +       the chipid, chip revision and strapping options.
> +- clocks: Should contain a pointer to the fuse clock.
> +
> +Example:
> +
> +        fuse at 7000f800 {
> +                compatible = "nvidia,tegra20-efuse";
> +                reg = <0x7000F800 0x400>,
> +                      <0x70000000 0x400>;
> +                clocks = <&tegra_car TEGRA20_CLK_FUSE>;
> +        };
> +
> +
> diff --git a/arch/arm/boot/dts/tegra114.dtsi b/arch/arm/boot/dts/tegra114.dtsi
> index 389e987..05ca90b 100644
> --- a/arch/arm/boot/dts/tegra114.dtsi
> +++ b/arch/arm/boot/dts/tegra114.dtsi
> @@ -481,6 +481,13 @@
>                 clock-names = "pclk", "clk32k_in";
>         };
>
> +       fuse at 7000f800 {
> +               compatible = "nvidia,tegra114-efuse";
> +               reg = <0x7000f800 0x400>,
> +                     <0x70000000 0x400>;
> +               clocks = <&tegra_car TEGRA114_CLK_FUSE>;
> +       };
> +
>         iommu at 70019010 {
>                 compatible = "nvidia,tegra114-smmu", "nvidia,tegra30-smmu";
>                 reg = <0x70019010 0x02c
> diff --git a/arch/arm/boot/dts/tegra124.dtsi b/arch/arm/boot/dts/tegra124.dtsi
> index ec0698a..30faa73 100644
> --- a/arch/arm/boot/dts/tegra124.dtsi
> +++ b/arch/arm/boot/dts/tegra124.dtsi
> @@ -381,6 +381,13 @@
>                 clock-names = "pclk", "clk32k_in";
>         };
>
> +       fuse at 7000f800 {
> +               compatible = "nvidia,tegra124-efuse";
> +               reg = <0x7000f800 0x400>,
> +                     <0x70000000 0x400>;
> +               clocks = <&tegra_car TEGRA124_CLK_FUSE>;
> +       };
> +
>         sdhci at 700b0000 {
>                 compatible = "nvidia,tegra124-sdhci";
>                 reg = <0x700b0000 0x200>;
> diff --git a/arch/arm/boot/dts/tegra20.dtsi b/arch/arm/boot/dts/tegra20.dtsi
> index 480ecda..a1a15d7 100644
> --- a/arch/arm/boot/dts/tegra20.dtsi
> +++ b/arch/arm/boot/dts/tegra20.dtsi
> @@ -541,6 +541,13 @@
>                 #size-cells = <0>;
>         };
>
> +       fuse at 7000f800 {
> +               compatible = "nvidia,tegra20-efuse";
> +               reg = <0x7000F800 0x400>,
> +                     <0x70000000 0x400>;
> +               clocks = <&tegra_car TEGRA20_CLK_FUSE>;
> +       };
> +
>         pcie-controller at 80003000 {
>                 compatible = "nvidia,tegra20-pcie";
>                 device_type = "pci";
> diff --git a/arch/arm/boot/dts/tegra30.dtsi b/arch/arm/boot/dts/tegra30.dtsi
> index ed8e770..1ec80fa 100644
> --- a/arch/arm/boot/dts/tegra30.dtsi
> +++ b/arch/arm/boot/dts/tegra30.dtsi
> @@ -623,6 +623,13 @@
>                 nvidia,ahb = <&ahb>;
>         };
>
> +       fuse at 7000f800 {
> +               compatible = "nvidia,tegra30-efuse";
> +               reg = <0x7000f800 0x400>,
> +                     <0x70000000 0x400>;
> +               clocks = <&tegra_car TEGRA30_CLK_FUSE>;
> +       };
> +
>         ahub at 70080000 {
>                 compatible = "nvidia,tegra30-ahub";
>                 reg = <0x70080000 0x200
> --
> 1.7.7.rc0.72.g4b5ea.dirty
>

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH v3 0/6] efuse driver for Tegra
  2014-01-29 15:00 ` [PATCH v3 0/6] efuse driver for Tegra Paul Gortmaker
@ 2014-01-30  9:45   ` Peter De Schrijver
  0 siblings, 0 replies; 21+ messages in thread
From: Peter De Schrijver @ 2014-01-30  9:45 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Jan 29, 2014 at 04:00:27PM +0100, Paul Gortmaker wrote:
> On Tue, Jan 28, 2014 at 6:36 PM, Peter De Schrijver
> <pdeschrijver@nvidia.com> wrote:
> > This driver allows userspace to read the raw efuse data. Its userspace
> > interface is modelled after the sunxi_sid driver which provides similar
> > functionality for some Allwinner SoCs. It has been tested on
> > Tegra20 (ventana), Tegra30 (beaverboard) and Tegra114 (dalmore).
> >
> > Changes since v1:
> >
> > * Add documentation for sysfs interface
> > * Cleanup messages
> >
> > Changes since v2:
> >
> > * Incorporate early fuse code
> > * Remove module support
> > * Make driver always build when Tegra platform is selected
> 
> Given the above, you should be able to remove #include <linux/module.h>
> and MODULE_DEVICE_TABLE, etc.

Indeed. Thanks for noticing!

Cheers,

Peter.

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH v3 3/6] misc: fuse: Add efuse driver for Tegra
  2014-01-29  2:26   ` Jim Lin
@ 2014-02-03 14:15     ` Peter De Schrijver
  2014-02-05 10:26       ` Jim Lin
  0 siblings, 1 reply; 21+ messages in thread
From: Peter De Schrijver @ 2014-02-03 14:15 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Jan 29, 2014 at 03:26:18AM +0100, Jim Lin wrote:
> On Wed, 2014-01-29 at 07:36 +0800, Peter De Schrijver wrote:
> > Implement fuse driver for Tegra20, Tegra30, Tegra114 and Tegra124.
> > 
> > Signed-off-by: Peter De Schrijver <pdeschrijver@nvidia.com>
> > ---
> >  Documentation/ABI/testing/sysfs-driver-tegra-fuse |    8 +
> >  drivers/misc/fuse/Makefile                        |    1 +
> >  drivers/misc/fuse/tegra/Makefile                  |    7 +
> >  drivers/misc/fuse/tegra/fuse-tegra.c              |  228 ++++++++++++++++
> >  drivers/misc/fuse/tegra/fuse-tegra20.c            |  136 ++++++++++
> >  drivers/misc/fuse/tegra/fuse-tegra30.c            |  178 +++++++++++++
> >  drivers/misc/fuse/tegra/fuse.h                    |   82 ++++++
> Could we move this fuse.h to other folder under /include/linux
> (like /include/linux/platform_data)
> for other driver to include?

I don't think we should expose everything in fuse.h to the world.

> So other driver can invoke function to read fuse data if needed.

Which functionality do you want? Just reading the fuse data exposed in
the sysfs file from a driver? exporting tegra_fuse_readl() should do
that I think?

Cheers,

Peter.

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH v3 3/6] misc: fuse: Add efuse driver for Tegra
  2014-02-03 14:15     ` Peter De Schrijver
@ 2014-02-05 10:26       ` Jim Lin
  0 siblings, 0 replies; 21+ messages in thread
From: Jim Lin @ 2014-02-05 10:26 UTC (permalink / raw)
  To: linux-arm-kernel

Please ignore my comment.
I will try to use exported tegra_fuse_readl().

-----Original Message-----
From: Peter De Schrijver [mailto:pdeschrijver at nvidia.com] 
Sent: Monday, February 03, 2014 10:15 PM
To: Jim Lin
Cc: linux-arm-kernel at lists.infradead.org; linux-tegra at vger.kernel.org; linux-kernel at vger.kernel.org; Rob Landley; Stephen Warren; Thierry Reding; Grant Likely; Rob Herring; Danny Huang; linux-doc at vger.kernel.org; devicetree at vger.kernel.org
Subject: Re: [PATCH v3 3/6] misc: fuse: Add efuse driver for Tegra

On Wed, Jan 29, 2014 at 03:26:18AM +0100, Jim Lin wrote:
> On Wed, 2014-01-29 at 07:36 +0800, Peter De Schrijver wrote:
> > Implement fuse driver for Tegra20, Tegra30, Tegra114 and Tegra124.
> > 
> > Signed-off-by: Peter De Schrijver <pdeschrijver@nvidia.com>
> > ---
> >  Documentation/ABI/testing/sysfs-driver-tegra-fuse |    8 +
> >  drivers/misc/fuse/Makefile                        |    1 +
> >  drivers/misc/fuse/tegra/Makefile                  |    7 +
> >  drivers/misc/fuse/tegra/fuse-tegra.c              |  228 ++++++++++++++++
> >  drivers/misc/fuse/tegra/fuse-tegra20.c            |  136 ++++++++++
> >  drivers/misc/fuse/tegra/fuse-tegra30.c            |  178 +++++++++++++
> >  drivers/misc/fuse/tegra/fuse.h                    |   82 ++++++
> Could we move this fuse.h to other folder under /include/linux (like 
> /include/linux/platform_data) for other driver to include?

I don't think we should expose everything in fuse.h to the world.

> So other driver can invoke function to read fuse data if needed.

Which functionality do you want? Just reading the fuse data exposed in the sysfs file from a driver? exporting tegra_fuse_readl() should do that I think?

Cheers,

Peter.

--nvpublic

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH v3 2/6] ARM: tegra: Add chipid, revision and fuse init
  2014-01-28 23:36 ` [PATCH v3 2/6] ARM: tegra: Add chipid, revision and fuse init Peter De Schrijver
@ 2014-02-05 18:40   ` Stephen Warren
  0 siblings, 0 replies; 21+ messages in thread
From: Stephen Warren @ 2014-02-05 18:40 UTC (permalink / raw)
  To: linux-arm-kernel

On 01/28/2014 04:36 PM, Peter De Schrijver wrote:
> All fuse related functionality will move to a driver in the following patches.
> To prepare for this, export all the required functionality in a global header
> file and move all users of fuse.h to tegra-soc.h

The patch subject and description don't appear related to each-other.

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH v3 4/6] ARM: tegra: Add efuse bindings
  2014-01-28 23:36 ` [PATCH v3 4/6] ARM: tegra: Add efuse bindings Peter De Schrijver
  2014-01-29 17:18   ` Rob Herring
@ 2014-02-05 18:42   ` Stephen Warren
  1 sibling, 0 replies; 21+ messages in thread
From: Stephen Warren @ 2014-02-05 18:42 UTC (permalink / raw)
  To: linux-arm-kernel

On 01/28/2014 04:36 PM, Peter De Schrijver wrote:
> Add efuse bindings for Tegra20, Tegra30, Tegra114 and Tegra124.

> diff --git a/Documentation/devicetree/bindings/fuse/fuse-tegra.txt b/Documentation/devicetree/bindings/fuse/fuse-tegra.txt

> +- clocks: Should contain a pointer to the fuse clock.

I would prefer to use clock-names, and to follow the same text as all
the other Tegra bindings that are clock clients. In other words:

  - 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

(this will allow easy future changes to the binding if required)

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH v3 5/6] misc: enable fuse drivers
  2014-01-28 23:36 ` [PATCH v3 5/6] misc: enable fuse drivers Peter De Schrijver
@ 2014-02-05 18:44   ` Stephen Warren
  0 siblings, 0 replies; 21+ messages in thread
From: Stephen Warren @ 2014-02-05 18:44 UTC (permalink / raw)
  To: linux-arm-kernel

On 01/28/2014 04:36 PM, Peter De Schrijver wrote:
> Enable building the fuse drivers.

This isn't really about enabling them. It's about changing which Tegra
fuse driver is built. Perhaps rephrase this more as:

ARM: tegra: build fuse driver from drivers/misc instead

The Tegra fuse code has moved to drivers/misc/fuse/tegra. Enable the
building of that code, and disable the building of the old fuse code in
arch/arm/mach-tegra/.

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH v3 6/6] ARM: tegra: remove fuse files from mach-tegra
  2014-01-28 23:36 ` [PATCH v3 6/6] ARM: tegra: remove fuse files from mach-tegra Peter De Schrijver
@ 2014-02-05 18:45   ` Stephen Warren
  0 siblings, 0 replies; 21+ messages in thread
From: Stephen Warren @ 2014-02-05 18:45 UTC (permalink / raw)
  To: linux-arm-kernel

On 01/28/2014 04:36 PM, Peter De Schrijver wrote:
> All fuse related functionality is now provided by the tegra fuse driver.
> Hence all the fuse related files in mach-tegra can be removed.

It's probably worth squashing this into patch 5, since that's what makes
these files unused.

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH v3 0/6] efuse driver for Tegra
  2014-01-28 23:36 [PATCH v3 0/6] efuse driver for Tegra Peter De Schrijver
                   ` (6 preceding siblings ...)
  2014-01-29 15:00 ` [PATCH v3 0/6] efuse driver for Tegra Paul Gortmaker
@ 2014-02-05 18:49 ` Stephen Warren
  7 siblings, 0 replies; 21+ messages in thread
From: Stephen Warren @ 2014-02-05 18:49 UTC (permalink / raw)
  To: linux-arm-kernel

On 01/28/2014 04:36 PM, Peter De Schrijver wrote:
> This driver allows userspace to read the raw efuse data. Its userspace
> interface is modelled after the sunxi_sid driver which provides similar
> functionality for some Allwinner SoCs. It has been tested on
> Tegra20 (ventana), Tegra30 (beaverboard) and Tegra114 (dalmore).

I think this series should have been CC'd to Greg and Arnd, since
they're listed in MAINTAINERS for drivers/misc/. I'll need their ack to
apply these patches to the Tegra tree.

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH v3 3/6] misc: fuse: Add efuse driver for Tegra
  2014-01-28 23:36 ` [PATCH v3 3/6] misc: fuse: Add efuse driver for Tegra Peter De Schrijver
  2014-01-29  2:26   ` Jim Lin
@ 2014-02-05 19:15   ` Stephen Warren
  2014-02-06  9:11     ` Peter De Schrijver
  1 sibling, 1 reply; 21+ messages in thread
From: Stephen Warren @ 2014-02-05 19:15 UTC (permalink / raw)
  To: linux-arm-kernel

On 01/28/2014 04:36 PM, Peter De Schrijver wrote:
> Implement fuse driver for Tegra20, Tegra30, Tegra114 and Tegra124.

I assume most of this code is simply cut/paste from the existing code in
arch/arm/mach-tegra/? If so, "git format-patch -C" would have been
useful to highlight what changed when duplicating the files.

> diff --git a/Documentation/ABI/testing/sysfs-driver-tegra-fuse b/Documentation/ABI/testing/sysfs-driver-tegra-fuse
> +What:		/sys/devices/*/<our-device>/fuse
> +Date:		December 2013
> +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.
> +Users:		any user space application which wants to read the efuses on
> +		Tegra SoC's

Surely this file should describe the format of the file, since that's
part of the ABI too, right?

> diff --git a/drivers/misc/fuse/tegra/fuse-tegra20.c b/drivers/misc/fuse/tegra/fuse-tegra20.c

> +static int tegra20_fuse_probe(struct platform_device *pdev)
...
> +	sku_info.revision = tegra_revision;
> +	tegra20_init_speedo_data(&sku_info, &pdev->dev);
...
> +}
> +
> +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);

That call to tegra20_init_speedo_data() now happens much later in boot.
Are you sure there's nothing that relies on data it sets up between when
tegra_fuse_init() is called (which is where it happens before this
series), and the somewhat arbitrary later time when this driver probes?

> diff --git a/drivers/misc/fuse/tegra/fuse-tegra30.c b/drivers/misc/fuse/tegra/fuse-tegra30.c

> +postcore_initcall(tegra30_fuse_init);
> +

There's a blank line at the end of the file. I thought checkpatch warned
about this? But actually it doesn't seem to at least in -f mode.

> diff --git a/drivers/misc/fuse/tegra/fuse.h b/drivers/misc/fuse/tegra/fuse.h

> +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;
> +};

The only use of this appears to be to pass to tegra_fuse_create_sysfs()
which prints out the fields. Will there be more users in the future?
Otherwise, I'd be tempted to just print it out outside/before-calling
tegra_fuse_create_sysfs().

That said, I wonder if these values could/should be exposed in the sysfs
file to make it easier to interpret the fuses?

> diff --git a/drivers/misc/fuse/tegra/tegra114_speedo.c b/drivers/misc/fuse/tegra/tegra114_speedo.c

It might be nice to make these filenames consistent with the others,
e.g. fuse-speedo-tegraNNN.c/speedo-tegraNNN.c, or wrap them into
fuse-tegraNNN.c?

> diff --git a/drivers/misc/fuse/tegra/tegra30_speedo.c b/drivers/misc/fuse/tegra/tegra30_speedo.c

> +#define FUSE_SPEEDO_CALIB_0	0x14
> +#define FUSE_PACKAGE_INFO	0XFC
> +#define FUSE_TEST_PROG_VER	0X28

In arch/arm/mach-tegra/tegra30_speedo.c, those values are different:

#define FUSE_SPEEDO_CALIB_0	0x114
#define FUSE_PACKAGE_INFO	0X1FC
#define FUSE_TEST_PROG_VER	0X128

Was this change intentional? Perhaps it should be in a separate patch to
highlight the change, if it's an intentional bug-fix?

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH v3 3/6] misc: fuse: Add efuse driver for Tegra
  2014-02-05 19:15   ` Stephen Warren
@ 2014-02-06  9:11     ` Peter De Schrijver
  2014-02-06 16:45       ` Stephen Warren
  0 siblings, 1 reply; 21+ messages in thread
From: Peter De Schrijver @ 2014-02-06  9:11 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Feb 05, 2014 at 08:15:46PM +0100, Stephen Warren wrote:
> On 01/28/2014 04:36 PM, Peter De Schrijver wrote:
> > Implement fuse driver for Tegra20, Tegra30, Tegra114 and Tegra124.
> 
> I assume most of this code is simply cut/paste from the existing code in
> arch/arm/mach-tegra/? If so, "git format-patch -C" would have been
> useful to highlight what changed when duplicating the files.
> 

It also has been rewritten slightly. Also the Tegra124 speedo file is new.

> > diff --git a/Documentation/ABI/testing/sysfs-driver-tegra-fuse b/Documentation/ABI/testing/sysfs-driver-tegra-fuse
> > +What:		/sys/devices/*/<our-device>/fuse
> > +Date:		December 2013
> > +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.
> > +Users:		any user space application which wants to read the efuses on
> > +		Tegra SoC's
> 
> Surely this file should describe the format of the file, since that's
> part of the ABI too, right?
> 

Part of the fuse data is ODM defined so possibly board specific.

> > diff --git a/drivers/misc/fuse/tegra/fuse-tegra20.c b/drivers/misc/fuse/tegra/fuse-tegra20.c
> 
> > +static int tegra20_fuse_probe(struct platform_device *pdev)
> ...
> > +	sku_info.revision = tegra_revision;
> > +	tegra20_init_speedo_data(&sku_info, &pdev->dev);
> ...
> > +}
> > +
> > +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);
> 
> That call to tegra20_init_speedo_data() now happens much later in boot.
> Are you sure there's nothing that relies on data it sets up between when
> tegra_fuse_init() is called (which is where it happens before this
> series), and the somewhat arbitrary later time when this driver probes?
> 

Will check.

> > diff --git a/drivers/misc/fuse/tegra/fuse-tegra30.c b/drivers/misc/fuse/tegra/fuse-tegra30.c
> 
> > +postcore_initcall(tegra30_fuse_init);
> > +
> 
> There's a blank line at the end of the file. I thought checkpatch warned
> about this? But actually it doesn't seem to at least in -f mode.
> 
> > diff --git a/drivers/misc/fuse/tegra/fuse.h b/drivers/misc/fuse/tegra/fuse.h
> 
> > +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;
> > +};
> 
> The only use of this appears to be to pass to tegra_fuse_create_sysfs()
> which prints out the fields. Will there be more users in the future?
> Otherwise, I'd be tempted to just print it out outside/before-calling
> tegra_fuse_create_sysfs().
> 
> That said, I wonder if these values could/should be exposed in the sysfs
> file to make it easier to interpret the fuses?
> 

That could be done I think...

> > diff --git a/drivers/misc/fuse/tegra/tegra114_speedo.c b/drivers/misc/fuse/tegra/tegra114_speedo.c
> 
> It might be nice to make these filenames consistent with the others,
> e.g. fuse-speedo-tegraNNN.c/speedo-tegraNNN.c, or wrap them into
> fuse-tegraNNN.c?
> 

I expect 1 speedo file per new SoC, but at least every SoC since Tegra30 has
used the same way of reading the fuse data. Hence I think it's better to
keep them separate.

> > diff --git a/drivers/misc/fuse/tegra/tegra30_speedo.c b/drivers/misc/fuse/tegra/tegra30_speedo.c
> 
> > +#define FUSE_SPEEDO_CALIB_0	0x14
> > +#define FUSE_PACKAGE_INFO	0XFC
> > +#define FUSE_TEST_PROG_VER	0X28
> 
> In arch/arm/mach-tegra/tegra30_speedo.c, those values are different:
> 
> #define FUSE_SPEEDO_CALIB_0	0x114
> #define FUSE_PACKAGE_INFO	0X1FC
> #define FUSE_TEST_PROG_VER	0X128
> 
> Was this change intentional? Perhaps it should be in a separate patch to
> highlight the change, if it's an intentional bug-fix?

This is intentional. The old files used the offset from the fuse IP block base
address. The new files use the offset in the fuse array.

Cheers,

Peter.

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH v3 3/6] misc: fuse: Add efuse driver for Tegra
  2014-02-06  9:11     ` Peter De Schrijver
@ 2014-02-06 16:45       ` Stephen Warren
  0 siblings, 0 replies; 21+ messages in thread
From: Stephen Warren @ 2014-02-06 16:45 UTC (permalink / raw)
  To: linux-arm-kernel

On 02/06/2014 02:11 AM, Peter De Schrijver wrote:
> On Wed, Feb 05, 2014 at 08:15:46PM +0100, Stephen Warren wrote:
>> On 01/28/2014 04:36 PM, Peter De Schrijver wrote:
>>> Implement fuse driver for Tegra20, Tegra30, Tegra114 and Tegra124.

>>> diff --git a/Documentation/ABI/testing/sysfs-driver-tegra-fuse b/Documentation/ABI/testing/sysfs-driver-tegra-fuse
>>> +What:		/sys/devices/*/<our-device>/fuse
>>> +Date:		December 2013
>>> +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.
>>> +Users:		any user space application which wants to read the efuses on
>>> +		Tegra SoC's
>>
>> Surely this file should describe the format of the file, since that's
>> part of the ABI too, right?
>>
> 
> Part of the fuse data is ODM defined so possibly board specific.

I didn't mean the interpretation of which fuses mean what semantically,
but rather the data format of the file. IIRC looking at the code, it's
just a binary dump of the fuses, but it might be worth spelling out that
it's a byte-oriented binary file, with fuse 0 in bit 0 of byte 0 etc.?

^ permalink raw reply	[flat|nested] 21+ messages in thread

end of thread, other threads:[~2014-02-06 16:45 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-01-28 23:36 [PATCH v3 0/6] efuse driver for Tegra Peter De Schrijver
2014-01-28 23:36 ` [PATCH v3 1/6] ARM: tegra: export apb dma readl/writel Peter De Schrijver
2014-01-28 23:36 ` [PATCH v3 2/6] ARM: tegra: Add chipid, revision and fuse init Peter De Schrijver
2014-02-05 18:40   ` Stephen Warren
2014-01-28 23:36 ` [PATCH v3 3/6] misc: fuse: Add efuse driver for Tegra Peter De Schrijver
2014-01-29  2:26   ` Jim Lin
2014-02-03 14:15     ` Peter De Schrijver
2014-02-05 10:26       ` Jim Lin
2014-02-05 19:15   ` Stephen Warren
2014-02-06  9:11     ` Peter De Schrijver
2014-02-06 16:45       ` Stephen Warren
2014-01-28 23:36 ` [PATCH v3 4/6] ARM: tegra: Add efuse bindings Peter De Schrijver
2014-01-29 17:18   ` Rob Herring
2014-02-05 18:42   ` Stephen Warren
2014-01-28 23:36 ` [PATCH v3 5/6] misc: enable fuse drivers Peter De Schrijver
2014-02-05 18:44   ` Stephen Warren
2014-01-28 23:36 ` [PATCH v3 6/6] ARM: tegra: remove fuse files from mach-tegra Peter De Schrijver
2014-02-05 18:45   ` Stephen Warren
2014-01-29 15:00 ` [PATCH v3 0/6] efuse driver for Tegra Paul Gortmaker
2014-01-30  9:45   ` Peter De Schrijver
2014-02-05 18:49 ` Stephen Warren

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox