Module Name:    src
Committed By:   jmcneill
Date:           Sat Nov 21 12:09:39 UTC 2015

Modified Files:
        src/sys/arch/arm/nvidia: files.tegra soc_tegra124.c tegra_car.c
            tegra_cpufreq.c tegra_io.c tegra_reg.h tegra_var.h
        src/sys/arch/evbarm/conf: JETSONTK1 NYAN-BIG
Added Files:
        src/sys/arch/arm/nvidia: tegra_fuse.c

Log Message:
Add FUSE driver, use it to determine maximum CPU frequency for the board.
Retire CPUFREQ_BOOT option and always use highest available CPU frequency.


To generate a diff of this commit:
cvs rdiff -u -r1.22 -r1.23 src/sys/arch/arm/nvidia/files.tegra
cvs rdiff -u -r1.8 -r1.9 src/sys/arch/arm/nvidia/soc_tegra124.c
cvs rdiff -u -r1.28 -r1.29 src/sys/arch/arm/nvidia/tegra_car.c
cvs rdiff -u -r1.1 -r1.2 src/sys/arch/arm/nvidia/tegra_cpufreq.c
cvs rdiff -u -r0 -r1.1 src/sys/arch/arm/nvidia/tegra_fuse.c
cvs rdiff -u -r1.19 -r1.20 src/sys/arch/arm/nvidia/tegra_io.c
cvs rdiff -u -r1.18 -r1.19 src/sys/arch/arm/nvidia/tegra_reg.h
cvs rdiff -u -r1.26 -r1.27 src/sys/arch/arm/nvidia/tegra_var.h
cvs rdiff -u -r1.39 -r1.40 src/sys/arch/evbarm/conf/JETSONTK1
cvs rdiff -u -r1.2 -r1.3 src/sys/arch/evbarm/conf/NYAN-BIG

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/arm/nvidia/files.tegra
diff -u src/sys/arch/arm/nvidia/files.tegra:1.22 src/sys/arch/arm/nvidia/files.tegra:1.23
--- src/sys/arch/arm/nvidia/files.tegra:1.22	Thu Nov 19 22:09:16 2015
+++ src/sys/arch/arm/nvidia/files.tegra	Sat Nov 21 12:09:39 2015
@@ -1,4 +1,4 @@
-#	$NetBSD: files.tegra,v 1.22 2015/11/19 22:09:16 jmcneill Exp $
+#	$NetBSD: files.tegra,v 1.23 2015/11/21 12:09:39 jmcneill Exp $
 #
 # Configuration info for NVIDIA Tegra ARM Peripherals
 #
@@ -32,6 +32,11 @@ device	tegrapmc
 attach	tegrapmc at tegraio with tegra_pmc
 file	arch/arm/nvidia/tegra_pmc.c		tegra_pmc
 
+# eFUSE
+device	tegrafuse
+attach	tegrafuse at tegraio with tegra_fuse
+file	arch/arm/nvidia/tegra_fuse.c		tegra_fuse
+
 # Clock and Reset controller
 device	tegracar
 attach	tegracar at tegraio with tegra_car
@@ -135,9 +140,6 @@ defparam opt_tegra.h			CONMODE
 # Memory parameters
 defparam opt_tegra.h			MEMSIZE
 
-# CPU parameters
-defparam opt_tegra.h			CPUFREQ_BOOT
-
 # SOC parameters
 defflag	opt_tegra.h			SOC_TEGRAK1
 defflag	opt_tegra.h			SOC_TEGRA124: SOC_TEGRAK1

