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 #include "mvTwsiSpec.h"
68 #include "cpu/mvCpu.h"
78 static MV_VOID
twsiIntFlgClr(MV_U8 chanNum
);
79 static MV_BOOL
twsiMainIntGet(MV_U8 chanNum
);
80 static MV_VOID
twsiAckBitSet(MV_U8 chanNum
);
81 static MV_U32
twsiStsGet(MV_U8 chanNum
);
82 static MV_VOID
twsiReset(MV_U8 chanNum
);
83 static MV_STATUS
twsiAddr7BitSet(MV_U8 chanNum
, MV_U32 deviceAddress
,MV_TWSI_CMD command
);
84 static MV_STATUS
twsiAddr10BitSet(MV_U8 chanNum
, MV_U32 deviceAddress
,MV_TWSI_CMD command
);
85 static MV_STATUS
twsiDataTransmit(MV_U8 chanNum
, MV_U8
*pBlock
, MV_U32 blockSize
);
86 static MV_STATUS
twsiDataReceive(MV_U8 chanNum
, MV_U8
*pBlock
, MV_U32 blockSize
);
87 static MV_STATUS
twsiTargetOffsSet(MV_U8 chanNum
, MV_U32 offset
,MV_BOOL moreThen256
);
90 static MV_BOOL
twsiTimeoutChk(MV_U32 timeout
, const MV_8
*pString
)
92 if(timeout
>= TWSI_TIMEOUT_VALUE
)
94 DB(mvOsPrintf("%s",pString
));
100 /*******************************************************************************
101 * mvTwsiStartBitSet - Set start bit on the bus
104 * This routine sets the start bit on the TWSI bus.
105 * The routine first checks for interrupt flag condition, then it sets
106 * the start bit in the TWSI Control register.
107 * If the interrupt flag condition check previously was set, the function
109 * The function then wait for the start bit to be cleared by the HW.
110 * Then it waits for the interrupt flag to be set and eventually, the
111 * TWSI status is checked to be 0x8 or 0x10(repeated start bit).
114 * chanNum - TWSI channel.
120 * MV_OK is start bit was set successfuly on the bus.
121 * MV_FAIL if interrupt flag was set before setting start bit.
123 *******************************************************************************/
124 MV_STATUS
mvTwsiStartBitSet(MV_U8 chanNum
)
126 MV_BOOL isIntFlag
= MV_FALSE
;
127 MV_U32 timeout
, temp
;
129 DB(mvOsPrintf("TWSI: mvTwsiStartBitSet \n"));
131 if(twsiMainIntGet(chanNum
))
134 temp
= MV_REG_READ(TWSI_CONTROL_REG(chanNum
));
135 MV_REG_WRITE(TWSI_CONTROL_REG(chanNum
), temp
| TWSI_CONTROL_START_BIT
);
137 /* in case that the int flag was set before i.e. repeated start bit */
139 DB(mvOsPrintf("TWSI: mvTwsiStartBitSet repeated start Bit\n"));
140 twsiIntFlgClr(chanNum
);
143 /* wait for interrupt */
145 while(!twsiMainIntGet(chanNum
) && (timeout
++ < TWSI_TIMEOUT_VALUE
));
147 /* check for timeout */
148 if(MV_TRUE
== twsiTimeoutChk(timeout
,"TWSI: mvTwsiStartBitSet ERROR - Start Clear bit TimeOut .\n"))
152 /* check that start bit went down */
153 if((MV_REG_READ(TWSI_CONTROL_REG(chanNum
)) & TWSI_CONTROL_START_BIT
) != 0)
155 mvOsPrintf("TWSI: mvTwsiStartBitSet ERROR - start bit didn't went down\n");
159 /* check the status */
160 temp
= twsiStsGet(chanNum
);
161 if(( temp
!= TWSI_START_CON_TRA
) && ( temp
!= TWSI_REPEATED_START_CON_TRA
))
163 mvOsPrintf("TWSI: mvTwsiStartBitSet ERROR - status %x after Set Start Bit. \n",temp
);
171 /*******************************************************************************
172 * mvTwsiStopBitSet - Set stop bit on the bus
175 * This routine set the stop bit on the TWSI bus.
176 * The function then wait for the stop bit to be cleared by the HW.
177 * Finally the function checks for status of 0xF8.
180 * chanNum - TWSI channel
186 * MV_TRUE is stop bit was set successfuly on the bus.
188 *******************************************************************************/
189 MV_STATUS
mvTwsiStopBitSet(MV_U8 chanNum
)
191 MV_U32 timeout
, temp
;
193 /* Generate stop bit */
194 temp
= MV_REG_READ(TWSI_CONTROL_REG(chanNum
));
195 MV_REG_WRITE(TWSI_CONTROL_REG(chanNum
), temp
| TWSI_CONTROL_STOP_BIT
);
197 twsiIntFlgClr(chanNum
);
199 /* wait for stop bit to come down */
201 while( ((MV_REG_READ(TWSI_CONTROL_REG(chanNum
)) & TWSI_CONTROL_STOP_BIT
) != 0) && (timeout
++ < TWSI_TIMEOUT_VALUE
));
203 /* check for timeout */
204 if(MV_TRUE
== twsiTimeoutChk(timeout
,"TWSI: mvTwsiStopBitSet ERROR - Stop bit TimeOut .\n"))
207 /* check that the stop bit went down */
208 if((MV_REG_READ(TWSI_CONTROL_REG(chanNum
)) & TWSI_CONTROL_STOP_BIT
) != 0)
210 mvOsPrintf("TWSI: mvTwsiStopBitSet ERROR - stop bit didn't went down. \n");
214 /* check the status */
215 temp
= twsiStsGet(chanNum
);
216 if( temp
!= TWSI_NO_REL_STS_INT_FLAG_IS_KEPT_0
){
217 mvOsPrintf("TWSI: mvTwsiStopBitSet ERROR - status %x after Stop Bit. \n", temp
);
224 /*******************************************************************************
225 * twsiMainIntGet - Get twsi bit from main Interrupt cause.
228 * This routine returns the twsi interrupt flag value.
237 * MV_TRUE is interrupt flag is set, MV_FALSE otherwise.
239 *******************************************************************************/
240 static MV_BOOL
twsiMainIntGet(MV_U8 chanNum
)
244 /* get the int flag bit */
246 temp
= MV_REG_READ(TWSI_CPU_MAIN_INT_CAUSE_REG
);
247 if (temp
& (TWSI0_CPU_MAIN_INT_BIT
<< chanNum
))
252 /*******************************************************************************
253 * twsiIntFlgClr - Clear Interrupt flag.
256 * This routine clears the interrupt flag. It does NOT poll the interrupt
257 * to make sure the clear. After clearing the interrupt, it waits for at
258 * least 1 miliseconds.
261 * chanNum - TWSI channel
269 *******************************************************************************/
270 static MV_VOID
twsiIntFlgClr(MV_U8 chanNum
)
274 /* wait for 1 mili to prevent TWSI register write after write problems */
276 /* clear the int flag bit */
277 temp
= MV_REG_READ(TWSI_CONTROL_REG(chanNum
));
278 MV_REG_WRITE(TWSI_CONTROL_REG(chanNum
),temp
& ~(TWSI_CONTROL_INT_FLAG_SET
));
280 /* wait for 1 mili sec for the clear to take effect */
287 /*******************************************************************************
288 * twsiAckBitSet - Set acknowledge bit on the bus
291 * This routine set the acknowledge bit on the TWSI bus.
302 *******************************************************************************/
303 static MV_VOID
twsiAckBitSet(MV_U8 chanNum
)
308 temp
= MV_REG_READ(TWSI_CONTROL_REG(chanNum
));
309 MV_REG_WRITE(TWSI_CONTROL_REG(chanNum
), temp
| TWSI_CONTROL_ACK
);
311 /* Add delay of 1ms */
317 /*******************************************************************************
318 * twsiInit - Initialize TWSI interface
323 * -Initialize the TWSI clock baud rate according to given frequancy
324 * parameter based on Tclk frequancy and enables TWSI slave.
326 * -Assign the TWSI slave address according to the TWSI address Type.
330 * chanNum - TWSI channel
331 * frequancy - TWSI frequancy in KHz. (up to 100KHZ)
339 *******************************************************************************/
340 MV_U32
mvTwsiInit(MV_U8 chanNum
, MV_HZ frequancy
, MV_U32 Tclk
, MV_TWSI_ADDR
*pTwsiAddr
, MV_BOOL generalCallEnable
)
342 MV_U32 n
,m
,freq
,margin
,minMargin
= 0xffffffff;
344 MV_U32 actualFreq
= 0,actualN
= 0,actualM
= 0,val
;
346 if(frequancy
> 100000)
348 mvOsPrintf("Warning TWSI frequancy is too high, please use up tp 100Khz. \n");
351 DB(mvOsPrintf("TWSI: mvTwsiInit - Tclk = %d freq = %d\n",Tclk
,frequancy
));
352 /* Calucalte N and M for the TWSI clock baud rate */
353 for(n
= 0 ; n
< 8 ; n
++)
355 for(m
= 0 ; m
< 16 ; m
++)
357 power
= 2 << n
; /* power = 2^(n+1) */
358 freq
= Tclk
/(10*(m
+1)*power
);
359 margin
= MV_ABS(frequancy
- freq
);
360 if(margin
< minMargin
)
369 DB(mvOsPrintf("TWSI: mvTwsiInit - actN %d actM %d actFreq %d\n",actualN
, actualM
, actualFreq
));
370 /* Reset the TWSI logic */
373 /* Set the baud rate */
374 val
= ((actualM
<< TWSI_BAUD_RATE_M_OFFS
) | actualN
<< TWSI_BAUD_RATE_N_OFFS
);
375 MV_REG_WRITE(TWSI_STATUS_BAUDE_RATE_REG(chanNum
),val
);
377 /* Enable the TWSI and slave */
378 MV_REG_WRITE(TWSI_CONTROL_REG(chanNum
), TWSI_CONTROL_ENA
| TWSI_CONTROL_ACK
);
380 /* set the TWSI slave address */
381 if( pTwsiAddr
->type
== ADDR10_BIT
)/* 10 Bit deviceAddress */
383 /* writing the 2 most significant bits of the 10 bit address*/
384 val
= ((pTwsiAddr
->address
& TWSI_SLAVE_ADDR_10BIT_MASK
) >> TWSI_SLAVE_ADDR_10BIT_OFFS
);
385 /* bits 7:3 must be 0x11110 */
386 val
|= TWSI_SLAVE_ADDR_10BIT_CONST
;
388 if(generalCallEnable
)
389 val
|= TWSI_SLAVE_ADDR_GCE_ENA
;
390 /* write slave address */
391 MV_REG_WRITE(TWSI_SLAVE_ADDR_REG(chanNum
),val
);
393 /* writing the 8 least significant bits of the 10 bit address*/
394 val
= (pTwsiAddr
->address
<< TWSI_EXTENDED_SLAVE_OFFS
) & TWSI_EXTENDED_SLAVE_MASK
;
395 MV_REG_WRITE(TWSI_EXTENDED_SLAVE_ADDR_REG(chanNum
), val
);
397 else /*7 bit address*/
399 /* set the 7 Bits address */
400 MV_REG_WRITE(TWSI_EXTENDED_SLAVE_ADDR_REG(chanNum
),0x0);
401 val
= (pTwsiAddr
->address
<< TWSI_SLAVE_ADDR_7BIT_OFFS
) & TWSI_SLAVE_ADDR_7BIT_MASK
;
402 MV_REG_WRITE(TWSI_SLAVE_ADDR_REG(chanNum
), val
);
405 /* unmask twsi int */
406 val
= MV_REG_READ(TWSI_CONTROL_REG(chanNum
));
407 MV_REG_WRITE(TWSI_CONTROL_REG(chanNum
), val
| TWSI_CONTROL_INT_ENA
);
408 /* Add delay of 1ms */
415 /*******************************************************************************
416 * twsiStsGet - Get the TWSI status value.
419 * This routine returns the TWSI status value.
422 * chanNum - TWSI channel
428 * MV_U32 - the TWSI status.
430 *******************************************************************************/
431 static MV_U32
twsiStsGet(MV_U8 chanNum
)
433 return MV_REG_READ(TWSI_STATUS_BAUDE_RATE_REG(chanNum
));
437 /*******************************************************************************
438 * twsiReset - Reset the TWSI.
441 * Resets the TWSI logic and sets all TWSI registers to their reset values.
444 * chanNum - TWSI channel
452 *******************************************************************************/
453 static MV_VOID
twsiReset(MV_U8 chanNum
)
455 /* Reset the TWSI logic */
456 MV_REG_WRITE(TWSI_SOFT_RESET_REG(chanNum
),0);
458 /* wait for 2 mili sec */
467 /******************************* POLICY ****************************************/
471 /*******************************************************************************
472 * mvTwsiAddrSet - Set address on TWSI bus.
475 * This function Set address (7 or 10 Bit address) on the Twsi Bus.
478 * chanNum - TWSI channel
479 * pTwsiAddr - twsi address.
480 * command - read / write .
486 * MV_OK - if setting the address completed succesfully.
487 * MV_FAIL otherwmise.
489 *******************************************************************************/
490 MV_STATUS
mvTwsiAddrSet(MV_U8 chanNum
, MV_TWSI_ADDR
*pTwsiAddr
, MV_TWSI_CMD command
)
492 DB(mvOsPrintf("TWSI: mvTwsiAddr7BitSet addr %x , type %d, cmd is %s\n",pTwsiAddr
->address
,\
493 pTwsiAddr
->type
, ((command
==MV_TWSI_WRITE
)?"Write":"Read") ));
495 if(pTwsiAddr
->type
== ADDR10_BIT
)
497 return twsiAddr10BitSet(chanNum
, pTwsiAddr
->address
,command
);
502 return twsiAddr7BitSet(chanNum
, pTwsiAddr
->address
,command
);
507 /*******************************************************************************
508 * twsiAddr10BitSet - Set 10 Bit address on TWSI bus.
511 * There are two address phases:
512 * 1) Write '11110' to data register bits [7:3] and 10-bit address MSB
513 * (bits [9:8]) to data register bits [2:1] plus a write(0) or read(1) bit
514 * to the Data register. Then it clears interrupt flag which drive
515 * the address on the TWSI bus. The function then waits for interrupt
516 * flag to be active and status 0x18 (write) or 0x40 (read) to be set.
517 * 2) write the rest of 10-bit address to data register and clears
518 * interrupt flag which drive the address on the TWSI bus. The
519 * function then waits for interrupt flag to be active and status
520 * 0xD0 (write) or 0xE0 (read) to be set.
523 * chanNum - TWSI channel
524 * deviceAddress - twsi address.
525 * command - read / write .
531 * MV_OK - if setting the address completed succesfully.
532 * MV_FAIL otherwmise.
534 *******************************************************************************/
535 static MV_STATUS
twsiAddr10BitSet(MV_U8 chanNum
, MV_U32 deviceAddress
,MV_TWSI_CMD command
)
539 /* writing the 2 most significant bits of the 10 bit address*/
540 val
= ((deviceAddress
& TWSI_DATA_ADDR_10BIT_MASK
) >> TWSI_DATA_ADDR_10BIT_OFFS
);
541 /* bits 7:3 must be 0x11110 */
542 val
|= TWSI_DATA_ADDR_10BIT_CONST
;
545 MV_REG_WRITE(TWSI_DATA_REG(chanNum
), val
);
550 twsiIntFlgClr(chanNum
);
552 /* wait for Int to be Set */
554 while( !twsiMainIntGet(chanNum
) && (timeout
++ < TWSI_TIMEOUT_VALUE
));
556 /* check for timeout */
557 if(MV_TRUE
== twsiTimeoutChk(timeout
,"TWSI: twsiAddr10BitSet ERROR - 1st addr (10Bit) Int TimeOut.\n"))
560 /* check the status */
561 val
= twsiStsGet(chanNum
);
562 if(( (val
!= TWSI_AD_PLS_RD_BIT_TRA_ACK_REC
) && (command
== MV_TWSI_READ
) ) ||
563 ( (val
!= TWSI_AD_PLS_WR_BIT_TRA_ACK_REC
) && (command
== MV_TWSI_WRITE
) ))
565 mvOsPrintf("TWSI: twsiAddr10BitSet ERROR - status %x 1st addr (10 Bit) in %s mode.\n"\
566 ,val
, ((command
==MV_TWSI_WRITE
)?"Write":"Read") );
570 /* set 8 LSB of the address */
571 val
= (deviceAddress
<< TWSI_DATA_ADDR_7BIT_OFFS
) & TWSI_DATA_ADDR_7BIT_MASK
;
572 MV_REG_WRITE(TWSI_DATA_REG(chanNum
), val
);
575 twsiIntFlgClr(chanNum
);
577 /* wait for Int to be Set */
579 while( !twsiMainIntGet(chanNum
) && (timeout
++ < TWSI_TIMEOUT_VALUE
));
581 /* check for timeout */
582 if(MV_TRUE
== twsiTimeoutChk(timeout
,"TWSI: twsiAddr10BitSet ERROR - 2nd (10 Bit) Int TimOut.\n"))
585 /* check the status */
586 val
= twsiStsGet(chanNum
);
587 if(( (val
!= TWSI_SEC_AD_PLS_RD_BIT_TRA_ACK_REC
) && (command
== MV_TWSI_READ
) ) ||
588 ( (val
!= TWSI_SEC_AD_PLS_WR_BIT_TRA_ACK_REC
) && (command
== MV_TWSI_WRITE
) ))
590 mvOsPrintf("TWSI: twsiAddr10BitSet ERROR - status %x 2nd addr(10 Bit) in %s mode.\n"\
591 ,val
, ((command
==MV_TWSI_WRITE
)?"Write":"Read") );
598 /*******************************************************************************
599 * twsiAddr7BitSet - Set 7 Bit address on TWSI bus.
602 * This function writes 7 bit address plus a write or read bit to the
603 * Data register. Then it clears interrupt flag which drive the address on
604 * the TWSI bus. The function then waits for interrupt flag to be active
605 * and status 0x18 (write) or 0x40 (read) to be set.
608 * chanNum - TWSI channel
609 * deviceAddress - twsi address.
610 * command - read / write .
616 * MV_OK - if setting the address completed succesfully.
617 * MV_FAIL otherwmise.
619 *******************************************************************************/
620 static MV_STATUS
twsiAddr7BitSet(MV_U8 chanNum
, MV_U32 deviceAddress
,MV_TWSI_CMD command
)
624 /* set the address */
625 val
= (deviceAddress
<< TWSI_DATA_ADDR_7BIT_OFFS
) & TWSI_DATA_ADDR_7BIT_MASK
;
628 MV_REG_WRITE(TWSI_DATA_REG(chanNum
), val
);
633 twsiIntFlgClr(chanNum
);
635 /* wait for Int to be Set */
637 while( !twsiMainIntGet(chanNum
) && (timeout
++ < TWSI_TIMEOUT_VALUE
));
639 /* check for timeout */
640 if(MV_TRUE
== twsiTimeoutChk(timeout
,"TWSI: twsiAddr7BitSet ERROR - Addr (7 Bit) int TimeOut.\n"))
643 /* check the status */
644 val
= twsiStsGet(chanNum
);
645 if(( (val
!= TWSI_AD_PLS_RD_BIT_TRA_ACK_REC
) && (command
== MV_TWSI_READ
) ) ||
646 ( (val
!= TWSI_AD_PLS_WR_BIT_TRA_ACK_REC
) && (command
== MV_TWSI_WRITE
) ))
648 /* only in debug, since in boot we try to read the SPD of both DRAM, and we don't
649 want error messeges in case DIMM doesn't exist. */
650 DB(mvOsPrintf("TWSI: twsiAddr7BitSet ERROR - status %x addr (7 Bit) in %s mode.\n"\
651 ,val
,((command
==MV_TWSI_WRITE
)?"Write":"Read") ));
658 /*******************************************************************************
659 * twsiDataWrite - Trnasmit a data block over TWSI bus.
662 * This function writes a given data block to TWSI bus in 8 bit granularity.
663 * first The function waits for interrupt flag to be active then
664 * For each 8-bit data:
665 * The function writes data to data register. It then clears
666 * interrupt flag which drives the data on the TWSI bus.
667 * The function then waits for interrupt flag to be active and status
672 * chanNum - TWSI channel
673 * pBlock - Data block.
674 * blockSize - number of chars in pBlock.
680 * MV_OK - if transmiting the block completed succesfully,
681 * MV_BAD_PARAM - if pBlock is NULL,
682 * MV_FAIL otherwmise.
684 *******************************************************************************/
685 static MV_STATUS
twsiDataTransmit(MV_U8 chanNum
, MV_U8
*pBlock
, MV_U32 blockSize
)
687 MV_U32 timeout
, temp
, blockSizeWr
= blockSize
;
692 /* wait for Int to be Set */
694 while( !twsiMainIntGet(chanNum
) && (timeout
++ < TWSI_TIMEOUT_VALUE
));
696 /* check for timeout */
697 if(MV_TRUE
== twsiTimeoutChk(timeout
,"TWSI: twsiDataTransmit ERROR - Read Data Int TimeOut.\n"))
703 MV_REG_WRITE(TWSI_DATA_REG(chanNum
),(MV_U32
)*pBlock
);
704 DB(mvOsPrintf("TWSI: twsiDataTransmit place = %d write %x \n",\
705 blockSize
- blockSizeWr
, *pBlock
));
709 twsiIntFlgClr(chanNum
);
711 /* wait for Int to be Set */
713 while( !twsiMainIntGet(chanNum
) && (timeout
++ < TWSI_TIMEOUT_VALUE
));
715 /* check for timeout */
716 if(MV_TRUE
== twsiTimeoutChk(timeout
,"TWSI: twsiDataTransmit ERROR - Read Data Int TimeOut.\n"))
719 /* check the status */
720 temp
= twsiStsGet(chanNum
);
721 if(temp
!= TWSI_M_TRAN_DATA_BYTE_ACK_REC
)
723 mvOsPrintf("TWSI: twsiDataTransmit ERROR - status %x in write trans\n",temp
);
732 /*******************************************************************************
733 * twsiDataReceive - Receive data block from TWSI bus.
736 * This function receive data block from TWSI bus in 8bit granularity
737 * into pBlock buffer.
738 * first The function waits for interrupt flag to be active then
739 * For each 8-bit data:
740 * It clears the interrupt flag which allows the next data to be
741 * received from TWSI bus.
742 * The function waits for interrupt flag to be active,
743 * and status reg is 0x50.
744 * Then the function reads data from data register, and copies it to
748 * chanNum - TWSI channel
749 * blockSize - number of bytes to read.
752 * pBlock - Data block.
755 * MV_OK - if receive transaction completed succesfully,
756 * MV_BAD_PARAM - if pBlock is NULL,
757 * MV_FAIL otherwmise.
759 *******************************************************************************/
760 static MV_STATUS
twsiDataReceive(MV_U8 chanNum
, MV_U8
*pBlock
, MV_U32 blockSize
)
762 MV_U32 timeout
, temp
, blockSizeRd
= blockSize
;
766 /* wait for Int to be Set */
768 while( !twsiMainIntGet(chanNum
) && (timeout
++ < TWSI_TIMEOUT_VALUE
));
770 /* check for timeout */
771 if(MV_TRUE
== twsiTimeoutChk(timeout
,"TWSI: twsiDataReceive ERROR - Read Data int Time out .\n"))
778 /* clear ack and Int flag */
779 temp
= MV_REG_READ(TWSI_CONTROL_REG(chanNum
));
780 temp
&= ~(TWSI_CONTROL_ACK
);
781 MV_REG_WRITE(TWSI_CONTROL_REG(chanNum
), temp
);
783 twsiIntFlgClr(chanNum
);
784 /* wait for Int to be Set */
786 while( (!twsiMainIntGet(chanNum
)) && (timeout
++ < TWSI_TIMEOUT_VALUE
));
788 /* check for timeout */
789 if(MV_TRUE
== twsiTimeoutChk(timeout
,"TWSI: twsiDataReceive ERROR - Read Data Int Time out .\n"))
792 /* check the status */
793 temp
= twsiStsGet(chanNum
);
794 if((temp
!= TWSI_M_REC_RD_DATA_ACK_TRA
) && (blockSizeRd
!=1))
796 mvOsPrintf("TWSI: twsiDataReceive ERROR - status %x in read trans \n",temp
);
799 else if((temp
!= TWSI_M_REC_RD_DATA_ACK_NOT_TRA
) && (blockSizeRd
==1))
801 mvOsPrintf("TWSI: twsiDataReceive ERROR - status %x in Rd Terminate\n",temp
);
806 *pBlock
= (MV_U8
)MV_REG_READ(TWSI_DATA_REG(chanNum
));
807 DB(mvOsPrintf("TWSI: twsiDataReceive place %d read %x \n",\
808 blockSize
- blockSizeRd
,*pBlock
));
818 /*******************************************************************************
819 * twsiTargetOffsSet - Set TWST target offset on TWSI bus.
822 * The function support TWSI targets that have inside address space (for
823 * example EEPROMs). The function:
824 * 1) Convert the given offset into pBlock and size.
825 * in case the offset should be set to a TWSI slave which support
826 * more then 256 bytes offset, the offset setting will be done
828 * 2) Use twsiDataTransmit to place those on the bus.
831 * chanNum - TWSI channel
832 * offset - offset to be set on the EEPROM device.
833 * moreThen256 - whether the EEPROM device support more then 256 byte offset.
839 * MV_OK - if setting the offset completed succesfully.
840 * MV_FAIL otherwmise.
842 *******************************************************************************/
843 static MV_STATUS
twsiTargetOffsSet(MV_U8 chanNum
, MV_U32 offset
, MV_BOOL moreThen256
)
848 if(moreThen256
== MV_TRUE
)
850 offBlock
[0] = (offset
>> 8) & 0xff;
851 offBlock
[1] = offset
& 0xff;
856 offBlock
[0] = offset
& 0xff;
859 DB(mvOsPrintf("TWSI: twsiTargetOffsSet offSize = %x addr1 = %x addr2 = %x\n",\
860 offSize
,offBlock
[0],offBlock
[1]));
861 return twsiDataTransmit(chanNum
, offBlock
, offSize
);
865 /*******************************************************************************
866 * mvTwsiRead - Read data block from a TWSI Slave.
869 * The function calls the following functions:
870 * -) mvTwsiStartBitSet();
872 * -) mvTwsiAddrSet(w);
873 * -) twsiTargetOffsSet();
874 * -) mvTwsiStartBitSet();
875 * -) mvTwsiAddrSet(r);
876 * -) twsiDataReceive();
877 * -) mvTwsiStopBitSet();
880 * chanNum - TWSI channel
881 * pTwsiSlave - Twsi Slave structure.
882 * blockSize - number of bytes to read.
885 * pBlock - Data block.
888 * MV_OK - if EEPROM read transaction completed succesfully,
889 * MV_BAD_PARAM - if pBlock is NULL,
890 * MV_FAIL otherwmise.
892 *******************************************************************************/
893 MV_STATUS
mvTwsiRead(MV_U8 chanNum
, MV_TWSI_SLAVE
*pTwsiSlave
, MV_U8
*pBlock
, MV_U32 blockSize
)
895 if((NULL
== pBlock
) || (NULL
== pTwsiSlave
))
897 if(MV_OK
!= mvTwsiStartBitSet(chanNum
))
899 mvTwsiStopBitSet(chanNum
);
903 DB(mvOsPrintf("TWSI: mvTwsiEepromRead after mvTwsiStartBitSet\n"));
905 /* in case offset exsist (i.e. eeprom ) */
906 if(MV_TRUE
== pTwsiSlave
->validOffset
)
908 if(MV_OK
!= mvTwsiAddrSet(chanNum
, &(pTwsiSlave
->slaveAddr
), MV_TWSI_WRITE
))
910 mvTwsiStopBitSet(chanNum
);
913 DB(mvOsPrintf("TWSI: mvTwsiEepromRead after mvTwsiAddrSet\n"));
914 if(MV_OK
!= twsiTargetOffsSet(chanNum
, pTwsiSlave
->offset
, pTwsiSlave
->moreThen256
))
916 mvTwsiStopBitSet(chanNum
);
919 DB(mvOsPrintf("TWSI: mvTwsiEepromRead after twsiTargetOffsSet\n"));
920 if(MV_OK
!= mvTwsiStartBitSet(chanNum
))
922 mvTwsiStopBitSet(chanNum
);
925 DB(mvOsPrintf("TWSI: mvTwsiEepromRead after mvTwsiStartBitSet\n"));
927 if(MV_OK
!= mvTwsiAddrSet(chanNum
, &(pTwsiSlave
->slaveAddr
), MV_TWSI_READ
))
929 mvTwsiStopBitSet(chanNum
);
932 DB(mvOsPrintf("TWSI: mvTwsiEepromRead after mvTwsiAddrSet\n"));
933 if(MV_OK
!= twsiDataReceive(chanNum
, pBlock
, blockSize
))
935 mvTwsiStopBitSet(chanNum
);
938 DB(mvOsPrintf("TWSI: mvTwsiEepromRead after twsiDataReceive\n"));
940 if(MV_OK
!= mvTwsiStopBitSet(chanNum
))
945 twsiAckBitSet(chanNum
);
947 DB(mvOsPrintf("TWSI: mvTwsiEepromRead after mvTwsiStopBitSet\n"));
952 /*******************************************************************************
953 * mvTwsiWrite - Write data block to a TWSI Slave.
956 * The function calls the following functions:
957 * -) mvTwsiStartBitSet();
958 * -) mvTwsiAddrSet();
959 * -)if(EEPROM device)
960 * -) twsiTargetOffsSet();
961 * -) twsiDataTransmit();
962 * -) mvTwsiStopBitSet();
965 * chanNum - TWSI channel
966 * eepromAddress - eeprom address.
967 * blockSize - number of bytes to write.
968 * pBlock - Data block.
974 * MV_OK - if EEPROM read transaction completed succesfully.
975 * MV_BAD_PARAM - if pBlock is NULL,
976 * MV_FAIL otherwmise.
978 * NOTE: Part of the EEPROM, required that the offset will be aligned to the
979 * max write burst supported.
980 *******************************************************************************/
981 MV_STATUS
mvTwsiWrite(MV_U8 chanNum
, MV_TWSI_SLAVE
*pTwsiSlave
, MV_U8
*pBlock
, MV_U32 blockSize
)
983 if((NULL
== pBlock
) || (NULL
== pTwsiSlave
))
986 if(MV_OK
!= mvTwsiStartBitSet(chanNum
))
988 mvTwsiStopBitSet(chanNum
);
992 DB(mvOsPrintf("TWSI: mvTwsiEepromWrite after mvTwsiStartBitSet\n"));
993 if(MV_OK
!= mvTwsiAddrSet(chanNum
, &(pTwsiSlave
->slaveAddr
), MV_TWSI_WRITE
))
995 mvTwsiStopBitSet(chanNum
);
998 DB(mvOsPrintf("TWSI :mvTwsiEepromWrite after mvTwsiAddrSet\n"));
1000 /* in case offset exsist (i.e. eeprom ) */
1001 if(MV_TRUE
== pTwsiSlave
->validOffset
)
1003 if(MV_OK
!= twsiTargetOffsSet(chanNum
, pTwsiSlave
->offset
, pTwsiSlave
->moreThen256
))
1005 mvTwsiStopBitSet(chanNum
);
1008 DB(mvOsPrintf("TWSI: mvTwsiEepromWrite after twsiTargetOffsSet\n"));
1010 if(MV_OK
!= twsiDataTransmit(chanNum
, pBlock
, blockSize
))
1012 mvTwsiStopBitSet(chanNum
);
1015 DB(mvOsPrintf("TWSI: mvTwsiEepromWrite after twsiDataTransmit\n"));
1016 if(MV_OK
!= mvTwsiStopBitSet(chanNum
))
1020 DB(mvOsPrintf("TWSI: mvTwsiEepromWrite after mvTwsiStopBitSet\n"));