[ARM/tegra] Add Tegra3 support
[linux-2.6.git] / arch / arm / mach-tegra / kfuse.c
1 /*
2  * arch/arm/mach-tegra/kfuse.c
3  *
4  * Copyright (C) 2010-2011 NVIDIA Corporation.
5  *
6  * This software is licensed under the terms of the GNU General Public
7  * License version 2, as published by the Free Software Foundation, and
8  * may be copied, distributed, and modified under those terms.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  */
16
17 /* The kfuse block stores downstream and upstream HDCP keys for use by HDMI
18  * module.
19  */
20
21 #include <linux/kernel.h>
22 #include <linux/io.h>
23 #include <linux/err.h>
24 #include <linux/string.h>
25 #include <linux/delay.h>
26
27 #include <mach/iomap.h>
28 #include <mach/kfuse.h>
29
30 #include "apbio.h"
31
32 /* register definition */
33 #define KFUSE_STATE                                     0x80
34 #define  KFUSE_STATE_DONE               (1u << 16)
35 #define  KFUSE_STATE_CRCPASS            (1u << 17)
36 #define KFUSE_KEYADDR                                   0x88
37 #define  KFUSE_KEYADDR_AUTOINC          (1u << 16)
38 #define KFUSE_KEYS                                      0x8c
39
40 static inline u32 tegra_kfuse_readl(unsigned long offset)
41 {
42         return tegra_apb_readl(TEGRA_KFUSE_BASE + offset);
43 }
44
45 static inline void tegra_kfuse_writel(u32 value, unsigned long offset)
46 {
47         tegra_apb_writel(value, TEGRA_KFUSE_BASE + offset);
48 }
49
50 static int wait_for_done(void)
51 {
52         u32 reg;
53         int retries = 50;
54         do {
55                 reg = tegra_kfuse_readl(KFUSE_STATE);
56                 if (reg & KFUSE_STATE_DONE);
57                         return 0;
58                 msleep(10);
59         } while(--retries);
60         return -ETIMEDOUT;
61 }
62
63 /* read up to KFUSE_DATA_SZ bytes into dest.
64  * always starts at the first kfuse.
65  */
66 int tegra_kfuse_read(void *dest, size_t len)
67 {
68         u32 v;
69         unsigned cnt;
70
71         if (len > KFUSE_DATA_SZ)
72                 return -EINVAL;
73
74         tegra_kfuse_writel(KFUSE_KEYADDR_AUTOINC, KFUSE_KEYADDR);
75         wait_for_done();
76
77         if ((tegra_kfuse_readl(KFUSE_STATE) & KFUSE_STATE_CRCPASS) == 0) {
78                 pr_err("kfuse: crc failed\n");
79                 return -EIO;
80         }
81
82         for (cnt = 0; cnt < len; cnt += 4) {
83                 v = tegra_kfuse_readl(KFUSE_KEYS);
84                 memcpy(dest + cnt, &v, sizeof v);
85         }
86
87         return 0;
88 }