aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThierry Reding <treding@nvidia.com>2015-04-29 10:54:04 -0400
committerThierry Reding <treding@nvidia.com>2015-07-16 04:38:28 -0400
commit7e939de1b2bb26496e4967e5346619700245e7c0 (patch)
tree678c17d76d5454d0856e148a6ba11537d562f5d2
parent297c4f3dcbffe11ce899a7d068ea18079094403b (diff)
soc/tegra: fuse: Unify Tegra20 and Tegra30 drivers
Unifying the drivers makes it easier to restrict the legacy probing paths to 32-bit ARM. This in turn will come in handy as support for new 64-bit ARM SoCs is added. Signed-off-by: Thierry Reding <treding@nvidia.com>
-rw-r--r--arch/arm/mach-tegra/iomap.h3
-rw-r--r--drivers/soc/tegra/fuse/Makefile1
-rw-r--r--drivers/soc/tegra/fuse/fuse-tegra.c245
-rw-r--r--drivers/soc/tegra/fuse/fuse-tegra20.c173
-rw-r--r--drivers/soc/tegra/fuse/fuse-tegra30.c213
-rw-r--r--drivers/soc/tegra/fuse/fuse.h87
-rw-r--r--drivers/soc/tegra/fuse/speedo-tegra114.c8
-rw-r--r--drivers/soc/tegra/fuse/speedo-tegra124.c14
-rw-r--r--drivers/soc/tegra/fuse/speedo-tegra20.c8
-rw-r--r--drivers/soc/tegra/fuse/speedo-tegra30.c22
-rw-r--r--drivers/soc/tegra/fuse/tegra-apbmisc.c9
11 files changed, 413 insertions, 370 deletions
diff --git a/arch/arm/mach-tegra/iomap.h b/arch/arm/mach-tegra/iomap.h
index 81dc950b4881..9e5b2f869fc8 100644
--- a/arch/arm/mach-tegra/iomap.h
+++ b/arch/arm/mach-tegra/iomap.h
@@ -82,9 +82,6 @@
82#define TEGRA_EMC_BASE 0x7000F400 82#define TEGRA_EMC_BASE 0x7000F400
83#define TEGRA_EMC_SIZE SZ_1K 83#define TEGRA_EMC_SIZE SZ_1K
84 84
85#define TEGRA_FUSE_BASE 0x7000F800
86#define TEGRA_FUSE_SIZE SZ_1K
87
88#define TEGRA_EMC0_BASE 0x7001A000 85#define TEGRA_EMC0_BASE 0x7001A000
89#define TEGRA_EMC0_SIZE SZ_2K 86#define TEGRA_EMC0_SIZE SZ_2K
90 87
diff --git a/drivers/soc/tegra/fuse/Makefile b/drivers/soc/tegra/fuse/Makefile
index 3af357da91f3..4adfce09d3a9 100644
--- a/drivers/soc/tegra/fuse/Makefile
+++ b/drivers/soc/tegra/fuse/Makefile
@@ -6,3 +6,4 @@ obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += speedo-tegra20.o
6obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += speedo-tegra30.o 6obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += speedo-tegra30.o
7obj-$(CONFIG_ARCH_TEGRA_114_SOC) += speedo-tegra114.o 7obj-$(CONFIG_ARCH_TEGRA_114_SOC) += speedo-tegra114.o
8obj-$(CONFIG_ARCH_TEGRA_124_SOC) += speedo-tegra124.o 8obj-$(CONFIG_ARCH_TEGRA_124_SOC) += speedo-tegra124.o
9obj-$(CONFIG_ARCH_TEGRA_132_SOC) += speedo-tegra124.o
diff --git a/drivers/soc/tegra/fuse/fuse-tegra.c b/drivers/soc/tegra/fuse/fuse-tegra.c
index c0d660f1aaac..407d7e359381 100644
--- a/drivers/soc/tegra/fuse/fuse-tegra.c
+++ b/drivers/soc/tegra/fuse/fuse-tegra.c
@@ -15,9 +15,10 @@
15 * 15 *
16 */ 16 */
17 17
18#include <linux/clk.h>
18#include <linux/device.h> 19#include <linux/device.h>
19#include <linux/kobject.h> 20#include <linux/kobject.h>
20#include <linux/kernel.h> 21#include <linux/module.h>
21#include <linux/platform_device.h> 22#include <linux/platform_device.h>
22#include <linux/of.h> 23#include <linux/of.h>
23#include <linux/of_address.h> 24#include <linux/of_address.h>
@@ -28,8 +29,6 @@
28 29
29#include "fuse.h" 30#include "fuse.h"
30 31
31static u32 (*fuse_readl)(const unsigned int offset);
32static int fuse_size;
33struct tegra_sku_info tegra_sku_info; 32struct tegra_sku_info tegra_sku_info;
34EXPORT_SYMBOL(tegra_sku_info); 33EXPORT_SYMBOL(tegra_sku_info);
35 34
@@ -42,11 +41,11 @@ static const char *tegra_revision_name[TEGRA_REVISION_MAX] = {
42 [TEGRA_REVISION_A04] = "A04", 41 [TEGRA_REVISION_A04] = "A04",
43}; 42};
44 43
45static u8 fuse_readb(const unsigned int offset) 44static u8 fuse_readb(struct tegra_fuse *fuse, unsigned int offset)
46{ 45{
47 u32 val; 46 u32 val;
48 47
49 val = fuse_readl(round_down(offset, 4)); 48 val = fuse->read(fuse, round_down(offset, 4));
50 val >>= (offset % 4) * 8; 49 val >>= (offset % 4) * 8;
51 val &= 0xff; 50 val &= 0xff;
52 51
@@ -54,19 +53,21 @@ static u8 fuse_readb(const unsigned int offset)
54} 53}
55 54
56static ssize_t fuse_read(struct file *fd, struct kobject *kobj, 55static ssize_t fuse_read(struct file *fd, struct kobject *kobj,
57 struct bin_attribute *attr, char *buf, 56 struct bin_attribute *attr, char *buf,
58 loff_t pos, size_t size) 57 loff_t pos, size_t size)
59{ 58{
59 struct device *dev = kobj_to_dev(kobj);
60 struct tegra_fuse *fuse = dev_get_drvdata(dev);
60 int i; 61 int i;
61 62
62 if (pos < 0 || pos >= fuse_size) 63 if (pos < 0 || pos >= attr->size)
63 return 0; 64 return 0;
64 65
65 if (size > fuse_size - pos) 66 if (size > attr->size - pos)
66 size = fuse_size - pos; 67 size = attr->size - pos;
67 68
68 for (i = 0; i < size; i++) 69 for (i = 0; i < size; i++)
69 buf[i] = fuse_readb(pos + i); 70 buf[i] = fuse_readb(fuse, pos + i);
70 71
71 return i; 72 return i;
72} 73}
@@ -76,6 +77,14 @@ static struct bin_attribute fuse_bin_attr = {
76 .read = fuse_read, 77 .read = fuse_read,
77}; 78};
78 79
80static int tegra_fuse_create_sysfs(struct device *dev, unsigned int size,
81 const struct tegra_fuse_info *info)
82{
83 fuse_bin_attr.size = size;
84
85 return device_create_bin_file(dev, &fuse_bin_attr);
86}
87
79static const struct of_device_id car_match[] __initconst = { 88static const struct of_device_id car_match[] __initconst = {
80 { .compatible = "nvidia,tegra20-car", }, 89 { .compatible = "nvidia,tegra20-car", },
81 { .compatible = "nvidia,tegra30-car", }, 90 { .compatible = "nvidia,tegra30-car", },
@@ -85,73 +94,211 @@ static const struct of_device_id car_match[] __initconst = {
85 {}, 94 {},
86}; 95};
87 96
88static void tegra_enable_fuse_clk(void __iomem *base) 97static struct tegra_fuse *fuse = &(struct tegra_fuse) {
98 .base = NULL,
99 .soc = NULL,
100};
101
102static const struct of_device_id tegra_fuse_match[] = {
103#ifdef CONFIG_ARCH_TEGRA_132_SOC
104 { .compatible = "nvidia,tegra132-efuse", .data = &tegra124_fuse_soc },
105#endif
106#ifdef CONFIG_ARCH_TEGRA_124_SOC
107 { .compatible = "nvidia,tegra124-efuse", .data = &tegra124_fuse_soc },
108#endif
109#ifdef CONFIG_ARCH_TEGRA_114_SOC
110 { .compatible = "nvidia,tegra114-efuse", .data = &tegra114_fuse_soc },
111#endif
112#ifdef CONFIG_ARCH_TEGRA_3x_SOC
113 { .compatible = "nvidia,tegra30-efuse", .data = &tegra30_fuse_soc },
114#endif
115#ifdef CONFIG_ARCH_TEGRA_2x_SOC
116 { .compatible = "nvidia,tegra20-efuse", .data = &tegra20_fuse_soc },
117#endif
118 { /* sentinel */ }
119};
120
121static int tegra_fuse_probe(struct platform_device *pdev)
89{ 122{
90 u32 reg; 123 void __iomem *base = fuse->base;
124 struct resource *res;
125 int err;
126
127 /* take over the memory region from the early initialization */
128 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
129 fuse->base = devm_ioremap_resource(&pdev->dev, res);
130 if (IS_ERR(fuse->base))
131 return PTR_ERR(fuse->base);
132
133 fuse->clk = devm_clk_get(&pdev->dev, "fuse");
134 if (IS_ERR(fuse->clk)) {
135 dev_err(&pdev->dev, "failed to get FUSE clock: %ld",
136 PTR_ERR(fuse->clk));
137 return PTR_ERR(fuse->clk);
138 }
91 139
92 reg = readl_relaxed(base + 0x48); 140 platform_set_drvdata(pdev, fuse);
93 reg |= 1 << 28; 141 fuse->dev = &pdev->dev;
94 writel(reg, base + 0x48);
95 142
96 /* 143 if (fuse->soc->probe) {
97 * Enable FUSE clock. This needs to be hardcoded because the clock 144 err = fuse->soc->probe(fuse);
98 * subsystem is not active during early boot. 145 if (err < 0)
99 */ 146 return err;
100 reg = readl(base + 0x14); 147 }
101 reg |= 1 << 7; 148
102 writel(reg, base + 0x14); 149 if (tegra_fuse_create_sysfs(&pdev->dev, fuse->soc->info->size,
150 fuse->soc->info))
151 return -ENODEV;
152
153 /* release the early I/O memory mapping */
154 iounmap(base);
155
156 return 0;
157}
158
159static struct platform_driver tegra_fuse_driver = {
160 .driver = {
161 .name = "tegra-fuse",
162 .of_match_table = tegra_fuse_match,
163 .suppress_bind_attrs = true,
164 },
165 .probe = tegra_fuse_probe,
166};
167module_platform_driver(tegra_fuse_driver);
168
169bool __init tegra_fuse_read_spare(unsigned int spare)
170{
171 unsigned int offset = fuse->soc->info->spare + spare * 4;
172
173 return fuse->read_early(fuse, offset) & 1;
174}
175
176u32 __init tegra_fuse_read_early(unsigned int offset)
177{
178 return fuse->read_early(fuse, offset);
103} 179}
104 180
105int tegra_fuse_readl(unsigned long offset, u32 *value) 181int tegra_fuse_readl(unsigned long offset, u32 *value)
106{ 182{
107 if (!fuse_readl) 183 if (!fuse->read)
108 return -EPROBE_DEFER; 184 return -EPROBE_DEFER;
109 185
110 *value = fuse_readl(offset); 186 *value = fuse->read(fuse, offset);
111 187
112 return 0; 188 return 0;
113} 189}
114EXPORT_SYMBOL(tegra_fuse_readl); 190EXPORT_SYMBOL(tegra_fuse_readl);
115 191
116int tegra_fuse_create_sysfs(struct device *dev, int size, 192static void tegra_enable_fuse_clk(void __iomem *base)
117 u32 (*readl)(const unsigned int offset))
118{ 193{
119 if (fuse_size) 194 u32 reg;
120 return -ENODEV;
121
122 fuse_bin_attr.size = size;
123 fuse_bin_attr.read = fuse_read;
124 195
125 fuse_size = size; 196 reg = readl_relaxed(base + 0x48);
126 fuse_readl = readl; 197 reg |= 1 << 28;
198 writel(reg, base + 0x48);
127 199
128 return device_create_bin_file(dev, &fuse_bin_attr); 200 /*
201 * Enable FUSE clock. This needs to be hardcoded because the clock
202 * subsystem is not active during early boot.
203 */
204 reg = readl(base + 0x14);
205 reg |= 1 << 7;
206 writel(reg, base + 0x14);
129} 207}
130 208
131static int __init tegra_init_fuse(void) 209static int __init tegra_init_fuse(void)
132{ 210{
211 const struct of_device_id *match;
133 struct device_node *np; 212 struct device_node *np;
134 void __iomem *car_base; 213 struct resource regs;
135
136 if (!soc_is_tegra())
137 return 0;
138 214
139 tegra_init_apbmisc(); 215 tegra_init_apbmisc();
140 216
141 np = of_find_matching_node(NULL, car_match); 217 np = of_find_matching_node_and_match(NULL, tegra_fuse_match, &match);
142 car_base = of_iomap(np, 0); 218 if (!np) {
143 if (car_base) { 219 /*
144 tegra_enable_fuse_clk(car_base); 220 * Fall back to legacy initialization for 32-bit ARM only. All
145 iounmap(car_base); 221 * 64-bit ARM device tree files for Tegra are required to have
222 * a FUSE node.
223 *
224 * This is for backwards-compatibility with old device trees
225 * that didn't contain a FUSE node.
226 */
227 if (IS_ENABLED(CONFIG_ARM) && soc_is_tegra()) {
228 u8 chip = tegra_get_chip_id();
229
230 regs.start = 0x7000f800;
231 regs.end = 0x7000fbff;
232 regs.flags = IORESOURCE_MEM;
233
234 switch (chip) {
235#ifdef CONFIG_ARCH_TEGRA_2x_SOC
236 case TEGRA20:
237 fuse->soc = &tegra20_fuse_soc;
238 break;
239#endif
240
241#ifdef CONFIG_ARCH_TEGRA_3x_SOC
242 case TEGRA30:
243 fuse->soc = &tegra30_fuse_soc;
244 break;
245#endif
246
247#ifdef CONFIG_ARCH_TEGRA_114_SOC
248 case TEGRA114:
249 fuse->soc = &tegra114_fuse_soc;
250 break;
251#endif
252
253#ifdef CONFIG_ARCH_TEGRA_124_SOC
254 case TEGRA124:
255 fuse->soc = &tegra124_fuse_soc;
256 break;
257#endif
258
259 default:
260 pr_warn("Unsupported SoC: %02x\n", chip);
261 break;
262 }
263 } else {
264 /*
265 * At this point we're not running on Tegra, so play
266 * nice with multi-platform kernels.
267 */
268 return 0;
269 }
146 } else { 270 } else {
147 pr_err("Could not enable fuse clk. ioremap tegra car failed.\n"); 271 /*
272 * Extract information from the device tree if we've found a
273 * matching node.
274 */
275 if (of_address_to_resource(np, 0, &regs) < 0) {
276 pr_err("failed to get FUSE register\n");
277 return -ENXIO;
278 }
279
280 fuse->soc = match->data;
281 }
282
283 np = of_find_matching_node(NULL, car_match);
284 if (np) {
285 void __iomem *base = of_iomap(np, 0);
286 if (base) {
287 tegra_enable_fuse_clk(base);
288 iounmap(base);
289 } else {
290 pr_err("failed to map clock registers\n");
291 return -ENXIO;
292 }
293 }
294
295 fuse->base = ioremap_nocache(regs.start, resource_size(&regs));
296 if (!fuse->base) {
297 pr_err("failed to map FUSE registers\n");
148 return -ENXIO; 298 return -ENXIO;
149 } 299 }
150 300
151 if (tegra_get_chip_id() == TEGRA20) 301 fuse->soc->init(fuse);
152 tegra20_init_fuse_early();
153 else
154 tegra30_init_fuse_early();
155 302
156 pr_info("Tegra Revision: %s SKU: %d CPU Process: %d Core Process: %d\n", 303 pr_info("Tegra Revision: %s SKU: %d CPU Process: %d Core Process: %d\n",
157 tegra_revision_name[tegra_sku_info.revision], 304 tegra_revision_name[tegra_sku_info.revision],
diff --git a/drivers/soc/tegra/fuse/fuse-tegra20.c b/drivers/soc/tegra/fuse/fuse-tegra20.c
index 6acc2c44ee2c..b2f2aaad5627 100644
--- a/drivers/soc/tegra/fuse/fuse-tegra20.c
+++ b/drivers/soc/tegra/fuse/fuse-tegra20.c
@@ -34,159 +34,107 @@
34#include "fuse.h" 34#include "fuse.h"
35 35
36#define FUSE_BEGIN 0x100 36#define FUSE_BEGIN 0x100
37#define FUSE_SIZE 0x1f8
38#define FUSE_UID_LOW 0x08 37#define FUSE_UID_LOW 0x08
39#define FUSE_UID_HIGH 0x0c 38#define FUSE_UID_HIGH 0x0c
40 39
41static phys_addr_t fuse_phys; 40static u32 tegra20_fuse_read_early(struct tegra_fuse *fuse, unsigned int offset)
42static struct clk *fuse_clk; 41{
43static void __iomem __initdata *fuse_base; 42 return readl_relaxed(fuse->base + FUSE_BEGIN + offset);
44 43}
45static DEFINE_MUTEX(apb_dma_lock);
46static DECLARE_COMPLETION(apb_dma_wait);
47static struct dma_chan *apb_dma_chan;
48static struct dma_slave_config dma_sconfig;
49static u32 *apb_buffer;
50static dma_addr_t apb_buffer_phys;
51 44
52static void apb_dma_complete(void *args) 45static void apb_dma_complete(void *args)
53{ 46{
54 complete(&apb_dma_wait); 47 struct tegra_fuse *fuse = args;
48
49 complete(&fuse->apbdma.wait);
55} 50}
56 51
57static u32 tegra20_fuse_readl(const unsigned int offset) 52static u32 tegra20_fuse_read(struct tegra_fuse *fuse, unsigned int offset)
58{ 53{
59 int ret; 54 unsigned long flags = DMA_PREP_INTERRUPT | DMA_CTRL_ACK;
60 u32 val = 0;
61 struct dma_async_tx_descriptor *dma_desc; 55 struct dma_async_tx_descriptor *dma_desc;
62 unsigned long time_left; 56 unsigned long time_left;
57 u32 value = 0;
58 int err;
59
60 mutex_lock(&fuse->apbdma.lock);
63 61
64 mutex_lock(&apb_dma_lock); 62 fuse->apbdma.config.src_addr = fuse->apbdma.phys + FUSE_BEGIN + offset;
65 63
66 dma_sconfig.src_addr = fuse_phys + FUSE_BEGIN + offset; 64 err = dmaengine_slave_config(fuse->apbdma.chan, &fuse->apbdma.config);
67 ret = dmaengine_slave_config(apb_dma_chan, &dma_sconfig); 65 if (err)
68 if (ret)
69 goto out; 66 goto out;
70 67
71 dma_desc = dmaengine_prep_slave_single(apb_dma_chan, apb_buffer_phys, 68 dma_desc = dmaengine_prep_slave_single(fuse->apbdma.chan,
72 sizeof(u32), DMA_DEV_TO_MEM, 69 fuse->apbdma.phys,
73 DMA_PREP_INTERRUPT | DMA_CTRL_ACK); 70 sizeof(u32), DMA_DEV_TO_MEM,
71 flags);
74 if (!dma_desc) 72 if (!dma_desc)
75 goto out; 73 goto out;
76 74
77 dma_desc->callback = apb_dma_complete; 75 dma_desc->callback = apb_dma_complete;
78 dma_desc->callback_param = NULL; 76 dma_desc->callback_param = fuse;
79 77
80 reinit_completion(&apb_dma_wait); 78 reinit_completion(&fuse->apbdma.wait);
81 79
82 clk_prepare_enable(fuse_clk); 80 clk_prepare_enable(fuse->clk);
83 81
84 dmaengine_submit(dma_desc); 82 dmaengine_submit(dma_desc);
85 dma_async_issue_pending(apb_dma_chan); 83 dma_async_issue_pending(fuse->apbdma.chan);
86 time_left = wait_for_completion_timeout(&apb_dma_wait, 84 time_left = wait_for_completion_timeout(&fuse->apbdma.wait,
87 msecs_to_jiffies(50)); 85 msecs_to_jiffies(50));
88 86
89 if (WARN(time_left == 0, "apb read dma timed out")) 87 if (WARN(time_left == 0, "apb read dma timed out"))
90 dmaengine_terminate_all(apb_dma_chan); 88 dmaengine_terminate_all(fuse->apbdma.chan);
91 else 89 else
92 val = *apb_buffer; 90 value = *fuse->apbdma.virt;
93 91
94 clk_disable_unprepare(fuse_clk); 92 clk_disable_unprepare(fuse->clk);
95out:
96 mutex_unlock(&apb_dma_lock);
97 93
98 return val; 94out:
95 mutex_unlock(&fuse->apbdma.lock);
96 return value;
99} 97}
100 98
101static const struct of_device_id tegra20_fuse_of_match[] = { 99static int tegra20_fuse_probe(struct tegra_fuse *fuse)
102 { .compatible = "nvidia,tegra20-efuse" },
103 {},
104};
105
106static int apb_dma_init(void)
107{ 100{
108 dma_cap_mask_t mask; 101 dma_cap_mask_t mask;
109 102
110 dma_cap_zero(mask); 103 dma_cap_zero(mask);
111 dma_cap_set(DMA_SLAVE, mask); 104 dma_cap_set(DMA_SLAVE, mask);
112 apb_dma_chan = dma_request_channel(mask, NULL, NULL); 105
113 if (!apb_dma_chan) 106 fuse->apbdma.chan = dma_request_channel(mask, NULL, NULL);
107 if (!fuse->apbdma.chan)
114 return -EPROBE_DEFER; 108 return -EPROBE_DEFER;
115 109
116 apb_buffer = dma_alloc_coherent(NULL, sizeof(u32), &apb_buffer_phys, 110 fuse->apbdma.virt = dma_alloc_coherent(fuse->dev, sizeof(u32),
117 GFP_KERNEL); 111 &fuse->apbdma.phys,
118 if (!apb_buffer) { 112 GFP_KERNEL);
119 dma_release_channel(apb_dma_chan); 113 if (!fuse->apbdma.virt) {
114 dma_release_channel(fuse->apbdma.chan);
120 return -ENOMEM; 115 return -ENOMEM;
121 } 116 }
122 117
123 dma_sconfig.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; 118 fuse->apbdma.config.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
124 dma_sconfig.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; 119 fuse->apbdma.config.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
125 dma_sconfig.src_maxburst = 1; 120 fuse->apbdma.config.src_maxburst = 1;
126 dma_sconfig.dst_maxburst = 1; 121 fuse->apbdma.config.dst_maxburst = 1;
127 122
128 return 0; 123 init_completion(&fuse->apbdma.wait);
129} 124 mutex_init(&fuse->apbdma.lock);
130 125 fuse->read = tegra20_fuse_read;
131static int tegra20_fuse_probe(struct platform_device *pdev)
132{
133 struct resource *res;
134 int err;
135
136 fuse_clk = devm_clk_get(&pdev->dev, NULL);
137 if (IS_ERR(fuse_clk)) {
138 dev_err(&pdev->dev, "missing clock");
139 return PTR_ERR(fuse_clk);
140 }
141
142 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
143 if (!res)
144 return -EINVAL;
145 fuse_phys = res->start;
146
147 err = apb_dma_init();
148 if (err)
149 return err;
150
151 if (tegra_fuse_create_sysfs(&pdev->dev, FUSE_SIZE, tegra20_fuse_readl))
152 return -ENODEV;
153
154 dev_dbg(&pdev->dev, "loaded\n");
155 126
156 return 0; 127 return 0;
157} 128}
158 129
159static struct platform_driver tegra20_fuse_driver = { 130static const struct tegra_fuse_info tegra20_fuse_info = {
160 .probe = tegra20_fuse_probe, 131 .read = tegra20_fuse_read,
161 .driver = { 132 .size = 0x1f8,
162 .name = "tegra20_fuse", 133 .spare = 0x100,
163 .of_match_table = tegra20_fuse_of_match,
164 }
165}; 134};
166 135
167static int __init tegra20_fuse_init(void)
168{
169 return platform_driver_register(&tegra20_fuse_driver);
170}
171postcore_initcall(tegra20_fuse_init);
172
173/* Early boot code. This code is called before the devices are created */ 136/* Early boot code. This code is called before the devices are created */
174 137
175u32 __init tegra20_fuse_early(const unsigned int offset)
176{
177 return readl_relaxed(fuse_base + FUSE_BEGIN + offset);
178}
179
180bool __init tegra20_spare_fuse_early(int spare_bit)
181{
182 u32 offset = spare_bit * 4;
183 bool value;
184
185 value = tegra20_fuse_early(offset + 0x100);
186
187 return value;
188}
189
190static void __init tegra20_fuse_add_randomness(void) 138static void __init tegra20_fuse_add_randomness(void)
191{ 139{
192 u32 randomness[7]; 140 u32 randomness[7];
@@ -198,19 +146,24 @@ static void __init tegra20_fuse_add_randomness(void)
198 randomness[3] |= tegra_sku_info.core_process_id; 146 randomness[3] |= tegra_sku_info.core_process_id;
199 randomness[4] = tegra_sku_info.cpu_speedo_id << 16; 147 randomness[4] = tegra_sku_info.cpu_speedo_id << 16;
200 randomness[4] |= tegra_sku_info.soc_speedo_id; 148 randomness[4] |= tegra_sku_info.soc_speedo_id;
201 randomness[5] = tegra20_fuse_early(FUSE_UID_LOW); 149 randomness[5] = tegra_fuse_read_early(FUSE_UID_LOW);
202 randomness[6] = tegra20_fuse_early(FUSE_UID_HIGH); 150 randomness[6] = tegra_fuse_read_early(FUSE_UID_HIGH);
203 151
204 add_device_randomness(randomness, sizeof(randomness)); 152 add_device_randomness(randomness, sizeof(randomness));
205} 153}
206 154
207void __init tegra20_init_fuse_early(void) 155static void __init tegra20_fuse_init(struct tegra_fuse *fuse)
208{ 156{
209 fuse_base = ioremap(TEGRA_FUSE_BASE, TEGRA_FUSE_SIZE); 157 fuse->read_early = tegra20_fuse_read_early;
210 158
211 tegra_init_revision(); 159 tegra_init_revision();
212 tegra20_init_speedo_data(&tegra_sku_info); 160 fuse->soc->speedo_init(&tegra_sku_info);
213 tegra20_fuse_add_randomness(); 161 tegra20_fuse_add_randomness();
214
215 iounmap(fuse_base);
216} 162}
163
164const struct tegra_fuse_soc tegra20_fuse_soc = {
165 .init = tegra20_fuse_init,
166 .speedo_init = tegra20_init_speedo_data,
167 .probe = tegra20_fuse_probe,
168 .info = &tegra20_fuse_info,
169};
diff --git a/drivers/soc/tegra/fuse/fuse-tegra30.c b/drivers/soc/tegra/fuse/fuse-tegra30.c
index 4d2f71bf65c5..23f8a4b5ca42 100644
--- a/drivers/soc/tegra/fuse/fuse-tegra30.c
+++ b/drivers/soc/tegra/fuse/fuse-tegra30.c
@@ -42,113 +42,32 @@
42 42
43#define FUSE_HAS_REVISION_INFO BIT(0) 43#define FUSE_HAS_REVISION_INFO BIT(0)
44 44
45enum speedo_idx { 45#if defined(CONFIG_ARCH_TEGRA_3x_SOC) || \
46 SPEEDO_TEGRA30 = 0, 46 defined(CONFIG_ARCH_TEGRA_114_SOC) || \
47 SPEEDO_TEGRA114, 47 defined(CONFIG_ARCH_TEGRA_124_SOC) || \
48 SPEEDO_TEGRA124, 48 defined(CONFIG_ARCH_TEGRA_132_SOC)
49}; 49static u32 tegra30_fuse_read_early(struct tegra_fuse *fuse, unsigned int offset)
50
51struct tegra_fuse_info {
52 int size;
53 int spare_bit;
54 enum speedo_idx speedo_idx;
55};
56
57static void __iomem *fuse_base;
58static struct clk *fuse_clk;
59static const struct tegra_fuse_info *fuse_info;
60
61u32 tegra30_fuse_readl(const unsigned int offset)
62{ 50{
63 u32 val; 51 return readl_relaxed(fuse->base + FUSE_BEGIN + offset);
64
65 /*
66 * early in the boot, the fuse clock will be enabled by
67 * tegra_init_fuse()
68 */
69
70 if (fuse_clk)
71 clk_prepare_enable(fuse_clk);
72
73 val = readl_relaxed(fuse_base + FUSE_BEGIN + offset);
74
75 if (fuse_clk)
76 clk_disable_unprepare(fuse_clk);
77
78 return val;
79} 52}
80 53
81static const struct tegra_fuse_info tegra30_info = { 54static u32 tegra30_fuse_read(struct tegra_fuse *fuse, unsigned int offset)
82 .size = 0x2a4,
83 .spare_bit = 0x144,
84 .speedo_idx = SPEEDO_TEGRA30,
85};
86
87static const struct tegra_fuse_info tegra114_info = {
88 .size = 0x2a0,
89 .speedo_idx = SPEEDO_TEGRA114,
90};
91
92static const struct tegra_fuse_info tegra124_info = {
93 .size = 0x300,
94 .speedo_idx = SPEEDO_TEGRA124,
95};
96
97static const struct of_device_id tegra30_fuse_of_match[] = {
98 { .compatible = "nvidia,tegra30-efuse", .data = &tegra30_info },
99 { .compatible = "nvidia,tegra114-efuse", .data = &tegra114_info },
100 { .compatible = "nvidia,tegra124-efuse", .data = &tegra124_info },
101 {},
102};
103
104static int tegra30_fuse_probe(struct platform_device *pdev)
105{ 55{
106 const struct of_device_id *of_dev_id; 56 u32 value;
57 int err;
107 58
108 of_dev_id = of_match_device(tegra30_fuse_of_match, &pdev->dev); 59 err = clk_prepare_enable(fuse->clk);
109 if (!of_dev_id) 60 if (err < 0) {
110 return -ENODEV; 61 dev_err(fuse->dev, "failed to enable FUSE clock: %d\n", err);
111 62 return 0;
112 fuse_clk = devm_clk_get(&pdev->dev, NULL);
113 if (IS_ERR(fuse_clk)) {
114 dev_err(&pdev->dev, "missing clock");
115 return PTR_ERR(fuse_clk);
116 } 63 }
117 64
118 platform_set_drvdata(pdev, NULL); 65 value = readl_relaxed(fuse->base + FUSE_BEGIN + offset);
119
120 if (tegra_fuse_create_sysfs(&pdev->dev, fuse_info->size,
121 tegra30_fuse_readl))
122 return -ENODEV;
123
124 dev_dbg(&pdev->dev, "loaded\n");
125 66
126 return 0; 67 clk_disable_unprepare(fuse->clk);
127}
128
129static struct platform_driver tegra30_fuse_driver = {
130 .probe = tegra30_fuse_probe,
131 .driver = {
132 .name = "tegra_fuse",
133 .of_match_table = tegra30_fuse_of_match,
134 }
135};
136 68
137static int __init tegra30_fuse_init(void) 69 return value;
138{
139 return platform_driver_register(&tegra30_fuse_driver);
140} 70}
141postcore_initcall(tegra30_fuse_init);
142
143/* Early boot code. This code is called before the devices are created */
144
145typedef void (*speedo_f)(struct tegra_sku_info *sku_info);
146
147static speedo_f __initdata speedo_tbl[] = {
148 [SPEEDO_TEGRA30] = tegra30_init_speedo_data,
149 [SPEEDO_TEGRA114] = tegra114_init_speedo_data,
150 [SPEEDO_TEGRA124] = tegra124_init_speedo_data,
151};
152 71
153static void __init tegra30_fuse_add_randomness(void) 72static void __init tegra30_fuse_add_randomness(void)
154{ 73{
@@ -161,64 +80,64 @@ static void __init tegra30_fuse_add_randomness(void)
161 randomness[3] |= tegra_sku_info.core_process_id; 80 randomness[3] |= tegra_sku_info.core_process_id;
162 randomness[4] = tegra_sku_info.cpu_speedo_id << 16; 81 randomness[4] = tegra_sku_info.cpu_speedo_id << 16;
163 randomness[4] |= tegra_sku_info.soc_speedo_id; 82 randomness[4] |= tegra_sku_info.soc_speedo_id;
164 randomness[5] = tegra30_fuse_readl(FUSE_VENDOR_CODE); 83 randomness[5] = tegra_fuse_read_early(FUSE_VENDOR_CODE);
165 randomness[6] = tegra30_fuse_readl(FUSE_FAB_CODE); 84 randomness[6] = tegra_fuse_read_early(FUSE_FAB_CODE);
166 randomness[7] = tegra30_fuse_readl(FUSE_LOT_CODE_0); 85 randomness[7] = tegra_fuse_read_early(FUSE_LOT_CODE_0);
167 randomness[8] = tegra30_fuse_readl(FUSE_LOT_CODE_1); 86 randomness[8] = tegra_fuse_read_early(FUSE_LOT_CODE_1);
168 randomness[9] = tegra30_fuse_readl(FUSE_WAFER_ID); 87 randomness[9] = tegra_fuse_read_early(FUSE_WAFER_ID);
169 randomness[10] = tegra30_fuse_readl(FUSE_X_COORDINATE); 88 randomness[10] = tegra_fuse_read_early(FUSE_X_COORDINATE);
170 randomness[11] = tegra30_fuse_readl(FUSE_Y_COORDINATE); 89 randomness[11] = tegra_fuse_read_early(FUSE_Y_COORDINATE);
171 90
172 add_device_randomness(randomness, sizeof(randomness)); 91 add_device_randomness(randomness, sizeof(randomness));
173} 92}
174 93
175static void __init legacy_fuse_init(void) 94static void __init tegra30_fuse_init(struct tegra_fuse *fuse)
176{ 95{
177 switch (tegra_get_chip_id()) { 96 fuse->read_early = tegra30_fuse_read_early;
178 case TEGRA30: 97 fuse->read = tegra30_fuse_read;
179 fuse_info = &tegra30_info;
180 break;
181 case TEGRA114:
182 fuse_info = &tegra114_info;
183 break;
184 case TEGRA124:
185 case TEGRA132:
186 fuse_info = &tegra124_info;
187 break;
188 default:
189 return;
190 }
191 98
192 fuse_base = ioremap(TEGRA_FUSE_BASE, TEGRA_FUSE_SIZE); 99 tegra_init_revision();
100 fuse->soc->speedo_init(&tegra_sku_info);
101 tegra30_fuse_add_randomness();
193} 102}
103#endif
194 104
195bool __init tegra30_spare_fuse(int spare_bit) 105#ifdef CONFIG_ARCH_TEGRA_3x_SOC
196{ 106static const struct tegra_fuse_info tegra30_fuse_info = {
197 u32 offset = fuse_info->spare_bit + spare_bit * 4; 107 .read = tegra30_fuse_read,
108 .size = 0x2a4,
109 .spare = 0x144,
110};
198 111
199 return tegra30_fuse_readl(offset) & 1; 112const struct tegra_fuse_soc tegra30_fuse_soc = {
200} 113 .init = tegra30_fuse_init,
114 .speedo_init = tegra30_init_speedo_data,
115 .info = &tegra30_fuse_info,
116};
117#endif
201 118
202void __init tegra30_init_fuse_early(void) 119#ifdef CONFIG_ARCH_TEGRA_114_SOC
203{ 120static const struct tegra_fuse_info tegra114_fuse_info = {
204 struct device_node *np; 121 .read = tegra30_fuse_read,
205 const struct of_device_id *of_match; 122 .size = 0x2a0,
206 123};
207 np = of_find_matching_node_and_match(NULL, tegra30_fuse_of_match,
208 &of_match);
209 if (np) {
210 fuse_base = of_iomap(np, 0);
211 fuse_info = (struct tegra_fuse_info *)of_match->data;
212 } else
213 legacy_fuse_init();
214
215 if (!fuse_base) {
216 pr_warn("fuse DT node missing and unknown chip id: 0x%02x\n",
217 tegra_get_chip_id());
218 return;
219 }
220 124
221 tegra_init_revision(); 125const struct tegra_fuse_soc tegra114_fuse_soc = {
222 speedo_tbl[fuse_info->speedo_idx](&tegra_sku_info); 126 .init = tegra30_fuse_init,
223 tegra30_fuse_add_randomness(); 127 .speedo_init = tegra114_init_speedo_data,
224} 128 .info = &tegra114_fuse_info,
129};
130#endif
131
132#if defined(CONFIG_ARCH_TEGRA_124_SOC) || defined(CONFIG_ARCH_TEGRA_132_SOC)
133static const struct tegra_fuse_info tegra124_fuse_info = {
134 .read = tegra30_fuse_read,
135 .size = 0x300,
136};
137
138const struct tegra_fuse_soc tegra124_fuse_soc = {
139 .init = tegra30_fuse_init,
140 .speedo_init = tegra124_init_speedo_data,
141 .info = &tegra124_fuse_info,
142};
143#endif
diff --git a/drivers/soc/tegra/fuse/fuse.h b/drivers/soc/tegra/fuse/fuse.h
index 3a398bf3572c..2a32bf9381ce 100644
--- a/drivers/soc/tegra/fuse/fuse.h
+++ b/drivers/soc/tegra/fuse/fuse.h
@@ -19,53 +19,82 @@
19#ifndef __DRIVERS_MISC_TEGRA_FUSE_H 19#ifndef __DRIVERS_MISC_TEGRA_FUSE_H
20#define __DRIVERS_MISC_TEGRA_FUSE_H 20#define __DRIVERS_MISC_TEGRA_FUSE_H
21 21
22#define TEGRA_FUSE_BASE 0x7000f800 22#include <linux/dmaengine.h>
23#define TEGRA_FUSE_SIZE 0x400 23#include <linux/types.h>
24 24
25int tegra_fuse_create_sysfs(struct device *dev, int size, 25struct tegra_fuse;
26 u32 (*readl)(const unsigned int offset)); 26
27struct tegra_fuse_info {
28 u32 (*read)(struct tegra_fuse *fuse, unsigned int offset);
29 unsigned int size;
30 unsigned int spare;
31};
32
33struct tegra_fuse_soc {
34 void (*init)(struct tegra_fuse *fuse);
35 void (*speedo_init)(struct tegra_sku_info *info);
36 int (*probe)(struct tegra_fuse *fuse);
37
38 const struct tegra_fuse_info *info;
39};
40
41struct tegra_fuse {
42 struct device *dev;
43 void __iomem *base;
44 phys_addr_t phys;
45 struct clk *clk;
46
47 u32 (*read_early)(struct tegra_fuse *fuse, unsigned int offset);
48 u32 (*read)(struct tegra_fuse *fuse, unsigned int offset);
49 const struct tegra_fuse_soc *soc;
50
51 /* APBDMA on Tegra20 */
52 struct {
53 struct mutex lock;
54 struct completion wait;
55 struct dma_chan *chan;
56 struct dma_slave_config config;
57 dma_addr_t phys;
58 u32 *virt;
59 } apbdma;
60};
27 61
28bool tegra30_spare_fuse(int bit);
29u32 tegra30_fuse_readl(const unsigned int offset);
30void tegra30_init_fuse_early(void);
31void tegra_init_revision(void); 62void tegra_init_revision(void);
32void tegra_init_apbmisc(void); 63void tegra_init_apbmisc(void);
33 64
65bool __init tegra_fuse_read_spare(unsigned int spare);
66u32 __init tegra_fuse_read_early(unsigned int offset);
67
34#ifdef CONFIG_ARCH_TEGRA_2x_SOC 68#ifdef CONFIG_ARCH_TEGRA_2x_SOC
35void tegra20_init_speedo_data(struct tegra_sku_info *sku_info); 69void tegra20_init_speedo_data(struct tegra_sku_info *sku_info);
36bool tegra20_spare_fuse_early(int spare_bit);
37void tegra20_init_fuse_early(void);
38u32 tegra20_fuse_early(const unsigned int offset);
39#else
40static inline void tegra20_init_speedo_data(struct tegra_sku_info *sku_info) {}
41static inline bool tegra20_spare_fuse_early(int spare_bit)
42{
43 return false;
44}
45static inline void tegra20_init_fuse_early(void) {}
46static inline u32 tegra20_fuse_early(const unsigned int offset)
47{
48 return 0;
49}
50#endif 70#endif
51 71
52
53#ifdef CONFIG_ARCH_TEGRA_3x_SOC 72#ifdef CONFIG_ARCH_TEGRA_3x_SOC
54void tegra30_init_speedo_data(struct tegra_sku_info *sku_info); 73void tegra30_init_speedo_data(struct tegra_sku_info *sku_info);
55#else
56static inline void tegra30_init_speedo_data(struct tegra_sku_info *sku_info) {}
57#endif 74#endif
58 75
59#ifdef CONFIG_ARCH_TEGRA_114_SOC 76#ifdef CONFIG_ARCH_TEGRA_114_SOC
60void tegra114_init_speedo_data(struct tegra_sku_info *sku_info); 77void tegra114_init_speedo_data(struct tegra_sku_info *sku_info);
61#else
62static inline void tegra114_init_speedo_data(struct tegra_sku_info *sku_info) {}
63#endif 78#endif
64 79
65#ifdef CONFIG_ARCH_TEGRA_124_SOC 80#if defined(CONFIG_ARCH_TEGRA_124_SOC) || defined(CONFIG_ARCH_TEGRA_132_SOC)
66void tegra124_init_speedo_data(struct tegra_sku_info *sku_info); 81void tegra124_init_speedo_data(struct tegra_sku_info *sku_info);
67#else 82#endif
68static inline void tegra124_init_speedo_data(struct tegra_sku_info *sku_info) {} 83
84#ifdef CONFIG_ARCH_TEGRA_2x_SOC
85extern const struct tegra_fuse_soc tegra20_fuse_soc;
86#endif
87
88#ifdef CONFIG_ARCH_TEGRA_3x_SOC
89extern const struct tegra_fuse_soc tegra30_fuse_soc;
90#endif
91
92#ifdef CONFIG_ARCH_TEGRA_114_SOC
93extern const struct tegra_fuse_soc tegra114_fuse_soc;
94#endif
95
96#if defined(CONFIG_ARCH_TEGRA_124_SOC) || defined(CONFIG_ARCH_TEGRA_132_SOC)
97extern const struct tegra_fuse_soc tegra124_fuse_soc;
69#endif 98#endif
70 99
71#endif 100#endif
diff --git a/drivers/soc/tegra/fuse/speedo-tegra114.c b/drivers/soc/tegra/fuse/speedo-tegra114.c
index 2a6ca036f09f..554c54b98b0c 100644
--- a/drivers/soc/tegra/fuse/speedo-tegra114.c
+++ b/drivers/soc/tegra/fuse/speedo-tegra114.c
@@ -74,8 +74,8 @@ static void __init rev_sku_to_speedo_ids(struct tegra_sku_info *sku_info,
74 } 74 }
75 75
76 if (rev == TEGRA_REVISION_A01) { 76 if (rev == TEGRA_REVISION_A01) {
77 tmp = tegra30_fuse_readl(0x270) << 1; 77 tmp = tegra_fuse_read_early(0x270) << 1;
78 tmp |= tegra30_fuse_readl(0x26c); 78 tmp |= tegra_fuse_read_early(0x26c);
79 if (!tmp) 79 if (!tmp)
80 sku_info->cpu_speedo_id = 0; 80 sku_info->cpu_speedo_id = 0;
81 } 81 }
@@ -95,8 +95,8 @@ void __init tegra114_init_speedo_data(struct tegra_sku_info *sku_info)
95 95
96 rev_sku_to_speedo_ids(sku_info, &threshold); 96 rev_sku_to_speedo_ids(sku_info, &threshold);
97 97
98 cpu_speedo_val = tegra30_fuse_readl(0x12c) + 1024; 98 cpu_speedo_val = tegra_fuse_read_early(0x12c) + 1024;
99 core_speedo_val = tegra30_fuse_readl(0x134); 99 core_speedo_val = tegra_fuse_read_early(0x134);
100 100
101 for (i = 0; i < CPU_PROCESS_CORNERS; i++) 101 for (i = 0; i < CPU_PROCESS_CORNERS; i++)
102 if (cpu_speedo_val < cpu_process_speedos[threshold][i]) 102 if (cpu_speedo_val < cpu_process_speedos[threshold][i])
diff --git a/drivers/soc/tegra/fuse/speedo-tegra124.c b/drivers/soc/tegra/fuse/speedo-tegra124.c
index 46362387d974..d1e896d8d8a2 100644
--- a/drivers/soc/tegra/fuse/speedo-tegra124.c
+++ b/drivers/soc/tegra/fuse/speedo-tegra124.c
@@ -122,16 +122,16 @@ void __init tegra124_init_speedo_data(struct tegra_sku_info *sku_info)
122 BUILD_BUG_ON(ARRAY_SIZE(core_process_speedos) != 122 BUILD_BUG_ON(ARRAY_SIZE(core_process_speedos) !=
123 THRESHOLD_INDEX_COUNT); 123 THRESHOLD_INDEX_COUNT);
124 124
125 cpu_speedo_0_value = tegra30_fuse_readl(FUSE_CPU_SPEEDO_0); 125 cpu_speedo_0_value = tegra_fuse_read_early(FUSE_CPU_SPEEDO_0);
126 126
127 /* GPU Speedo is stored in CPU_SPEEDO_2 */ 127 /* GPU Speedo is stored in CPU_SPEEDO_2 */
128 sku_info->gpu_speedo_value = tegra30_fuse_readl(FUSE_CPU_SPEEDO_2); 128 sku_info->gpu_speedo_value = tegra_fuse_read_early(FUSE_CPU_SPEEDO_2);
129 129
130 soc_speedo_0_value = tegra30_fuse_readl(FUSE_SOC_SPEEDO_0); 130 soc_speedo_0_value = tegra_fuse_read_early(FUSE_SOC_SPEEDO_0);
131 131
132 cpu_iddq_value = tegra30_fuse_readl(FUSE_CPU_IDDQ); 132 cpu_iddq_value = tegra_fuse_read_early(FUSE_CPU_IDDQ);
133 soc_iddq_value = tegra30_fuse_readl(FUSE_SOC_IDDQ); 133 soc_iddq_value = tegra_fuse_read_early(FUSE_SOC_IDDQ);
134 gpu_iddq_value = tegra30_fuse_readl(FUSE_GPU_IDDQ); 134 gpu_iddq_value = tegra_fuse_read_early(FUSE_GPU_IDDQ);
135 135
136 sku_info->cpu_speedo_value = cpu_speedo_0_value; 136 sku_info->cpu_speedo_value = cpu_speedo_0_value;
137 137
@@ -143,7 +143,7 @@ void __init tegra124_init_speedo_data(struct tegra_sku_info *sku_info)
143 143
144 rev_sku_to_speedo_ids(sku_info, &threshold); 144 rev_sku_to_speedo_ids(sku_info, &threshold);
145 145
146 sku_info->cpu_iddq_value = tegra30_fuse_readl(FUSE_CPU_IDDQ); 146 sku_info->cpu_iddq_value = tegra_fuse_read_early(FUSE_CPU_IDDQ);
147 147
148 for (i = 0; i < GPU_PROCESS_CORNERS; i++) 148 for (i = 0; i < GPU_PROCESS_CORNERS; i++)
149 if (sku_info->gpu_speedo_value < 149 if (sku_info->gpu_speedo_value <
diff --git a/drivers/soc/tegra/fuse/speedo-tegra20.c b/drivers/soc/tegra/fuse/speedo-tegra20.c
index eff1b63f330d..ed5180b01e17 100644
--- a/drivers/soc/tegra/fuse/speedo-tegra20.c
+++ b/drivers/soc/tegra/fuse/speedo-tegra20.c
@@ -80,8 +80,8 @@ void __init tegra20_init_speedo_data(struct tegra_sku_info *sku_info)
80 80
81 val = 0; 81 val = 0;
82 for (i = CPU_SPEEDO_MSBIT; i >= CPU_SPEEDO_LSBIT; i--) { 82 for (i = CPU_SPEEDO_MSBIT; i >= CPU_SPEEDO_LSBIT; i--) {
83 reg = tegra20_spare_fuse_early(i) | 83 reg = tegra_fuse_read_spare(i) |
84 tegra20_spare_fuse_early(i + CPU_SPEEDO_REDUND_OFFS); 84 tegra_fuse_read_spare(i + CPU_SPEEDO_REDUND_OFFS);
85 val = (val << 1) | (reg & 0x1); 85 val = (val << 1) | (reg & 0x1);
86 } 86 }
87 val = val * SPEEDO_MULT; 87 val = val * SPEEDO_MULT;
@@ -95,8 +95,8 @@ void __init tegra20_init_speedo_data(struct tegra_sku_info *sku_info)
95 95
96 val = 0; 96 val = 0;
97 for (i = CORE_SPEEDO_MSBIT; i >= CORE_SPEEDO_LSBIT; i--) { 97 for (i = CORE_SPEEDO_MSBIT; i >= CORE_SPEEDO_LSBIT; i--) {
98 reg = tegra20_spare_fuse_early(i) | 98 reg = tegra_fuse_read_spare(i) |
99 tegra20_spare_fuse_early(i + CORE_SPEEDO_REDUND_OFFS); 99 tegra_fuse_read_spare(i + CORE_SPEEDO_REDUND_OFFS);
100 val = (val << 1) | (reg & 0x1); 100 val = (val << 1) | (reg & 0x1);
101 } 101 }
102 val = val * SPEEDO_MULT; 102 val = val * SPEEDO_MULT;
diff --git a/drivers/soc/tegra/fuse/speedo-tegra30.c b/drivers/soc/tegra/fuse/speedo-tegra30.c
index b17f0dcdfebe..fd0cefae54ef 100644
--- a/drivers/soc/tegra/fuse/speedo-tegra30.c
+++ b/drivers/soc/tegra/fuse/speedo-tegra30.c
@@ -93,25 +93,25 @@ static void __init fuse_speedo_calib(u32 *speedo_g, u32 *speedo_lp)
93 int bit_minus1; 93 int bit_minus1;
94 int bit_minus2; 94 int bit_minus2;
95 95
96 reg = tegra30_fuse_readl(FUSE_SPEEDO_CALIB_0); 96 reg = tegra_fuse_read_early(FUSE_SPEEDO_CALIB_0);
97 97
98 *speedo_lp = (reg & 0xFFFF) * 4; 98 *speedo_lp = (reg & 0xFFFF) * 4;
99 *speedo_g = ((reg >> 16) & 0xFFFF) * 4; 99 *speedo_g = ((reg >> 16) & 0xFFFF) * 4;
100 100
101 ate_ver = tegra30_fuse_readl(FUSE_TEST_PROG_VER); 101 ate_ver = tegra_fuse_read_early(FUSE_TEST_PROG_VER);
102 pr_debug("Tegra ATE prog ver %d.%d\n", ate_ver/10, ate_ver%10); 102 pr_debug("Tegra ATE prog ver %d.%d\n", ate_ver/10, ate_ver%10);
103 103
104 if (ate_ver >= 26) { 104 if (ate_ver >= 26) {
105 bit_minus1 = tegra30_spare_fuse(LP_SPEEDO_BIT_MINUS1); 105 bit_minus1 = tegra_fuse_read_spare(LP_SPEEDO_BIT_MINUS1);
106 bit_minus1 |= tegra30_spare_fuse(LP_SPEEDO_BIT_MINUS1_R); 106 bit_minus1 |= tegra_fuse_read_spare(LP_SPEEDO_BIT_MINUS1_R);
107 bit_minus2 = tegra30_spare_fuse(LP_SPEEDO_BIT_MINUS2); 107 bit_minus2 = tegra_fuse_read_spare(LP_SPEEDO_BIT_MINUS2);
108 bit_minus2 |= tegra30_spare_fuse(LP_SPEEDO_BIT_MINUS2_R); 108 bit_minus2 |= tegra_fuse_read_spare(LP_SPEEDO_BIT_MINUS2_R);
109 *speedo_lp |= (bit_minus1 << 1) | bit_minus2; 109 *speedo_lp |= (bit_minus1 << 1) | bit_minus2;
110 110
111 bit_minus1 = tegra30_spare_fuse(G_SPEEDO_BIT_MINUS1); 111 bit_minus1 = tegra_fuse_read_spare(G_SPEEDO_BIT_MINUS1);
112 bit_minus1 |= tegra30_spare_fuse(G_SPEEDO_BIT_MINUS1_R); 112 bit_minus1 |= tegra_fuse_read_spare(G_SPEEDO_BIT_MINUS1_R);
113 bit_minus2 = tegra30_spare_fuse(G_SPEEDO_BIT_MINUS2); 113 bit_minus2 = tegra_fuse_read_spare(G_SPEEDO_BIT_MINUS2);
114 bit_minus2 |= tegra30_spare_fuse(G_SPEEDO_BIT_MINUS2_R); 114 bit_minus2 |= tegra_fuse_read_spare(G_SPEEDO_BIT_MINUS2_R);
115 *speedo_g |= (bit_minus1 << 1) | bit_minus2; 115 *speedo_g |= (bit_minus1 << 1) | bit_minus2;
116 } else { 116 } else {
117 *speedo_lp |= 0x3; 117 *speedo_lp |= 0x3;
@@ -121,7 +121,7 @@ static void __init fuse_speedo_calib(u32 *speedo_g, u32 *speedo_lp)
121 121
122static void __init rev_sku_to_speedo_ids(struct tegra_sku_info *sku_info) 122static void __init rev_sku_to_speedo_ids(struct tegra_sku_info *sku_info)
123{ 123{
124 int package_id = tegra30_fuse_readl(FUSE_PACKAGE_INFO) & 0x0F; 124 int package_id = tegra_fuse_read_early(FUSE_PACKAGE_INFO) & 0x0F;
125 125
126 switch (sku_info->revision) { 126 switch (sku_info->revision) {
127 case TEGRA_REVISION_A01: 127 case TEGRA_REVISION_A01:
diff --git a/drivers/soc/tegra/fuse/tegra-apbmisc.c b/drivers/soc/tegra/fuse/tegra-apbmisc.c
index 29d7714515b7..5b18f6ffa45c 100644
--- a/drivers/soc/tegra/fuse/tegra-apbmisc.c
+++ b/drivers/soc/tegra/fuse/tegra-apbmisc.c
@@ -94,8 +94,8 @@ void __init tegra_init_revision(void)
94 rev = TEGRA_REVISION_A02; 94 rev = TEGRA_REVISION_A02;
95 break; 95 break;
96 case 3: 96 case 3:
97 if (chip_id == TEGRA20 && (tegra20_spare_fuse_early(18) || 97 if (chip_id == TEGRA20 && (tegra_fuse_read_spare(18) ||
98 tegra20_spare_fuse_early(19))) 98 tegra_fuse_read_spare(19)))
99 rev = TEGRA_REVISION_A03p; 99 rev = TEGRA_REVISION_A03p;
100 else 100 else
101 rev = TEGRA_REVISION_A03; 101 rev = TEGRA_REVISION_A03;
@@ -109,10 +109,7 @@ void __init tegra_init_revision(void)
109 109
110 tegra_sku_info.revision = rev; 110 tegra_sku_info.revision = rev;
111 111
112 if (chip_id == TEGRA20) 112 tegra_sku_info.sku_id = tegra_fuse_read_early(FUSE_SKU_INFO);
113 tegra_sku_info.sku_id = tegra20_fuse_early(FUSE_SKU_INFO);
114 else
115 tegra_sku_info.sku_id = tegra30_fuse_readl(FUSE_SKU_INFO);
116} 113}
117 114
118void __init tegra_init_apbmisc(void) 115void __init tegra_init_apbmisc(void)