ocf: update to version 20120127
[openwrt/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 */