1 /*******************************************************************************
2 Copyright (C) Marvell International Ltd. and its affiliates
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.
12 ********************************************************************************
13 Marvell Commercial License Option
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.
19 ********************************************************************************
20 Marvell GPL License Option
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.
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
33 ********************************************************************************
34 Marvell BSD License Option
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:
41 * Redistributions of source code must retain the above copyright notice,
42 this list of conditions and the following disclaimer.
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.
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.
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.
63 *******************************************************************************/
67 #define MV_ASMLANGUAGE
68 #include "ctrlEnv/mvCtrlEnvSpec.h"
69 #include "boardEnv/mvBoardEnvSpec.h"
71 #include "mvTwsiSpec.h"
72 #include "mvSysHwConfig.h"
73 #include "ctrlEnv/sys/mvCpuIfRegs.h"
76 #define I2C_CH MV_BOARD_DIMM_I2C_CHANNEL
88 /*******************************************************************************
89 * _i2cInit - Initialize TWSI interface
92 * The function performs TWSI interface initialization. It resets the
93 * TWSI state machine and initialize its clock to 100KHz assuming Tclock
105 *******************************************************************************/
107 mov r9, LR /* Save link register */
108 mov r0, #0 /* Make sure r0 is zero */
110 /* Reset the i2c Mechanism first */
111 MV_REG_WRITE_ASM (r0, r1, TWSI_SOFT_RESET_REG(I2C_CH))
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))
124 /* Enable the I2C master */
125 /* Enable TWSI interrupt in main mask reg */
127 MV_REG_WRITE_ASM (r6, r1, TWSI_CONTROL_REG(I2C_CH))
129 /* Let the slow TWSI machine get used to the idea that it is enabled */
133 mov PC, r9 /* r9 is saved link register */
135 /*******************************************************************************
136 * _twsiDelay - Perform delay.
139 * The function performs a delay to enable TWSI logic to stable.
150 *******************************************************************************/
152 mov r10, #0x100000 /*was 0x400*/
160 /*******************************************************************************
161 * _i2cRead - Read byte from I2C EEPROM device.
164 * The function returns a byte from I2C EEPROM device.
165 * The EEPROM device is 7-bit address type.
168 * r4 has the DIMM0 base address with shift 1 bit to the left
169 * r7 has the EEPROM offset
175 * r4 returns '0' if address can not be read.
176 * r7 has byte value in case read is successful.
178 *******************************************************************************/
180 mov r9, LR /* Save link register */
182 /* Transmit the device address and desired offset within the EEPROM. */
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))
189 /* Wait for the interrupt flag (bit3) to be set */
195 MV_REG_READ_ASM (r6, r1, CPU_INT_LOW_REG(I2C_CH))
198 MV_REG_READ_ASM (r6, r1, CPU_MAIN_INT_CAUSE_REG)
205 /* Wait for the start bit to be reset by HW */
210 MV_REG_READ_ASM (r6, r1, TWSI_CONTROL_REG(I2C_CH))
211 tst r6, #TWSI_CONTROL_START_BIT
216 /* Wait for the status TWSI_START_CONDITION_TRA = 0x8 */
221 MV_REG_READ_ASM (r6, r1, TWSI_STATUS_BAUDE_RATE_REG(I2C_CH))
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))
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))
238 /* Waiting for the interrupt flag to be set which means that the
239 address has been transmitted */
242 MV_REG_READ_ASM (r6, r1, CPU_INT_LOW_REG(I2C_CH))
245 MV_REG_READ_ASM (r6, r1, CPU_MAIN_INT_CAUSE_REG)
248 beq loop_4 /* if tst = 0, then the bit is not set yet */
250 /* Wait for status TWSI_ADDR_PLUS_WRITE_BIT_TRA_ACK_REC = 0x18 */
251 mov r10, #0x50000 /* Set r10 to 0x50000 =~ 328,000 */
254 subs r10, r10, #1 /* timeout count down */
256 mov r4, #0 /* r4 = 0 -> operation failed */
257 b exit_i2cRead /* Exit if timeout (No DIMM) */
260 MV_REG_READ_ASM (r6, r1, TWSI_STATUS_BAUDE_RATE_REG(I2C_CH))
265 /* check if the offset is bigger than 256 byte*/
269 /* Write the offset to be read from the DIMM EEPROM */
270 MV_REG_WRITE_ASM (r7, r1, TWSI_DATA_REG(I2C_CH))
277 /* Write the offset0 to be read from the EEPROM */
278 MV_REG_WRITE_ASM (r10, r1, TWSI_DATA_REG(I2C_CH))
280 /* Clear the interrupt flag ==> signaling that the address can now
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))
289 /* Wait for the interrupt to be set again ==> address has transmited */
292 MV_REG_READ_ASM (r6, r1, CPU_INT_LOW_REG(I2C_CH))
295 MV_REG_READ_ASM (r6, r1, CPU_MAIN_INT_CAUSE_REG)
300 /* Wait for status TWSI_MAS_TRAN_DATA_BYTE_ACK_REC = 0x28 */
302 MV_REG_READ_ASM (r6, r1, TWSI_STATUS_BAUDE_RATE_REG(I2C_CH))
309 /* Write the offset1 to be read from the EEPROM */
310 MV_REG_WRITE_ASM (r10, r1, TWSI_DATA_REG(I2C_CH))
316 /* Clear the interrupt flag ==> signaling that the address can now
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))
325 /* Wait for the interrupt to be set again ==> address has transmited */
328 MV_REG_READ_ASM (r6, r1, CPU_INT_LOW_REG(I2C_CH))
331 MV_REG_READ_ASM (r6, r1, CPU_MAIN_INT_CAUSE_REG)
336 /* Wait for status TWSI_MAS_TRAN_DATA_BYTE_ACK_REC = 0x28 */
338 MV_REG_READ_ASM (r6, r1, TWSI_STATUS_BAUDE_RATE_REG(I2C_CH))
342 /* Retransmit the device address with read indication to get the data */
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))
350 /* Clear the interrupt flag ==> the start bit will be transmitted. */
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))
357 /* Wait for the interrupt flag (bit3) to be set */
360 MV_REG_READ_ASM (r6, r1, CPU_INT_LOW_REG(I2C_CH))
363 MV_REG_READ_ASM (r6, r1, CPU_MAIN_INT_CAUSE_REG)
368 /* Wait for the start bit to be reset by HW */
370 MV_REG_READ_ASM (r6, r1, TWSI_CONTROL_REG(I2C_CH))
371 tst r6, #TWSI_CONTROL_START_BIT
374 /* Wait for status TWSI_REPEATED_START_CONDITION_TRA = 0x10 */
376 MV_REG_READ_ASM (r6, r1, TWSI_STATUS_BAUDE_RATE_REG(I2C_CH))
380 /* Writing the address of (DIMM0<<1) with read indication (bit0 is 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))
385 /* Clear the interrupt flag ==> the address will be transmitted */
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))
392 /* Wait for the interrupt flag (bit3) to be set as a result of
393 transmitting the address. */
396 MV_REG_READ_ASM (r6, r1, CPU_INT_LOW_REG(I2C_CH))
399 MV_REG_READ_ASM (r6, r1, CPU_MAIN_INT_CAUSE_REG)
404 /* Wait for status TWSI_ADDR_PLUS_READ_BIT_TRA_ACK_REC = 0x40 */
406 MV_REG_READ_ASM (r6, r1, TWSI_STATUS_BAUDE_RATE_REG(I2C_CH))
410 /* Clear the interrupt flag and the Acknoledge bit */
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))
417 /* Wait for the interrupt flag (bit3) to be set */
420 MV_REG_READ_ASM (r6, r1, CPU_INT_LOW_REG(I2C_CH))
423 MV_REG_READ_ASM (r6, r1, CPU_MAIN_INT_CAUSE_REG)
428 /* Wait for status TWSI_MAS_REC_READ_DATA_ACK_NOT_TRA = 0x58 */
430 MV_REG_READ_ASM (r6, r1, TWSI_STATUS_BAUDE_RATE_REG(I2C_CH))
434 /* Store the data in r7. */
435 MV_REG_READ_ASM (r7, r1, TWSI_DATA_REG(I2C_CH))
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))
443 /* Clear the interrupt flag */
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))
450 /* Wait for the stop bit to be reset by HW */
452 MV_REG_READ_ASM (r6, r1, TWSI_CONTROL_REG(I2C_CH))
453 tst r6, #TWSI_CONTROL_INT_FLAG_SET
457 mov PC, r9 /* r9 is saved link register */