tizen 2.4 release
[profile/mobile/platform/kernel/u-boot-tm1.git] / arch / arm / cpu / armv7 / sc8830 / efuse.c
1 /*
2  * Copyright (C) 2014 Spreadtrum Communications Inc.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  */
15
16 /* IMPORTANT:
17  * The electrical fuse is a type of non-volatile memory fabricated
18  * in standard CMOS logic process. This electrical fuse macro is widely
19  * used in chip ID, memory redundancy, security code, configuration setting,
20  * and feature selection, etc.
21  *
22  * This efuse controller is designed for 32*32 bits electrical fuses,
23  * support TSMC HPM 28nm product of "TEF28HPM32X32HD18_PHRM".
24  *
25  * and we default use double-bit, 512bits efuse are visiable for software.
26  *
27  * efuse driver ONLY support module ip version since from r3p0
28  * which had integrated into scx30g and scx35l etc.
29  *
30  * TODO:
31  * 1. do something when block had been locked with bit31 if need
32  * 1. check and clear blk prog/err flag if need
33  * 1. wait *300ms* for read/prog ready time-out
34  * 1. only mutexlock and hwspinlock for efuse access sync with cp
35  * 1. be care not do use efuse API in interrupt function
36  * 1. no need soft reset after efuse read/prog and power on/off
37  * 1. efuse block width should less than 8bits
38  * 1. efuse block count should not bigger than 32! or not should expland the cached otp arrary
39  * 1. support efuse DT info (version, blocks, ...) later
40  * 1. there is no handle for efuse module removed
41  */
42
43 #include <common.h>
44 #include <linux/types.h>
45 #include <linux/err.h>
46 #include <asm/io.h>
47 //#include <asm/arch/hardware.h>
48 #include <asm/arch/sprd_reg.h>
49 #include <asm/arch/sci.h>
50 #include <asm/arch/__regs_efuse.h>
51 #define EFUSE_MAGIC 0x8810
52
53 #define pr_debug(args...)  printf(args)
54 #define pr_info() printf
55
56 #define WARN_ON(a)
57 u32 SCI_GetTickCount(void);
58 #define jiffies (SCI_GetTickCount()) /* return msec count */
59 #define msecs_to_jiffies(a) (a)
60 #define time_after(a,b) ((int)(b) - (int)(a) < 0)
61 #define cpu_relax()
62
63 static void msleep(u32 ms)
64 {
65         u32 timeout = jiffies + ms;
66         while(!time_after(jiffies, timeout)) {
67                 ;
68         }
69 }
70
71 #define REGS_EFUSE_BASE                 SPRD_UIDEFUSE_PHYS
72
73 #define EFUSE_BLOCK_MAX                 ( 16 )
74 #define EFUSE_BLOCK_WIDTH               ( 32 )  /* bit counts */
75
76 void efuse_lookat(void)
77 {
78         volatile u32 *reg = (volatile u32 *)REGS_EFUSE_BASE;
79         int cnt = 16;
80         while(cnt--) {
81                 printf("[%p] = %08x\n", reg, *reg);
82                 reg++;
83         }
84         printf("\n");
85 }
86
87 static void efuse_lock(void)
88 {
89 }
90
91 static void efuse_unlock(void)
92 {
93 }
94
95 static void efuse_reset(void)
96 {
97         /* should enable module before soft reset efuse */
98         WARN_ON(!sci_glb_read(REG_AON_APB_APB_EB0, BIT_EFUSE_EB));
99         sci_glb_set(REG_AON_APB_APB_RST0, BIT_EFUSE_SOFT_RST);
100         udelay(5);
101         sci_glb_clr(REG_AON_APB_APB_RST0, BIT_EFUSE_SOFT_RST);
102 }
103
104 /* FIXME: Set EFS_VDD_ON will open 0.9v static power supply for efuse memory,
105  * before any operation towards to efuse memory this bit have to set to 1.
106  * Once this bit is cleared, the efuse will go to power down mode.
107  *
108  * each time when EFS_VDD_ON changes, software should wait at least 1ms to let
109  * VDD become stable.
110  *
111  * For VDDQ(1.8v) power, to prevent the overshot of VDDQ, a extra power switch
112  * connected to ground are controlled by "EFS_VDDQ_K2_ON"
113  */
114 void __efuse_power_on(void)
115 {
116         u32 cfg0;
117         sci_glb_set(REG_AON_APB_APB_EB0, BIT_EFUSE_EB);
118         efuse_reset();
119         cfg0 = __raw_readl((void *)REG_EFUSE_CFG0);
120         cfg0 &= ~BIT_EFS_VDDQ_K1_ON;
121         cfg0 |= BIT_EFS_VDD_ON | BIT_EFS_VDDQ_K2_ON;
122         __raw_writel(cfg0, (void *)REG_EFUSE_CFG0);
123         msleep(1);
124 }
125
126 void __efuse_power_off(void)
127 {
128         u32 cfg0 = __raw_readl((void *)REG_EFUSE_CFG0);
129         if (cfg0 & BIT_EFS_VDDQ_K1_ON) {
130                 cfg0 &= ~BIT_EFS_VDDQ_K1_ON;
131                 __raw_writel(cfg0, (void *)REG_EFUSE_CFG0);
132                 msleep(1);
133         }
134
135         cfg0 |= BIT_EFS_VDDQ_K2_ON;
136         cfg0 &= ~BIT_EFS_VDD_ON;
137         __raw_writel(cfg0, (void *)REG_EFUSE_CFG0);
138         msleep(1);
139
140         sci_glb_clr(REG_AON_APB_APB_EB0, BIT_EFUSE_EB);
141 }
142
143 static __inline int __efuse_wait_clear(u32 bits)
144 {
145         int ret = 0;
146         unsigned long timeout;
147
148         pr_debug("wait %x\n", __raw_readl((void *)REG_EFUSE_STATUS));
149
150         /* wait for maximum of 300 msec */
151         timeout = jiffies + msecs_to_jiffies(300);
152         while (__raw_readl((void *)REG_EFUSE_STATUS) & bits) {
153                 if (time_after(jiffies, timeout)) {
154                         WARN_ON(1);
155                         ret = -ETIMEDOUT;
156                         break;
157                 }
158                 cpu_relax();
159         }
160         return ret;
161 }
162
163 static u32 __efuse_read(int blk)
164 {
165         u32 val = 0;
166
167         /* enable efuse module clk and power before */
168
169         __raw_writel(BITS_READ_WRITE_INDEX(blk),
170                      (void *)REG_EFUSE_READ_WRITE_INDEX);
171         __raw_writel(BIT_RD_START, (void *)REG_EFUSE_MODE_CTRL);
172
173         if (IS_ERR_VALUE(__efuse_wait_clear(BIT_READ_BUSY)))
174                 goto out;
175
176         val = __raw_readl((void *)REG_EFUSE_DATA_RD);
177
178 out:
179         return val;
180 }
181
182 static u32 efuse_read(int blk_index)
183 {
184         u32 val;
185         pr_debug("efuse read %d\n", blk_index);
186         efuse_lock();
187
188         __efuse_power_on();
189         val = __efuse_read(blk_index);
190         __efuse_power_off();
191
192         efuse_unlock();
193         return val;
194 }
195
196 u32 __ddie_efuse_read(int blk_index)
197 {
198         return efuse_read(blk_index);
199 }
200 //EXPORT_SYMBOL_GPL(__ddie_efuse_read);
201
202
203 void __efuse_prog_power_on(void)
204 {
205         u32 cfg0;
206         sci_glb_set(REG_AON_APB_APB_EB0, BIT_EFUSE_EB);
207         cfg0 = __raw_readl((void *)REG_EFUSE_CFG0);
208         cfg0 &= ~(BIT_EFS_VDDQ_K2_ON | BIT_EFS_VDDQ_K1_ON);
209         cfg0 |= BIT_EFS_VDD_ON;
210         __raw_writel(cfg0, (void *)REG_EFUSE_CFG0);
211         msleep(1);
212
213         cfg0 |= BIT_EFS_VDDQ_K1_ON;
214         __raw_writel(cfg0, (void *)REG_EFUSE_CFG0);
215         msleep(1);
216 }
217
218
219 static int __efuse_prog(int blk, u32 val)
220 {
221         u32 cfg0 = __raw_readl((void *)REG_EFUSE_CFG0);
222
223
224         if (blk < 0 || blk >= EFUSE_BLOCK_MAX)  /* debug purpose */
225                 goto out;
226
227         /* enable pgm mode and setup magic number before programming */
228         cfg0 |= BIT_PGM_EN;
229         __raw_writel(cfg0, (void *)REG_EFUSE_CFG0);
230         __raw_writel(BITS_MAGIC_NUMBER(EFUSE_MAGIC),
231                      (void *)REG_EFUSE_MAGIC_NUMBER);
232
233         __raw_writel(val, (void *)REG_EFUSE_DATA_WR);
234         __raw_writel(BITS_READ_WRITE_INDEX(blk),
235                      (void *)REG_EFUSE_READ_WRITE_INDEX);
236         pr_debug("cfg0 %x\n", __raw_readl((void *)REG_EFUSE_CFG0));
237         __raw_writel(BIT_PG_START, (void *)REG_EFUSE_MODE_CTRL);
238         if (IS_ERR_VALUE(__efuse_wait_clear(BIT_PGM_BUSY)))
239                 goto out;
240
241 out:
242         __raw_writel(0, (void *)REG_EFUSE_MAGIC_NUMBER);
243         cfg0 &= ~BIT_PGM_EN;
244         __raw_writel(cfg0, (void *)REG_EFUSE_CFG0);
245         return 0;
246 }
247
248
249 static int efuse_prog(int blk_index, u32 val)
250 {
251         int ret;
252         pr_debug("efuse prog %d %08x\n", blk_index, val);
253
254         efuse_lock();
255
256         /* enable vddon && vddq */
257         __efuse_prog_power_on();
258         ret = __efuse_prog(blk_index, val);
259         __efuse_power_off();
260
261         efuse_unlock();
262         return ret;
263 }
264
265
266 int __ddie_efuse_prog(int blk_index, u32 val)
267 {
268         return efuse_prog(blk_index, val);
269 }
270 //20141016 add end
271 void __ddie_efuse_block_dump(void)
272 {
273         int idx;
274         printf("ddie efuse base %08x\n", REGS_EFUSE_BASE);
275         printf("ddie efuse blocks dump:\n");
276         for (idx = 0; idx < EFUSE_BLOCK_MAX; idx++) {
277                 printf("[%02d] %08x\n", idx, __ddie_efuse_read(idx));
278         }
279 }