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