0bf8b7571b1e1909e73b16f1a4c8d5c548632b57
[15.05/openwrt.git] / target / linux / generic / files / crypto / ocf / kirkwood / mvHal / mv_hal / twsi / mvTwsi.c
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 #include "mvTwsi.h"
67 #include "mvTwsiSpec.h"
68 #include "cpu/mvCpu.h"
69
70
71 /*#define MV_DEBUG*/
72 #ifdef MV_DEBUG
73 #define DB(x) x
74 #else
75 #define DB(x)
76 #endif
77
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);
88
89
90 static MV_BOOL twsiTimeoutChk(MV_U32 timeout, const MV_8 *pString)
91 {
92         if(timeout >= TWSI_TIMEOUT_VALUE)
93         {
94                 DB(mvOsPrintf("%s",pString));
95                 return MV_TRUE;
96         }
97         return MV_FALSE;
98         
99 }
100 /*******************************************************************************
101 * mvTwsiStartBitSet - Set start bit on the bus
102 *
103 * DESCRIPTION:
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 
108 *       will clear it.
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).
112 *
113 * INPUT:
114 *       chanNum - TWSI channel.
115 *
116 * OUTPUT:
117 *       None.
118 *
119 * RETURN:
120 *       MV_OK is start bit was set successfuly on the bus.
121 *       MV_FAIL if interrupt flag was set before setting start bit.
122 *
123 *******************************************************************************/
124 MV_STATUS mvTwsiStartBitSet(MV_U8 chanNum)
125 {
126         MV_BOOL isIntFlag = MV_FALSE;
127         MV_U32 timeout, temp;
128
129         DB(mvOsPrintf("TWSI: mvTwsiStartBitSet \n"));
130         /* check Int flag */
131         if(twsiMainIntGet(chanNum))
132                 isIntFlag = MV_TRUE;
133         /* set start Bit */
134         temp = MV_REG_READ(TWSI_CONTROL_REG(chanNum));
135         MV_REG_WRITE(TWSI_CONTROL_REG(chanNum), temp | TWSI_CONTROL_START_BIT);
136         
137         /* in case that the int flag was set before i.e. repeated start bit */
138         if(isIntFlag){
139                 DB(mvOsPrintf("TWSI: mvTwsiStartBitSet repeated start Bit\n"));
140                 twsiIntFlgClr(chanNum);
141         }
142         
143         /* wait for interrupt */
144         timeout = 0;
145         while(!twsiMainIntGet(chanNum) && (timeout++ < TWSI_TIMEOUT_VALUE));
146         
147         /* check for timeout */ 
148         if(MV_TRUE == twsiTimeoutChk(timeout,"TWSI: mvTwsiStartBitSet ERROR - Start Clear bit TimeOut .\n"))
149                 return MV_TIMEOUT;
150
151
152         /* check that start bit went down */
153         if((MV_REG_READ(TWSI_CONTROL_REG(chanNum)) & TWSI_CONTROL_START_BIT) != 0)
154         {
155                 mvOsPrintf("TWSI: mvTwsiStartBitSet ERROR - start bit didn't went down\n");
156                 return MV_FAIL;
157         }       
158
159         /* check the status */
160         temp = twsiStsGet(chanNum);
161         if(( temp != TWSI_START_CON_TRA ) && ( temp != TWSI_REPEATED_START_CON_TRA ))
162           {
163                 mvOsPrintf("TWSI: mvTwsiStartBitSet ERROR - status %x after Set Start Bit. \n",temp);
164                 return MV_FAIL;
165         }
166
167         return MV_OK;   
168
169 }
170
171 /*******************************************************************************
172 * mvTwsiStopBitSet - Set stop bit on the bus
173 *
174 * DESCRIPTION:
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.
178 *
179 * INPUT:
180 *       chanNum - TWSI channel
181 *
182 * OUTPUT:
183 *       None.
184 *
185 * RETURN:
186 *       MV_TRUE is stop bit was set successfuly on the bus.
187 *
188 *******************************************************************************/
189 MV_STATUS mvTwsiStopBitSet(MV_U8 chanNum)
190 {
191         MV_U32  timeout, temp;
192
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);
196
197         twsiIntFlgClr(chanNum);
198                 
199         /* wait for stop bit to come down */
200         timeout = 0;
201         while( ((MV_REG_READ(TWSI_CONTROL_REG(chanNum)) & TWSI_CONTROL_STOP_BIT) != 0) && (timeout++ < TWSI_TIMEOUT_VALUE));
202
203         /* check for timeout */
204         if(MV_TRUE == twsiTimeoutChk(timeout,"TWSI: mvTwsiStopBitSet ERROR - Stop bit TimeOut .\n"))
205                 return MV_TIMEOUT;
206         
207         /* check that the stop bit went down */
208         if((MV_REG_READ(TWSI_CONTROL_REG(chanNum)) & TWSI_CONTROL_STOP_BIT) != 0)       
209         {
210                 mvOsPrintf("TWSI: mvTwsiStopBitSet ERROR - stop bit didn't went down. \n");
211                 return MV_FAIL;
212         }
213         
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);
218                 return MV_FAIL;
219         }
220
221         return MV_OK;
222 }
223
224 /*******************************************************************************
225 * twsiMainIntGet - Get twsi bit from main Interrupt cause.
226 *
227 * DESCRIPTION:
228 *       This routine returns the twsi interrupt flag value.
229 *       
230 * INPUT:
231 *       None.
232 *
233 * OUTPUT:
234 *       None.
235 *
236 * RETURN:
237 *       MV_TRUE is interrupt flag is set, MV_FALSE otherwise.
238 *
239 *******************************************************************************/
240 static MV_BOOL twsiMainIntGet(MV_U8 chanNum)
241 {
242         MV_U32 temp;
243         
244         /* get the int flag bit */
245
246         temp = MV_REG_READ(TWSI_CPU_MAIN_INT_CAUSE_REG);
247         if (temp & (TWSI0_CPU_MAIN_INT_BIT << chanNum))
248             return MV_TRUE;
249     
250         return MV_FALSE;
251 }
252 /*******************************************************************************
253 * twsiIntFlgClr - Clear Interrupt flag.
254 *
255 * DESCRIPTION:
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.
259 *
260 * INPUT:
261 *       chanNum - TWSI channel
262 *
263 * OUTPUT:
264 *       None.
265 *
266 * RETURN:
267 *       None.
268 *
269 *******************************************************************************/
270 static MV_VOID twsiIntFlgClr(MV_U8 chanNum)
271 {
272         MV_U32 temp;
273
274         /* wait for 1 mili to prevent TWSI register write after write problems */
275         mvOsDelay(1);
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));
279
280         /* wait for 1 mili sec for the clear to take effect */
281         mvOsDelay(1);
282         
283         return;
284 }
285
286
287 /*******************************************************************************
288 * twsiAckBitSet - Set acknowledge bit on the bus
289 *
290 * DESCRIPTION:
291 *       This routine set the acknowledge bit on the TWSI bus.
292 *
293 * INPUT:
294 *       None.
295 *
296 * OUTPUT:
297 *       None.
298 *
299 * RETURN:
300 *       None.
301 *
302 *******************************************************************************/
303 static MV_VOID twsiAckBitSet(MV_U8 chanNum)
304 {
305         MV_U32 temp;
306
307         /*Set the Ack bit */
308         temp = MV_REG_READ(TWSI_CONTROL_REG(chanNum));
309         MV_REG_WRITE(TWSI_CONTROL_REG(chanNum), temp | TWSI_CONTROL_ACK);
310
311         /* Add delay of 1ms */
312         mvOsDelay(1);
313         return;
314 }
315
316
317 /*******************************************************************************
318 * twsiInit - Initialize TWSI interface
319 *
320 * DESCRIPTION:
321 *       This routine:
322 *       -Reset the TWSI.
323 *       -Initialize the TWSI clock baud rate according to given frequancy
324 *        parameter based on Tclk frequancy and enables TWSI slave.
325 *       -Set the ack bit.
326 *       -Assign the TWSI slave address according to the TWSI address Type.
327 *       
328 *
329 * INPUT:
330 *       chanNum - TWSI channel
331 *       frequancy - TWSI frequancy in KHz. (up to 100KHZ)
332 *
333 * OUTPUT:
334 *       None.
335 *
336 * RETURN:
337 *       Actual frequancy.
338 *
339 *******************************************************************************/
340 MV_U32 mvTwsiInit(MV_U8 chanNum, MV_HZ frequancy, MV_U32 Tclk, MV_TWSI_ADDR *pTwsiAddr, MV_BOOL generalCallEnable)
341 {
342         MV_U32  n,m,freq,margin,minMargin = 0xffffffff;
343         MV_U32  power;
344         MV_U32  actualFreq = 0,actualN = 0,actualM = 0,val;
345
346         if(frequancy > 100000)
347         {
348                 mvOsPrintf("Warning TWSI frequancy is too high, please use up tp 100Khz. \n");
349         }
350
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++)
354         {
355                 for(m = 0 ; m < 16 ; m++)
356                 {
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)
361                         {
362                                 minMargin   = margin;
363                                 actualFreq  = freq;
364                                 actualN     = n;
365                                 actualM     = m;
366                         }
367                 }
368                 }
369         DB(mvOsPrintf("TWSI: mvTwsiInit - actN %d actM %d actFreq %d\n",actualN , actualM, actualFreq));
370         /* Reset the TWSI logic */
371         twsiReset(chanNum);
372
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);
376
377         /* Enable the TWSI and slave */
378         MV_REG_WRITE(TWSI_CONTROL_REG(chanNum), TWSI_CONTROL_ENA | TWSI_CONTROL_ACK); 
379
380         /* set the TWSI slave address */
381         if( pTwsiAddr->type == ADDR10_BIT )/* 10 Bit deviceAddress */
382         {
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;
387                 /* set GCE bit */
388                 if(generalCallEnable)
389                         val |= TWSI_SLAVE_ADDR_GCE_ENA;
390                 /* write slave address */
391                 MV_REG_WRITE(TWSI_SLAVE_ADDR_REG(chanNum),val);
392
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);
396         }
397         else /*7 bit address*/
398         {
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);
403         }
404
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 */
409         mvOsDelay(1);
410         
411    return actualFreq;
412
413
414
415 /*******************************************************************************
416 * twsiStsGet - Get the TWSI status value.
417 *
418 * DESCRIPTION:
419 *       This routine returns the TWSI status value.
420 *
421 * INPUT:
422 *       chanNum - TWSI channel
423 *
424 * OUTPUT:
425 *       None.
426 *
427 * RETURN:
428 *       MV_U32 - the TWSI status.
429 *
430 *******************************************************************************/
431 static MV_U32 twsiStsGet(MV_U8 chanNum)
432 {
433     return MV_REG_READ(TWSI_STATUS_BAUDE_RATE_REG(chanNum));
434
435 }
436
437 /*******************************************************************************
438 * twsiReset - Reset the TWSI.
439 *
440 * DESCRIPTION:
441 *       Resets the TWSI logic and sets all TWSI registers to their reset values.
442 *
443 * INPUT:
444 *      chanNum - TWSI channel
445 *
446 * OUTPUT:
447 *       None.
448 *
449 * RETURN:
450 *       None
451 *
452 *******************************************************************************/
453 static MV_VOID twsiReset(MV_U8 chanNum)
454 {
455         /* Reset the TWSI logic */
456         MV_REG_WRITE(TWSI_SOFT_RESET_REG(chanNum),0);
457
458         /* wait for 2 mili sec */
459         mvOsDelay(2);
460
461         return;
462 }
463
464
465
466
467 /******************************* POLICY ****************************************/
468
469
470
471 /*******************************************************************************
472 * mvTwsiAddrSet - Set address on TWSI bus.
473 *
474 * DESCRIPTION:
475 *       This function Set address (7 or 10 Bit address) on the Twsi Bus.
476 *
477 * INPUT:
478 *       chanNum - TWSI channel
479 *       pTwsiAddr - twsi address.
480 *       command  - read / write .
481 *
482 * OUTPUT:
483 *       None.
484 *
485 * RETURN:
486 *       MV_OK - if setting the address completed succesfully.
487 *       MV_FAIL otherwmise.
488 *
489 *******************************************************************************/
490 MV_STATUS mvTwsiAddrSet(MV_U8 chanNum, MV_TWSI_ADDR *pTwsiAddr, MV_TWSI_CMD command)
491 {
492         DB(mvOsPrintf("TWSI: mvTwsiAddr7BitSet addr %x , type %d, cmd is %s\n",pTwsiAddr->address,\
493                                         pTwsiAddr->type, ((command==MV_TWSI_WRITE)?"Write":"Read") ));
494         /* 10 Bit address */
495         if(pTwsiAddr->type == ADDR10_BIT)
496         {
497                 return twsiAddr10BitSet(chanNum, pTwsiAddr->address,command);
498         }
499         /* 7 Bit address */
500         else
501         {
502                 return twsiAddr7BitSet(chanNum, pTwsiAddr->address,command);
503         }
504
505 }
506
507 /*******************************************************************************
508 * twsiAddr10BitSet - Set 10 Bit address on TWSI bus.
509 *
510 * DESCRIPTION:
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. 
521 *
522 * INPUT:
523 *       chanNum - TWSI channel
524 *       deviceAddress - twsi address.
525 *       command  - read / write .
526 *
527 * OUTPUT:
528 *       None.
529 *
530 * RETURN:
531 *       MV_OK - if setting the address completed succesfully.
532 *       MV_FAIL otherwmise.
533 *
534 *******************************************************************************/
535 static MV_STATUS twsiAddr10BitSet(MV_U8 chanNum, MV_U32 deviceAddress,MV_TWSI_CMD command)
536 {
537         MV_U32 val,timeout;
538
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;
543         /* set command */
544         val |= command;
545         MV_REG_WRITE(TWSI_DATA_REG(chanNum), val);
546         /* WA add a delay */
547         mvOsDelay(1);
548
549         /* clear Int flag */
550         twsiIntFlgClr(chanNum);
551
552         /* wait for Int to be Set */
553         timeout = 0;
554         while( !twsiMainIntGet(chanNum) && (timeout++ < TWSI_TIMEOUT_VALUE));
555
556         /* check for timeout */
557         if(MV_TRUE == twsiTimeoutChk(timeout,"TWSI: twsiAddr10BitSet ERROR - 1st addr (10Bit) Int TimeOut.\n"))
558                 return MV_TIMEOUT;
559         
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) ))
564         {
565                 mvOsPrintf("TWSI: twsiAddr10BitSet ERROR - status %x 1st addr (10 Bit) in %s mode.\n"\
566                                                 ,val, ((command==MV_TWSI_WRITE)?"Write":"Read") );
567                 return MV_FAIL;
568         }
569
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);
573
574         /* clear Int flag */
575         twsiIntFlgClr(chanNum);
576
577         /* wait for Int to be Set */
578         timeout = 0;
579         while( !twsiMainIntGet(chanNum) && (timeout++ < TWSI_TIMEOUT_VALUE));
580
581         /* check for timeout */
582         if(MV_TRUE == twsiTimeoutChk(timeout,"TWSI: twsiAddr10BitSet ERROR - 2nd (10 Bit) Int TimOut.\n"))
583                 return MV_TIMEOUT;
584         
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) ))
589         {
590                 mvOsPrintf("TWSI: twsiAddr10BitSet ERROR - status %x 2nd addr(10 Bit) in %s mode.\n"\
591                                                 ,val, ((command==MV_TWSI_WRITE)?"Write":"Read") );
592                 return MV_FAIL;
593         }
594         
595         return MV_OK;
596 }
597
598 /*******************************************************************************
599 * twsiAddr7BitSet - Set 7 Bit address on TWSI bus.
600 *
601 * DESCRIPTION:
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.
606 *
607 * INPUT:
608 *       chanNum - TWSI channel
609 *       deviceAddress - twsi address.
610 *       command  - read / write .
611 *
612 * OUTPUT:
613 *       None.
614 *
615 * RETURN:
616 *       MV_OK - if setting the address completed succesfully.
617 *       MV_FAIL otherwmise.
618 *
619 *******************************************************************************/
620 static MV_STATUS twsiAddr7BitSet(MV_U8 chanNum, MV_U32 deviceAddress,MV_TWSI_CMD command)
621 {
622         MV_U32 val,timeout;
623
624         /* set the address */
625         val = (deviceAddress << TWSI_DATA_ADDR_7BIT_OFFS) & TWSI_DATA_ADDR_7BIT_MASK;
626         /* set command */
627         val |= command; 
628         MV_REG_WRITE(TWSI_DATA_REG(chanNum), val);
629         /* WA add a delay */
630         mvOsDelay(1);
631
632         /* clear Int flag */
633         twsiIntFlgClr(chanNum);
634
635         /* wait for Int to be Set */
636         timeout = 0;
637         while( !twsiMainIntGet(chanNum) && (timeout++ < TWSI_TIMEOUT_VALUE));
638
639         /* check for timeout */
640         if(MV_TRUE == twsiTimeoutChk(timeout,"TWSI: twsiAddr7BitSet ERROR - Addr (7 Bit) int TimeOut.\n"))
641                 return MV_TIMEOUT;
642         
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) ))
647         {
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") ));
652                 return MV_FAIL;
653         }
654         
655         return MV_OK;
656 }
657
658 /*******************************************************************************
659 * twsiDataWrite - Trnasmit a data block over TWSI bus.
660 *
661 * DESCRIPTION:
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 
668 *        0x28 to be set. 
669 *      
670 *
671 * INPUT:
672 *       chanNum - TWSI channel
673 *       pBlock - Data block.
674 *       blockSize - number of chars in pBlock.
675 *
676 * OUTPUT:
677 *       None.
678 *
679 * RETURN:
680 *       MV_OK - if transmiting the block completed succesfully,
681 *       MV_BAD_PARAM - if pBlock is NULL,
682 *       MV_FAIL otherwmise.
683 *
684 *******************************************************************************/
685 static MV_STATUS twsiDataTransmit(MV_U8 chanNum, MV_U8 *pBlock, MV_U32 blockSize)
686 {
687         MV_U32 timeout, temp, blockSizeWr = blockSize;
688
689         if(NULL == pBlock)
690                 return MV_BAD_PARAM;
691
692         /* wait for Int to be Set */
693         timeout = 0;
694         while( !twsiMainIntGet(chanNum) && (timeout++ < TWSI_TIMEOUT_VALUE));
695
696         /* check for timeout */
697         if(MV_TRUE == twsiTimeoutChk(timeout,"TWSI: twsiDataTransmit ERROR - Read Data Int TimeOut.\n"))
698                 return MV_TIMEOUT;
699
700         while(blockSizeWr)
701         {
702                 /* write the data*/
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));
706                 pBlock++;
707                 blockSizeWr--;
708
709                 twsiIntFlgClr(chanNum);
710
711                 /* wait for Int to be Set */
712                 timeout = 0;
713                 while( !twsiMainIntGet(chanNum) && (timeout++ < TWSI_TIMEOUT_VALUE));
714
715                 /* check for timeout */
716                 if(MV_TRUE == twsiTimeoutChk(timeout,"TWSI: twsiDataTransmit ERROR - Read Data Int TimeOut.\n"))
717                         return MV_TIMEOUT;
718
719                 /* check the status */
720                 temp = twsiStsGet(chanNum);
721                 if(temp != TWSI_M_TRAN_DATA_BYTE_ACK_REC) 
722                 {
723                         mvOsPrintf("TWSI: twsiDataTransmit ERROR - status %x in write trans\n",temp);
724                         return MV_FAIL;
725                 }
726                 
727         }
728
729         return MV_OK;
730 }
731
732 /*******************************************************************************
733 * twsiDataReceive - Receive data block from TWSI bus.
734 *
735 * DESCRIPTION:
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 
745 *        the given buffer. 
746 *
747 * INPUT:
748 *       chanNum - TWSI channel
749 *       blockSize - number of bytes to read.
750 *
751 * OUTPUT:
752 *       pBlock - Data block.
753 *
754 * RETURN:
755 *       MV_OK - if receive transaction completed succesfully,
756 *       MV_BAD_PARAM - if pBlock is NULL,
757 *       MV_FAIL otherwmise.
758 *
759 *******************************************************************************/
760 static MV_STATUS twsiDataReceive(MV_U8 chanNum, MV_U8 *pBlock, MV_U32 blockSize)
761 {
762         MV_U32 timeout, temp, blockSizeRd = blockSize;
763         if(NULL == pBlock)
764                 return MV_BAD_PARAM;
765
766         /* wait for Int to be Set */
767         timeout = 0;
768         while( !twsiMainIntGet(chanNum) && (timeout++ < TWSI_TIMEOUT_VALUE));
769
770         /* check for timeout */
771         if(MV_TRUE == twsiTimeoutChk(timeout,"TWSI: twsiDataReceive ERROR - Read Data int Time out .\n"))
772                 return MV_TIMEOUT;
773
774         while(blockSizeRd)
775         {
776                 if(blockSizeRd == 1)
777                 {
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);
782                 }
783                 twsiIntFlgClr(chanNum);
784                 /* wait for Int to be Set */
785                 timeout = 0;
786                 while( (!twsiMainIntGet(chanNum)) && (timeout++ < TWSI_TIMEOUT_VALUE));
787
788                 /* check for timeout */
789                 if(MV_TRUE == twsiTimeoutChk(timeout,"TWSI: twsiDataReceive ERROR - Read Data Int Time out .\n"))
790                         return MV_TIMEOUT;
791
792                 /* check the status */
793                 temp = twsiStsGet(chanNum);
794                 if((temp != TWSI_M_REC_RD_DATA_ACK_TRA) && (blockSizeRd !=1))
795                 {
796                         mvOsPrintf("TWSI: twsiDataReceive ERROR - status %x in read trans \n",temp);
797                         return MV_FAIL;
798                 }
799                 else if((temp != TWSI_M_REC_RD_DATA_ACK_NOT_TRA) && (blockSizeRd ==1))
800                 {
801                         mvOsPrintf("TWSI: twsiDataReceive ERROR - status %x in Rd Terminate\n",temp);
802                         return MV_FAIL;
803                 }
804                 
805                 /* read the data*/
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));
809                 pBlock++;
810                 blockSizeRd--;
811         }
812
813         return MV_OK;
814 }
815
816
817
818 /*******************************************************************************
819 * twsiTargetOffsSet - Set TWST target offset on TWSI bus.
820 *
821 * DESCRIPTION:
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
827 *               in 2 transactions.
828 *       2) Use twsiDataTransmit to place those on the bus.
829 *
830 * INPUT:
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. 
834 *
835 * OUTPUT:
836 *       None.
837 *
838 * RETURN:
839 *       MV_OK - if setting the offset completed succesfully.
840 *       MV_FAIL otherwmise.
841 *
842 *******************************************************************************/
843 static MV_STATUS twsiTargetOffsSet(MV_U8 chanNum, MV_U32 offset, MV_BOOL moreThen256)
844 {
845         MV_U8 offBlock[2];
846         MV_U32 offSize;
847
848         if(moreThen256 == MV_TRUE)
849         {
850                 offBlock[0] = (offset >> 8) & 0xff;
851                 offBlock[1] = offset & 0xff;
852                 offSize = 2;
853         }
854         else
855         {
856                 offBlock[0] = offset & 0xff;
857                 offSize = 1;
858         }
859         DB(mvOsPrintf("TWSI: twsiTargetOffsSet offSize = %x addr1 = %x addr2 = %x\n",\
860                                                         offSize,offBlock[0],offBlock[1]));
861         return twsiDataTransmit(chanNum, offBlock, offSize);
862
863 }
864
865 /*******************************************************************************
866 * mvTwsiRead - Read data block from a TWSI Slave.
867 *
868 * DESCRIPTION:
869 *       The function calls the following functions:
870 *       -) mvTwsiStartBitSet();
871 *       if(EEPROM device)
872 *               -) mvTwsiAddrSet(w);
873 *               -) twsiTargetOffsSet();
874 *               -) mvTwsiStartBitSet();
875 *       -) mvTwsiAddrSet(r);
876 *       -) twsiDataReceive();
877 *       -) mvTwsiStopBitSet();
878 *
879 * INPUT:
880 *       chanNum - TWSI channel
881 *       pTwsiSlave - Twsi Slave structure. 
882 *       blockSize - number of bytes to read.    
883 *
884 * OUTPUT:
885 *       pBlock - Data block.
886 *
887 * RETURN:
888 *       MV_OK - if EEPROM read transaction completed succesfully,
889 *       MV_BAD_PARAM - if pBlock is NULL,
890 *       MV_FAIL otherwmise.
891 *
892 *******************************************************************************/
893 MV_STATUS mvTwsiRead(MV_U8 chanNum, MV_TWSI_SLAVE *pTwsiSlave, MV_U8 *pBlock, MV_U32 blockSize)
894 {
895         if((NULL == pBlock) || (NULL == pTwsiSlave))
896                 return MV_BAD_PARAM;
897         if(MV_OK != mvTwsiStartBitSet(chanNum))
898         {
899                 mvTwsiStopBitSet(chanNum);
900                  return MV_FAIL;
901         }
902         
903         DB(mvOsPrintf("TWSI: mvTwsiEepromRead after mvTwsiStartBitSet\n"));
904         
905         /* in case offset exsist (i.e. eeprom ) */
906         if(MV_TRUE == pTwsiSlave->validOffset)
907         {
908                 if(MV_OK != mvTwsiAddrSet(chanNum, &(pTwsiSlave->slaveAddr), MV_TWSI_WRITE)) 
909                 {
910                         mvTwsiStopBitSet(chanNum);
911                         return MV_FAIL;
912                 } 
913                 DB(mvOsPrintf("TWSI: mvTwsiEepromRead after mvTwsiAddrSet\n"));
914                 if(MV_OK != twsiTargetOffsSet(chanNum, pTwsiSlave->offset, pTwsiSlave->moreThen256)) 
915                 {
916                         mvTwsiStopBitSet(chanNum);
917                         return MV_FAIL;
918                 }
919                 DB(mvOsPrintf("TWSI: mvTwsiEepromRead after twsiTargetOffsSet\n"));
920                 if(MV_OK != mvTwsiStartBitSet(chanNum)) 
921                 {
922                         mvTwsiStopBitSet(chanNum);
923                         return MV_FAIL;
924                 }
925                 DB(mvOsPrintf("TWSI: mvTwsiEepromRead after mvTwsiStartBitSet\n"));
926         }
927         if(MV_OK != mvTwsiAddrSet(chanNum, &(pTwsiSlave->slaveAddr), MV_TWSI_READ)) 
928         {
929                 mvTwsiStopBitSet(chanNum);
930                 return MV_FAIL;
931         } 
932         DB(mvOsPrintf("TWSI: mvTwsiEepromRead after mvTwsiAddrSet\n"));
933         if(MV_OK != twsiDataReceive(chanNum, pBlock, blockSize))
934         {
935                 mvTwsiStopBitSet(chanNum);
936                 return MV_FAIL;
937         }
938         DB(mvOsPrintf("TWSI: mvTwsiEepromRead after twsiDataReceive\n"));
939
940         if(MV_OK != mvTwsiStopBitSet(chanNum))
941         {
942                 return MV_FAIL;
943         }
944
945         twsiAckBitSet(chanNum);
946
947         DB(mvOsPrintf("TWSI: mvTwsiEepromRead after mvTwsiStopBitSet\n"));
948
949         return MV_OK;
950 }
951
952 /*******************************************************************************
953 * mvTwsiWrite - Write data block to a TWSI Slave.
954 *
955 * DESCRIPTION:
956 *       The function calls the following functions:
957 *       -) mvTwsiStartBitSet();
958 *       -) mvTwsiAddrSet();
959 *       -)if(EEPROM device)
960 *               -) twsiTargetOffsSet();
961 *       -) twsiDataTransmit();
962 *       -) mvTwsiStopBitSet();
963 *
964 * INPUT:
965 *       chanNum - TWSI channel
966 *       eepromAddress - eeprom address. 
967 *       blockSize - number of bytes to write.   
968 *       pBlock - Data block.
969 *
970 * OUTPUT:
971 *       None
972 *
973 * RETURN:
974 *       MV_OK - if EEPROM read transaction completed succesfully.
975 *       MV_BAD_PARAM - if pBlock is NULL,
976 *       MV_FAIL otherwmise.
977 *
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)
982 {
983         if((NULL == pBlock) || (NULL == pTwsiSlave))
984                 return MV_BAD_PARAM;
985
986         if(MV_OK != mvTwsiStartBitSet(chanNum)) 
987         {
988                 mvTwsiStopBitSet(chanNum);
989                 return MV_FAIL;
990         }
991
992         DB(mvOsPrintf("TWSI: mvTwsiEepromWrite after mvTwsiStartBitSet\n"));
993         if(MV_OK != mvTwsiAddrSet(chanNum, &(pTwsiSlave->slaveAddr), MV_TWSI_WRITE))
994         {
995                 mvTwsiStopBitSet(chanNum);
996                 return MV_FAIL;
997         }
998         DB(mvOsPrintf("TWSI :mvTwsiEepromWrite after mvTwsiAddrSet\n"));
999
1000         /* in case offset exsist (i.e. eeprom ) */
1001         if(MV_TRUE == pTwsiSlave->validOffset)
1002         {
1003                 if(MV_OK != twsiTargetOffsSet(chanNum, pTwsiSlave->offset, pTwsiSlave->moreThen256)) 
1004                 {
1005                         mvTwsiStopBitSet(chanNum);
1006                         return MV_FAIL;
1007                 }
1008                 DB(mvOsPrintf("TWSI: mvTwsiEepromWrite after twsiTargetOffsSet\n"));
1009         }
1010         if(MV_OK != twsiDataTransmit(chanNum, pBlock, blockSize)) 
1011         {
1012                 mvTwsiStopBitSet(chanNum);
1013                 return MV_FAIL;
1014         }
1015         DB(mvOsPrintf("TWSI: mvTwsiEepromWrite after twsiDataTransmit\n"));
1016         if(MV_OK != mvTwsiStopBitSet(chanNum)) 
1017         {
1018                 return MV_FAIL;
1019         }
1020         DB(mvOsPrintf("TWSI: mvTwsiEepromWrite after mvTwsiStopBitSet\n"));
1021
1022         return MV_OK;
1023 }