arm: rockchip: efuse: fix compilation error on arm
[firefly-linux-kernel-4.4.55.git] / arch / arm / mach-rockchip / efuse.c
1 /*
2  * Copyright (C) 2013-2014 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/rockchip/cpu.h>
12 #include <linux/rockchip/iomap.h>
13 #include <asm/compiler.h>
14 #include <asm/psci.h>
15 #ifdef CONFIG_ARM
16 #include <asm/system_info.h>
17 #endif
18 #include "efuse.h"
19
20 #define efuse_readl(offset) readl_relaxed(RK_EFUSE_VIRT + offset)
21 #define efuse_writel(val, offset) writel_relaxed(val, RK_EFUSE_VIRT + offset)
22
23 static u8 efuse_buf[32] = {};
24
25 struct rockchip_efuse {
26         int (*get_leakage)(int ch);
27         int (*get_temp)(int ch);
28         int efuse_version;
29         int process_version;
30 };
31
32 static struct rockchip_efuse efuse;
33
34 #ifdef CONFIG_ARM64
35 /****************************secure reg access****************************/
36
37 #define SEC_REG_RW_SHT (0x0)
38 #define SEC_REG_RD (0x0)
39 #define SEC_REG_WR (0x1)
40
41 #define SEC_REG_BITS_SHT (0x1)
42 #define SEC_REG_32 (0x0)
43 #define SEC_REG_64 (0x2)
44
45 #define SEC_REG_RD_32 (SEC_REG_RD | SEC_REG_32)
46 #define SEC_REG_RD_64 (SEC_REG_RD | SEC_REG_64)
47 #define SEC_REG_WR_32 (SEC_REG_WR | SEC_REG_32)
48 #define SEC_REG_WR_64 (SEC_REG_WR | SEC_REG_64)
49
50 #define PSCI_OS_ACCESS_REG              (0xa600ffb0)
51 #define EFUSE_BASE        0xffb00000
52 /*
53  * arg2: rd/wr control, bit[0] 0-rd 1-rt, bit[1] 0-32bit, 1-64bit
54  * arg1: base addr
55  * arg0: read or write val
56  * function_id: return fail/succes
57  */
58 noinline int __invoke_reg_access_fn_hvc(u64 function_id, u64 arg0, u64 arg1, u64 arg2, u64 *val)
59 {
60         asm volatile(
61                         __asmeq("%0", "x0")
62                         __asmeq("%1", "x1")
63                         __asmeq("%2", "x2")
64                         __asmeq("%3", "x3")
65                         "hvc    #0\n"
66                 : "+r" (function_id), "+r" (arg0)
67                 : "r" (arg1), "r" (arg2));
68
69         if(!(arg2 & SEC_REG_WR))
70                 *val = arg0;
71
72         return function_id;
73 }
74
75 noinline int __invoke_reg_wr_fn_smc(u64 function_id, u64 arg0, u64 arg1, u64 arg2)
76 {
77         asm volatile(
78                         __asmeq("%0", "x0")
79                         __asmeq("%1", "x1")
80                         __asmeq("%2", "x2")
81                         __asmeq("%3", "x3")
82                         "smc    #0\n"
83                 : "+r" (function_id) ,"+r" (arg0)
84                 : "r" (arg1), "r" (arg2));
85
86         return function_id;
87 }
88
89 noinline int __invoke_reg_rd_fn_smc(u64 function_id, u64 arg0, u64 arg1,
90                                          u64 arg2, u64 *val)
91 {
92         asm volatile(
93                         __asmeq("%0", "x0")
94                         __asmeq("%1", "x1")
95                         __asmeq("%2", "x2")
96                         __asmeq("%3", "x3")
97                         "smc    #0\n"
98                 : "+r" (function_id) ,"+r" (arg0)
99                 : "r" (arg1), "r" (arg2));
100
101                 *val = arg0;
102
103         return function_id;
104 }
105
106 int (*invoke_regs_wr_fn)(u64, u64 , u64, u64) = __invoke_reg_wr_fn_smc;
107
108 int (*invoke_regs_rd_fn)(u64, u64 , u64, u64, u64 *) = __invoke_reg_rd_fn_smc;
109
110
111 int secure_regs_rd(u64 addr_phy)
112 {
113         u64 val_64;
114         u32 val;
115         int ret;
116         ret = invoke_regs_rd_fn(PSCI_OS_ACCESS_REG, 0, addr_phy, SEC_REG_RD_32, &val_64);
117         val = val_64;
118         return val;
119 }
120
121 int secure_regs_wr_32(u64 addr_phy, u32 val)
122 {
123         u64 val_64 = val;
124         return invoke_regs_wr_fn(PSCI_OS_ACCESS_REG, val_64, addr_phy, SEC_REG_WR_32);
125 }
126
127 static int rk3368_efuse_readregs(u32 addr, u32 length, u8 *buf)
128 {
129         int ret = length;
130                 if (!length)
131                 return 0;
132         if (!buf)
133                 return 0;
134
135         secure_regs_wr_32(EFUSE_BASE+REG_EFUSE_CTRL , EFUSE_CSB);
136         secure_regs_wr_32(EFUSE_BASE+REG_EFUSE_CTRL , EFUSE_LOAD | EFUSE_PGENB);
137         udelay(2);
138         do {
139                 secure_regs_wr_32(EFUSE_BASE+REG_EFUSE_CTRL ,
140                                 secure_regs_rd(EFUSE_BASE+REG_EFUSE_CTRL) &
141                                         (~(EFUSE_A_MASK << EFUSE_A_SHIFT)));
142                 secure_regs_wr_32(EFUSE_BASE+REG_EFUSE_CTRL,
143                                 secure_regs_rd(EFUSE_BASE+REG_EFUSE_CTRL) |
144                                                 ((addr & EFUSE_A_MASK) << EFUSE_A_SHIFT));
145                 udelay(2);
146                 secure_regs_wr_32(EFUSE_BASE+REG_EFUSE_CTRL ,
147                                 secure_regs_rd(EFUSE_BASE+REG_EFUSE_CTRL) | EFUSE_STROBE);
148                 udelay(2);
149                 *buf = secure_regs_rd(EFUSE_BASE+REG_EFUSE_DOUT);
150                 secure_regs_wr_32(EFUSE_BASE+REG_EFUSE_CTRL ,
151                                 secure_regs_rd(EFUSE_BASE+REG_EFUSE_CTRL) & (~EFUSE_STROBE));
152                 udelay(2);
153                 buf++;
154                 addr++;
155         } while (--length);
156         udelay(2);
157         secure_regs_wr_32(EFUSE_BASE+REG_EFUSE_CTRL ,
158                         secure_regs_rd(EFUSE_BASE+REG_EFUSE_CTRL) | EFUSE_CSB);
159         udelay(1);
160
161         return ret;
162 }
163 #else
164 static int rk3368_efuse_readregs(u32 addr, u32 length, u8 *buf)
165 {
166         return 0;
167 }
168 #endif
169
170 static int __init rk3288_efuse_readregs(u32 addr, u32 length, u8 *buf)
171 {
172         int ret = length;
173
174         if (!length)
175                 return 0;
176         if (!buf)
177                 return 0;
178
179         efuse_writel(EFUSE_CSB, REG_EFUSE_CTRL);
180         efuse_writel(EFUSE_LOAD | EFUSE_PGENB, REG_EFUSE_CTRL);
181         udelay(2);
182         do {
183                 efuse_writel(efuse_readl(REG_EFUSE_CTRL) &
184                         (~(EFUSE_A_MASK << EFUSE_A_SHIFT)), REG_EFUSE_CTRL);
185                 efuse_writel(efuse_readl(REG_EFUSE_CTRL) |
186                         ((addr & EFUSE_A_MASK) << EFUSE_A_SHIFT),
187                         REG_EFUSE_CTRL);
188                 udelay(2);
189                 efuse_writel(efuse_readl(REG_EFUSE_CTRL) |
190                                 EFUSE_STROBE, REG_EFUSE_CTRL);
191                 udelay(2);
192                 *buf = efuse_readl(REG_EFUSE_DOUT);
193                 efuse_writel(efuse_readl(REG_EFUSE_CTRL) &
194                                 (~EFUSE_STROBE), REG_EFUSE_CTRL);
195                 udelay(2);
196                 buf++;
197                 addr++;
198         } while (--length);
199         udelay(2);
200         efuse_writel(efuse_readl(REG_EFUSE_CTRL) | EFUSE_CSB, REG_EFUSE_CTRL);
201         udelay(1);
202
203         return ret;
204 }
205
206 static int __init rk3288_get_efuse_version(void)
207 {
208         int ret = efuse_buf[4] & (~(0x1 << 3));
209         return ret;
210 }
211
212 static int __init rk3288_get_process_version(void)
213 {
214         int ret = efuse_buf[6]&0x0f;
215
216         return ret;
217 }
218
219 static int rk3288_get_leakage(int ch)
220 {
221         if ((ch < 0) || (ch > 2))
222                 return 0;
223
224         return efuse_buf[23+ch];
225 }
226
227 #ifdef CONFIG_ARM
228 static void __init rk3288_set_system_serial(void)
229 {
230         int i;
231         u8 buf[16];
232
233         for (i = 0; i < 8; i++) {
234                 buf[i] = efuse_buf[8 + (i << 1)];
235                 buf[i + 8] = efuse_buf[7 + (i << 1)];
236         }
237
238         system_serial_low = crc32(0, buf, 8);
239         system_serial_high = crc32(system_serial_low, buf + 8, 8);
240 }
241 #else
242 static inline void __init rk3288_set_system_serial(void) {}
243 #endif
244
245 int rk312x_efuse_readregs(u32 addr, u32 length, u8 *buf)
246 {
247         int ret = length;
248
249         if (!length)
250                 return 0;
251
252         efuse_writel(EFUSE_LOAD, REG_EFUSE_CTRL);
253         udelay(2);
254         do {
255                 efuse_writel(efuse_readl(REG_EFUSE_CTRL) &
256                                 (~(EFUSE_A_MASK << RK312X_EFUSE_A_SHIFT)),
257                                 REG_EFUSE_CTRL);
258                 efuse_writel(efuse_readl(REG_EFUSE_CTRL) |
259                                 ((addr & EFUSE_A_MASK) << RK312X_EFUSE_A_SHIFT),
260                                 REG_EFUSE_CTRL);
261                 udelay(2);
262                 efuse_writel(efuse_readl(REG_EFUSE_CTRL) |
263                                 EFUSE_STROBE, REG_EFUSE_CTRL);
264                 udelay(2);
265                 *buf = efuse_readl(REG_EFUSE_DOUT);
266                 efuse_writel(efuse_readl(REG_EFUSE_CTRL) &
267                                 (~EFUSE_STROBE), REG_EFUSE_CTRL);
268                 udelay(2);
269                 buf++;
270                 addr++;
271         } while (--length);
272         udelay(2);
273         efuse_writel(efuse_readl(REG_EFUSE_CTRL) &
274                         (~EFUSE_LOAD) , REG_EFUSE_CTRL);
275         udelay(1);
276
277         return ret;
278 }
279
280 int rockchip_efuse_version(void)
281 {
282         return efuse.efuse_version;
283 }
284
285 int rockchip_process_version(void)
286 {
287         return efuse.process_version;
288 }
289
290 int rockchip_get_leakage(int ch)
291 {
292         int ret = 0;
293         if (efuse.get_leakage){
294                 return efuse.get_leakage(ch);
295         }else{
296                 ret = rk3368_efuse_readregs(0,32,efuse_buf);
297                 if (ret == 32){
298                         return efuse_buf[23+ch];
299                 }
300         }
301         return 0;
302 }
303 int rockchip_efuse_get_temp_adjust(int ch)
304 {
305         int ret = 0;
306         int temp = 0;
307         ret = rk3368_efuse_readregs(0,32,efuse_buf);
308         if (ret == 32){
309                 temp = efuse_buf[31+ch];
310                 if(efuse_buf[31+ch] & 0x80)
311                 {
312                         temp = -(efuse_buf[31+ch] & 0x7f);
313                 }
314                 return temp;
315         }
316         return 0;
317 }
318
319 void __init rockchip_efuse_init(void)
320 {
321         int ret;
322         if (cpu_is_rk3288()) {
323                 ret = rk3288_efuse_readregs(0, 32, efuse_buf);
324                 if (ret == 32) {
325                         efuse.get_leakage = rk3288_get_leakage;
326                         efuse.efuse_version = rk3288_get_efuse_version();
327                         efuse.process_version = rk3288_get_process_version();
328                         rockchip_set_cpu_version((efuse_buf[6] >> 4) & 3);
329                         rk3288_set_system_serial();
330                 } else {
331                         pr_err("failed to read eFuse, return %d\n", ret);
332                 }
333         } else if (cpu_is_rk312x()) {
334                 ret = rk312x_efuse_readregs(0, 32, efuse_buf);
335                 if (ret == 32)
336                         efuse.get_leakage = rk3288_get_leakage;
337                 else
338                         pr_err("failed to read eFuse, return %d\n", ret);
339         }
340 }