Merge branch 'develop-3.10' of ssh://10.10.10.29/rk/kernel into develop-3.10
[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/delay.h>
10 #include <linux/rockchip/cpu.h>
11 #include <linux/rockchip/iomap.h>
12 #include "efuse.h"
13
14 #define efuse_readl(offset) readl_relaxed(RK_EFUSE_VIRT + offset)
15 #define efuse_writel(val, offset) writel_relaxed(val, RK_EFUSE_VIRT + offset)
16
17 static u8 efuse_buf[32] = {};
18
19 struct rockchip_efuse {
20         int (*get_leakage)(int ch);
21         int efuse_version;
22 };
23
24 static struct rockchip_efuse efuse;
25
26 static int __init rk3288_efuse_readregs(u32 addr, u32 length, u8 *buf)
27 {
28         int ret = length;
29
30         if (!length)
31                 return 0;
32         if (!buf)
33                 return 0;
34
35         efuse_writel(EFUSE_CSB, REG_EFUSE_CTRL);
36         efuse_writel(EFUSE_LOAD | EFUSE_PGENB, REG_EFUSE_CTRL);
37         udelay(2);
38         do {
39                 efuse_writel(efuse_readl(REG_EFUSE_CTRL) &
40                         (~(EFUSE_A_MASK << EFUSE_A_SHIFT)), REG_EFUSE_CTRL);
41                 efuse_writel(efuse_readl(REG_EFUSE_CTRL) |
42                         ((addr & EFUSE_A_MASK) << EFUSE_A_SHIFT),
43                         REG_EFUSE_CTRL);
44                 udelay(2);
45                 efuse_writel(efuse_readl(REG_EFUSE_CTRL) |
46                                 EFUSE_STROBE, REG_EFUSE_CTRL);
47                 udelay(2);
48                 *buf = efuse_readl(REG_EFUSE_DOUT);
49                 efuse_writel(efuse_readl(REG_EFUSE_CTRL) &
50                                 (~EFUSE_STROBE), REG_EFUSE_CTRL);
51                 udelay(2);
52                 buf++;
53                 addr++;
54         } while (--length);
55         udelay(2);
56         efuse_writel(efuse_readl(REG_EFUSE_CTRL) | EFUSE_CSB, REG_EFUSE_CTRL);
57         udelay(1);
58
59         return ret;
60 }
61
62 static int __init rk3288_get_efuse_version(void)
63 {
64         int ret = efuse_buf[4] & (~(0x1 << 3));
65         return ret;
66 }
67
68 static int rk3288_get_leakage(int ch)
69 {
70         if ((ch < 0) || (ch > 2))
71                 return 0;
72
73         return efuse_buf[23+ch];
74 }
75
76 int rockchip_efuse_version(void)
77 {
78         return efuse.efuse_version;
79 }
80
81 int rockchip_get_leakage(int ch)
82 {
83         if (efuse.get_leakage)
84                 return efuse.get_leakage(ch);
85         return 0;
86 }
87
88 void __init rockchip_efuse_init(void)
89 {
90         int ret;
91
92         if (cpu_is_rk3288()) {
93                 ret = rk3288_efuse_readregs(0, 32, efuse_buf);
94                 if (ret == 32) {
95                         efuse.get_leakage = rk3288_get_leakage;
96                         efuse.efuse_version = rk3288_get_efuse_version();
97                         rockchip_set_cpu_version((efuse_buf[6] >> 4) & 3);
98                 } else {
99                         pr_err("failed to read eFuse, return %d\n", ret);
100                 }
101         }
102 }