tizen 2.4 release
[profile/mobile/platform/kernel/u-boot-tm1.git] / arch / arm / cpu / armv7 / sc9630 / ana_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  *
18  * TODO:
19  */
20 #include <common.h>
21 #include <linux/types.h>
22 #include <linux/err.h>
23 #include <asm/io.h>
24 //#include <asm/arch/hardware.h>
25 #include <asm/arch/sprd_reg.h>
26 #include <asm/arch/sci.h>
27 #include <asm/arch/adi.h>
28 #include <asm/arch/__regs_efuse.h>
29 #include <asm/arch/__regs_ana_efuse.h>
30
31 #define pr_debug(args...)  printf(args)
32
33 #define WARN_ON(a)
34 u32 SCI_GetTickCount(void);
35 #define jiffies (SCI_GetTickCount())    /* return msec count */
36 #define msecs_to_jiffies(a) (a)
37 #define time_after(a,b) ((int)(b) - (int)(a) < 0)
38 #define cpu_relax()
39
40 #define SPRD_ADISLAVE_BASE (SPRD_ADI_PHYS + 0x8000)
41
42 #define ANA_REGS_EFUSE_BASE             ( SPRD_ADISLAVE_BASE + 0x200 )
43
44 #define EFUSE_BLOCK_MAX                 ( 32 )
45 #define EFUSE_BLOCK_WIDTH               ( 8 )   /* bit counts */
46
47 static u8 dummy_cached_otp[EFUSE_BLOCK_MAX] = {
48         0x9f, 0xdf, 0xef, 0x37, 0x91, 0x27, 0xfc, 0xfd,
49         0x7f, 0x7f, 0x7f, 0x7f, 0xff, 0xfe, 0x7d, 0xbf,
50         0x7f, 0xff, 0x6c, 0x00, 0xe7, 0x71, 0x5f, 0xb7,
51         0x81, 0x5b, 0xe7, 0x3c, 0xa1, 0x27, 0x8a, 0xa1,
52 };
53
54 void adie_efuse_workaround(void)
55 {
56 #define REG_ADI_GSSI_CFG0                                       (SPRD_ADI_PHYS + 0x1C)
57 /** BIT_RF_GSSI_SCK_ALL_IN
58    * 0: sclk auto gate
59    * 1: sclk always on
60 */
61 #define BIT_RF_GSSI_SCK_ALL_IN          BIT(30)
62         sci_glb_write(REG_ADI_GSSI_CFG0,
63                       BIT_RF_GSSI_SCK_ALL_IN, BIT_RF_GSSI_SCK_ALL_IN);
64 }
65
66 void adie_efuse_lookat(void)
67 {
68         volatile u32 *reg = (volatile u32 *)ANA_REGS_EFUSE_BASE;
69         int cnt = 16;
70         while (cnt--) {
71                 printf("[%p] = %08x\n", reg, sci_adi_read((u32) reg));
72                 reg++;
73         }
74         printf("\n");
75 }
76
77 static void adie_efuse_lock(void)
78 {
79 }
80
81 static void adie_efuse_unlock(void)
82 {
83 }
84
85 static void adie_efuse_reset(void)
86 {
87 }
88
89 static void __adie_efuse_power_on(void)
90 {
91         sci_adi_set(ANA_REG_GLB_ARM_MODULE_EN, BIT_ANA_EFS_EN);
92         /* FIXME: rtc_efs only for prog
93            sci_adi_set(ANA_REG_GLB_RTC_CLK_EN, BIT_RTC_EFS_EN);
94          */
95
96         /* FIXME: sclk always on or not ? */
97         /* adie_efuse_workaround(); */
98 }
99
100 static void __adie_efuse_power_off(void)
101 {
102         /* FIXME: rtc_efs only for prog
103            sci_adi_clr(ANA_REG_GLB_RTC_CLK_EN, BIT_RTC_EFS_EN);
104          */
105         sci_adi_clr(ANA_REG_GLB_ARM_MODULE_EN, BIT_ANA_EFS_EN);
106 }
107
108 static __inline int __adie_efuse_wait_clear(u32 bits)
109 {
110         int ret = 0;
111         unsigned long timeout;
112
113         pr_debug("wait %x\n", sci_adi_read(ANA_REG_EFUSE_STATUS));
114
115         /* wait for maximum of 3000 msec */
116         timeout = jiffies + msecs_to_jiffies(3000);
117         while (sci_adi_read(ANA_REG_EFUSE_STATUS) & bits) {
118                 if (time_after(jiffies, timeout)) {
119                         WARN_ON(1);
120                         ret = -ETIMEDOUT;
121                         break;
122                 }
123                 cpu_relax();
124         }
125         return ret;
126 }
127
128 static u32 adie_efuse_read(int blk_index)
129 {
130         u32 val = 0;
131
132         pr_debug("adie efuse read %d\n", blk_index);
133         adie_efuse_lock();
134         __adie_efuse_power_on();
135         /* enable adie_efuse module clk and power before */
136
137         /* adie_efuse_lookat(); */
138
139         /* FIXME: set read timing, why 0x20 (default value)
140            sci_adi_raw_write(ANA_REG_EFUSE_RD_TIMING_CTRL,
141            BITS_EFUSE_RD_TIMING(0x20));
142          */
143
144         sci_adi_raw_write(ANA_REG_EFUSE_BLOCK_INDEX,
145                           BITS_READ_WRITE_INDEX(blk_index));
146         sci_adi_raw_write(ANA_REG_EFUSE_MODE_CTRL, BIT_RD_START);
147
148         if (IS_ERR_VALUE(__adie_efuse_wait_clear(BIT_READ_BUSY)))
149                 goto out;
150
151         val = sci_adi_read(ANA_REG_EFUSE_DATA_RD);
152
153         /* FIXME: reverse the otp value */
154         val = BITS_EFUSE_DATA_RD(~val);
155
156 out:
157         __adie_efuse_power_off();
158         adie_efuse_unlock();
159         return val;
160 }
161
162 u32 __adie_efuse_read(int blk_index)
163 {
164         return adie_efuse_read(blk_index);
165 }
166
167 //EXPORT_SYMBOL_GPL(__adie_efuse_read);
168
169 u32 __adie_efuse_read_bits(int bit_index, int length)
170 {
171         int i, blk_index = (int)bit_index / EFUSE_BLOCK_WIDTH;
172         int blk_max = DIV_ROUND_UP(bit_index + length, EFUSE_BLOCK_WIDTH);
173         u32 val = 0;
174         pr_debug("otp read blk %d - %d\n", blk_index, blk_max);
175         /* FIXME: length should not bigger than 8 */
176         for (i = blk_index; i < blk_max; i++) {
177                 val |= __adie_efuse_read(i)
178                     << ((i - blk_index) * EFUSE_BLOCK_WIDTH);
179         }
180         //pr_debug("val=%08x\n", val);
181         val >>= (bit_index & (EFUSE_BLOCK_WIDTH - 1));
182         val &= BIT(length) - 1;
183         pr_debug("otp read bits %d ++ %d 0x%08x\n\n", bit_index, length, val);
184         return val;
185 }
186
187 void __adie_efuse_block_dump(void)
188 {
189         int i, idx;
190         printf("adie efuse blocks dump:\n");
191         printf("--  7 6 5 4 3 2 1 0");
192         for (idx = 0; idx < EFUSE_BLOCK_MAX; idx++) {
193                 u32 val = 0;
194                 printf("\n");
195                 val = __adie_efuse_read(idx);
196                 dummy_cached_otp[idx] = (u8) val;
197                 printf("%02d  ", idx);
198                 for (i = EFUSE_BLOCK_WIDTH - 1; i >= 0; --i)
199                         printf("%s ", (val & BIT(i)) ? "1" : "0");
200                 printf("\n");
201         }
202         printf("\n");
203 }