Root/target/linux/generic/files/crypto/ocf/kirkwood/mvHal/mv_hal/twsi/mvTwsi.c

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#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
78static MV_VOID twsiIntFlgClr(MV_U8 chanNum);
79static MV_BOOL twsiMainIntGet(MV_U8 chanNum);
80static MV_VOID twsiAckBitSet(MV_U8 chanNum);
81static MV_U32 twsiStsGet(MV_U8 chanNum);
82static MV_VOID twsiReset(MV_U8 chanNum);
83static MV_STATUS twsiAddr7BitSet(MV_U8 chanNum, MV_U32 deviceAddress,MV_TWSI_CMD command);
84static MV_STATUS twsiAddr10BitSet(MV_U8 chanNum, MV_U32 deviceAddress,MV_TWSI_CMD command);
85static MV_STATUS twsiDataTransmit(MV_U8 chanNum, MV_U8 *pBlock, MV_U32 blockSize);
86static MV_STATUS twsiDataReceive(MV_U8 chanNum, MV_U8 *pBlock, MV_U32 blockSize);
87static MV_STATUS twsiTargetOffsSet(MV_U8 chanNum, MV_U32 offset,MV_BOOL moreThen256);
88
89
90static 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*******************************************************************************/
124MV_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*******************************************************************************/
189MV_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*******************************************************************************/
240static 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*******************************************************************************/
270static 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*******************************************************************************/
303static 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*******************************************************************************/
340MV_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*******************************************************************************/
431static 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*******************************************************************************/
453static 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*******************************************************************************/
490MV_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*******************************************************************************/
535static 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*******************************************************************************/
620static 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*******************************************************************************/
685static 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*******************************************************************************/
760static 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*******************************************************************************/
843static 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*******************************************************************************/
893MV_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*******************************************************************************/
981MV_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}
1024

Archive Download this file



interactive