2 * Copyright (C) 2013-2014 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>
11 #include <linux/rockchip/cpu.h>
12 #include <linux/rockchip/iomap.h>
14 #include <asm/system_info.h>
18 #define efuse_readl(offset) readl_relaxed(RK_EFUSE_VIRT + offset)
19 #define efuse_writel(val, offset) writel_relaxed(val, RK_EFUSE_VIRT + offset)
21 static u8 efuse_buf[32] = {};
23 struct rockchip_efuse {
24 int (*get_leakage)(int ch);
29 static struct rockchip_efuse efuse;
31 static int __init rk3288_efuse_readregs(u32 addr, u32 length, u8 *buf)
40 efuse_writel(EFUSE_CSB, REG_EFUSE_CTRL);
41 efuse_writel(EFUSE_LOAD | EFUSE_PGENB, REG_EFUSE_CTRL);
44 efuse_writel(efuse_readl(REG_EFUSE_CTRL) &
45 (~(EFUSE_A_MASK << EFUSE_A_SHIFT)), REG_EFUSE_CTRL);
46 efuse_writel(efuse_readl(REG_EFUSE_CTRL) |
47 ((addr & EFUSE_A_MASK) << EFUSE_A_SHIFT),
50 efuse_writel(efuse_readl(REG_EFUSE_CTRL) |
51 EFUSE_STROBE, REG_EFUSE_CTRL);
53 *buf = efuse_readl(REG_EFUSE_DOUT);
54 efuse_writel(efuse_readl(REG_EFUSE_CTRL) &
55 (~EFUSE_STROBE), REG_EFUSE_CTRL);
61 efuse_writel(efuse_readl(REG_EFUSE_CTRL) | EFUSE_CSB, REG_EFUSE_CTRL);
67 static int __init rk3288_get_efuse_version(void)
69 int ret = efuse_buf[4] & (~(0x1 << 3));
73 static int __init rk3288_get_process_version(void)
75 int ret = efuse_buf[6]&0x0f;
80 static int rk3288_get_leakage(int ch)
82 if ((ch < 0) || (ch > 2))
85 return efuse_buf[23+ch];
89 static void __init rk3288_set_system_serial(void)
94 for (i = 0; i < 8; i++) {
95 buf[i] = efuse_buf[8 + (i << 1)];
96 buf[i + 8] = efuse_buf[7 + (i << 1)];
99 system_serial_low = crc32(0, buf, 8);
100 system_serial_high = crc32(system_serial_low, buf + 8, 8);
103 static inline void __init rk3288_set_system_serial(void) {}
106 int rk312x_efuse_readregs(u32 addr, u32 length, u8 *buf)
113 efuse_writel(EFUSE_LOAD, REG_EFUSE_CTRL);
116 efuse_writel(efuse_readl(REG_EFUSE_CTRL) &
117 (~(EFUSE_A_MASK << RK312X_EFUSE_A_SHIFT)),
119 efuse_writel(efuse_readl(REG_EFUSE_CTRL) |
120 ((addr & EFUSE_A_MASK) << RK312X_EFUSE_A_SHIFT),
123 efuse_writel(efuse_readl(REG_EFUSE_CTRL) |
124 EFUSE_STROBE, REG_EFUSE_CTRL);
126 *buf = efuse_readl(REG_EFUSE_DOUT);
127 efuse_writel(efuse_readl(REG_EFUSE_CTRL) &
128 (~EFUSE_STROBE), REG_EFUSE_CTRL);
134 efuse_writel(efuse_readl(REG_EFUSE_CTRL) &
135 (~EFUSE_LOAD) , REG_EFUSE_CTRL);
141 int rockchip_efuse_version(void)
143 return efuse.efuse_version;
146 int rockchip_process_version(void)
148 return efuse.process_version;
151 int rockchip_get_leakage(int ch)
153 if (efuse.get_leakage)
154 return efuse.get_leakage(ch);
158 void __init rockchip_efuse_init(void)
162 if (cpu_is_rk3288()) {
163 ret = rk3288_efuse_readregs(0, 32, efuse_buf);
165 efuse.get_leakage = rk3288_get_leakage;
166 efuse.efuse_version = rk3288_get_efuse_version();
167 efuse.process_version = rk3288_get_process_version();
168 rockchip_set_cpu_version((efuse_buf[6] >> 4) & 3);
169 rk3288_set_system_serial();
171 pr_err("failed to read eFuse, return %d\n", ret);
173 } else if (cpu_is_rk312x()) {
174 ret = rk312x_efuse_readregs(0, 32, efuse_buf);
176 efuse.get_leakage = rk3288_get_leakage;
178 pr_err("failed to read eFuse, return %d\n", ret);