tizen 2.4 release
[profile/mobile/platform/kernel/u-boot-tm1.git] / arch / arm / cpu / armv7 / sc9630 / efuse_drv.c
1 /*
2  * Copyright (C) 2012 Spreadtrum Communications Inc.
3  *
4  * This software is licensed under the terms of the GNU General Public
5  * License version 2, as published by the Free Software Foundation, and
6  * may be copied, distributed, and modified under those terms.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * GNU General Public License for more details.
12  */
13 #include <common.h>
14 #include <asm/io.h>
15 #include <asm/arch/sprd_reg.h>
16 #include <asm/arch/adi.h>
17 #include "asm/arch/efuse_drv.h"
18
19 #ifndef REG32
20 #define REG32(x)                                                        (*((volatile uint32 *)(x)))
21 #endif
22
23 static inline void efuse_udelay(unsigned long usec)
24 {
25         unsigned long i;
26         for (i = 0; i < (usec << 1); i++);
27 }
28
29 //static void __iomem *ctl_efuse_base = 0;
30 void sci_efuse_poweron(void)
31 {
32         uint32 i = 0;
33         /* enable efuse clock */
34         REG32(REG_AON_APB_APB_EB0)  |= BIT_EFUSE_EB;
35
36         // efuse reset
37         REG32(REG_AON_APB_APB_RST0) |=  BIT_EFUSE_SOFT_RST;
38         for(i = 0; i < 100; i++);
39         REG32(REG_AON_APB_APB_RST0) &= ~BIT_EFUSE_SOFT_RST;
40
41         /* power on effuse */
42         REG32(EFUSE_PGM_PARA) |= BIT_EFS_VDD_ON;
43         REG32(EFUSE_PGM_PARA) |= BIT_CLK_EFS_EN;
44 }
45
46 void sci_efuse_poweroff(void)
47 {
48         REG32(EFUSE_PGM_PARA) &= ~BIT_CLK_EFS_EN;
49         REG32(EFUSE_PGM_PARA) &= ~BIT_EFS_VDD_ON;
50         REG32(REG_AON_APB_APB_EB0)  &= ~BIT_EFUSE_EB;
51 }
52
53 int sci_efuse_read(unsigned blk)
54 {
55         int busy = 0;
56
57         if (blk > (MASK_READ_INDEX >> SHIFT_READ_INDEX))
58         {
59                 return 0;
60         }
61
62         REG32(EFUSE_BLOCK_INDEX) = BITS_READ_INDEX(blk);
63         REG32(EFUSE_MODE_CTRL) |= BIT_RD_START;
64
65         do
66         {
67                 busy = REG32(EFUSE_STATUS) & BIT_READ_BUSY;
68         } while (busy);
69
70         return REG32(EFUSE_DATA_RD);
71 }
72
73 #ifdef EFUSE_DEBUG
74 #define EFUSE_MAGIC_VAL                         0x8810
75 int sci_efuse_program(unsigned blk, int data)
76 {
77         int busy = 0;
78
79         if (blk > (MASK_PGM_INDEX >> SHIFT_PGM_INDEX))
80         {
81                 return 0;
82         }
83
84         REG32(EFUSE_BLOCK_INDEX) = BITS_PGM_INDEX(blk);
85         REG32(EFUSE_DATA_WR) = data;
86         REG32(EFUSE_MODE_CTRL) |= BIT_PG_START;
87
88         do
89         {
90                 busy = REG32(EFUSE_STATUS) & BIT_PGM_BUSY;
91         } while(busy);
92
93         return 1;
94 }
95
96 /* low level */
97 int sci_efuse_raw_write(unsigned blk, int data, u32 magic)
98 {
99         int retVal;
100
101         REG32(REG_AON_APB_PWR_CTRL) |= BIT_EFUSE0_PWR_ON;
102         REG32(REG_AON_APB_PWR_CTRL) |= BIT_EFUSE1_PWR_ON;
103
104         REG32(EFUSE_PGM_PARA) |= BIT_PGM_EN;
105         REG32(EFUSE_MAGIC_NUMBER) = BITS_MAGIC_NUMBER(magic);
106
107         delay(10000);
108
109         retVal = sci_efuse_program(blk, data);
110         REG32(EFUSE_PGM_PARA) &= ~BIT_PGM_EN;
111
112         return retVal;
113 }
114 #else
115 int sci_efuse_program(unsigned blk, int data)
116 {
117         return 0;
118 }
119
120 int sci_efuse_raw_write(unsigned blk, int data, u32 magic)
121 {
122         return 0;
123 }
124 #endif
125
126 #define CAL_DATA_BLK                                    7
127 #define BASE_ADC_P0                                             711                     /* 3.6V */
128 #define BASE_ADC_P1                                             830                     /* 4.2V */
129 #define VOL_P0                                                  3600
130 #define VOL_P1                                                  4200
131 #define ADC_DATA_OFFSET                                 128
132 /* they were stored in afuse of shark*/
133 int sci_efuse_calibration_get(unsigned int * p_cal_data)
134 {
135         int timeout;
136         unsigned int data;
137         unsigned short adc_temp;
138 #if defined(CONFIG_SPX15)||defined(CONFIG_ARCH_SCX35L)
139         sci_efuse_poweron();
140         data = sci_efuse_read(CAL_DATA_BLK);
141         sci_efuse_poweroff();
142
143 #else
144         /* wait for maximum of 100 msec */
145         sci_adi_raw_write(ANA_REG_GLB_AFUSE_CTRL, BIT_AFUSE_READ_REQ);
146         efuse_udelay(1);
147         timeout = 1000;
148         while(BIT_AFUSE_READ_REQ & sci_adi_read(ANA_REG_GLB_AFUSE_CTRL)) {
149                 if(timeout <= 0){
150                         break;
151                 }
152                 efuse_udelay(500);
153                 timeout--;
154         }
155
156         if (timeout <= 0)
157         {
158                 return 0;
159         }
160
161         data = sci_adi_read(ANA_REG_GLB_AFUSE_OUT0);
162         data |= (sci_adi_read(ANA_REG_GLB_AFUSE_OUT1)) << 16;
163 #endif
164
165         if (data == 0)
166         {
167                 return 0;
168         }
169
170         printf("afuse: data = 0x%x\n\r",data);
171         /* adc 3.6V  */
172         adc_temp = ((data & 0xFF00) >> 8) + BASE_ADC_P0 - ADC_DATA_OFFSET;
173         p_cal_data[1] = (VOL_P0) | ((adc_temp << 2) << 16);
174
175         /* adc 4.2V */
176         adc_temp = (data & 0xFF) + BASE_ADC_P1 - ADC_DATA_OFFSET;
177         p_cal_data[0] = (VOL_P1)|((adc_temp << 2) << 16);
178         return 1;
179 }
180