add OCF 20100325 support to brcm-2.4
[openwrt/openwrt.git] / target / linux / generic-2.4 / 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 }