• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7800-V1.0.2.28/target/linux/generic/files/crypto/ocf/kirkwood/mvHal/mv_hal/twsi/
1/*******************************************************************************
2Copyright (C) Marvell International Ltd. and its affiliates
3
4This software file (the "File") is owned and distributed by Marvell
5International Ltd. and/or its affiliates ("Marvell") under the following
6alternative licensing terms.  Once you have made an election to distribute the
7File under one of the following license alternatives, please (i) delete this
8introductory statement regarding license alternatives, (ii) delete the two
9license alternatives that you have not elected to use and (iii) preserve the
10Marvell copyright notice above.
11
12********************************************************************************
13Marvell Commercial License Option
14
15If you received this File from Marvell and you have entered into a commercial
16license agreement (a "Commercial License") with Marvell, the File is licensed
17to you under the terms of the applicable Commercial License.
18
19********************************************************************************
20Marvell GPL License Option
21
22If you received this File from Marvell, you may opt to use, redistribute and/or
23modify this File in accordance with the terms and conditions of the General
24Public License Version 2, June 1991 (the "GPL License"), a copy of which is
25available along with the File in the license.txt file or by writing to the Free
26Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
27on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
28
29THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
30WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
31DISCLAIMED.  The GPL License provides additional details about this warranty
32disclaimer.
33********************************************************************************
34Marvell BSD License Option
35
36If you received this File from Marvell, you may opt to use, redistribute and/or
37modify this File under the following licensing terms.
38Redistribution and use in source and binary forms, with or without modification,
39are 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
52THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
53ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
54WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
55DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
56ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
57(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
58LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
59ANY 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
61SOFTWARE, 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
191loop_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
203loop_1_timeout:
204
205        /* Wait for the start bit to be reset by HW */
206        mov     r10, #0x50000
207loop_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
214loop_2_timeout:
215
216        /* Wait for the status TWSI_START_CONDITION_TRA = 0x8 */
217        mov     r10, #0x50000
218loop_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
225loop_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                                  */
240loop_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
253loop_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
259testStatus:
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
274great_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 */
290loop_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 */
301loop_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
314after_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 */
326loop_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 */
337loop_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 */
358loop_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 */
369loop_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 */
375loop_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.                                     */
394loop_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 */
405loop_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 */
418loop_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 */
429loop_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 */
451loop_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
456exit_i2cRead:
457        mov     PC, r9         /* r9 is saved link register */
458