arm64: rockchip: check tf version later
[firefly-linux-kernel-4.4.55.git] / arch / arm / mach-rockchip / efuse.c
1 /*
2  * Copyright (C) 2013-2015 ROCKCHIP, Inc.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation.
7  */
8
9 #include <linux/crc32.h>
10 #include <linux/delay.h>
11 #include <linux/of.h>
12 #include <linux/platform_device.h>
13 #include <linux/rockchip/cpu.h>
14 #include <linux/rockchip/iomap.h>
15 #include <asm/compiler.h>
16 #include <asm/psci.h>
17 #include <asm/system_info.h>
18 #include "efuse.h"
19
20 #ifdef CONFIG_ARM
21 #define efuse_readl(offset) readl_relaxed(RK_EFUSE_VIRT + offset)
22 #define efuse_writel(val, offset) writel_relaxed(val, RK_EFUSE_VIRT + offset)
23 #endif
24
25 static u8 efuse_buf[32] = {};
26
27 struct rockchip_efuse {
28         int (*get_leakage)(int ch);
29         int (*get_temp)(int ch);
30         int efuse_version;
31         int process_version;
32 };
33
34 static struct rockchip_efuse efuse;
35
36 #ifdef CONFIG_ARM64
37 /****************************secure reg access****************************/
38
39 #define SEC_REG_RW_SHT (0x0)
40 #define SEC_REG_RD (0x0)
41 #define SEC_REG_WR (0x1)
42
43 #define SEC_REG_BITS_SHT (0x1)
44 #define SEC_REG_32 (0x0)
45 #define SEC_REG_64 (0x2)
46
47 #define SEC_REG_RD_32 (SEC_REG_RD | SEC_REG_32)
48 #define SEC_REG_RD_64 (SEC_REG_RD | SEC_REG_64)
49 #define SEC_REG_WR_32 (SEC_REG_WR | SEC_REG_32)
50 #define SEC_REG_WR_64 (SEC_REG_WR | SEC_REG_64)
51
52 #define PSCI_SIP_ACCESS_REG             (0x82000002)
53 #define PSCI_SIP_RKTF_VER               (0x82000001)
54
55 static phys_addr_t efuse_phys;
56
57 /*
58  * arg2: rd/wr control, bit[0] 0-rd 1-rt, bit[1] 0-32bit, 1-64bit
59  * arg1: base addr
60  * arg0: read or write val
61  * function_id: return fail/succes
62  */
63 static u32 reg_wr_fn_smc(u64 function_id, u64 arg0, u64 arg1, u64 arg2)
64 {
65         asm volatile(
66                         __asmeq("%0", "x0")
67                         __asmeq("%1", "x1")
68                         __asmeq("%2", "x2")
69                         __asmeq("%3", "x3")
70                         "smc    #0\n"
71                 : "+r" (function_id), "+r" (arg0)
72                 : "r" (arg1), "r" (arg2));
73
74         return function_id;
75 }
76
77 static u32 reg_rd_fn_smc(u64 function_id, u64 arg0, u64 arg1, u64 arg2,
78                          u64 *val)
79 {
80         asm volatile(
81                         __asmeq("%0", "x0")
82                         __asmeq("%1", "x1")
83                         __asmeq("%2", "x2")
84                         __asmeq("%3", "x3")
85                         "smc    #0\n"
86                 : "+r" (function_id), "+r" (arg0)
87                 : "r" (arg1), "r" (arg2));
88
89                 *val = arg0;
90
91         return function_id;
92 }
93
94 static u32 (*reg_wr_fn)(u64, u64, u64, u64) = reg_wr_fn_smc;
95 static u32 (*reg_rd_fn)(u64, u64, u64, u64, u64 *) = reg_rd_fn_smc;
96
97 static u32 secure_regs_rd_32(u64 addr_phy)
98 {
99         u64 val = 0;
100
101         reg_rd_fn(PSCI_SIP_ACCESS_REG, 0, addr_phy, SEC_REG_RD_32, &val);
102         return val;
103 }
104
105 static u32 secure_regs_wr_32(u64 addr_phy, u32 val)
106 {
107         u64 val_64 = val;
108
109         return reg_wr_fn(PSCI_SIP_ACCESS_REG, val_64, addr_phy, SEC_REG_WR_32);
110 }
111
112 static u32 efuse_readl(u32 offset)
113 {
114         return secure_regs_rd_32(efuse_phys + offset);
115 }
116
117 static void efuse_writel(u32 val, u32 offset)
118 {
119         secure_regs_wr_32(efuse_phys + offset, val);
120 }
121
122 #define RKTF_VER_MAJOR(ver) (((ver) >> 16) & 0xffff)
123 #define RKTF_VER_MINOR(ver) ((ver) & 0xffff)
124 /* valid ver */
125 #define RKTF_VLDVER_MAJOR (1)
126 #define RKTF_VLDVER_MINOR (3)
127
128
129 static int __init rockchip_tf_ver_check(void)
130 {
131         u64 val;
132         u32 ver_val;
133
134         ver_val = reg_rd_fn(PSCI_SIP_RKTF_VER, 0, 0, 0, &val);
135         if (ver_val == 0xffffffff)
136                 goto ver_error;
137
138         if ((RKTF_VER_MAJOR(ver_val) >= RKTF_VLDVER_MAJOR) &&
139                 (RKTF_VER_MINOR(ver_val) >= RKTF_VLDVER_MINOR))
140                 return 0;
141
142 ver_error:
143
144         pr_err("read tf version 0x%x!\n", ver_val);
145
146         do {
147                 mdelay(1000);
148                 pr_err("trusted firmware need to update to(%d.%d) or is invaild!\n",
149                         RKTF_VLDVER_MAJOR, RKTF_VLDVER_MINOR);
150         } while(1);
151
152         return 0;
153 }
154 device_initcall_sync(rockchip_tf_ver_check);
155 #endif
156
157 static int rk3288_efuse_readregs(u32 addr, u32 length, u8 *buf)
158 {
159         int ret = length;
160
161         if (!length)
162                 return 0;
163         if (!buf)
164                 return 0;
165
166         efuse_writel(EFUSE_CSB, REG_EFUSE_CTRL);
167         efuse_writel(EFUSE_LOAD | EFUSE_PGENB, REG_EFUSE_CTRL);
168         udelay(2);
169         do {
170                 efuse_writel(efuse_readl(REG_EFUSE_CTRL) &
171                         (~(EFUSE_A_MASK << EFUSE_A_SHIFT)), REG_EFUSE_CTRL);
172                 efuse_writel(efuse_readl(REG_EFUSE_CTRL) |
173                         ((addr & EFUSE_A_MASK) << EFUSE_A_SHIFT),
174                         REG_EFUSE_CTRL);
175                 udelay(2);
176                 efuse_writel(efuse_readl(REG_EFUSE_CTRL) |
177                                 EFUSE_STROBE, REG_EFUSE_CTRL);
178                 udelay(2);
179                 *buf = efuse_readl(REG_EFUSE_DOUT);
180                 efuse_writel(efuse_readl(REG_EFUSE_CTRL) &
181                                 (~EFUSE_STROBE), REG_EFUSE_CTRL);
182                 udelay(2);
183                 buf++;
184                 addr++;
185         } while (--length);
186         udelay(2);
187         efuse_writel(efuse_readl(REG_EFUSE_CTRL) | EFUSE_CSB, REG_EFUSE_CTRL);
188         udelay(1);
189
190         return ret;
191 }
192
193 static int __init rk3288_get_efuse_version(void)
194 {
195         int ret = efuse_buf[4] & (~(0x1 << 3));
196         return ret;
197 }
198
199 static int __init rk3288_get_process_version(void)
200 {
201         int ret = efuse_buf[6]&0x0f;
202
203         return ret;
204 }
205
206 static int rk3288_get_leakage(int ch)
207 {
208         if ((ch < 0) || (ch > 2))
209                 return 0;
210
211         return efuse_buf[23+ch];
212 }
213
214 #ifdef CONFIG_ARM
215 static void __init rk3288_set_system_serial(void)
216 {
217         int i;
218         u8 buf[16];
219
220         for (i = 0; i < 8; i++) {
221                 buf[i] = efuse_buf[8 + (i << 1)];
222                 buf[i + 8] = efuse_buf[7 + (i << 1)];
223         }
224
225         system_serial_low = crc32(0, buf, 8);
226         system_serial_high = crc32(system_serial_low, buf + 8, 8);
227 }
228 #else
229 static inline void __init rk3288_set_system_serial(void) {}
230 #endif
231
232 int rk312x_efuse_readregs(u32 addr, u32 length, u8 *buf)
233 {
234         int ret = length;
235
236         if (!length)
237                 return 0;
238
239         efuse_writel(EFUSE_LOAD, REG_EFUSE_CTRL);
240         udelay(2);
241         do {
242                 efuse_writel(efuse_readl(REG_EFUSE_CTRL) &
243                                 (~(EFUSE_A_MASK << RK312X_EFUSE_A_SHIFT)),
244                                 REG_EFUSE_CTRL);
245                 efuse_writel(efuse_readl(REG_EFUSE_CTRL) |
246                                 ((addr & EFUSE_A_MASK) << RK312X_EFUSE_A_SHIFT),
247                                 REG_EFUSE_CTRL);
248                 udelay(2);
249                 efuse_writel(efuse_readl(REG_EFUSE_CTRL) |
250                                 EFUSE_STROBE, REG_EFUSE_CTRL);
251                 udelay(2);
252                 *buf = efuse_readl(REG_EFUSE_DOUT);
253                 efuse_writel(efuse_readl(REG_EFUSE_CTRL) &
254                                 (~EFUSE_STROBE), REG_EFUSE_CTRL);
255                 udelay(2);
256                 buf++;
257                 addr++;
258         } while (--length);
259         udelay(2);
260         efuse_writel(efuse_readl(REG_EFUSE_CTRL) &
261                         (~EFUSE_LOAD) , REG_EFUSE_CTRL);
262         udelay(1);
263
264         return ret;
265 }
266
267 int rockchip_efuse_version(void)
268 {
269         return efuse.efuse_version;
270 }
271
272 int rockchip_process_version(void)
273 {
274         return efuse.process_version;
275 }
276
277 int rockchip_get_leakage(int ch)
278 {
279         int ret = 0;
280
281         if (efuse.get_leakage) {
282                 return efuse.get_leakage(ch);
283         } else {
284                 ret = rk3288_efuse_readregs(0, 32, efuse_buf);
285                 if (ret == 32)
286                         return efuse_buf[23+ch];
287         }
288         return 0;
289 }
290
291 int rockchip_efuse_get_temp_adjust(int ch)
292 {
293         int temp;
294
295         if (efuse_buf[31] & 0x80)
296                 temp = -(efuse_buf[31] & 0x7f);
297         else
298                 temp = efuse_buf[31];
299
300         return temp;
301 }
302
303 static void __init rk3288_efuse_init(void)
304 {
305         int ret;
306
307         ret = rk3288_efuse_readregs(0, 32, efuse_buf);
308         if (ret == 32) {
309                 efuse.get_leakage = rk3288_get_leakage;
310                 efuse.efuse_version = rk3288_get_efuse_version();
311                 efuse.process_version = rk3288_get_process_version();
312                 rockchip_set_cpu_version((efuse_buf[6] >> 4) & 3);
313                 rk3288_set_system_serial();
314         } else {
315                 pr_err("failed to read eFuse, return %d\n", ret);
316         }
317 }
318
319 void __init rockchip_efuse_init(void)
320 {
321         int ret;
322
323         if (cpu_is_rk3288()) {
324                 rk3288_efuse_init();
325         } else if (cpu_is_rk312x()) {
326                 ret = rk312x_efuse_readregs(0, 32, efuse_buf);
327                 if (ret == 32)
328                         efuse.get_leakage = rk3288_get_leakage;
329                 else
330                         pr_err("failed to read eFuse, return %d\n", ret);
331         }
332 }
333
334 #ifdef CONFIG_ARM64
335 static int __init rockchip_efuse_probe(struct platform_device *pdev)
336 {
337         struct resource *regs;
338
339         regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
340         if (!regs) {
341                 dev_err(&pdev->dev, "failed to get I/O memory\n");
342                 return -ENODEV;
343         }
344         efuse_phys = regs->start;
345
346         rk3288_efuse_init();
347         return 0;
348 }
349
350 static const struct of_device_id rockchip_efuse_of_match[] = {
351         { .compatible = "rockchip,rk3368-efuse-256", .data = NULL, },
352         {},
353 };
354
355 static struct platform_driver rockchip_efuse_driver = {
356         .driver         = {
357                 .name           = "efuse",
358                 .owner          = THIS_MODULE,
359                 .of_match_table = of_match_ptr(rockchip_efuse_of_match),
360         },
361 };
362
363 static int __init rockchip_efuse_module_init(void)
364 {
365         return platform_driver_probe(&rockchip_efuse_driver,
366                                      rockchip_efuse_probe);
367 }
368 arch_initcall_sync(rockchip_efuse_module_init);
369 #endif