2 * Copyright (C) 2013-2015 ROCKCHIP, Inc.
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.
9 #include <linux/crc32.h>
10 #include <linux/delay.h>
12 #include <linux/platform_device.h>
13 #include <linux/rockchip/cpu.h>
14 #include <linux/rockchip/iomap.h>
15 #include <asm/compiler.h>
17 #include <asm/system_info.h>
21 #define efuse_readl(offset) readl_relaxed(RK_EFUSE_VIRT + offset)
22 #define efuse_writel(val, offset) writel_relaxed(val, RK_EFUSE_VIRT + offset)
25 static u8 efuse_buf[32] = {};
27 struct rockchip_efuse {
28 int (*get_leakage)(int ch);
29 int (*get_temp)(int ch);
34 static struct rockchip_efuse efuse;
37 /****************************secure reg access****************************/
39 #define SEC_REG_RW_SHT (0x0)
40 #define SEC_REG_RD (0x0)
41 #define SEC_REG_WR (0x1)
43 #define SEC_REG_BITS_SHT (0x1)
44 #define SEC_REG_32 (0x0)
45 #define SEC_REG_64 (0x2)
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)
52 #define PSCI_OS_ACCESS_REG (0xa600ffb0)
53 static phys_addr_t efuse_phys;
56 * arg2: rd/wr control, bit[0] 0-rd 1-rt, bit[1] 0-32bit, 1-64bit
58 * arg0: read or write val
59 * function_id: return fail/succes
61 static u32 reg_wr_fn_smc(u64 function_id, u64 arg0, u64 arg1, u64 arg2)
69 : "+r" (function_id), "+r" (arg0)
70 : "r" (arg1), "r" (arg2));
75 static u32 reg_rd_fn_smc(u64 function_id, u64 arg0, u64 arg1, u64 arg2,
84 : "+r" (function_id), "+r" (arg0)
85 : "r" (arg1), "r" (arg2));
92 static u32 (*reg_wr_fn)(u64, u64, u64, u64) = reg_wr_fn_smc;
93 static u32 (*reg_rd_fn)(u64, u64, u64, u64, u64 *) = reg_rd_fn_smc;
95 static u32 secure_regs_rd_32(u64 addr_phy)
99 reg_rd_fn(PSCI_OS_ACCESS_REG, 0, addr_phy, SEC_REG_RD_32, &val);
103 static u32 secure_regs_wr_32(u64 addr_phy, u32 val)
107 return reg_wr_fn(PSCI_OS_ACCESS_REG, val_64, addr_phy, SEC_REG_WR_32);
110 static u32 efuse_readl(u32 offset)
112 return secure_regs_rd_32(efuse_phys + offset);
115 static void efuse_writel(u32 val, u32 offset)
117 secure_regs_wr_32(efuse_phys + offset, val);
121 static int rk3288_efuse_readregs(u32 addr, u32 length, u8 *buf)
130 efuse_writel(EFUSE_CSB, REG_EFUSE_CTRL);
131 efuse_writel(EFUSE_LOAD | EFUSE_PGENB, REG_EFUSE_CTRL);
134 efuse_writel(efuse_readl(REG_EFUSE_CTRL) &
135 (~(EFUSE_A_MASK << EFUSE_A_SHIFT)), REG_EFUSE_CTRL);
136 efuse_writel(efuse_readl(REG_EFUSE_CTRL) |
137 ((addr & EFUSE_A_MASK) << EFUSE_A_SHIFT),
140 efuse_writel(efuse_readl(REG_EFUSE_CTRL) |
141 EFUSE_STROBE, REG_EFUSE_CTRL);
143 *buf = efuse_readl(REG_EFUSE_DOUT);
144 efuse_writel(efuse_readl(REG_EFUSE_CTRL) &
145 (~EFUSE_STROBE), REG_EFUSE_CTRL);
151 efuse_writel(efuse_readl(REG_EFUSE_CTRL) | EFUSE_CSB, REG_EFUSE_CTRL);
157 static int __init rk3288_get_efuse_version(void)
159 int ret = efuse_buf[4] & (~(0x1 << 3));
163 static int __init rk3288_get_process_version(void)
165 int ret = efuse_buf[6]&0x0f;
170 static int rk3288_get_leakage(int ch)
172 if ((ch < 0) || (ch > 2))
175 return efuse_buf[23+ch];
179 static void __init rk3288_set_system_serial(void)
184 for (i = 0; i < 8; i++) {
185 buf[i] = efuse_buf[8 + (i << 1)];
186 buf[i + 8] = efuse_buf[7 + (i << 1)];
189 system_serial_low = crc32(0, buf, 8);
190 system_serial_high = crc32(system_serial_low, buf + 8, 8);
193 static inline void __init rk3288_set_system_serial(void) {}
196 int rk312x_efuse_readregs(u32 addr, u32 length, u8 *buf)
203 efuse_writel(EFUSE_LOAD, REG_EFUSE_CTRL);
206 efuse_writel(efuse_readl(REG_EFUSE_CTRL) &
207 (~(EFUSE_A_MASK << RK312X_EFUSE_A_SHIFT)),
209 efuse_writel(efuse_readl(REG_EFUSE_CTRL) |
210 ((addr & EFUSE_A_MASK) << RK312X_EFUSE_A_SHIFT),
213 efuse_writel(efuse_readl(REG_EFUSE_CTRL) |
214 EFUSE_STROBE, REG_EFUSE_CTRL);
216 *buf = efuse_readl(REG_EFUSE_DOUT);
217 efuse_writel(efuse_readl(REG_EFUSE_CTRL) &
218 (~EFUSE_STROBE), REG_EFUSE_CTRL);
224 efuse_writel(efuse_readl(REG_EFUSE_CTRL) &
225 (~EFUSE_LOAD) , REG_EFUSE_CTRL);
231 int rockchip_efuse_version(void)
233 return efuse.efuse_version;
236 int rockchip_process_version(void)
238 return efuse.process_version;
241 int rockchip_get_leakage(int ch)
245 if (efuse.get_leakage) {
246 return efuse.get_leakage(ch);
248 ret = rk3288_efuse_readregs(0, 32, efuse_buf);
250 return efuse_buf[23+ch];
255 int rockchip_efuse_get_temp_adjust(int ch)
259 if (efuse_buf[31] & 0x80)
260 temp = -(efuse_buf[31] & 0x7f);
262 temp = efuse_buf[31];
267 static void __init rk3288_efuse_init(void)
271 ret = rk3288_efuse_readregs(0, 32, efuse_buf);
273 efuse.get_leakage = rk3288_get_leakage;
274 efuse.efuse_version = rk3288_get_efuse_version();
275 efuse.process_version = rk3288_get_process_version();
276 rockchip_set_cpu_version((efuse_buf[6] >> 4) & 3);
277 rk3288_set_system_serial();
279 pr_err("failed to read eFuse, return %d\n", ret);
283 void __init rockchip_efuse_init(void)
287 if (cpu_is_rk3288()) {
289 } else if (cpu_is_rk312x()) {
290 ret = rk312x_efuse_readregs(0, 32, efuse_buf);
292 efuse.get_leakage = rk3288_get_leakage;
294 pr_err("failed to read eFuse, return %d\n", ret);
299 static int __init rockchip_efuse_probe(struct platform_device *pdev)
301 struct resource *regs;
303 regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
305 dev_err(&pdev->dev, "failed to get I/O memory\n");
308 efuse_phys = regs->start;
315 static const struct of_device_id rockchip_efuse_of_match[] = {
316 { .compatible = "rockchip,rk3368-efuse-256", .data = NULL, },
320 static struct platform_driver rockchip_efuse_driver = {
323 .owner = THIS_MODULE,
324 .of_match_table = of_match_ptr(rockchip_efuse_of_match),
328 static int __init rockchip_efuse_module_init(void)
330 return platform_driver_probe(&rockchip_efuse_driver,
331 rockchip_efuse_probe);
333 arch_initcall_sync(rockchip_efuse_module_init);