diff options
-rw-r--r-- | arch/arm/mach-tegra/Makefile | 1 | ||||
-rw-r--r-- | arch/arm/mach-tegra/include/mach/kfuse.h | 20 | ||||
-rw-r--r-- | arch/arm/mach-tegra/kfuse.c | 83 |
3 files changed, 104 insertions, 0 deletions
diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile index 2d7969e4812b..952bbf32d9f4 100644 --- a/arch/arm/mach-tegra/Makefile +++ b/arch/arm/mach-tegra/Makefile @@ -13,6 +13,7 @@ obj-y += delay.o obj-y += powergate.o obj-y += suspend.o obj-y += fuse.o +obj-y += kfuse.o ifeq ($(CONFIG_TEGRA_ALSA),y) obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra2_i2s.o else diff --git a/arch/arm/mach-tegra/include/mach/kfuse.h b/arch/arm/mach-tegra/include/mach/kfuse.h new file mode 100644 index 000000000000..cfe85cc86ff2 --- /dev/null +++ b/arch/arm/mach-tegra/include/mach/kfuse.h @@ -0,0 +1,20 @@ +/* + * arch/arm/mach-tegra/kfuse.h + * + * Copyright (C) 2010-2011 NVIDIA Corporation. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +/* there are 144 32-bit values in total */ +#define KFUSE_DATA_SZ (144 * 4) + +int tegra_kfuse_read(void *dest, size_t len); diff --git a/arch/arm/mach-tegra/kfuse.c b/arch/arm/mach-tegra/kfuse.c new file mode 100644 index 000000000000..b2439f5a4ae2 --- /dev/null +++ b/arch/arm/mach-tegra/kfuse.c @@ -0,0 +1,83 @@ +/* + * arch/arm/mach-tegra/kfuse.c + * + * Copyright (C) 2010-2011 NVIDIA Corporation. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +/* The kfuse block stores downstream and upstream HDCP keys for use by HDMI + * module. + */ + +#include <linux/kernel.h> +#include <linux/io.h> +#include <linux/err.h> +#include <linux/string.h> + +#include <mach/iomap.h> +#include <mach/kfuse.h> + +#include "apbio.h" + +/* register definition */ +#define KFUSE_STATE 0x80 +#define KFUSE_STATE_DONE (1u << 16) +#define KFUSE_STATE_CRCPASS (1u << 17) +#define KFUSE_KEYADDR 0x88 +#define KFUSE_KEYADDR_AUTOINC (1u << 16) +#define KFUSE_KEYS 0x8c + +static inline u32 tegra_kfuse_readl(unsigned long offset) +{ + return tegra_apb_readl(TEGRA_KFUSE_BASE + offset); +} + +static inline void tegra_kfuse_writel(u32 value, unsigned long offset) +{ + tegra_apb_writel(value, TEGRA_KFUSE_BASE + offset); +} + +static void wait_for_done(void) +{ + u32 reg; + + do { + reg = tegra_kfuse_readl(KFUSE_STATE); + } while ((reg & KFUSE_STATE_DONE) == 0); +} + +/* read up to KFUSE_DATA_SZ bytes into dest. + * always starts at the first kfuse. + */ +int tegra_kfuse_read(void *dest, size_t len) +{ + u32 v; + unsigned cnt; + + if (len > KFUSE_DATA_SZ) + return -EINVAL; + + tegra_kfuse_writel(KFUSE_KEYADDR_AUTOINC, KFUSE_KEYADDR); + wait_for_done(); + + if ((tegra_kfuse_readl(KFUSE_STATE) & KFUSE_STATE_CRCPASS) == 0) { + pr_err("kfuse: crc failed\n"); + return -EIO; + } + + for (cnt = 0; cnt < len; cnt += 4) { + v = tegra_kfuse_readl(KFUSE_KEYS); + memcpy(dest + cnt, &v, sizeof v); + } + + return 0; +} |