tizen 2.4 release
[kernel/u-boot-tm1.git] / arch / arm / cpu / armv7 / sc8830 / adi.c
1 /*
2  * Copyright (C) 2012 Spreadtrum Communications Inc.
3  * Copyright (C) 2012 steve zhan
4  *
5  * This software is licensed under the terms of the GNU General Public
6  * License version 2, as published by the Free Software Foundation, and
7  * may be copied, distributed, and modified under those terms.
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 *For arm read ,delay about 1us when clk_adi runs at 76.8M
17 *The interface timing is compatible with spi timing
18 */
19
20 #include <common.h>
21 #include <asm/io.h>
22 #include <asm/errno.h>
23 #include <asm/arch/ldo.h>
24 #include <ubi_uboot.h>
25 #include <asm/sizes.h>
26 #include <asm/arch/sprd_reg.h>
27
28 #include <asm/arch/chip_drv_common_io.h>
29
30 #ifdef SPRD_MISC_BASE
31 #undef SPRD_MISC_BASE
32 #endif
33 #define SPRD_MISC_BASE SPRD_MISC_PHYS
34
35 /* registers definitions for controller CTL_ADI */
36 #define REG_ADI_CTRL0                                   (SPRD_MISC_BASE + 0x04)
37 #define REG_ADI_CHNL_PRI                                (SPRD_MISC_PHYS + 0x08)
38 #define REG_ADI_INT_RAW                                 (SPRD_MISC_PHYS + 0x10)
39 #define REG_ADI_RD_CMD                                  (SPRD_MISC_PHYS + 0x24)
40 #define REG_ADI_RD_DATA                                 (SPRD_MISC_PHYS + 0x28)
41 #define REG_ADI_FIFO_STS                                (SPRD_MISC_PHYS + 0x2c)
42
43 /* bits definitions for register REG_ADI_CTRL0 */
44 #define BIT_ARM_SCLK_EN                 ( BIT_1 )
45 #define BITS_CMMB_WR_PRI                        ( (1) << 4 & (BIT_4|BIT_5) )
46
47 /* bits definitions for register REG_ADI_CHNL_PRI */
48 #define BITS_PD_WR_PRI             ( (1) << 14 & (BIT_14|BIT_15) )
49 #define BITS_RFT_WR_PRI            ( (1) << 12 & (BIT_12|BIT_13) )
50 #define BITS_DSP_RD_PRI            ( (2) << 10 & (BIT_10|BIT_11) )
51 #define BITS_DSP_WR_PRI            ( (2) << 8 & (BIT_8|BIT_9) )
52 #define BITS_ARM_RD_PRI            ( (3) << 6 & (BIT_6|BIT_7) )
53 #define BITS_ARM_WR_PRI            ( (3) << 4 & (BIT_4|BIT_5) )
54 #define BITS_STC_WR_PRI            ( (1) << 2 & (BIT_2|BIT_3) )
55 #define BITS_INT_STEAL_PRI         ( (3) << 0 & (BIT_0|BIT_1) )
56
57 /* bits definitions for register REG_ADI_RD_DATA */
58 #define BIT_RD_CMD_BUSY                 ( BIT_31 )
59 #define SHIFT_RD_ADDR                   ( 16 )
60
61 #define SHIFT_RD_VALU                   ( 0 )
62 #define MASK_RD_VALU                    ( 0xFFFF )
63
64 /* bits definitions for register REG_ADI_FIFO_STS */
65 #define BIT_FIFO_FULL                   ( BIT_11 )
66 #define FIFO_IS_FULL()  (__raw_readl(REG_ADI_FIFO_STS) & BIT_FIFO_FULL)
67
68 #define BIT_FIFO_EMPTY                  ( BIT_10 )
69
70 /* special V1 (sc8830 soc) defined */
71 /* bits definitions for register REG_ADI_CTRL0 */
72 #define BIT_ADI_WR(_X_)                 ( (_X_) << 2 )
73 #define BITS_ADDR_BYTE_SEL(_X_)                 ( (_X_) << 0 & (BIT_0|BIT_1) )
74
75 /* bits definitions for register REG_ADI_CHNL_PRI */
76 #define VALUE_CH_PRI    (0x0)
77
78 #define REG_ADI_GSSI_CFG0                                       (SPRD_MISC_PHYS + 0x1C)
79 #define REG_ADI_GSSI_CFG1                                       (SPRD_MISC_PHYS + 0x20)
80
81 /* soc defined end*/
82
83 static u32 readback_addr_mak = 0;
84 static u8 is_ana_init = 0;
85
86 #if defined(CONFIG_NAND_SPL) || defined(CONFIG_FDL1)
87 #define panic(x...) do{}while(0)
88 #define printf(x...) do{}while(0)
89 #define udelay(x)       \
90         do { \
91                 volatile int i; \
92                 int cnt = 1000 * x; \
93                 for (i=0; i<cnt; i++);\
94         } while(0);
95 #endif
96
97 /*FIXME: Now define adi IP version, sc8825 is zero, sc8830 is one,
98 * Adi need init early that than read soc id, now using this ARCH dependency.
99 */
100 static inline int __adi_ver(void)
101 {
102 #ifdef  CONFIG_SC8825
103         return 0;
104 #else
105         return 1;
106 #endif
107 }
108
109 #define TO_ADDR(_x_)            ( ((_x_) >> SHIFT_RD_ADDR) & readback_addr_mak )
110
111 /*FIXME:If we have not hwspinlock , we need use spinlock to do it*/
112 static inline void __adi_lock(unsigned long *flags, unsigned long *hw_flags)
113 {
114         return;
115 }
116
117 static inline void __adi_unlock(unsigned long *flags, unsigned long *hw_flags)
118 {
119         return;
120 }
121
122 static inline int __adi_fifo_drain(void)
123 {
124         int cnt = 1000;
125         while (!(__raw_readl(REG_ADI_FIFO_STS) & BIT_FIFO_EMPTY) && cnt--) {
126                 udelay(1);
127         }
128         if(cnt < 0) {
129                 while(1) {
130                         printf("[0x%s]: ADI READ timeout!!! \n", __func__);
131                         udelay(1000000);
132                 }
133         }
134         return 0;
135 }
136
137 #define ANA_VIRT_BASE                   ( SPRD_MISC_BASE )
138 #define ANA_PHYS_BASE                   ( SPRD_MISC_PHYS )
139 #define ANA_ADDR_SIZE                   ( SZ_32K + SZ_4K )
140 #define ADDR_VERIFY(_X_)        do { \
141         BUG_ON((_X_) < ANA_VIRT_BASE || (_X_) > (ANA_VIRT_BASE + ANA_ADDR_SIZE));} while (0)
142
143 static inline u32 __adi_translate_addr(u32 regvddr)
144 {
145         regvddr = regvddr - ANA_VIRT_BASE + ANA_PHYS_BASE;
146         return regvddr;
147 }
148
149 static inline int __adi_read(u32 regPddr)
150 {
151         unsigned long val;
152         int cnt = 200000;
153
154         /*
155          * We don't wait write fifo empty in here,
156          * Because if normal write is SYNC, that will
157          * wait fifo empty at the end of the write.
158          */
159         __raw_writel(regPddr, REG_ADI_RD_CMD);
160
161         /*
162          * wait read operation complete, RD_data[31]
163          * is set simulaneously when writing read command.
164          * RD_data[31] will be cleared after the read operation complete, 
165          */
166         do {
167                 val = __raw_readl(REG_ADI_RD_DATA);
168         } while ((val & BIT_RD_CMD_BUSY) && cnt--);
169
170         if (cnt + 1 <= 0){
171                 while(1){
172                         printf("[0x%s]: ADI READ timeout!!! reg = 0x%x, value = 0x%x\n", __func__, regPddr, val);
173                         udelay(1000000);
174                 }
175         }
176         /* val high part should be the address of the last read operation */
177         BUG_ON(TO_ADDR(val) != (regPddr & readback_addr_mak));
178
179         return (val & MASK_RD_VALU);
180 }
181
182 int sci_adi_read(u32 reg)
183 {
184         unsigned long val;
185         unsigned long flags;
186         ADDR_VERIFY(reg);
187         reg = __adi_translate_addr(reg);
188         __adi_lock(&flags, NULL);
189         val = __adi_read(reg);
190         __adi_unlock(&flags, NULL);
191         return val;
192 }
193
194 /*This value have a bit of depending on  real hardware fifo size*/
195 #define CACHE_SIZE      (16)
196 static struct __data {
197         u32 reg;
198         u16 val;
199 } __data_array[CACHE_SIZE];
200 struct __data *head_p = &__data_array[0];
201 struct __data *tail_p = &__data_array[0];
202 static u32 data_in_cache = 0;
203 #define HEAD_ADD        (1)
204 #define TAIL_ADD        (0)
205 static inline void __p_add(struct __data **p, u32 isHead)
206 {
207         if (++(*p) > &__data_array[CACHE_SIZE - 1])
208                 (*p) = &__data_array[0];
209         if (head_p == tail_p) {
210                 if (isHead == HEAD_ADD) {
211                         data_in_cache = 0;
212                 } else {
213                         data_in_cache = CACHE_SIZE;
214                 }
215         } else {
216                 data_in_cache = 2;
217         }
218 }
219
220 static inline int __adi_write(u32 reg, u16 val, u32 sync)
221 {
222         tail_p->reg = reg;
223         tail_p->val = val;
224         __p_add(&tail_p, TAIL_ADD);
225         while (!FIFO_IS_FULL() && (data_in_cache != 0)) {
226                 __raw_writel(head_p->val, head_p->reg);
227                 __p_add(&head_p, HEAD_ADD);
228         }
229
230         if (sync || data_in_cache == CACHE_SIZE) {
231                 __adi_fifo_drain();
232                 while (data_in_cache != 0) {
233                         while (FIFO_IS_FULL()) {
234                                 //cpu_relax();
235                         }
236                         __raw_writel(head_p->val, head_p->reg);
237                         __p_add(&head_p, HEAD_ADD);
238                 }
239                 __adi_fifo_drain();
240         }
241
242         return 0;
243 }
244
245 int sci_adi_write_fast(u32 reg, u16 val, u32 sync)
246 {
247         unsigned long flags;
248         ADDR_VERIFY(reg);
249         __adi_lock(&flags, NULL);
250         __adi_write(reg, val, sync);
251         __adi_unlock(&flags, NULL);
252         return 0;
253 }
254
255 int sci_adi_write(u32 reg, u16 or_val, u16 clear_msk)
256 {
257         unsigned long flags;
258
259         ADDR_VERIFY(reg);
260         __adi_lock(&flags, NULL);
261         __adi_write(reg,
262                     (__adi_read(__adi_translate_addr(reg)) &
263                      ~clear_msk) | or_val, 1);
264         __adi_unlock(&flags, NULL);
265         return 0;
266 }
267
268 static void __adi_init(void)
269 {
270         uint32_t value;
271         value = __raw_readl(REG_ADI_CTRL0);
272
273         if (__adi_ver() == 0) {
274                 value &= ~BIT_ARM_SCLK_EN;
275                 value |= BITS_CMMB_WR_PRI;
276                 __raw_writel(value, REG_ADI_CTRL0);
277
278                 value = __raw_readl(REG_ADI_CHNL_PRI);
279                 value |= BITS_PD_WR_PRI | BITS_RFT_WR_PRI |
280                     BITS_DSP_RD_PRI | BITS_DSP_WR_PRI |
281                     BITS_ARM_RD_PRI | BITS_ARM_WR_PRI |
282                     BITS_STC_WR_PRI | BITS_INT_STEAL_PRI;
283                 __raw_writel(value, REG_ADI_CHNL_PRI);
284
285                 readback_addr_mak = 0x7ff;
286         } else if (__adi_ver() == 1) {
287                 if (value) {
288                         WARN_ON(1);
289                 }
290                 value = VALUE_CH_PRI;
291                 __raw_writel(value, REG_ADI_CHNL_PRI);
292
293                 value = __raw_readl(REG_ADI_GSSI_CFG0);
294                 readback_addr_mak = (value & 0x3f) - ((value >> 11) & 0x1f) - 1;
295         }
296 }
297
298 void sci_adi_init(void)
299 {
300         if(!is_ana_init) {
301                 /* enable adi in global regs */
302                 CHIP_REG_OR(REG_AON_APB_APB_EB0, BIT_ADI_EB);
303                 /* reset adi */
304                 CHIP_REG_OR(REG_AON_APB_APB_RST0, BIT_ADI_SOFT_RST);
305                 udelay(2);
306                 CHIP_REG_AND(REG_AON_APB_APB_RST0, (~BIT_ADI_SOFT_RST));
307                 __adi_init();
308
309                 is_ana_init = 1;
310         }
311 }
312
313 /*
314  * sci_get_adie_chip_id - read a-die chip id
315  *
316  * return:
317  * the a-die chip id, example: 0x2711A000
318  */
319 u32 sci_get_adie_chip_id(void)
320 {
321         u32 chip_id;
322
323         if(!is_ana_init) {
324                 sci_adi_init();
325         }
326
327         chip_id = (sci_adi_read(ANA_REG_GLB_CHIP_ID_HIGH) & 0xffff) << 16;
328         chip_id |= sci_adi_read(ANA_REG_GLB_CHIP_ID_LOW) & 0xffff;
329
330         return chip_id;
331 }
332