Index: src/sys/arch/arm/nvidia/soc_tegra124.c
diff -u src/sys/arch/arm/nvidia/soc_tegra124.c:1.8 src/sys/arch/arm/nvidia/soc_tegra124.c:1.9
--- src/sys/arch/arm/nvidia/soc_tegra124.c:1.8	Thu Nov 12 10:31:29 2015
+++ src/sys/arch/arm/nvidia/soc_tegra124.c	Sat Nov 21 12:09:39 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: soc_tegra124.c,v 1.8 2015/11/12 10:31:29 jmcneill Exp $ */
+/* $NetBSD: soc_tegra124.c,v 1.9 2015/11/21 12:09:39 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2015 Jared D. McNeill <[email protected]>
@@ -30,7 +30,7 @@
 #include "opt_multiprocessor.h"
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: soc_tegra124.c,v 1.8 2015/11/12 10:31:29 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: soc_tegra124.c,v 1.9 2015/11/21 12:09:39 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -47,6 +47,22 @@ __KERNEL_RCSID(0, "$NetBSD: soc_tegra124
 
 #define EVP_RESET_VECTOR_0_REG	0x100
 
+#define FUSE_SKU_INFO_REG	0x110
+#define FUSE_CPU_SPEEDO_0_REG	0x114
+#define FUSE_CPU_IDDQ_REG	0x118
+#define FUSE_FT_REV_REG		0x128
+#define FUSE_CPU_SPEEDO_1_REG	0x12c
+#define FUSE_CPU_SPEEDO_2_REG	0x130
+#define FUSE_SOC_SPEEDO_0_REG	0x134
+#define FUSE_SOC_SPEEDO_1_REG	0x138
+#define FUSE_SOC_SPEEDO_2_REG	0x13c
+#define FUSE_SOC_IDDQ_REG	0x140
+#define FUSE_GPU_IDDQ_REG	0x228
+
+static void	tegra124_speedo_init(void);
+static int	tegra124_speedo_init_ids(uint32_t);
+static bool	tegra124_speedo_rate_ok(u_int);
+
 static u_int	tegra124_cpufreq_set_rate(u_int);
 static u_int	tegra124_cpufreq_get_rate(void);
 static size_t	tegra124_cpufreq_get_available(u_int *, size_t);
@@ -74,6 +90,23 @@ static struct tegra124_cpufreq_rate {
 	{ 696, 1, 58, 0 }
 };
 
+static const u_int tegra124_cpufreq_max[] = {
+	2014,
+	2320,
+	2116,
+	2524
+};
+
+static struct tegra124_speedo {
+	u_int cpu_speedo_id;
+	u_int soc_speedo_id;
+	u_int gpu_speedo_id;
+} tegra124_speedo = {
+	.cpu_speedo_id = 0,
+	.soc_speedo_id = 0,
+	.gpu_speedo_id = 0
+};
+
 void
 tegra124_cpuinit(void)
 {
@@ -85,15 +118,85 @@ tegra124_cpuinit(void)
 	tegra_i2c_dvc_write(0x40, (sd0_vsel << 8) | 00, 2);
 	delay(10000);
 
+	tegra124_speedo_init();
+
 	tegra_cpufreq_register(&tegra124_cpufreq_func);
 }
 
+static void
+tegra124_speedo_init(void)
+{
+	uint32_t sku_id;
+
+	sku_id = tegra_fuse_read(FUSE_SKU_INFO_REG);
+	tegra124_speedo_init_ids(sku_id);
+}
+
+static int
+tegra124_speedo_init_ids(uint32_t sku_id)
+{
+	int threshold = 0;
+
+	switch (sku_id) {
+	case 0x00:
+	case 0x0f:
+	case 0x23:
+		break;	/* use default */
+	case 0x83:
+		tegra124_speedo.cpu_speedo_id = 2;
+		break;
+	case 0x1f:
+	case 0x87:
+	case 0x27:
+		tegra124_speedo.cpu_speedo_id = 2;
+		tegra124_speedo.soc_speedo_id = 0;
+		tegra124_speedo.gpu_speedo_id = 1;
+		break;
+	case 0x81:
+	case 0x21:
+	case 0x07:
+		tegra124_speedo.cpu_speedo_id = 1;
+		tegra124_speedo.soc_speedo_id = 1;
+		tegra124_speedo.gpu_speedo_id = 1;
+		threshold = 1;
+		break;
+	case 0x49:
+	case 0x4a:
+	case 0x48:
+		tegra124_speedo.cpu_speedo_id = 4;
+		tegra124_speedo.soc_speedo_id = 2;
+		tegra124_speedo.gpu_speedo_id = 3;
+		threshold = 1;
+		break;
+	default:
+		aprint_error("tegra124: unknown SKU ID %#x\n", sku_id);
+		break;	/* use default */
+	}
+
+	return threshold;
+}
+
+static bool
+tegra124_speedo_rate_ok(u_int rate)
+{
+	u_int tbl = 0;
+
+	if (tegra124_speedo.cpu_speedo_id < __arraycount(tegra124_cpufreq_max))
+		tbl = tegra124_speedo.cpu_speedo_id;
+
+	return rate <= tegra124_cpufreq_max[tbl];
+}
+
+
 static u_int
 tegra124_cpufreq_set_rate(u_int rate)
 {
 	const u_int nrates = __arraycount(tegra124_cpufreq_rates);
 	const struct tegra124_cpufreq_rate *r = NULL;
 
+	if (tegra124_speedo_rate_ok(rate) == false)
+		return EINVAL;
+
 	for (int i = 0; i < nrates; i++) {
 		if (tegra124_cpufreq_rates[i].rate == rate) {
 			r = &tegra124_cpufreq_rates[i];
@@ -118,15 +221,17 @@ static size_t
 tegra124_cpufreq_get_available(u_int *pavail, size_t maxavail)
 {
 	const u_int nrates = __arraycount(tegra124_cpufreq_rates);
-	u_int n;
+	u_int n, cnt;
 
 	KASSERT(nrates <= maxavail);
 
-	for (n = 0; n < nrates; n++) {
-		pavail[n] = tegra124_cpufreq_rates[n].rate;
+	for (n = 0, cnt = 0; n < nrates; n++) {
+		if (tegra124_speedo_rate_ok(tegra124_cpufreq_rates[n].rate)) {
+			pavail[cnt++] = tegra124_cpufreq_rates[n].rate;
+		}
 	}
 
-	return nrates;
+	return cnt;
 }
 
 void

Index: src/sys/arch/arm/nvidia/tegra_car.c
diff -u src/sys/arch/arm/nvidia/tegra_car.c:1.28 src/sys/arch/arm/nvidia/tegra_car.c:1.29
--- src/sys/arch/arm/nvidia/tegra_car.c:1.28	Thu Nov 19 22:26:48 2015
+++ src/sys/arch/arm/nvidia/tegra_car.c	Sat Nov 21 12:09:39 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: tegra_car.c,v 1.28 2015/11/19 22:26:48 jmcneill Exp $ */
+/* $NetBSD: tegra_car.c,v 1.29 2015/11/21 12:09:39 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2015 Jared D. McNeill <[email protected]>
@@ -29,7 +29,7 @@
 #include "locators.h"
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: tegra_car.c,v 1.28 2015/11/19 22:26:48 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: tegra_car.c,v 1.29 2015/11/21 12:09:39 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -860,3 +860,25 @@ tegra_car_gpu_enable(void)
 	/* Leave reset */
 	bus_space_write_4(bst, bsh, CAR_RST_DEV_X_CLR_REG, CAR_DEV_X_GPU);
 }
+
+void
+tegra_car_fuse_enable(void)
+{
+	bus_space_tag_t bst;
+	bus_space_handle_t bsh;
+
+	tegra_car_get_bs(&bst, &bsh);
+
+	tegra_reg_set_clear(bst, bsh, CAR_CLK_ENB_H_SET_REG, CAR_DEV_H_FUSE, 0);
+}
+
+void
+tegra_car_fuse_disable(void)
+{
+	bus_space_tag_t bst;
+	bus_space_handle_t bsh;
+
+	tegra_car_get_bs(&bst, &bsh);
+
+	tegra_reg_set_clear(bst, bsh, CAR_CLK_ENB_H_SET_REG, 0, CAR_DEV_H_FUSE);
+}

Index: src/sys/arch/arm/nvidia/tegra_cpufreq.c
diff -u src/sys/arch/arm/nvidia/tegra_cpufreq.c:1.1 src/sys/arch/arm/nvidia/tegra_cpufreq.c:1.2
--- src/sys/arch/arm/nvidia/tegra_cpufreq.c:1.1	Wed May 13 11:06:13 2015
+++ src/sys/arch/arm/nvidia/tegra_cpufreq.c	Sat Nov 21 12:09:39 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: tegra_cpufreq.c,v 1.1 2015/05/13 11:06:13 jmcneill Exp $ */
+/* $NetBSD: tegra_cpufreq.c,v 1.2 2015/11/21 12:09:39 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2015 Jared D. McNeill <[email protected]>
@@ -29,7 +29,7 @@
 #include "locators.h"
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: tegra_cpufreq.c,v 1.1 2015/05/13 11:06:13 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: tegra_cpufreq.c,v 1.2 2015/11/21 12:09:39 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -128,10 +128,8 @@ tegra_cpufreq_init(void)
 		goto sysctl_failed;
 	cpufreq_node_available = node->sysctl_num;
 
-#ifdef CPUFREQ_BOOT
-	cpufreq_set_rate(CPUFREQ_BOOT);
+	cpufreq_set_rate(availfreq[0]);
 	tegra_cpufreq_post(NULL, NULL);
-#endif
 
 	return;
 

Index: src/sys/arch/arm/nvidia/tegra_io.c
diff -u src/sys/arch/arm/nvidia/tegra_io.c:1.19 src/sys/arch/arm/nvidia/tegra_io.c:1.20
--- src/sys/arch/arm/nvidia/tegra_io.c:1.19	Thu Nov 19 22:09:16 2015
+++ src/sys/arch/arm/nvidia/tegra_io.c	Sat Nov 21 12:09:39 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: tegra_io.c,v 1.19 2015/11/19 22:09:16 jmcneill Exp $ */
+/* $NetBSD: tegra_io.c,v 1.20 2015/11/21 12:09:39 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2015 Jared D. McNeill <[email protected]>
@@ -29,7 +29,7 @@
 #include "opt_tegra.h"
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: tegra_io.c,v 1.19 2015/11/19 22:09:16 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: tegra_io.c,v 1.20 2015/11/21 12:09:39 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -75,6 +75,8 @@ static const struct tegra_locators tegra
     TEGRA_MC_OFFSET, TEGRA_MC_SIZE, NOPORT, TEGRA_INTR_MC },
   { "tegrapmc",
     TEGRA_PMC_OFFSET, TEGRA_PMC_SIZE, NOPORT, NOINTR },
+  { "tegrafuse",
+    TEGRA_FUSE_OFFSET, TEGRA_FUSE_SIZE, NOPORT, NOINTR },
   { "tegraxusbpad",
     TEGRA_XUSB_PADCTL_OFFSET, TEGRA_XUSB_PADCTL_SIZE, NOPORT, NOINTR },
   { "tegrampio",

Index: src/sys/arch/arm/nvidia/tegra_reg.h
diff -u src/sys/arch/arm/nvidia/tegra_reg.h:1.18 src/sys/arch/arm/nvidia/tegra_reg.h:1.19
--- src/sys/arch/arm/nvidia/tegra_reg.h:1.18	Thu Nov 19 22:09:16 2015
+++ src/sys/arch/arm/nvidia/tegra_reg.h	Sat Nov 21 12:09:39 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: tegra_reg.h,v 1.18 2015/11/19 22:09:16 jmcneill Exp $ */
+/* $NetBSD: tegra_reg.h,v 1.19 2015/11/21 12:09:39 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2015 Jared D. McNeill <[email protected]>
@@ -106,6 +106,8 @@
 #define TEGRA_KBC_SIZE		0x100
 #define TEGRA_PMC_OFFSET	0x0000e400
 #define TEGRA_PMC_SIZE		0x800
+#define TEGRA_FUSE_OFFSET	0x0000f800
+#define TEGRA_FUSE_SIZE		0x00000400
 #define TEGRA_CEC_OFFSET	0x00015000
 #define TEGRA_CEC_SIZE		0x1000
 #define TEGRA_MC_OFFSET		0x00019000

Index: src/sys/arch/arm/nvidia/tegra_var.h
diff -u src/sys/arch/arm/nvidia/tegra_var.h:1.26 src/sys/arch/arm/nvidia/tegra_var.h:1.27
--- src/sys/arch/arm/nvidia/tegra_var.h:1.26	Thu Nov 19 22:09:16 2015
+++ src/sys/arch/arm/nvidia/tegra_var.h	Sat Nov 21 12:09:39 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: tegra_var.h,v 1.26 2015/11/19 22:09:16 jmcneill Exp $ */
+/* $NetBSD: tegra_var.h,v 1.27 2015/11/21 12:09:39 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2015 Jared D. McNeill <[email protected]>
@@ -111,6 +111,8 @@ int	tegra_car_dc_enable(u_int);
 void	tegra_car_host1x_enable(void);
 void	tegra_car_wdt_enable(u_int, bool);
 void	tegra_car_gpu_enable(void);
+void	tegra_car_fuse_enable(void);
+void	tegra_car_fuse_disable(void);
 
 struct tegra_gpio_pin;
 struct tegra_gpio_pin *tegra_gpio_acquire(const char *, u_int);
@@ -148,6 +150,8 @@ void	tegra_i2c_dvc_write(uint8_t, uint32
 
 psize_t	tegra_mc_memsize(void);
 
+uint32_t tegra_fuse_read(u_int);
+
 void	tegra_xusbpad_sata_enable(void);
 
 struct videomode;

Index: src/sys/arch/evbarm/conf/JETSONTK1
diff -u src/sys/arch/evbarm/conf/JETSONTK1:1.39 src/sys/arch/evbarm/conf/JETSONTK1:1.40
--- src/sys/arch/evbarm/conf/JETSONTK1:1.39	Thu Nov 19 22:09:16 2015
+++ src/sys/arch/evbarm/conf/JETSONTK1	Sat Nov 21 12:09:39 2015
@@ -1,5 +1,5 @@
 #
-#	$NetBSD: JETSONTK1,v 1.39 2015/11/19 22:09:16 jmcneill Exp $
+#	$NetBSD: JETSONTK1,v 1.40 2015/11/21 12:09:39 jmcneill Exp $
 #
 #	NVIDIA Jetson TK1 - Tegra K1 development kit
 #	https://developer.nvidia.com/jetson-tk1
@@ -11,7 +11,6 @@ include	"arch/evbarm/conf/GENERIC.common
 options 	CPU_CORTEXA15
 options 	SOC_TEGRA124
 options 	BOARD_JETSONTK1
-options 	CPUFREQ_BOOT=2292
 options 	MULTIPROCESSOR
 #options 	MEMSIZE=2048
 
@@ -40,6 +39,9 @@ tegraio0	at mainbus?
 # Memory controller
 tegramc0	at tegraio?		# MC
 
+# FUSE controller
+tegrafuse0	at tegraio?		# FUSE
+
 # Power management controller
 tegrapmc0	at tegraio?		# PMC
 

Index: src/sys/arch/evbarm/conf/NYAN-BIG
diff -u src/sys/arch/evbarm/conf/NYAN-BIG:1.2 src/sys/arch/evbarm/conf/NYAN-BIG:1.3
--- src/sys/arch/evbarm/conf/NYAN-BIG:1.2	Mon Nov  9 23:05:58 2015
+++ src/sys/arch/evbarm/conf/NYAN-BIG	Sat Nov 21 12:09:39 2015
@@ -1,5 +1,5 @@
 #
-#	$NetBSD: NYAN-BIG,v 1.2 2015/11/09 23:05:58 jmcneill Exp $
+#	$NetBSD: NYAN-BIG,v 1.3 2015/11/21 12:09:39 jmcneill Exp $
 #
 #	Chrome OS nyan_big board - Tegra K1
 #	- Acer Chromebook 13 (CB5-311)
@@ -11,7 +11,6 @@ include "arch/evbarm/conf/JETSONTK1"
 
 no options 	BOARD_JETSONTK1
 options 	BOARD_NYAN_BIG
-no options 	CPUFREQ_BOOT
 
 options 	BOOT_ARGS="\"console=fb\""
 

Added files:

Index: src/sys/arch/arm/nvidia/tegra_fuse.c
diff -u /dev/null src/sys/arch/arm/nvidia/tegra_fuse.c:1.1
--- /dev/null	Sat Nov 21 12:09:39 2015
+++ src/sys/arch/arm/nvidia/tegra_fuse.c	Sat Nov 21 12:09:39 2015
@@ -0,0 +1,103 @@
+/* $NetBSD: tegra_fuse.c,v 1.1 2015/11/21 12:09:39 jmcneill Exp $ */
+
+/*-
+ * Copyright (c) 2015 Jared D. McNeill <[email protected]>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "locators.h"
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: tegra_fuse.c,v 1.1 2015/11/21 12:09:39 jmcneill Exp $");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/device.h>
+#include <sys/intr.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+
+#include <arm/nvidia/tegra_reg.h>
+#include <arm/nvidia/tegra_var.h>
+
+static int	tegra_fuse_match(device_t, cfdata_t, void *);
+static void	tegra_fuse_attach(device_t, device_t, void *);
+
+struct tegra_fuse_softc {
+	device_t		sc_dev;
+	bus_space_tag_t		sc_bst;
+	bus_space_handle_t	sc_bsh;
+};
+
+static struct tegra_fuse_softc *fuse_softc = NULL;
+
+CFATTACH_DECL_NEW(tegra_fuse, sizeof(struct tegra_fuse_softc),
+	tegra_fuse_match, tegra_fuse_attach, NULL, NULL);
+
+static int
+tegra_fuse_match(device_t parent, cfdata_t cf, void *aux)
+{
+	return 1;
+}
+
+static void
+tegra_fuse_attach(device_t parent, device_t self, void *aux)
+{
+	struct tegra_fuse_softc * const sc = device_private(self);
+	struct tegraio_attach_args * const tio = aux;
+	const struct tegra_locators * const loc = &tio->tio_loc;
+
+	sc->sc_dev = self;
+	sc->sc_bst = tio->tio_bst;
+	bus_space_subregion(tio->tio_bst, tio->tio_bsh,
+	    loc->loc_offset, loc->loc_size, &sc->sc_bsh);
+
+	KASSERT(fuse_softc == NULL);
+	fuse_softc = sc;
+
+	aprint_naive("\n");
+	aprint_normal(": FUSE\n");
+}
+
+uint32_t
+tegra_fuse_read(u_int offset)
+{
+	bus_space_tag_t bst;
+	bus_space_handle_t bsh;
+
+	if (fuse_softc) {
+		bst = fuse_softc->sc_bst;
+		bsh = fuse_softc->sc_bsh;
+	} else {
+		bst = &armv7_generic_bs_tag;
+		bus_space_subregion(bst, tegra_apb_bsh,
+		    TEGRA_FUSE_OFFSET, TEGRA_FUSE_SIZE, &bsh);
+	}
+
+	tegra_car_fuse_enable();
+	const uint32_t v = bus_space_read_4(bst, bsh, offset);
+	tegra_car_fuse_disable();
+
+	return v;
+}

Reply via email to