ocf: update to version 20120127
[15.05/openwrt.git] / target / linux / generic / files / crypto / ocf / kirkwood / mvHal / mv_hal / twsi / mvTwsiEeprom.S
1 /*******************************************************************************
2 Copyright (C) Marvell International Ltd. and its affiliates
3
4 This software file (the "File") is owned and distributed by Marvell 
5 International Ltd. and/or its affiliates ("Marvell") under the following
6 alternative licensing terms.  Once you have made an election to distribute the
7 File under one of the following license alternatives, please (i) delete this
8 introductory statement regarding license alternatives, (ii) delete the two
9 license alternatives that you have not elected to use and (iii) preserve the
10 Marvell copyright notice above.
11
12 ********************************************************************************
13 Marvell Commercial License Option
14
15 If you received this File from Marvell and you have entered into a commercial
16 license agreement (a "Commercial License") with Marvell, the File is licensed
17 to you under the terms of the applicable Commercial License.
18
19 ********************************************************************************
20 Marvell GPL License Option
21
22 If you received this File from Marvell, you may opt to use, redistribute and/or 
23 modify this File in accordance with the terms and conditions of the General 
24 Public License Version 2, June 1991 (the "GPL License"), a copy of which is 
25 available along with the File in the license.txt file or by writing to the Free 
26 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 
27 on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 
28
29 THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 
30 WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 
31 DISCLAIMED.  The GPL License provides additional details about this warranty 
32 disclaimer.
33 ********************************************************************************
34 Marvell BSD License Option
35
36 If you received this File from Marvell, you may opt to use, redistribute and/or 
37 modify this File under the following licensing terms. 
38 Redistribution and use in source and binary forms, with or without modification, 
39 are permitted provided that the following conditions are met:
40
41     *   Redistributions of source code must retain the above copyright notice,
42             this list of conditions and the following disclaimer. 
43
44     *   Redistributions in binary form must reproduce the above copyright
45         notice, this list of conditions and the following disclaimer in the
46         documentation and/or other materials provided with the distribution. 
47
48     *   Neither the name of Marvell nor the names of its contributors may be 
49         used to endorse or promote products derived from this software without 
50         specific prior written permission. 
51     
52 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
53 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
54 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
55 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 
56 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
57 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
58 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
59 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
60 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
61 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
62
63 *******************************************************************************/
64
65
66 /* includes */
67 #define MV_ASMLANGUAGE
68 #include "ctrlEnv/mvCtrlEnvSpec.h"
69 #include "boardEnv/mvBoardEnvSpec.h"
70 #include "mvOsAsm.h"
71 #include "mvTwsiSpec.h"
72 #include "mvSysHwConfig.h"
73 #include "ctrlEnv/sys/mvCpuIfRegs.h"
74 #include "mvCommon.h"
75
76 #define I2C_CH MV_BOARD_DIMM_I2C_CHANNEL
77
78 /* defines */
79 /* defines  */
80
81
82         .data
83         .global _i2cInit
84         .global _i2cRead
85
86         .text
87
88 /*******************************************************************************
89 * _i2cInit - Initialize TWSI interface
90 *
91 * DESCRIPTION:
92 *       The function performs TWSI interface initialization. It resets the 
93 *       TWSI state machine and initialize its clock to 100KHz assuming Tclock
94 *       of 133MHz.
95 *
96 * INPUT:
97 *       None.
98 *
99 * OUTPUT:
100 *       None.
101 *
102 * RETURN:
103 *       None.
104 *
105 *******************************************************************************/
106 _i2cInit:        
107         mov     r9, LR     /* Save link register */
108         mov     r0, #0     /* Make sure r0 is zero */        
109         
110         /* Reset the i2c Mechanism first */
111         MV_REG_WRITE_ASM (r0, r1, TWSI_SOFT_RESET_REG(I2C_CH))
112
113         bl      _twsiDelay        
114         bl      _twsiDelay              
115
116         /* Initializing the I2C mechanism. Assuming Tclock frequency          */
117         /* of 166MHz. The I2C frequency in that case will be 100KHz.          */
118         /* For this settings, M = 9 and N = 3. Set the baud-rate with the     */
119         /* value of 0x2b (freq of ==> 100KHz                                  */
120         /* see spec for more details about the calculation of this value)     */
121         mov     r6, #(9 << 3 | 3)
122         MV_REG_WRITE_ASM (r6, r1, TWSI_STATUS_BAUDE_RATE_REG(I2C_CH))
123         
124         /* Enable the I2C master */
125         /* Enable TWSI interrupt in main mask reg */
126         mov     r6, #0xC4
127         MV_REG_WRITE_ASM (r6, r1, TWSI_CONTROL_REG(I2C_CH))
128         
129         /* Let the slow TWSI machine get used to the idea that it is enabled  */
130         bl      _twsiDelay
131         
132         
133         mov     PC, r9         /* r9 is saved link register */
134
135 /*******************************************************************************
136 * _twsiDelay - Perform delay.
137 *
138 * DESCRIPTION:
139 *       The function performs a delay to enable TWSI logic to stable.
140 *
141 * INPUT:
142 *       None.
143 *
144 * OUTPUT:
145 *       None.
146 *
147 * RETURN:
148 *       None.
149 *
150 *******************************************************************************/
151 _twsiDelay:
152         mov     r10, #0x100000 /*was 0x400*/ 
153     
154 _twsiDelayLoop:
155         subs    r10, r10, #1
156         bne     _twsiDelayLoop
157         
158         mov     PC, LR
159
160 /*******************************************************************************
161 * _i2cRead - Read byte from I2C EEPROM device.
162 *
163 * DESCRIPTION:
164 *       The function returns a byte from I2C EEPROM device. 
165 *       The EEPROM device is 7-bit address type. 
166 *
167 * INPUT:
168 *       r4 has the DIMM0 base address with shift 1 bit to the left
169 *       r7 has the EEPROM offset
170 *
171 * OUTPUT:
172 *       None.
173 *
174 * RETURN:
175 *       r4 returns '0' if address can not be read.
176 *       r7 has byte value in case read is successful.
177 *
178 *******************************************************************************/
179 _i2cRead:
180         mov     r9, LR     /* Save link register */
181        
182         /* Transmit the device address and desired offset within the EEPROM. */
183         
184         /* Generate Start Bit */
185         MV_REG_READ_ASM (r6, r1, TWSI_CONTROL_REG(I2C_CH))
186         orr     r6, r6, #TWSI_CONTROL_START_BIT
187         MV_REG_WRITE_ASM (r6, r1, TWSI_CONTROL_REG(I2C_CH))
188
189         /* Wait for the interrupt flag (bit3) to be set  */
190         mov     r10, #0x50000        
191 loop_1:
192         subs    r10, r10, #1
193         beq     loop_1_timeout
194 #ifdef MV78XX0
195         MV_REG_READ_ASM (r6, r1, CPU_INT_LOW_REG(I2C_CH))
196         tst     r6, #BIT2
197 #else
198         MV_REG_READ_ASM (r6, r1, CPU_MAIN_INT_CAUSE_REG) 
199         tst     r6, #BIT5
200 #endif
201         beq     loop_1
202             
203 loop_1_timeout:        
204             
205         /* Wait for the start bit to be reset by HW */
206         mov     r10, #0x50000 
207 loop_2:
208         subs    r10, r10, #1
209         beq     loop_2_timeout
210         MV_REG_READ_ASM (r6, r1, TWSI_CONTROL_REG(I2C_CH))
211         tst     r6, #TWSI_CONTROL_START_BIT
212         bne     loop_2
213            
214 loop_2_timeout:
215
216         /* Wait for the status TWSI_START_CONDITION_TRA = 0x8 */
217         mov     r10, #0x50000
218 loop_3:
219         subs    r10, r10, #1
220         beq     loop_3_timeout
221         MV_REG_READ_ASM (r6, r1, TWSI_STATUS_BAUDE_RATE_REG(I2C_CH))
222         cmp     r6, #0x08
223         bne     loop_3
224         
225 loop_3_timeout:
226         
227         /* writing the address of (DIMM0/1 << 1) with write indication */
228         mov     r6, r4, LSL #1 /* Write operation address bit 0 must be 0 */
229         MV_REG_WRITE_ASM (r6, r1, TWSI_DATA_REG(I2C_CH))
230         
231         bl      _twsiDelay
232         /* Clear the interrupt flag */
233         MV_REG_READ_ASM (r6, r1, TWSI_CONTROL_REG(I2C_CH))
234         bic     r6, r6, #TWSI_CONTROL_INT_FLAG_SET
235         MV_REG_WRITE_ASM (r6, r1, TWSI_CONTROL_REG(I2C_CH))
236         bl      _twsiDelay
237         
238         /* Waiting for the interrupt flag to be set which means that the
239            address has been transmitted                                  */
240 loop_4:
241 #ifdef MV78XX0
242         MV_REG_READ_ASM (r6, r1, CPU_INT_LOW_REG(I2C_CH))
243         tst     r6, #BIT2
244 #else
245         MV_REG_READ_ASM (r6, r1, CPU_MAIN_INT_CAUSE_REG)
246         tst     r6, #BIT5
247 #endif
248         beq     loop_4       /* if tst = 0, then the bit is not set yet */
249         
250         /* Wait for status TWSI_ADDR_PLUS_WRITE_BIT_TRA_ACK_REC = 0x18 */
251         mov     r10, #0x50000         /* Set r10 to 0x50000 =~ 328,000 */
252
253 loop_5:
254         subs    r10, r10, #1          /* timeout count down         */
255         bne     testStatus
256         mov     r4, #0                /* r4 = 0 -> operation failed */  
257         b       exit_i2cRead          /* Exit if timeout (No DIMM)  */
258
259 testStatus:    
260         MV_REG_READ_ASM (r6, r1, TWSI_STATUS_BAUDE_RATE_REG(I2C_CH))
261         cmp     r6, #0x18
262         bne     loop_5
263                 
264
265         /* check if the offset is bigger than 256 byte*/
266         tst     r7, #0x80000000
267         bne     great_than_256
268                         
269         /* Write the offset to be read from the DIMM EEPROM */
270         MV_REG_WRITE_ASM (r7, r1, TWSI_DATA_REG(I2C_CH))
271         
272         b after_offset
273         
274 great_than_256:
275         mov     r10, r7, LSR #8
276         and     r10, r10, #0xff
277         /* Write the offset0 to be read from the  EEPROM */
278         MV_REG_WRITE_ASM (r10, r1, TWSI_DATA_REG(I2C_CH))
279         
280         /* Clear the interrupt flag ==> signaling that the address can now
281            be transmited                                                    */
282         
283         bl      _twsiDelay
284         MV_REG_READ_ASM (r6, r1, TWSI_CONTROL_REG(I2C_CH))
285         bic     r6, r6, #TWSI_CONTROL_INT_FLAG_SET
286         MV_REG_WRITE_ASM (r6, r1, TWSI_CONTROL_REG(I2C_CH))
287         bl      _twsiDelay
288     
289         /* Wait for the interrupt to be set again ==> address has transmited */
290 loop_6_1:
291 #ifdef MV78XX0
292         MV_REG_READ_ASM (r6, r1, CPU_INT_LOW_REG(I2C_CH))
293         tst     r6, #BIT2
294 #else
295         MV_REG_READ_ASM (r6, r1, CPU_MAIN_INT_CAUSE_REG)
296         tst     r6, #BIT5
297 #endif
298         beq     loop_6_1
299         
300         /* Wait for status TWSI_MAS_TRAN_DATA_BYTE_ACK_REC = 0x28 */
301 loop_7_1:
302         MV_REG_READ_ASM (r6, r1, TWSI_STATUS_BAUDE_RATE_REG(I2C_CH))
303         cmp     r6, #0x28
304         bne     loop_7_1
305         
306         
307         mov     r10, r7
308         and     r10, r10, #0xff
309         /* Write the offset1 to be read from the  EEPROM */
310         MV_REG_WRITE_ASM (r10, r1, TWSI_DATA_REG(I2C_CH))
311         
312         
313         
314 after_offset:                
315         
316         /* Clear the interrupt flag ==> signaling that the address can now
317            be transmited                                                    */
318         
319         bl      _twsiDelay
320         MV_REG_READ_ASM (r6, r1, TWSI_CONTROL_REG(I2C_CH))
321         bic     r6, r6, #TWSI_CONTROL_INT_FLAG_SET
322         MV_REG_WRITE_ASM (r6, r1, TWSI_CONTROL_REG(I2C_CH))
323         bl      _twsiDelay
324     
325         /* Wait for the interrupt to be set again ==> address has transmited */
326 loop_6:
327 #ifdef MV78XX0
328         MV_REG_READ_ASM (r6, r1, CPU_INT_LOW_REG(I2C_CH))
329         tst     r6, #BIT2
330 #else
331         MV_REG_READ_ASM (r6, r1, CPU_MAIN_INT_CAUSE_REG)
332         tst     r6, #BIT5
333 #endif
334         beq     loop_6
335         
336         /* Wait for status TWSI_MAS_TRAN_DATA_BYTE_ACK_REC = 0x28 */
337 loop_7:
338         MV_REG_READ_ASM (r6, r1, TWSI_STATUS_BAUDE_RATE_REG(I2C_CH))
339         cmp     r6, #0x28
340         bne     loop_7
341         
342         /* Retransmit the device address with read indication to get the data */
343         
344         /* generate a repeated start bit */
345         MV_REG_READ_ASM (r6, r1, TWSI_CONTROL_REG(I2C_CH))
346         orr     r6, r6, #TWSI_CONTROL_START_BIT
347         MV_REG_WRITE_ASM (r6, r1, TWSI_CONTROL_REG(I2C_CH))
348
349         
350         /* Clear the interrupt flag ==> the start bit will be transmitted. */ 
351         bl      _twsiDelay
352         MV_REG_READ_ASM (r6, r1, TWSI_CONTROL_REG(I2C_CH))
353         bic     r6, r6, #TWSI_CONTROL_INT_FLAG_SET
354         MV_REG_WRITE_ASM (r6, r1, TWSI_CONTROL_REG(I2C_CH))
355         bl      _twsiDelay
356         
357        /* Wait for the interrupt flag (bit3) to be set */
358 loop_9:
359 #ifdef MV78XX0
360         MV_REG_READ_ASM (r6, r1, CPU_INT_LOW_REG(I2C_CH))
361         tst     r6, #BIT2
362 #else
363         MV_REG_READ_ASM (r6, r1, CPU_MAIN_INT_CAUSE_REG)
364         tst     r6, #BIT5
365 #endif
366         beq     loop_9
367
368         /* Wait for the start bit to be reset by HW */
369 loop_8:
370         MV_REG_READ_ASM (r6, r1, TWSI_CONTROL_REG(I2C_CH)) 
371         tst     r6, #TWSI_CONTROL_START_BIT
372         bne     loop_8
373         
374         /* Wait for status TWSI_REPEATED_START_CONDITION_TRA = 0x10 */
375 loop_10:
376         MV_REG_READ_ASM (r6, r1, TWSI_STATUS_BAUDE_RATE_REG(I2C_CH))
377         cmp     r6, #0x10
378         bne     loop_10
379         
380         /* Writing the address of (DIMM0<<1) with read indication (bit0 is 1) */
381         mov     r6, r4, LSL #1
382         orr     r6, r6, #1     /* Read operation address bit 0 must be 1 */
383         MV_REG_WRITE_ASM (r6, r1, TWSI_DATA_REG(I2C_CH))
384         
385         /* Clear the interrupt flag ==> the address will be transmitted */
386         bl      _twsiDelay
387         MV_REG_READ_ASM (r6, r1, TWSI_CONTROL_REG(I2C_CH))
388         bic     r6, r6, #TWSI_CONTROL_INT_FLAG_SET
389         MV_REG_WRITE_ASM (r6, r1, TWSI_CONTROL_REG(I2C_CH))
390         bl      _twsiDelay
391         
392         /* Wait for the interrupt flag (bit3) to be set as a result of
393            transmitting the address.                                     */
394 loop_11:
395 #ifdef MV78XX0
396         MV_REG_READ_ASM (r6, r1, CPU_INT_LOW_REG(I2C_CH))
397         tst     r6, #BIT2
398 #else
399         MV_REG_READ_ASM (r6, r1, CPU_MAIN_INT_CAUSE_REG)
400         tst     r6, #BIT5
401 #endif
402         beq     loop_11
403         
404          /* Wait for status TWSI_ADDR_PLUS_READ_BIT_TRA_ACK_REC = 0x40 */
405 loop_12:
406         MV_REG_READ_ASM (r6, r1, TWSI_STATUS_BAUDE_RATE_REG(I2C_CH))
407         cmp     r6, #0x40
408         bne     loop_12
409         
410         /* Clear the interrupt flag and the Acknoledge bit */
411         bl      _twsiDelay
412         MV_REG_READ_ASM (r6, r1, TWSI_CONTROL_REG(I2C_CH))
413         bic     r6, r6, #(TWSI_CONTROL_INT_FLAG_SET | TWSI_CONTROL_ACK)
414         MV_REG_WRITE_ASM (r6, r1, TWSI_CONTROL_REG(I2C_CH))
415         bl      _twsiDelay
416         
417         /* Wait for the interrupt flag (bit3) to be set */
418 loop_14:
419 #ifdef MV78XX0
420         MV_REG_READ_ASM (r6, r1, CPU_INT_LOW_REG(I2C_CH))
421         tst     r6, #BIT2
422 #else
423         MV_REG_READ_ASM (r6, r1, CPU_MAIN_INT_CAUSE_REG)
424         tst     r6, #BIT5
425 #endif
426         beq     loop_14
427         
428         /* Wait for status TWSI_MAS_REC_READ_DATA_ACK_NOT_TRA = 0x58 */
429 loop_15:
430         MV_REG_READ_ASM (r6, r1, TWSI_STATUS_BAUDE_RATE_REG(I2C_CH))
431         cmp     r6, #0x58
432         bne     loop_15
433         
434         /* Store the data in r7. */
435         MV_REG_READ_ASM (r7, r1, TWSI_DATA_REG(I2C_CH))
436         
437         /* Generate stop bit */
438         MV_REG_READ_ASM (r6, r1, TWSI_CONTROL_REG(I2C_CH))
439         orr     r6, r6, #TWSI_CONTROL_STOP_BIT
440         MV_REG_WRITE_ASM (r6, r1, TWSI_CONTROL_REG(I2C_CH))
441
442         
443         /* Clear the interrupt flag  */
444         bl      _twsiDelay
445         MV_REG_READ_ASM (r6, r1, TWSI_CONTROL_REG(I2C_CH))
446         bic     r6, r6, #TWSI_CONTROL_INT_FLAG_SET
447         MV_REG_WRITE_ASM (r6, r1, TWSI_CONTROL_REG(I2C_CH))
448         bl      _twsiDelay
449         
450         /* Wait for the stop bit to be reset by HW */
451 loop_16:
452         MV_REG_READ_ASM (r6, r1, TWSI_CONTROL_REG(I2C_CH))
453         tst     r6, #TWSI_CONTROL_INT_FLAG_SET
454         bne     loop_16
455
456 exit_i2cRead:
457         mov     PC, r9         /* r9 is saved link register */