3374440cda190d7a55207ff95744425f6a4ab563
[profile/mobile/platform/kernel/u-boot-tm1.git] / arch / arm / cpu / armv7 / sc9630 / 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 (sc9630 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 #if defined(CONFIG_FPGA)
125         return 0;
126 #else
127         int cnt = 1000;
128         while (!(__raw_readl(REG_ADI_FIFO_STS) & BIT_FIFO_EMPTY) && cnt--) {
129                 udelay(1);
130         }
131         if(cnt < 0) {
132                 while(1) {
133                         printf("[0x%s]: ADI READ timeout!!! \n", __func__);
134                         udelay(1000000);
135                 }
136         }
137         return 0;
138 #endif  /* CONFIG_FPGA */
139 }
140
141 #define ANA_VIRT_BASE                   ( SPRD_MISC_BASE )
142 #define ANA_PHYS_BASE                   ( SPRD_MISC_PHYS )
143 #define ANA_ADDR_SIZE                   ( SZ_32K + SZ_4K )
144 #define ADDR_VERIFY(_X_)
145
146 static inline u32 __adi_translate_addr(u32 regvddr)
147 {
148         regvddr = regvddr - ANA_VIRT_BASE + ANA_PHYS_BASE;
149         return regvddr;
150 }
151
152 static inline int __adi_read(u32 regPddr)
153 {
154         unsigned long val;
155         int cnt = 200000;
156 #if defined(CONFIG_FPGA)
157         return 0;
158 #else
159         /*
160          * We don't wait write fifo empty in here,
161          * Because if normal write is SYNC, that will
162          * wait fifo empty at the end of the write.
163          */
164         __raw_writel(regPddr, REG_ADI_RD_CMD);
165
166         /*
167          * wait read operation complete, RD_data[31]
168          * is set simulaneously when writing read command.
169          * RD_data[31] will be cleared after the read operation complete, 
170          */
171         do {
172                 val = __raw_readl(REG_ADI_RD_DATA);
173         } while ((val & BIT_RD_CMD_BUSY) && cnt--);
174
175         if (cnt + 1 <= 0){
176                 while(1){
177                         printf("[0x%s]: ADI READ timeout!!! reg = 0x%x, value = 0x%x\n", __func__, regPddr, val);
178                         udelay(1000000);
179                 }
180         }
181         /* val high part should be the address of the last read operation */
182         BUG_ON(TO_ADDR(val) != (regPddr & readback_addr_mak));
183
184         return (val & MASK_RD_VALU);
185 #endif  /* CONFIG_FPGA */
186 }
187
188 int sci_adi_read(u32 reg)
189 {
190         unsigned long val;
191         unsigned long flags;
192 #if defined(CONFIG_FPGA)
193         return 0;
194 #else
195         ADDR_VERIFY(reg);
196         reg = __adi_translate_addr(reg);
197         __adi_lock(&flags, NULL);
198         val = __adi_read(reg);
199         __adi_unlock(&flags, NULL);
200         return val;
201 #endif  /* CONFIG_FPGA */
202 }
203
204 /*This value have a bit of depending on  real hardware fifo size*/
205 #define CACHE_SIZE      (16)
206 static struct __data {
207         u32 reg;
208         u16 val;
209 } __data_array[CACHE_SIZE];
210 struct __data *head_p = &__data_array[0];
211 struct __data *tail_p = &__data_array[0];
212 static u32 data_in_cache = 0;
213 #define HEAD_ADD        (1)
214 #define TAIL_ADD        (0)
215 static inline void __p_add(struct __data **p, u32 isHead)
216 {
217         if (++(*p) > &__data_array[CACHE_SIZE - 1])
218                 (*p) = &__data_array[0];
219         if (head_p == tail_p) {
220                 if (isHead == HEAD_ADD) {
221                         data_in_cache = 0;
222                 } else {
223                         data_in_cache = CACHE_SIZE;
224                 }
225         } else {
226                 data_in_cache = 2;
227         }
228 }
229
230 static inline int __adi_write(u32 reg, u16 val, u32 sync)
231 {
232 #if defined(CONFIG_FPGA)
233         return 0;
234 #else
235         tail_p->reg = reg;
236         tail_p->val = val;
237         __p_add(&tail_p, TAIL_ADD);
238         while (!FIFO_IS_FULL() && (data_in_cache != 0)) {
239                 __raw_writel(head_p->val, head_p->reg);
240                 __p_add(&head_p, HEAD_ADD);
241         }
242
243         if (sync || data_in_cache == CACHE_SIZE) {
244                 __adi_fifo_drain();
245                 while (data_in_cache != 0) {
246                         while (FIFO_IS_FULL()) {
247                                 //cpu_relax();
248                         }
249                         __raw_writel(head_p->val, head_p->reg);
250                         __p_add(&head_p, HEAD_ADD);
251                 }
252                 __adi_fifo_drain();
253         }
254
255         return 0;
256 #endif  /* CONFIG_FPGA */
257 }
258
259 int sci_adi_write_fast(u32 reg, u16 val, u32 sync)
260 {
261 #if defined(CONFIG_FPGA)
262         return 0;
263 #else
264         unsigned long flags;
265         ADDR_VERIFY(reg);
266         __adi_lock(&flags, NULL);
267         __adi_write(reg, val, sync);
268         __adi_unlock(&flags, NULL);
269         return 0;
270 #endif  /* CONFIG_FPGA */
271 }
272
273 int sci_adi_write(u32 reg, u16 or_val, u16 clear_msk)
274 {
275         unsigned long flags;
276 #if defined(CONFIG_FPGA)
277         return 0;       
278 #else
279         ADDR_VERIFY(reg);
280         __adi_lock(&flags, NULL);
281         __adi_write(reg,
282                     (__adi_read(__adi_translate_addr(reg)) &
283                      ~clear_msk) | or_val, 1);
284         __adi_unlock(&flags, NULL);
285         return 0;
286 #endif  /* CONFIG_FPGA */
287 }
288
289 static void __adi_init(void)
290 {
291 #if defined(CONFIG_FPGA)
292         return;
293 #else
294         uint32_t value;
295         value = __raw_readl(REG_ADI_CTRL0);
296
297         if (__adi_ver() == 0) {
298                 value &= ~BIT_ARM_SCLK_EN;
299                 value |= BITS_CMMB_WR_PRI;
300                 __raw_writel(value, REG_ADI_CTRL0);
301
302                 value = __raw_readl(REG_ADI_CHNL_PRI);
303                 value |= BITS_PD_WR_PRI | BITS_RFT_WR_PRI |
304                     BITS_DSP_RD_PRI | BITS_DSP_WR_PRI |
305                     BITS_ARM_RD_PRI | BITS_ARM_WR_PRI |
306                     BITS_STC_WR_PRI | BITS_INT_STEAL_PRI;
307                 __raw_writel(value, REG_ADI_CHNL_PRI);
308
309                 readback_addr_mak = 0x7ff;
310         } else if (__adi_ver() == 1) {
311                 if (value) {
312                         WARN_ON(1);
313                 }
314                 value = VALUE_CH_PRI;
315                 __raw_writel(value, REG_ADI_CHNL_PRI);
316
317                 value = __raw_readl(REG_ADI_GSSI_CFG0);
318                 readback_addr_mak = (value & 0x3f) - ((value >> 11) & 0x1f) - 1;
319         }
320 #endif  /* CONFIG_FPGA */
321 }
322
323 void sci_adi_init(void)
324 {
325 #if defined(CONFIG_FPGA)
326         return;
327 #else
328         if(!is_ana_init) {
329                 /* enable adi in global regs */
330                 CHIP_REG_OR(REG_AON_APB_APB_EB0, BIT_ADI_EB);
331                 /* reset adi */
332                 CHIP_REG_OR(REG_AON_APB_APB_RST0, BIT_ADI_SOFT_RST);
333                 udelay(2);
334                 CHIP_REG_AND(REG_AON_APB_APB_RST0, (~BIT_ADI_SOFT_RST));
335                 __adi_init();
336
337                 is_ana_init = 1;
338         }
339 #endif  /* CONFIG_FPGA */
340 }
341
342 /*
343  * sci_get_adie_chip_id - read a-die chip id
344  *
345  * return:
346  * the a-die chip id, example: 0x2711A000
347  */
348 u32 sci_get_adie_chip_id(void)
349 {
350 #if defined(CONFIG_FPGA)
351         return 0;
352 #else
353         u32 chip_id;
354
355         if(!is_ana_init) {
356                 sci_adi_init();
357         }
358
359         chip_id = (sci_adi_read(ANA_REG_GLB_CHIP_ID_HIGH) & 0xffff) << 16;
360         chip_id |= sci_adi_read(ANA_REG_GLB_CHIP_ID_LOW) & 0xffff;
361         return chip_id;
362 #endif  /* CONFIG_FPGA */
363 }
364