source: svn/trunk/newcon3bcm2_21bu/nexus/modules/i2c/7552/src/nexus_i2c.c

Last change on this file was 2, checked in by phkim, 11 years ago

1.phkim

  1. revision copy newcon3sk r27
  • Property svn:executable set to *
File size: 59.8 KB
Line 
1/***************************************************************************
2*     (c)2004-2011 Broadcom Corporation
3*
4*  This program is the proprietary software of Broadcom Corporation and/or its licensors,
5*  and may only be used, duplicated, modified or distributed pursuant to the terms and
6*  conditions of a separate, written license agreement executed between you and Broadcom
7*  (an "Authorized License").  Except as set forth in an Authorized License, Broadcom grants
8*  no license (express or implied), right to use, or waiver of any kind with respect to the
9*  Software, and Broadcom expressly reserves all rights in and to the Software and all
10*  intellectual property rights therein.  IF YOU HAVE NO AUTHORIZED LICENSE, THEN YOU
11*  HAVE NO RIGHT TO USE THIS SOFTWARE IN ANY WAY, AND SHOULD IMMEDIATELY
12*  NOTIFY BROADCOM AND DISCONTINUE ALL USE OF THE SOFTWARE.
13*
14*  Except as expressly set forth in the Authorized License,
15*
16*  1.     This program, including its structure, sequence and organization, constitutes the valuable trade
17*  secrets of Broadcom, and you shall use all reasonable efforts to protect the confidentiality thereof,
18*  and to use this information only in connection with your use of Broadcom integrated circuit products.
19*
20*  2.     TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
21*  AND WITH ALL FAULTS AND BROADCOM MAKES NO PROMISES, REPRESENTATIONS OR
22*  WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO
23*  THE SOFTWARE.  BROADCOM SPECIFICALLY DISCLAIMS ANY AND ALL IMPLIED WARRANTIES
24*  OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE,
25*  LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION
26*  OR CORRESPONDENCE TO DESCRIPTION. YOU ASSUME THE ENTIRE RISK ARISING OUT OF
27*  USE OR PERFORMANCE OF THE SOFTWARE.
28*
29*  3.     TO THE MAXIMUM EXTENT PERMITTED BY LAW, IN NO EVENT SHALL BROADCOM OR ITS
30*  LICENSORS BE LIABLE FOR (i) CONSEQUENTIAL, INCIDENTAL, SPECIAL, INDIRECT, OR
31*  EXEMPLARY DAMAGES WHATSOEVER ARISING OUT OF OR IN ANY WAY RELATING TO YOUR
32*  USE OF OR INABILITY TO USE THE SOFTWARE EVEN IF BROADCOM HAS BEEN ADVISED OF
33*  THE POSSIBILITY OF SUCH DAMAGES; OR (ii) ANY AMOUNT IN EXCESS OF THE AMOUNT
34*  ACTUALLY PAID FOR THE SOFTWARE ITSELF OR U.S. $1, WHICHEVER IS GREATER. THESE
35*  LIMITATIONS SHALL APPLY NOTWITHSTANDING ANY FAILURE OF ESSENTIAL PURPOSE OF
36*  ANY LIMITED REMEDY.
37*
38* $brcm_Workfile: nexus_i2c.c $
39* $brcm_Revision: 12 $
40* $brcm_Date: 12/2/11 6:32p $
41*
42* API Description:
43*   API name: I2c
44*    Specific APIs related to I2c Control.
45*
46* Revision History:
47*
48* $brcm_Log: /nexus/modules/i2c/7425/src/nexus_i2c.c $
49*
50* 12   12/2/11 6:32p jtna
51* SW7425-1708: add i2c s3 standby power management
52*
53* 11   4/6/11 5:01p erickson
54* SW7420-1671: add warning
55*
56* 10   10/4/10 2:27p erickson
57* SW35230-1525: merge NEXUS_I2c_WriteRead
58*
59* SW35230-1525/1   9/30/10 6:04p adtran
60* SW35230-1525: add new NEXUS_I2c_WriteRead API
61*
62* 9   10/22/09 2:36p erickson
63* SW7405-2686: add softI2c support
64*
65* 8   9/25/09 3:56p erickson
66* SW7405-3038: added NEXUS_I2c_SwReset
67*
68* 7   4/2/09 11:36a erickson
69* PR51899: merge
70*
71* PR51899/1   3/31/09 2:41p vle
72* PR51899: Add I2C_ReadSwEDDC support to nexus
73*
74* 6   2/18/09 9:38a erickson
75* PR52223: add NEXUS_I2c_SetSettings
76*
77* 5   1/26/09 12:05p erickson
78* PR51468: global variable naming convention
79*
80* 4   12/16/08 2:54p erickson
81* PR48497: merge
82*
83* HDMI_TX_Plugfest11_200811/1   11/13/08 7:35p vle
84* PR 48987: Add run time option to enable I2C bit bang mode.
85*
86* 3   4/24/08 9:54a erickson
87* PR41989: added NEXUS_I2c_ReadNoAddrNoAck
88*
89* 2   4/11/08 9:53a erickson
90* PR41246: convert BDBG_OBJECT_UNSET to BDBG_OBJECT_DESTROY if freeing
91*  memory
92*
93* 1   1/18/08 2:21p jgarrett
94* PR 38808: Merging to main branch
95*
96* Nexus_Devel/5   11/7/07 9:44a erickson
97* PR36725: use BDBG_OBJECT instead of just checking handle != NULL
98*
99* Nexus_Devel/4   11/5/07 2:12p erickson
100* PR36725: remove NEXUS_I2c_Get
101*
102* Nexus_Devel/3   10/10/07 11:29a jgarrett
103* PR 35551: Revising I2C Handle for synchronization purposes
104*
105* Nexus_Devel/2   10/5/07 5:52p jgarrett
106* PR 35744: Removing debug timeout
107*
108* Nexus_Devel/1   10/5/07 1:42p jgarrett
109* PR 35744: Adding i2c module
110*
111* Nexus_Devel/2   9/12/07 4:35p jgarrett
112* PR 34702: Adding I2C interface
113*
114* Nexus_Devel/1   9/12/07 10:39a jgarrett
115* PR 34702: Adding initial IO headers
116*
117***************************************************************************/
118
119#include "nexus_i2c_module.h"
120#include "breg_i2c.h"
121#include "bi2c.h"
122#include "priv/nexus_core.h"
123#include "nexus_base.h"
124#include "nexus_platform_features.h"
125#include "breg_i2c_priv.h"  /* For BREG_I2C_Impl */
126
127BDBG_MODULE(nexus_i2c);
128
129BDBG_OBJECT_ID(NEXUS_I2c);
130
131typedef struct NEXUS_I2c
132{
133    BDBG_OBJECT(NEXUS_I2c)
134    BI2C_ChannelHandle channel; /* Set only for local masters, NULL otherwise */
135    NEXUS_ModuleHandle owner;   /* The module that created this handle.  Required for synchronization decisions. */
136    BREG_I2C_Impl syncReg;      /* A pointer to this will be returned when someone other than the module owner requests a handle */
137    BREG_I2C_Impl asyncReg;     /* A pointer to this will be returned when the module owner requests a handle */
138    NEXUS_I2cSettings settings;
139    bool s3standby;
140} NEXUS_I2c;
141
142static NEXUS_I2c g_localI2cChannels[NEXUS_NUM_I2C_CHANNELS];
143
144static void NEXUS_I2c_P_FillSyncRegHandle(
145    NEXUS_I2c *pI2cDevice,
146    NEXUS_ModuleHandle moduleHandle
147    );
148
149/***************************************************************************
150Summary:
151    This function gets the default settings for an I2C channel.
152
153Description:
154    This function is responsible for returning the default setting for
155    an I2C channel.
156
157See Also:
158    NEXUS_I2c_Open()
159
160****************************************************************************/
161void NEXUS_I2c_GetDefaultSettings(
162    NEXUS_I2cSettings *pSettings    /* [out] */
163    )
164{
165    BI2C_ChannelSettings channelSettings;
166
167    BDBG_ASSERT(NULL != pSettings);
168
169    BI2C_GetChannelDefaultSettings(g_NEXUS_i2cHandle, 0, &channelSettings);
170
171    pSettings->clockRate = (NEXUS_I2cClockRate)channelSettings.clkRate;
172    pSettings->interruptMode = channelSettings.intMode;
173    pSettings->timeout = channelSettings.timeoutMs;
174    pSettings->burstMode = channelSettings.burstMode;
175    pSettings->softI2c = channelSettings.softI2c;
176    BDBG_MSG(("Default Settings - clk %d, int %d, timeout %d, burst %d, soft i2c %d",
177              pSettings->clockRate, pSettings->interruptMode, pSettings->timeout, pSettings->burstMode, pSettings->softI2c));
178}
179
180/***************************************************************************
181Summary:
182    This function opens an I2c channel.
183
184Description:
185    This function opens an I2c channel.
186
187See Also:
188    NEXUS_I2c_Close(), NEXUS_I2c_GetDefaultSettings()
189****************************************************************************/
190NEXUS_I2cHandle NEXUS_I2c_Open(
191    unsigned channelIndex,
192    const NEXUS_I2cSettings *pSettings
193    )
194{
195    BERR_Code errCode;
196    NEXUS_I2cSettings settings;
197    BI2C_ChannelSettings channelSettings;
198    BREG_I2C_Handle regHandle;
199    NEXUS_I2cHandle i2cHandle;
200
201    if ( channelIndex >= NEXUS_NUM_I2C_CHANNELS )
202    {
203        BDBG_ERR(("Channel index %u out of range", channelIndex));
204        errCode = BERR_TRACE(BERR_INVALID_PARAMETER);
205        return NULL;
206    }
207
208    i2cHandle = &g_localI2cChannels[channelIndex];
209    if ( NULL != i2cHandle->channel )
210    {
211        BDBG_ERR(("Channel already opened."));
212        errCode = BERR_TRACE(BERR_INVALID_PARAMETER);
213        return NULL;
214    }
215
216    if ( NULL == pSettings )
217    {
218        NEXUS_I2c_GetDefaultSettings(&settings);
219        pSettings = &settings;
220    }
221
222    BKNI_Memset(i2cHandle, 0, sizeof(NEXUS_I2c));
223    BDBG_OBJECT_SET(i2cHandle, NEXUS_I2c);
224    i2cHandle->settings = *pSettings;
225
226    BDBG_CASSERT(BI2C_Clk_eClk400Khz == NEXUS_I2cClockRate_e400Khz);
227    channelSettings.clkRate = pSettings->clockRate;
228    channelSettings.intMode = pSettings->interruptMode;
229    channelSettings.timeoutMs = pSettings->timeout;
230    channelSettings.burstMode = pSettings->burstMode;
231    channelSettings.softI2c = pSettings->softI2c;
232    BDBG_MSG(("Open I2C Channel %d: clk %d, int %d, timeout %d, burst %d, softI2c %d",
233        channelIndex, channelSettings.clkRate, channelSettings.intMode, channelSettings.timeoutMs, channelSettings.burstMode, channelSettings.softI2c));
234    errCode = BI2C_OpenChannel(g_NEXUS_i2cHandle, &i2cHandle->channel, channelIndex, &channelSettings);
235    if ( errCode )
236    {
237        BDBG_ERR(("Unable to open I2C Device Channel"));
238        errCode = BERR_TRACE(errCode);
239        goto err_channel;
240    }
241
242    errCode = BI2C_CreateI2cRegHandle(i2cHandle->channel, &regHandle);
243    if ( errCode )
244    {
245        BDBG_ERR(("Unable to create BREG I2C Handle"));
246        errCode = BERR_TRACE(errCode);
247        goto err_reg;
248    }
249
250    /* The default handle is our async version */
251    BKNI_Memcpy(&i2cHandle->asyncReg, regHandle, sizeof(BREG_I2C_Impl));
252    BI2C_CloseI2cRegHandle(regHandle);
253
254    /* Success */
255    NEXUS_I2c_P_FillSyncRegHandle(i2cHandle, NEXUS_MODULE_SELF);
256    return i2cHandle;
257
258err_reg:
259    BI2C_CloseChannel(i2cHandle->channel);
260    i2cHandle->channel = NULL;
261err_channel:
262    return NULL;
263}
264
265NEXUS_Error NEXUS_I2c_SetSettings( NEXUS_I2cHandle i2cHandle, const NEXUS_I2cSettings *pSettings)
266{
267    NEXUS_Error rc;
268
269    BDBG_OBJECT_ASSERT(i2cHandle, NEXUS_I2c);
270
271    BI2C_SetClk(i2cHandle->channel, pSettings->clockRate);
272
273    rc = BI2C_SetBurstMode(i2cHandle->channel, pSettings->burstMode);
274    if (rc) return BERR_TRACE(rc);
275
276    i2cHandle->settings = *pSettings;
277    return 0;
278}
279
280void NEXUS_I2c_GetSettings( NEXUS_I2cHandle i2cHandle, NEXUS_I2cSettings *pSettings)
281{
282    BDBG_OBJECT_ASSERT(i2cHandle, NEXUS_I2c);
283    *pSettings = i2cHandle->settings;
284}
285
286/***************************************************************************
287Summary:
288    This function closes an I2c channel.
289
290Description:
291    This function closes an I2c channel.
292
293See Also:
294    NEXUS_I2c_Open()
295
296****************************************************************************/
297void NEXUS_I2c_Close(
298    NEXUS_I2cHandle i2cHandle
299    )
300{
301    unsigned channelIndex;
302
303    BDBG_OBJECT_ASSERT(i2cHandle, NEXUS_I2c);
304
305    if ( i2cHandle < &g_localI2cChannels[0] ||
306         i2cHandle >= &g_localI2cChannels[NEXUS_NUM_I2C_CHANNELS] )
307    {
308        BDBG_ERR(("This channel was not opened with NEXUS_I2c_Open."));
309        return;
310    }
311
312    channelIndex = i2cHandle - (&g_localI2cChannels[0]);
313    BDBG_MSG(("Closing I2C Channel %u", channelIndex));
314
315    BDBG_ASSERT(NULL != i2cHandle->channel);
316
317    BI2C_CloseChannel(i2cHandle->channel);
318    BDBG_OBJECT_UNSET(i2cHandle, NEXUS_I2c);
319    BKNI_Memset(i2cHandle, 0, sizeof(NEXUS_I2c));
320}
321
322/*
323Summary:
324This function writes a programmable number of I2C registers using an 8 bit
325sub address.
326*/
327NEXUS_Error NEXUS_I2c_Write(
328    NEXUS_I2cHandle i2cHandle, /* I2C Handle */
329    uint16_t chipAddr, /* 7 or 10 bit chip address (_unshifted_) */
330    uint8_t subAddr, /* 8 bit sub address */
331    const uint8_t *pData, /* pointer to data to write */
332    size_t length /* number of bytes to write */
333    )
334{
335    NEXUS_Error errCode;
336    BREG_I2C_Handle regHandle;
337
338    BDBG_OBJECT_ASSERT(i2cHandle, NEXUS_I2c);
339
340    if ( i2cHandle->owner == NEXUS_MODULE_SELF )
341    {
342        regHandle = &i2cHandle->asyncReg;
343    }
344    else
345    {
346        NEXUS_UnlockModule();
347        regHandle = &i2cHandle->syncReg;
348    }
349
350    errCode = BREG_I2C_Write(regHandle, chipAddr, subAddr, pData, length);
351
352    if ( i2cHandle->owner != NEXUS_MODULE_SELF )
353    {
354        NEXUS_LockModule();
355    }
356
357    return errCode;
358}
359
360/*
361Summary:
362This function writes and read a programmable number of I2C registers using an 8 bit
363sub address in an atomic operation.
364*/
365NEXUS_Error NEXUS_I2c_WriteRead(
366    NEXUS_I2cHandle i2cHandle,
367    uint16_t chipAddr,
368    uint8_t subAddr,
369    const uint8_t *pWriteData,
370    size_t writeLength,
371    uint8_t *pReadData,
372    size_t readLength
373    )
374{
375    NEXUS_Error errCode;
376    BREG_I2C_Handle regHandle;
377
378    BDBG_OBJECT_ASSERT(i2cHandle, NEXUS_I2c);
379
380    if ( i2cHandle->owner == NEXUS_MODULE_SELF )
381    {
382        regHandle = &i2cHandle->asyncReg;
383    }
384    else
385    {
386        NEXUS_UnlockModule();
387        regHandle = &i2cHandle->syncReg;
388    }
389
390    errCode = BREG_I2C_WriteRead(regHandle, chipAddr, subAddr, pWriteData, writeLength, pReadData, readLength);
391
392    if ( i2cHandle->owner != NEXUS_MODULE_SELF )
393    {
394        NEXUS_LockModule();
395    }
396
397    return errCode;
398}
399
400/*
401Summary:
402This function writes a programmable number of I2C registers using an 8 bit
403sub address and no ack.
404*/
405NEXUS_Error NEXUS_I2c_WriteNoAck(
406    NEXUS_I2cHandle i2cHandle, /* I2C Handle */
407    uint16_t chipAddr, /* 7 or 10 bit chip address (_unshifted_) */
408    uint8_t subAddr, /* 8 bit sub address */
409    const uint8_t *pData, /* pointer to data to write */
410    size_t length /* number of bytes to write */
411    )
412{
413    BERR_Code errCode;
414    BREG_I2C_Handle regHandle;
415
416    BDBG_OBJECT_ASSERT(i2cHandle, NEXUS_I2c);
417
418    if ( i2cHandle->owner == NEXUS_MODULE_SELF )
419    {
420        regHandle = &i2cHandle->asyncReg;
421    }
422    else
423    {
424        NEXUS_UnlockModule();
425        regHandle = &i2cHandle->syncReg;
426    }
427
428    errCode = BREG_I2C_WriteNoAck(regHandle, chipAddr, subAddr, pData, length);
429
430    if ( i2cHandle->owner != NEXUS_MODULE_SELF )
431    {
432        NEXUS_LockModule();
433    }
434
435    return errCode;
436}
437
438/*
439Summary:
440This function writes a programmable number of I2C registers using a 16 bit
441sub address.
442*/
443NEXUS_Error NEXUS_I2c_WriteA16(
444    NEXUS_I2cHandle i2cHandle, /* I2C Handle */
445    uint16_t chipAddr, /* 7 or 10 bit chip address (_unshifted_) */
446    uint16_t subAddr, /* 16 bit sub address */
447    const uint8_t *pData, /* pointer to data to write */
448    size_t length /* number of bytes to write */
449    )
450{
451    BERR_Code errCode;
452    BREG_I2C_Handle regHandle;
453
454    BDBG_OBJECT_ASSERT(i2cHandle, NEXUS_I2c);
455
456    if ( i2cHandle->owner == NEXUS_MODULE_SELF )
457    {
458        regHandle = &i2cHandle->asyncReg;
459    }
460    else
461    {
462        NEXUS_UnlockModule();
463        regHandle = &i2cHandle->syncReg;
464    }
465
466    errCode = BREG_I2C_WriteA16(regHandle, chipAddr, subAddr, pData, length);
467
468    if ( i2cHandle->owner != NEXUS_MODULE_SELF )
469    {
470        NEXUS_LockModule();
471    }
472
473    return errCode;
474}
475
476/*
477Summary:
478This function writes a programmable number of I2C registers using a 24 bit
479sub address.
480*/
481NEXUS_Error NEXUS_I2c_WriteA24(
482    NEXUS_I2cHandle i2cHandle, /* I2C Handle */
483    uint16_t chipAddr, /* 7 or 10 bit chip address (_unshifted_) */
484    uint32_t subAddr, /* 24 bit sub address */
485    const uint8_t *pData, /* pointer to data to write */
486    size_t length /* number of bytes to write */
487    )
488{
489    BERR_Code errCode;
490    BREG_I2C_Handle regHandle;
491
492    BDBG_OBJECT_ASSERT(i2cHandle, NEXUS_I2c);
493
494    if ( i2cHandle->owner == NEXUS_MODULE_SELF )
495    {
496        regHandle = &i2cHandle->asyncReg;
497    }
498    else
499    {
500        NEXUS_UnlockModule();
501        regHandle = &i2cHandle->syncReg;
502    }
503
504    errCode = BREG_I2C_WriteA24(regHandle, chipAddr, subAddr, pData, length);
505
506    if ( i2cHandle->owner != NEXUS_MODULE_SELF )
507    {
508        NEXUS_LockModule();
509    }
510
511    return errCode;
512}
513
514/*
515Summary:
516This function writes a programmable number of I2C registers without a sub address
517(raw write).
518*/
519NEXUS_Error NEXUS_I2c_WriteNoAddr(
520    NEXUS_I2cHandle i2cHandle, /* I2C Handle */
521    uint16_t chipAddr, /* 7 or 10 bit chip address (_unshifted_) */
522    const uint8_t *pData, /* pointer to data to write */
523    size_t length /* number of bytes to write */
524    )
525{
526    BERR_Code errCode;
527    BREG_I2C_Handle regHandle;
528
529    BDBG_OBJECT_ASSERT(i2cHandle, NEXUS_I2c);
530
531    if ( i2cHandle->owner == NEXUS_MODULE_SELF )
532    {
533        regHandle = &i2cHandle->asyncReg;
534    }
535    else
536    {
537        NEXUS_UnlockModule();
538        regHandle = &i2cHandle->syncReg;
539    }
540
541    errCode = BREG_I2C_WriteNoAddr(regHandle, chipAddr, pData, length);
542
543    if ( i2cHandle->owner != NEXUS_MODULE_SELF )
544    {
545        NEXUS_LockModule();
546    }
547
548    return errCode;
549}
550
551/*
552Summary:
553This function writes a programmable number of I2C registers without a sub address
554(raw write), and without waiting for an ack.
555*/
556NEXUS_Error NEXUS_I2c_WriteNoAddrNoAck(
557    NEXUS_I2cHandle i2cHandle, /* I2C Handle */
558    uint16_t chipAddr, /* 7 or 10 bit chip address (_unshifted_) */
559    const uint8_t *pData, /* pointer to data to write */
560    size_t length /* number of bytes to write */
561    )
562{
563    BERR_Code errCode;
564    BREG_I2C_Handle regHandle;
565
566    BDBG_OBJECT_ASSERT(i2cHandle, NEXUS_I2c);
567
568    if ( i2cHandle->owner == NEXUS_MODULE_SELF )
569    {
570        regHandle = &i2cHandle->asyncReg;
571    }
572    else
573    {
574        NEXUS_UnlockModule();
575        regHandle = &i2cHandle->syncReg;
576    }
577
578    errCode = BREG_I2C_WriteNoAddrNoAck(regHandle, chipAddr, pData, length);
579
580    if ( i2cHandle->owner != NEXUS_MODULE_SELF )
581    {
582        NEXUS_LockModule();
583    }
584
585    return errCode;
586}
587
588/*
589Summary:
590This function writes an I2C NVRAM device using an 8 bit sub address.
591*/
592NEXUS_Error NEXUS_I2c_WriteNvram(
593    NEXUS_I2cHandle i2cHandle, /* I2C Handle */
594    uint16_t chipAddr, /* 7 or 10 bit chip address (_unshifted_) */
595    uint8_t subAddr, /* 8 bit sub address */
596    const uint8_t *pData, /* pointer to data to write */
597    size_t length /* number of bytes to write */
598    )
599{
600    BERR_Code errCode;
601    BREG_I2C_Handle regHandle;
602
603    BDBG_OBJECT_ASSERT(i2cHandle, NEXUS_I2c);
604
605    if ( i2cHandle->owner == NEXUS_MODULE_SELF )
606    {
607        regHandle = &i2cHandle->asyncReg;
608    }
609    else
610    {
611        NEXUS_UnlockModule();
612        regHandle = &i2cHandle->syncReg;
613    }
614
615    errCode = BREG_I2C_WriteNvram(regHandle, chipAddr, subAddr, pData, length);
616
617    if ( i2cHandle->owner != NEXUS_MODULE_SELF )
618    {
619        NEXUS_LockModule();
620    }
621
622    return errCode;
623}
624
625/*
626Summary:
627This function reads a programmable number of I2C registers using an 8 bit
628sub address.
629*/
630NEXUS_Error NEXUS_I2c_Read(
631    NEXUS_I2cHandle i2cHandle, /* I2C Handle */
632    uint16_t chipAddr, /* 7 or 10 bit chip address (_unshifted_) */
633    uint8_t subAddr, /* 8 bit sub address */
634    uint8_t *pData, /* pointer to memory location to store read data */
635    size_t length /* number of bytes to read */
636    )
637{
638    BERR_Code errCode;
639    BREG_I2C_Handle regHandle;
640
641    BDBG_OBJECT_ASSERT(i2cHandle, NEXUS_I2c);
642
643    if ( i2cHandle->owner == NEXUS_MODULE_SELF )
644    {
645        regHandle = &i2cHandle->asyncReg;
646    }
647    else
648    {
649        NEXUS_UnlockModule();
650        regHandle = &i2cHandle->syncReg;
651    }
652
653    errCode = BREG_I2C_Read(regHandle, chipAddr, subAddr, pData, length);
654
655    if ( i2cHandle->owner != NEXUS_MODULE_SELF )
656    {
657        NEXUS_LockModule();
658    }
659
660    return errCode;
661}
662
663/*
664Summary:
665This function reads a programmable number of I2C registers using an 8 bit
666sub address and no ack..
667*/
668NEXUS_Error NEXUS_I2c_ReadNoAck(
669    NEXUS_I2cHandle i2cHandle, /* I2C Handle */
670    uint16_t chipAddr, /* 7 or 10 bit chip address (_unshifted_) */
671    uint8_t subAddr, /* 8 bit sub address */
672    uint8_t *pData, /* pointer to memory location to store read data */
673    size_t length /* number of bytes to read */
674    )
675{
676    BERR_Code errCode;
677    BREG_I2C_Handle regHandle;
678
679    BDBG_OBJECT_ASSERT(i2cHandle, NEXUS_I2c);
680
681    if ( i2cHandle->owner == NEXUS_MODULE_SELF )
682    {
683        regHandle = &i2cHandle->asyncReg;
684    }
685    else
686    {
687        NEXUS_UnlockModule();
688        regHandle = &i2cHandle->syncReg;
689    }
690
691    errCode = BREG_I2C_ReadNoAck(regHandle, chipAddr, subAddr, pData, length);
692
693    if ( i2cHandle->owner != NEXUS_MODULE_SELF )
694    {
695        NEXUS_LockModule();
696    }
697
698    return errCode;
699}
700
701/*
702Summary:
703This function reads a programmable number of I2C registers using a 16 bit
704sub address.
705*/
706NEXUS_Error NEXUS_I2c_ReadA16(
707    NEXUS_I2cHandle i2cHandle, /* I2C Handle */
708    uint16_t chipAddr, /* 7 or 10 bit chip address (_unshifted_) */
709    uint16_t subAddr, /* 16 bit sub address */
710    uint8_t *pData, /* pointer to memory location to store read data */
711    size_t length /* number of bytes to read */
712    )
713{
714    BERR_Code errCode;
715    BREG_I2C_Handle regHandle;
716
717    BDBG_OBJECT_ASSERT(i2cHandle, NEXUS_I2c);
718
719    if ( i2cHandle->owner == NEXUS_MODULE_SELF )
720    {
721        regHandle = &i2cHandle->asyncReg;
722    }
723    else
724    {
725        NEXUS_UnlockModule();
726        regHandle = &i2cHandle->syncReg;
727    }
728
729    errCode = BREG_I2C_ReadA16(regHandle, chipAddr, subAddr, pData, length);
730
731    if ( i2cHandle->owner != NEXUS_MODULE_SELF )
732    {
733        NEXUS_LockModule();
734    }
735
736    return errCode;
737}
738
739/*
740Summary:
741This function reads a programmable number of I2C registers using a 24 bit
742sub address.
743*/
744NEXUS_Error NEXUS_I2c_ReadA24(
745    NEXUS_I2cHandle i2cHandle, /* I2C Handle */
746    uint16_t chipAddr, /* 7 or 10 bit chip address (_unshifted_) */
747    uint32_t subAddr, /* 32 bit sub address */
748    uint8_t *pData, /* pointer to memory location to store read data */
749    size_t length /* number of bytes to read */
750    )
751{
752    BERR_Code errCode;
753    BREG_I2C_Handle regHandle;
754
755    BDBG_OBJECT_ASSERT(i2cHandle, NEXUS_I2c);
756
757    if ( i2cHandle->owner == NEXUS_MODULE_SELF )
758    {
759        regHandle = &i2cHandle->asyncReg;
760    }
761    else
762    {
763        NEXUS_UnlockModule();
764        regHandle = &i2cHandle->syncReg;
765    }
766
767    errCode = BREG_I2C_ReadA24(regHandle, chipAddr, subAddr, pData, length);
768
769    if ( i2cHandle->owner != NEXUS_MODULE_SELF )
770    {
771        NEXUS_LockModule();
772    }
773
774    return errCode;
775}
776
777/*
778Summary:
779This function reads a programmable number of I2C registers without a sub address
780(raw read).
781*/
782NEXUS_Error NEXUS_I2c_ReadNoAddr(
783    NEXUS_I2cHandle i2cHandle, /* I2C Handle */
784    uint16_t chipAddr, /* 7 or 10 bit chip address (_unshifted_) */
785    uint8_t *pData, /* pointer to memory location to store read data */
786    size_t length /* number of bytes to read */
787    )
788{
789    BERR_Code errCode;
790    BREG_I2C_Handle regHandle;
791
792    BDBG_OBJECT_ASSERT(i2cHandle, NEXUS_I2c);
793
794    if ( i2cHandle->owner == NEXUS_MODULE_SELF )
795    {
796        regHandle = &i2cHandle->asyncReg;
797    }
798    else
799    {
800        NEXUS_UnlockModule();
801        regHandle = &i2cHandle->syncReg;
802    }
803
804    errCode = BREG_I2C_ReadNoAddr(regHandle, chipAddr, pData, length);
805
806    if ( i2cHandle->owner != NEXUS_MODULE_SELF )
807    {
808        NEXUS_LockModule();
809    }
810
811    return errCode;
812}
813
814NEXUS_Error NEXUS_I2c_ReadNoAddrNoAck(
815    NEXUS_I2cHandle i2cHandle, /* I2C Handle */
816    uint16_t chipAddr, /* 7 or 10 bit chip address (_unshifted_) */
817    uint8_t *pData, /* pointer to memory location to store read data */
818    size_t length /* number of bytes to read */
819    )
820{
821    BERR_Code errCode;
822    BREG_I2C_Handle regHandle;
823
824    BDBG_OBJECT_ASSERT(i2cHandle, NEXUS_I2c);
825
826    if ( i2cHandle->owner == NEXUS_MODULE_SELF )
827    {
828        regHandle = &i2cHandle->asyncReg;
829    }
830    else
831    {
832        NEXUS_UnlockModule();
833        regHandle = &i2cHandle->syncReg;
834    }
835
836    errCode = BREG_I2C_ReadNoAddrNoAck(regHandle, chipAddr, pData, length);
837
838    if ( i2cHandle->owner != NEXUS_MODULE_SELF )
839    {
840        NEXUS_LockModule();
841    }
842
843    return errCode;
844}
845
846/*
847Summary:
848This function is used to perform an Enhanced Display Data Channel read protocol.
849*/
850NEXUS_Error NEXUS_I2c_ReadEDDC(
851    NEXUS_I2cHandle i2cHandle,  /* I2C Handle */
852    uint8_t chipAddr,           /* chip address */
853    uint8_t segment,            /* EDDC segment pointer */
854    uint8_t subAddr,            /* 8-bit sub address */
855    uint8_t *pData,             /* pointer to memory location to store read data  */
856    size_t length               /* number of bytes to read */
857    )
858{
859    BERR_Code errCode;
860    BREG_I2C_Handle regHandle;
861
862    BDBG_OBJECT_ASSERT(i2cHandle, NEXUS_I2c);
863
864    if ( i2cHandle->owner == NEXUS_MODULE_SELF )
865    {
866        regHandle = &i2cHandle->asyncReg;
867    }
868    else
869    {
870        NEXUS_UnlockModule();
871        regHandle = &i2cHandle->syncReg;
872    }
873
874    errCode = BREG_I2C_ReadEDDC(regHandle, chipAddr, segment, subAddr, pData, length);
875
876    if ( i2cHandle->owner != NEXUS_MODULE_SELF )
877    {
878        NEXUS_LockModule();
879    }
880
881    return errCode;
882}
883
884/*
885Summary:
886This function is used to perform an Enhanced Display Data Channel write protocol.
887*/
888NEXUS_Error NEXUS_I2c_WriteEDDC(
889    NEXUS_I2cHandle i2cHandle,  /* I2C Handle */
890    uint8_t chipAddr,           /* chip address */
891    uint8_t segment,            /* EDDC segment pointer */
892    uint8_t subAddr,            /* 8-bit sub address */
893    const uint8_t *pData,       /* pointer to data to write */
894    size_t length               /* number of bytes to write */
895    )
896{
897    BERR_Code errCode;
898    BREG_I2C_Handle regHandle;
899
900    BDBG_OBJECT_ASSERT(i2cHandle, NEXUS_I2c);
901
902    if ( i2cHandle->owner == NEXUS_MODULE_SELF )
903    {
904        regHandle = &i2cHandle->asyncReg;
905    }
906    else
907    {
908        NEXUS_UnlockModule();
909        regHandle = &i2cHandle->syncReg;
910    }
911
912    errCode = BREG_I2C_WriteEDDC(regHandle, chipAddr, segment, subAddr, pData, length);
913
914    if ( i2cHandle->owner != NEXUS_MODULE_SELF )
915    {
916        NEXUS_LockModule();
917    }
918
919    return errCode;
920}
921
922void NEXUS_I2c_P_CloseAll(void)
923{
924    int i;
925
926    for ( i = 0; i < NEXUS_NUM_I2C_CHANNELS; i++ )
927    {
928        if ( NULL != g_localI2cChannels[i].channel )
929        {
930            NEXUS_I2c_Close(&g_localI2cChannels[i]);
931        }
932    }
933}
934
935/*
936Summary:
937This function writes a programmable number of I2C registers using an 8 bit
938sub address.
939*/
940static BERR_Code NEXUS_I2c_P_WriteSync(
941    void * i2cHandle, /* I2C Handle */
942    uint16_t chipAddr, /* 7 or 10 bit chip address (_unshifted_) */
943    uint8_t subAddr, /* 8 bit sub address */
944    const uint8_t *pData, /* pointer to data to write */
945    size_t length /* number of bytes to write */
946    )
947{
948    BERR_Code errCode;
949    NEXUS_I2c *pDevice = i2cHandle;
950
951    BDBG_ENTER(NEXUS_I2c_P_Write);
952
953    NEXUS_Module_Lock(pDevice->owner);
954
955    errCode = BREG_I2C_Write(&pDevice->asyncReg, chipAddr, subAddr, pData, length);
956
957    NEXUS_Module_Unlock(pDevice->owner);
958
959    BDBG_LEAVE(NEXUS_I2c_P_Write);
960    return errCode;
961}
962
963static BERR_Code NEXUS_I2c_P_WriteSwSync(
964    void * i2cHandle, /* I2C Handle */
965    uint16_t chipAddr, /* 7 or 10 bit chip address (_unshifted_) */
966    uint8_t subAddr, /* 8 bit sub address */
967    const uint8_t *pData, /* pointer to data to write */
968    size_t length /* number of bytes to write */
969    )
970{
971    BERR_Code errCode;
972    NEXUS_I2c *pDevice = i2cHandle;
973
974    BDBG_ENTER(NEXUS_I2c_P_WriteSw);
975
976    NEXUS_Module_Lock(pDevice->owner);
977
978    errCode = BREG_I2C_WriteSw(&pDevice->asyncReg, chipAddr, subAddr, pData, length);
979
980    NEXUS_Module_Unlock(pDevice->owner);
981
982    BDBG_LEAVE(NEXUS_I2c_P_WriteSw);
983    return errCode;
984}
985
986
987static BERR_Code NEXUS_I2c_P_WriteDummy(
988    void * i2cHandle, /* I2C Handle */
989    uint16_t chipAddr, /* 7 or 10 bit chip address (_unshifted_) */
990    uint8_t subAddr, /* 8 bit sub address */
991    const uint8_t *pData, /* pointer to data to write */
992    size_t length /* number of bytes to write */
993    )
994{
995    BSTD_UNUSED(i2cHandle);
996    BSTD_UNUSED(chipAddr);
997    BSTD_UNUSED(subAddr);
998    BSTD_UNUSED(pData);
999    BSTD_UNUSED(length);
1000    return BERR_TRACE(BERR_NOT_SUPPORTED);
1001}
1002
1003/*
1004Summary:
1005This function writes a programmable number of I2C registers using an 8 bit
1006sub address and no ack.
1007*/
1008static BERR_Code NEXUS_I2c_P_WriteNoAckSync(
1009    void * i2cHandle, /* I2C Handle */
1010    uint16_t chipAddr, /* 7 or 10 bit chip address (_unshifted_) */
1011    uint8_t subAddr, /* 8 bit sub address */
1012    const uint8_t *pData, /* pointer to data to write */
1013    size_t length /* number of bytes to write */
1014    )
1015{
1016    BERR_Code errCode;
1017    NEXUS_I2c *pDevice = i2cHandle;
1018
1019    BDBG_ENTER(NEXUS_I2c_P_Write);
1020
1021    NEXUS_Module_Lock(pDevice->owner);
1022
1023    errCode = BREG_I2C_WriteNoAck(&pDevice->asyncReg, chipAddr, subAddr, pData, length);
1024
1025    NEXUS_Module_Unlock(pDevice->owner);
1026
1027    BDBG_LEAVE(NEXUS_I2c_P_Write);
1028    return errCode;
1029}
1030static BERR_Code NEXUS_I2c_P_WriteNoAckDummy(
1031    void * i2cHandle, /* I2C Handle */
1032    uint16_t chipAddr, /* 7 or 10 bit chip address (_unshifted_) */
1033    uint8_t subAddr, /* 8 bit sub address */
1034    const uint8_t *pData, /* pointer to data to write */
1035    size_t length /* number of bytes to write */
1036    )
1037{
1038    BSTD_UNUSED(i2cHandle);
1039    BSTD_UNUSED(chipAddr);
1040    BSTD_UNUSED(subAddr);
1041    BSTD_UNUSED(pData);
1042    BSTD_UNUSED(length);
1043    return BERR_TRACE(BERR_NOT_SUPPORTED);
1044}
1045
1046/*
1047Summary:
1048This function writes a programmable number of I2C registers using a 16 bit
1049sub address.
1050*/
1051static BERR_Code NEXUS_I2c_P_WriteA16Sync(
1052    void * i2cHandle, /* I2C Handle */
1053    uint16_t chipAddr, /* 7 or 10 bit chip address (_unshifted_) */
1054    uint16_t subAddr, /* 16 bit sub address */
1055    const uint8_t *pData, /* pointer to data to write */
1056    size_t length /* number of bytes to write */
1057    )
1058{
1059    BERR_Code errCode;
1060    NEXUS_I2c *pDevice = i2cHandle;
1061
1062    BDBG_ENTER(NEXUS_I2c_P_Write);
1063
1064    NEXUS_Module_Lock(pDevice->owner);
1065
1066    errCode = BREG_I2C_WriteA16(&pDevice->asyncReg, chipAddr, subAddr, pData, length);
1067
1068    NEXUS_Module_Unlock(pDevice->owner);
1069
1070    BDBG_LEAVE(NEXUS_I2c_P_Write);
1071    return errCode;
1072}
1073static BERR_Code NEXUS_I2c_P_WriteA16Dummy(
1074    void * i2cHandle, /* I2C Handle */
1075    uint16_t chipAddr, /* 7 or 10 bit chip address (_unshifted_) */
1076    uint16_t subAddr, /* 16 bit sub address */
1077    const uint8_t *pData, /* pointer to data to write */
1078    size_t length /* number of bytes to write */
1079    )
1080{
1081    BSTD_UNUSED(i2cHandle);
1082    BSTD_UNUSED(chipAddr);
1083    BSTD_UNUSED(subAddr);
1084    BSTD_UNUSED(pData);
1085    BSTD_UNUSED(length);
1086    return BERR_TRACE(BERR_NOT_SUPPORTED);
1087}
1088
1089/*
1090Summary:
1091This function writes a programmable number of I2C registers using a 24 bit
1092sub address.
1093*/
1094static BERR_Code NEXUS_I2c_P_WriteA24Sync(
1095    void * i2cHandle, /* I2C Handle */
1096    uint16_t chipAddr, /* 7 or 10 bit chip address (_unshifted_) */
1097    uint32_t subAddr, /* 24 bit sub address */
1098    const uint8_t *pData, /* pointer to data to write */
1099    size_t length /* number of bytes to write */
1100    )
1101{
1102    BERR_Code errCode;
1103    NEXUS_I2c *pDevice = i2cHandle;
1104
1105    BDBG_ENTER(NEXUS_I2c_P_Write);
1106
1107    NEXUS_Module_Lock(pDevice->owner);
1108
1109    errCode = BREG_I2C_WriteA24(&pDevice->asyncReg, chipAddr, subAddr, pData, length);
1110
1111    NEXUS_Module_Unlock(pDevice->owner);
1112
1113    BDBG_LEAVE(NEXUS_I2c_P_Write);
1114    return errCode;
1115}
1116static BERR_Code NEXUS_I2c_P_WriteA24Dummy(
1117    void * i2cHandle, /* I2C Handle */
1118    uint16_t chipAddr, /* 7 or 10 bit chip address (_unshifted_) */
1119    uint32_t subAddr, /* 24 bit sub address */
1120    const uint8_t *pData, /* pointer to data to write */
1121    size_t length /* number of bytes to write */
1122    )
1123{
1124    BSTD_UNUSED(i2cHandle);
1125    BSTD_UNUSED(chipAddr);
1126    BSTD_UNUSED(subAddr);
1127    BSTD_UNUSED(pData);
1128    BSTD_UNUSED(length);
1129    return BERR_TRACE(BERR_NOT_SUPPORTED);
1130}
1131
1132/*
1133Summary:
1134This function writes a programmable number of I2C registers without a sub address
1135(raw write).
1136*/
1137static BERR_Code NEXUS_I2c_P_WriteNoAddrSync(
1138    void * i2cHandle, /* I2C Handle */
1139    uint16_t chipAddr, /* 7 or 10 bit chip address (_unshifted_) */
1140    const uint8_t *pData, /* pointer to data to write */
1141    size_t length /* number of bytes to write */
1142    )
1143{
1144    BERR_Code errCode;
1145    NEXUS_I2c *pDevice = i2cHandle;
1146
1147    BDBG_ENTER(NEXUS_I2c_P_Write);
1148
1149    NEXUS_Module_Lock(pDevice->owner);
1150
1151    errCode = BREG_I2C_WriteNoAddr(&pDevice->asyncReg, chipAddr, pData, length);
1152
1153    NEXUS_Module_Unlock(pDevice->owner);
1154
1155    BDBG_LEAVE(NEXUS_I2c_P_Write);
1156    return errCode;
1157}
1158static BERR_Code NEXUS_I2c_P_WriteNoAddrDummy(
1159    void * i2cHandle, /* I2C Handle */
1160    uint16_t chipAddr, /* 7 or 10 bit chip address (_unshifted_) */
1161    const uint8_t *pData, /* pointer to data to write */
1162    size_t length /* number of bytes to write */
1163    )
1164{
1165    BSTD_UNUSED(i2cHandle);
1166    BSTD_UNUSED(chipAddr);
1167    BSTD_UNUSED(pData);
1168    BSTD_UNUSED(length);
1169    return BERR_TRACE(BERR_NOT_SUPPORTED);
1170}
1171
1172/*
1173Summary:
1174This function writes a programmable number of I2C registers without a sub address
1175(raw write), and without waiting for an ack.
1176*/
1177static BERR_Code NEXUS_I2c_P_WriteNoAddrNoAckSync(
1178    void * i2cHandle, /* I2C Handle */
1179    uint16_t chipAddr, /* 7 or 10 bit chip address (_unshifted_) */
1180    const uint8_t *pData, /* pointer to data to write */
1181    size_t length /* number of bytes to write */
1182    )
1183{
1184    BERR_Code errCode;
1185    NEXUS_I2c *pDevice = i2cHandle;
1186
1187    BDBG_ENTER(NEXUS_I2c_P_Write);
1188
1189    NEXUS_Module_Lock(pDevice->owner);
1190
1191    errCode = BREG_I2C_WriteNoAddrNoAck(&pDevice->asyncReg, chipAddr, pData, length);
1192
1193    NEXUS_Module_Unlock(pDevice->owner);
1194
1195    BDBG_LEAVE(NEXUS_I2c_P_Write);
1196    return errCode;
1197}
1198static BERR_Code NEXUS_I2c_P_WriteNoAddrNoAckDummy(
1199    void * i2cHandle, /* I2C Handle */
1200    uint16_t chipAddr, /* 7 or 10 bit chip address (_unshifted_) */
1201    const uint8_t *pData, /* pointer to data to write */
1202    size_t length /* number of bytes to write */
1203    )
1204{
1205    BSTD_UNUSED(i2cHandle);
1206    BSTD_UNUSED(chipAddr);
1207    BSTD_UNUSED(pData);
1208    BSTD_UNUSED(length);
1209    return BERR_TRACE(BERR_NOT_SUPPORTED);
1210}
1211
1212/*
1213Summary:
1214This function writes an I2C NVRAM device using an 8 bit sub address.
1215*/
1216static BERR_Code NEXUS_I2c_P_WriteNvramSync(
1217    void * i2cHandle, /* I2C Handle */
1218    uint16_t chipAddr, /* 7 or 10 bit chip address (_unshifted_) */
1219    uint8_t subAddr, /* 8 bit sub address */
1220    const uint8_t *pData, /* pointer to data to write */
1221    size_t length /* number of bytes to write */
1222    )
1223{
1224    BERR_Code errCode;
1225    NEXUS_I2c *pDevice = i2cHandle;
1226
1227    BDBG_ENTER(NEXUS_I2c_P_Write);
1228
1229    NEXUS_Module_Lock(pDevice->owner);
1230
1231    errCode = BREG_I2C_WriteNvram(&pDevice->asyncReg, chipAddr, subAddr, pData, length);
1232
1233    NEXUS_Module_Unlock(pDevice->owner);
1234
1235    BDBG_LEAVE(NEXUS_I2c_P_Write);
1236    return errCode;
1237}
1238static BERR_Code NEXUS_I2c_P_WriteNvramDummy(
1239    void * i2cHandle, /* I2C Handle */
1240    uint16_t chipAddr, /* 7 or 10 bit chip address (_unshifted_) */
1241    uint8_t subAddr, /* 8 bit sub address */
1242    const uint8_t *pData, /* pointer to data to write */
1243    size_t length /* number of bytes to write */
1244    )
1245{
1246    BSTD_UNUSED(i2cHandle);
1247    BSTD_UNUSED(chipAddr);
1248    BSTD_UNUSED(subAddr);
1249    BSTD_UNUSED(pData);
1250    BSTD_UNUSED(length);
1251    return BERR_TRACE(BERR_NOT_SUPPORTED);
1252}
1253
1254/*
1255Summary:
1256This function reads a programmable number of I2C registers using an 8 bit
1257sub address.
1258*/
1259static BERR_Code NEXUS_I2c_P_ReadSync(
1260    void * i2cHandle, /* I2C Handle */
1261    uint16_t chipAddr, /* 7 or 10 bit chip address (_unshifted_) */
1262    uint8_t subAddr, /* 8 bit sub address */
1263    uint8_t *pData, /* pointer to memory location to store read data */
1264    size_t length /* number of bytes to read */
1265    )
1266{
1267    BERR_Code errCode;
1268    NEXUS_I2c *pDevice = i2cHandle;
1269
1270    BDBG_ENTER(NEXUS_I2c_P_Write);
1271
1272    NEXUS_Module_Lock(pDevice->owner);
1273
1274    errCode = BREG_I2C_Read(&pDevice->asyncReg, chipAddr, subAddr, pData, length);
1275
1276    NEXUS_Module_Unlock(pDevice->owner);
1277
1278    BDBG_LEAVE(NEXUS_I2c_P_Write);
1279    return errCode;
1280}
1281
1282static BERR_Code NEXUS_I2c_P_ReadSwSync(
1283    void * i2cHandle, /* I2C Handle */
1284    uint16_t chipAddr, /* 7 or 10 bit chip address (_unshifted_) */
1285    uint8_t subAddr, /* 8 bit sub address */
1286    uint8_t *pData, /* pointer to memory location to store read data */
1287    size_t length /* number of bytes to read */
1288    )
1289{
1290    BERR_Code errCode;
1291    NEXUS_I2c *pDevice = i2cHandle;
1292
1293    BDBG_ENTER(NEXUS_I2c_P_ReadSw);
1294
1295    NEXUS_Module_Lock(pDevice->owner);
1296
1297    errCode = BREG_I2C_ReadSw(&pDevice->asyncReg, chipAddr, subAddr, pData, length);
1298
1299    NEXUS_Module_Unlock(pDevice->owner);
1300
1301    BDBG_LEAVE(NEXUS_I2c_P_ReadSw);
1302    return errCode;
1303}
1304
1305
1306static BERR_Code NEXUS_I2c_P_ReadDummy(
1307    void * i2cHandle, /* I2C Handle */
1308    uint16_t chipAddr, /* 7 or 10 bit chip address (_unshifted_) */
1309    uint8_t subAddr, /* 8 bit sub address */
1310    uint8_t *pData, /* pointer to memory location to store read data */
1311    size_t length /* number of bytes to read */
1312    )
1313{
1314    BSTD_UNUSED(i2cHandle);
1315    BSTD_UNUSED(chipAddr);
1316    BSTD_UNUSED(subAddr);
1317    BSTD_UNUSED(pData);
1318    BSTD_UNUSED(length);
1319    return BERR_TRACE(BERR_NOT_SUPPORTED);
1320}
1321
1322/*
1323Summary:
1324This function reads a programmable number of I2C registers using an 8 bit
1325sub address and no ack..
1326*/
1327static BERR_Code NEXUS_I2c_P_ReadNoAckSync(
1328    void * i2cHandle, /* I2C Handle */
1329    uint16_t chipAddr, /* 7 or 10 bit chip address (_unshifted_) */
1330    uint8_t subAddr, /* 8 bit sub address */
1331    uint8_t *pData, /* pointer to memory location to store read data */
1332    size_t length /* number of bytes to read */
1333    )
1334{
1335    BERR_Code errCode;
1336    NEXUS_I2c *pDevice = i2cHandle;
1337
1338    BDBG_ENTER(NEXUS_I2c_P_Write);
1339
1340    NEXUS_Module_Lock(pDevice->owner);
1341
1342    errCode = BREG_I2C_ReadNoAck(&pDevice->asyncReg, chipAddr, subAddr, pData, length);
1343
1344    NEXUS_Module_Unlock(pDevice->owner);
1345
1346    BDBG_LEAVE(NEXUS_I2c_P_Write);
1347    return errCode;
1348}
1349static BERR_Code NEXUS_I2c_P_ReadNoAckDummy(
1350    void * i2cHandle, /* I2C Handle */
1351    uint16_t chipAddr, /* 7 or 10 bit chip address (_unshifted_) */
1352    uint8_t subAddr, /* 8 bit sub address */
1353    uint8_t *pData, /* pointer to memory location to store read data */
1354    size_t length /* number of bytes to read */
1355    )
1356{
1357    BSTD_UNUSED(i2cHandle);
1358    BSTD_UNUSED(chipAddr);
1359    BSTD_UNUSED(subAddr);
1360    BSTD_UNUSED(pData);
1361    BSTD_UNUSED(length);
1362    return BERR_TRACE(BERR_NOT_SUPPORTED);
1363}
1364
1365/*
1366Summary:
1367This function reads a programmable number of I2C registers using a 16 bit
1368sub address.
1369*/
1370static BERR_Code NEXUS_I2c_P_ReadA16Sync(
1371    void * i2cHandle, /* I2C Handle */
1372    uint16_t chipAddr, /* 7 or 10 bit chip address (_unshifted_) */
1373    uint16_t subAddr, /* 16 bit sub address */
1374    uint8_t *pData, /* pointer to memory location to store read data */
1375    size_t length /* number of bytes to read */
1376    )
1377{
1378    BERR_Code errCode;
1379    NEXUS_I2c *pDevice = i2cHandle;
1380
1381    BDBG_ENTER(NEXUS_I2c_P_Write);
1382
1383    NEXUS_Module_Lock(pDevice->owner);
1384
1385    errCode = BREG_I2C_ReadA16(&pDevice->asyncReg, chipAddr, subAddr, pData, length);
1386
1387    NEXUS_Module_Unlock(pDevice->owner);
1388
1389    BDBG_LEAVE(NEXUS_I2c_P_Write);
1390    return errCode;
1391}
1392static BERR_Code NEXUS_I2c_P_ReadA16Dummy(
1393    void * i2cHandle, /* I2C Handle */
1394    uint16_t chipAddr, /* 7 or 10 bit chip address (_unshifted_) */
1395    uint16_t subAddr, /* 16 bit sub address */
1396    uint8_t *pData, /* pointer to memory location to store read data */
1397    size_t length /* number of bytes to read */
1398    )
1399{
1400    BSTD_UNUSED(i2cHandle);
1401    BSTD_UNUSED(chipAddr);
1402    BSTD_UNUSED(subAddr);
1403    BSTD_UNUSED(pData);
1404    BSTD_UNUSED(length);
1405    return BERR_TRACE(BERR_NOT_SUPPORTED);
1406}
1407
1408/*
1409Summary:
1410This function reads a programmable number of I2C registers using a 24 bit
1411sub address.
1412*/
1413static BERR_Code NEXUS_I2c_P_ReadA24Sync(
1414    void * i2cHandle, /* I2C Handle */
1415    uint16_t chipAddr, /* 7 or 10 bit chip address (_unshifted_) */
1416    uint32_t subAddr, /* 32 bit sub address */
1417    uint8_t *pData, /* pointer to memory location to store read data */
1418    size_t length /* number of bytes to read */
1419    )
1420{
1421    BERR_Code errCode;
1422    NEXUS_I2c *pDevice = i2cHandle;
1423
1424    BDBG_ENTER(NEXUS_I2c_P_Write);
1425
1426    NEXUS_Module_Lock(pDevice->owner);
1427
1428    errCode = BREG_I2C_ReadA24(&pDevice->asyncReg, chipAddr, subAddr, pData, length);
1429
1430    NEXUS_Module_Unlock(pDevice->owner);
1431
1432    BDBG_LEAVE(NEXUS_I2c_P_Write);
1433    return errCode;
1434}
1435static BERR_Code NEXUS_I2c_P_ReadA24Dummy(
1436    void * i2cHandle, /* I2C Handle */
1437    uint16_t chipAddr, /* 7 or 10 bit chip address (_unshifted_) */
1438    uint32_t subAddr, /* 24 bit sub address */
1439    uint8_t *pData, /* pointer to memory location to store read data */
1440    size_t length /* number of bytes to read */
1441    )
1442{
1443    BSTD_UNUSED(i2cHandle);
1444    BSTD_UNUSED(chipAddr);
1445    BSTD_UNUSED(subAddr);
1446    BSTD_UNUSED(pData);
1447    BSTD_UNUSED(length);
1448    return BERR_TRACE(BERR_NOT_SUPPORTED);
1449}
1450
1451/*
1452Summary:
1453This function reads a programmable number of I2C registers without a sub address
1454(raw read).
1455*/
1456static BERR_Code NEXUS_I2c_P_ReadNoAddrSync(
1457    void * i2cHandle, /* I2C Handle */
1458    uint16_t chipAddr, /* 7 or 10 bit chip address (_unshifted_) */
1459    uint8_t *pData, /* pointer to memory location to store read data */
1460    size_t length /* number of bytes to read */
1461    )
1462{
1463    BERR_Code errCode;
1464    NEXUS_I2c *pDevice = i2cHandle;
1465
1466    BDBG_ENTER(NEXUS_I2c_P_Write);
1467
1468    NEXUS_Module_Lock(pDevice->owner);
1469
1470    errCode = BREG_I2C_ReadNoAddr(&pDevice->asyncReg, chipAddr, pData, length);
1471
1472    NEXUS_Module_Unlock(pDevice->owner);
1473
1474    BDBG_LEAVE(NEXUS_I2c_P_Write);
1475    return errCode;
1476}
1477
1478static BERR_Code NEXUS_I2c_P_ReadSwNoAddrSync(
1479    void * i2cHandle, /* I2C Handle */
1480    uint16_t chipAddr, /* 7 or 10 bit chip address (_unshifted_) */
1481    uint8_t *pData, /* pointer to memory location to store read data */
1482    size_t length /* number of bytes to read */
1483    )
1484{
1485    BERR_Code errCode;
1486    NEXUS_I2c *pDevice = i2cHandle;
1487
1488    BDBG_ENTER(NEXUS_I2c_P_ReadSw);
1489
1490    NEXUS_Module_Lock(pDevice->owner);
1491
1492    errCode = BREG_I2C_ReadSwNoAddr(&pDevice->asyncReg, chipAddr, pData, length);
1493
1494    NEXUS_Module_Unlock(pDevice->owner);
1495
1496    BDBG_LEAVE(NEXUS_I2c_P_ReadSw);
1497    return errCode;
1498}
1499
1500static BERR_Code NEXUS_I2c_P_ReadNoAddrDummy(
1501    void * i2cHandle, /* I2C Handle */
1502    uint16_t chipAddr, /* 7 or 10 bit chip address (_unshifted_) */
1503    uint8_t *pData, /* pointer to memory location to store read data */
1504    size_t length /* number of bytes to read */
1505    )
1506{
1507    BSTD_UNUSED(i2cHandle);
1508    BSTD_UNUSED(chipAddr);
1509    BSTD_UNUSED(pData);
1510    BSTD_UNUSED(length);
1511    return BERR_TRACE(BERR_NOT_SUPPORTED);
1512}
1513
1514/*
1515Summary:
1516This function is used to perform an Enhanced Display Data Channel read protocol.
1517*/
1518static BERR_Code NEXUS_I2c_P_ReadEDDCSync(
1519    void * i2cHandle,   /* I2C Handle */
1520    uint8_t chipAddr,           /* chip address */
1521    uint8_t segment,            /* EDDC segment pointer */
1522    uint8_t subAddr,            /* 8-bit sub address */
1523    uint8_t *pData,             /* pointer to memory location to store read data  */
1524    size_t length               /* number of bytes to read */
1525    )
1526{
1527    BERR_Code errCode;
1528    NEXUS_I2c *pDevice = i2cHandle;
1529
1530    BDBG_ENTER(NEXUS_I2c_P_ReadEDDCSync);
1531
1532    NEXUS_Module_Lock(pDevice->owner);
1533
1534    errCode = BREG_I2C_ReadEDDC(&pDevice->asyncReg, chipAddr, segment, subAddr, pData, length);
1535
1536    NEXUS_Module_Unlock(pDevice->owner);
1537
1538    BDBG_LEAVE(NEXUS_I2c_P_ReadEDDCSync);
1539    return errCode;
1540}
1541
1542static BERR_Code NEXUS_I2c_P_ReadSwEDDCSync(
1543    void * i2cHandle,   /* I2C Handle */
1544    uint8_t chipAddr,           /* chip address */
1545    uint8_t segment,            /* EDDC segment pointer */
1546    uint8_t subAddr,            /* 8-bit sub address */
1547    uint8_t *pData,             /* pointer to memory location to store read data  */
1548    size_t length               /* number of bytes to read */
1549    )
1550{
1551    BERR_Code errCode;
1552    NEXUS_I2c *pDevice = i2cHandle;
1553
1554    BDBG_ENTER(NEXUS_I2c_P_ReadSwEDDCSync);
1555
1556    NEXUS_Module_Lock(pDevice->owner);
1557
1558    errCode = BREG_I2C_ReadSwEDDC(&pDevice->asyncReg, chipAddr, segment, subAddr, pData, length);
1559
1560    NEXUS_Module_Unlock(pDevice->owner);
1561
1562    BDBG_LEAVE(NEXUS_I2c_P_ReadSwEDDCSync);
1563    return errCode;
1564}
1565
1566static BERR_Code NEXUS_I2c_P_ReadEDDCDummy(
1567    void * i2cHandle,   /* I2C Handle */
1568    uint8_t chipAddr,           /* chip address */
1569    uint8_t segment,            /* EDDC segment pointer */
1570    uint8_t subAddr,            /* 8-bit sub address */
1571    uint8_t *pData,             /* pointer to memory location to store read data  */
1572    size_t length               /* number of bytes to read */
1573    )
1574{
1575    BSTD_UNUSED(i2cHandle);
1576    BSTD_UNUSED(chipAddr);
1577    BSTD_UNUSED(segment);
1578    BSTD_UNUSED(subAddr);
1579    BSTD_UNUSED(pData);
1580    BSTD_UNUSED(length);
1581    return BERR_TRACE(BERR_NOT_SUPPORTED);
1582}
1583
1584/*
1585Summary:
1586This function is used to perform an Enhanced Display Data Channel write protocol.
1587*/
1588static BERR_Code NEXUS_I2c_P_WriteEDDCSync(
1589    void * i2cHandle,           /* I2C Handle */
1590    uint8_t chipAddr,           /* chip address */
1591    uint8_t segment,            /* EDDC segment pointer */
1592    uint8_t subAddr,            /* 8-bit sub address */
1593    const uint8_t *pData,       /* pointer to data to write */
1594    size_t length               /* number of bytes to write */
1595    )
1596{
1597    BERR_Code errCode;
1598    NEXUS_I2c *pDevice = i2cHandle;
1599
1600    BDBG_ENTER(NEXUS_I2c_P_Write);
1601
1602    NEXUS_Module_Lock(pDevice->owner);
1603
1604    errCode = BREG_I2C_WriteEDDC(&pDevice->asyncReg, chipAddr, segment, subAddr, pData, length);
1605
1606    NEXUS_Module_Unlock(pDevice->owner);
1607
1608    BDBG_LEAVE(NEXUS_I2c_P_Write);
1609    return errCode;
1610}
1611static BERR_Code NEXUS_I2c_P_WriteEDDCDummy(
1612    void * i2cHandle,           /* I2C Handle */
1613    uint8_t chipAddr,           /* chip address */
1614    uint8_t segment,            /* EDDC segment pointer */
1615    uint8_t subAddr,            /* 8-bit sub address */
1616    const uint8_t *pData,       /* pointer to data to write */
1617    size_t length               /* number of bytes to write */
1618    )
1619{
1620    BSTD_UNUSED(i2cHandle);
1621    BSTD_UNUSED(chipAddr);
1622    BSTD_UNUSED(segment);
1623    BSTD_UNUSED(subAddr);
1624    BSTD_UNUSED(pData);
1625    BSTD_UNUSED(length);
1626    return BERR_TRACE(BERR_NOT_SUPPORTED);
1627}
1628
1629/* Magnum modules call BREG_I2C, Nexus modules call NEXUS_I2C.  Both cases need to synchronize */
1630static void NEXUS_I2c_P_FillSyncRegHandle(
1631    NEXUS_I2c *pI2cDevice,
1632    NEXUS_ModuleHandle moduleHandle
1633    )
1634{
1635    BDBG_ENTER(NEXUS_I2c_P_FillLocalRegHandle);
1636    pI2cDevice->owner = moduleHandle;
1637    BKNI_Memset(&pI2cDevice->syncReg, 0, sizeof(pI2cDevice->syncReg));
1638    pI2cDevice->syncReg.context = pI2cDevice;
1639
1640    /*  This would be _much_ simpler if BREG handled NULL...  */
1641    if ( pI2cDevice->asyncReg.BREG_I2C_Write_Func )
1642        pI2cDevice->syncReg.BREG_I2C_Write_Func = NEXUS_I2c_P_WriteSync;
1643    else
1644        pI2cDevice->syncReg.BREG_I2C_Write_Func = NEXUS_I2c_P_WriteDummy;
1645
1646    if ( pI2cDevice->asyncReg.BREG_I2C_WriteSw_Func )
1647        pI2cDevice->syncReg.BREG_I2C_WriteSw_Func = NEXUS_I2c_P_WriteSwSync;
1648    else
1649        pI2cDevice->syncReg.BREG_I2C_WriteSw_Func = NEXUS_I2c_P_WriteDummy;
1650
1651    if ( pI2cDevice->asyncReg.BREG_I2C_WriteNoAck_Func )
1652        pI2cDevice->syncReg.BREG_I2C_WriteNoAck_Func = NEXUS_I2c_P_WriteNoAckSync;
1653    else
1654        pI2cDevice->syncReg.BREG_I2C_WriteNoAck_Func = NEXUS_I2c_P_WriteNoAckDummy;
1655
1656    if ( pI2cDevice->asyncReg.BREG_I2C_WriteA16_Func )
1657        pI2cDevice->syncReg.BREG_I2C_WriteA16_Func = NEXUS_I2c_P_WriteA16Sync;
1658    else
1659        pI2cDevice->syncReg.BREG_I2C_WriteA16_Func = NEXUS_I2c_P_WriteA16Dummy;
1660
1661    if ( pI2cDevice->asyncReg.BREG_I2C_WriteA24_Func )
1662        pI2cDevice->syncReg.BREG_I2C_WriteA24_Func = NEXUS_I2c_P_WriteA24Sync;
1663    else
1664        pI2cDevice->syncReg.BREG_I2C_WriteA24_Func = NEXUS_I2c_P_WriteA24Dummy;
1665
1666    if ( pI2cDevice->asyncReg.BREG_I2C_WriteNoAddr_Func )
1667        pI2cDevice->syncReg.BREG_I2C_WriteNoAddr_Func = NEXUS_I2c_P_WriteNoAddrSync;
1668    else
1669        pI2cDevice->syncReg.BREG_I2C_WriteNoAddr_Func = NEXUS_I2c_P_WriteNoAddrDummy;
1670
1671    if ( pI2cDevice->asyncReg.BREG_I2C_WriteNoAddrNoAck_Func )
1672        pI2cDevice->syncReg.BREG_I2C_WriteNoAddrNoAck_Func = NEXUS_I2c_P_WriteNoAddrNoAckSync;
1673    else
1674        pI2cDevice->syncReg.BREG_I2C_WriteNoAddrNoAck_Func = NEXUS_I2c_P_WriteNoAddrNoAckDummy;
1675
1676    if ( pI2cDevice->asyncReg.BREG_I2C_WriteNvram_Func )
1677        pI2cDevice->syncReg.BREG_I2C_WriteNvram_Func = NEXUS_I2c_P_WriteNvramSync;
1678    else
1679        pI2cDevice->syncReg.BREG_I2C_WriteNvram_Func = NEXUS_I2c_P_WriteNvramDummy;
1680
1681    if ( pI2cDevice->asyncReg.BREG_I2C_Read_Func )
1682        pI2cDevice->syncReg.BREG_I2C_Read_Func = NEXUS_I2c_P_ReadSync;
1683    else
1684        pI2cDevice->syncReg.BREG_I2C_Read_Func = NEXUS_I2c_P_ReadDummy;
1685
1686    if ( pI2cDevice->asyncReg.BREG_I2C_ReadSw_Func )
1687        pI2cDevice->syncReg.BREG_I2C_ReadSw_Func = NEXUS_I2c_P_ReadSwSync;
1688    else
1689        pI2cDevice->syncReg.BREG_I2C_ReadSw_Func = NEXUS_I2c_P_ReadDummy;
1690
1691    if ( pI2cDevice->asyncReg.BREG_I2C_ReadNoAck_Func )
1692        pI2cDevice->syncReg.BREG_I2C_ReadNoAck_Func = NEXUS_I2c_P_ReadNoAckSync;
1693    else
1694        pI2cDevice->syncReg.BREG_I2C_ReadNoAck_Func = NEXUS_I2c_P_ReadNoAckDummy;
1695
1696    if ( pI2cDevice->asyncReg.BREG_I2C_ReadA16_Func )
1697        pI2cDevice->syncReg.BREG_I2C_ReadA16_Func = NEXUS_I2c_P_ReadA16Sync;
1698    else
1699        pI2cDevice->syncReg.BREG_I2C_ReadA16_Func = NEXUS_I2c_P_ReadA16Dummy;
1700
1701    if ( pI2cDevice->asyncReg.BREG_I2C_ReadA24_Func )
1702        pI2cDevice->syncReg.BREG_I2C_ReadA24_Func = NEXUS_I2c_P_ReadA24Sync;
1703    else
1704        pI2cDevice->syncReg.BREG_I2C_ReadA24_Func = NEXUS_I2c_P_ReadA24Dummy;
1705
1706    if ( pI2cDevice->asyncReg.BREG_I2C_ReadNoAddr_Func )
1707        pI2cDevice->syncReg.BREG_I2C_ReadNoAddr_Func = NEXUS_I2c_P_ReadNoAddrSync;
1708    else
1709        pI2cDevice->syncReg.BREG_I2C_ReadNoAddr_Func = NEXUS_I2c_P_ReadNoAddrDummy;
1710
1711    if ( pI2cDevice->asyncReg.BREG_I2C_ReadSwNoAddr_Func )
1712        pI2cDevice->syncReg.BREG_I2C_ReadSwNoAddr_Func = NEXUS_I2c_P_ReadSwNoAddrSync;
1713    else
1714        pI2cDevice->syncReg.BREG_I2C_ReadSwNoAddr_Func = NEXUS_I2c_P_ReadNoAddrDummy;
1715
1716    if ( pI2cDevice->asyncReg.BREG_I2C_ReadEDDC_Func )
1717        pI2cDevice->syncReg.BREG_I2C_ReadEDDC_Func = NEXUS_I2c_P_ReadEDDCSync;
1718    else
1719        pI2cDevice->syncReg.BREG_I2C_ReadEDDC_Func = NEXUS_I2c_P_ReadEDDCDummy;
1720
1721    if ( pI2cDevice->asyncReg.BREG_I2C_ReadSwEDDC_Func )
1722        pI2cDevice->syncReg.BREG_I2C_ReadSwEDDC_Func = NEXUS_I2c_P_ReadSwEDDCSync;
1723    else
1724        pI2cDevice->syncReg.BREG_I2C_ReadSwEDDC_Func = NEXUS_I2c_P_ReadEDDCDummy;
1725
1726    if ( pI2cDevice->asyncReg.BREG_I2C_WriteEDDC_Func )
1727        pI2cDevice->syncReg.BREG_I2C_WriteEDDC_Func = NEXUS_I2c_P_WriteEDDCSync;
1728    else
1729        pI2cDevice->syncReg.BREG_I2C_WriteEDDC_Func = NEXUS_I2c_P_WriteEDDCDummy;
1730
1731    BDBG_LEAVE(NEXUS_I2c_P_FillLocalRegHandle);
1732}
1733
1734/***************************************************************************
1735Summary:
1736    This function returns a BREG_I2C_Handle from a NEXUS_I2cHandle.
1737
1738Description:
1739    This function returns a BREG_I2C_Handle that will handle internal
1740    synchronization properly based upon two factors.  The first is the module
1741    that created the I2C Handle (not all are local I2C Masters), and the
1742    second is the module that intends to use it.  Supported models are as
1743    follows:  1) Local I2C Master, any nexus module may use it.  2) Module-
1744    specific I2C Master (e.g. Frontend), only that module may use it.  If
1745    platform requires a BREG_I2C_Handle for some reason, it may pass NULL
1746    for the module handle here.  That is only supported for local i2c masters.
1747
1748See Also:
1749    NEXUS_I2c_Close(), NEXUS_I2c_GetDefaultSettings()
1750
1751****************************************************************************/
1752BREG_I2C_Handle NEXUS_I2c_GetRegHandle(
1753    NEXUS_I2cHandle i2cHandle,
1754    NEXUS_ModuleHandle moduleHandle     /* The module requiring a BREG_I2C Handle, determines synchronization. model */
1755    )
1756{
1757    NEXUS_Error errCode;
1758    BDBG_OBJECT_ASSERT(i2cHandle, NEXUS_I2c);
1759
1760    /* WARNING: This is a private function, but is called throughout nexus without the i2c module lock
1761    acquired. do not modify state or depend on non-atomic state here. currently, this function returns
1762    a magnum pointer which must be used outside of nexus module lock anyway. */
1763
1764    if ( moduleHandle != i2cHandle->owner )
1765    {
1766        if ( NULL == moduleHandle || i2cHandle->owner == NEXUS_MODULE_SELF )
1767        {
1768            /* If the app requested it, always be sync.  If another module requested it, it must be a local i2c device */
1769            return &i2cHandle->syncReg;
1770        }
1771        else
1772        {
1773            BDBG_ERR(("This combination of I2C Handles is not supported"));
1774            errCode = BERR_TRACE(BERR_NOT_SUPPORTED);
1775            return NULL;
1776        }
1777    }
1778    else
1779    {
1780        /* If a module requests it's own I2C Reg Handle, it must be asynchronous to avoid internal deadlock.*/
1781        return &i2cHandle->asyncReg;
1782    }
1783}
1784
1785/***************************************************************************
1786Summary:
1787    This function initializes an I2C Callback structure to defaults
1788See Also:
1789    NEXUS_I2c_CreateHandle
1790****************************************************************************/
1791void NEXUS_I2c_InitCallbacks(
1792    NEXUS_I2cCallbacks *pCallbacks  /* [out] */
1793    )
1794{
1795    BKNI_Memset(pCallbacks, 0, sizeof(*pCallbacks));
1796}
1797
1798/***************************************************************************
1799Summary:
1800    Create a NEXUS_I2cHandle for a module from a set of callbacks.
1801
1802Description:
1803    This function allows another nexus module to create a new I2C handle
1804    that can be used with the standard NEXUS_I2c_Xxx routines by the application.
1805    This is required for several frontend devices.
1806
1807See Also:
1808    NEXUS_I2c_DestroyHandle(), NEXUS_I2c_InitCallbacks()
1809****************************************************************************/
1810NEXUS_I2cHandle NEXUS_I2c_CreateHandle(
1811    NEXUS_ModuleHandle moduleHandle,            /* The module requiring a BREG_I2C Handle, determines synchronization model */
1812    void *pContext,                             /* This is the device context that will be passed to each callback */
1813    const NEXUS_I2cCallbacks *pI2cCallbacks     /* A list of callbacks supported by this device */
1814    )
1815{
1816    NEXUS_I2c *pI2cDevice;
1817    NEXUS_Error errCode;
1818
1819    BDBG_ASSERT(NULL != moduleHandle);
1820    BDBG_ASSERT(NULL != pContext);
1821    BDBG_ASSERT(NULL != pI2cCallbacks);
1822
1823    pI2cDevice = BKNI_Malloc(sizeof(NEXUS_I2c));
1824    if ( NULL == pI2cDevice )
1825    {
1826        errCode = BERR_TRACE(BERR_OUT_OF_SYSTEM_MEMORY);
1827        return NULL;
1828    }
1829
1830    /* Set to defaults */
1831    BKNI_Memset(pI2cDevice, 0, sizeof(NEXUS_I2c));
1832    BDBG_OBJECT_SET(pI2cDevice, NEXUS_I2c);
1833
1834    /* Fill async values with provided callbacks -- This would be _much_ simpler if BREG handled NULL... */
1835    pI2cDevice->asyncReg.context = pContext;
1836    if ( pI2cCallbacks->write )
1837        pI2cDevice->asyncReg.BREG_I2C_Write_Func = pI2cCallbacks->write;
1838    else
1839        pI2cDevice->asyncReg.BREG_I2C_Write_Func = NEXUS_I2c_P_WriteDummy;
1840
1841    if ( pI2cCallbacks->writeSw )
1842        pI2cDevice->asyncReg.BREG_I2C_WriteSw_Func = pI2cCallbacks->writeSw;
1843    else
1844        pI2cDevice->asyncReg.BREG_I2C_WriteSw_Func = NEXUS_I2c_P_WriteDummy;
1845
1846    if ( pI2cCallbacks->writeNoAck )
1847        pI2cDevice->asyncReg.BREG_I2C_WriteNoAck_Func = pI2cCallbacks->writeNoAck;
1848    else
1849        pI2cDevice->asyncReg.BREG_I2C_WriteNoAck_Func = NEXUS_I2c_P_WriteNoAckDummy;
1850
1851    if ( pI2cCallbacks->writeA16 )
1852        pI2cDevice->asyncReg.BREG_I2C_WriteA16_Func = pI2cCallbacks->writeA16;
1853    else
1854        pI2cDevice->asyncReg.BREG_I2C_WriteA16_Func = NEXUS_I2c_P_WriteA16Dummy;
1855
1856    if ( pI2cCallbacks->writeA24 )
1857        pI2cDevice->asyncReg.BREG_I2C_WriteA24_Func = pI2cCallbacks->writeA24;
1858    else
1859        pI2cDevice->asyncReg.BREG_I2C_WriteA24_Func = NEXUS_I2c_P_WriteA24Dummy;
1860
1861    if ( pI2cCallbacks->writeNoAddr )
1862        pI2cDevice->asyncReg.BREG_I2C_WriteNoAddr_Func = pI2cCallbacks->writeNoAddr;
1863    else
1864        pI2cDevice->asyncReg.BREG_I2C_WriteNoAddr_Func = NEXUS_I2c_P_WriteNoAddrDummy;
1865
1866    if ( pI2cCallbacks->writeNoAck )
1867        pI2cDevice->asyncReg.BREG_I2C_WriteNoAck_Func = pI2cCallbacks->writeNoAck;
1868    else
1869        pI2cDevice->asyncReg.BREG_I2C_WriteNoAck_Func = NEXUS_I2c_P_WriteNoAckDummy;
1870
1871    if ( pI2cCallbacks->writeNvram )
1872        pI2cDevice->asyncReg.BREG_I2C_WriteNvram_Func = pI2cCallbacks->writeNvram;
1873    else
1874        pI2cDevice->asyncReg.BREG_I2C_WriteNvram_Func = NEXUS_I2c_P_WriteNvramDummy;
1875
1876    if ( pI2cCallbacks->read )
1877        pI2cDevice->asyncReg.BREG_I2C_Read_Func = pI2cCallbacks->read;
1878    else
1879        pI2cDevice->asyncReg.BREG_I2C_Read_Func = NEXUS_I2c_P_ReadDummy;
1880
1881    if ( pI2cCallbacks->readSw )
1882        pI2cDevice->asyncReg.BREG_I2C_ReadSw_Func = pI2cCallbacks->readSw;
1883    else
1884        pI2cDevice->asyncReg.BREG_I2C_ReadSw_Func = NEXUS_I2c_P_ReadDummy;
1885
1886    if ( pI2cCallbacks->readNoAck )
1887        pI2cDevice->asyncReg.BREG_I2C_ReadNoAck_Func = pI2cCallbacks->readNoAck;
1888    else
1889        pI2cDevice->asyncReg.BREG_I2C_ReadNoAck_Func = NEXUS_I2c_P_ReadNoAckDummy;
1890    if ( pI2cCallbacks->readA16 )
1891        pI2cDevice->asyncReg.BREG_I2C_ReadA16_Func = pI2cCallbacks->readA16;
1892    else
1893        pI2cDevice->asyncReg.BREG_I2C_ReadA16_Func = NEXUS_I2c_P_ReadA16Dummy;
1894
1895    if ( pI2cCallbacks->readA24 )
1896        pI2cDevice->asyncReg.BREG_I2C_ReadA24_Func = pI2cCallbacks->readA24;
1897    else
1898        pI2cDevice->asyncReg.BREG_I2C_ReadA24_Func = NEXUS_I2c_P_ReadA24Dummy;
1899
1900    if ( pI2cCallbacks->readNoAddr )
1901        pI2cDevice->asyncReg.BREG_I2C_ReadNoAddr_Func = pI2cCallbacks->readNoAddr;
1902    else
1903        pI2cDevice->asyncReg.BREG_I2C_ReadNoAddr_Func = NEXUS_I2c_P_ReadNoAddrDummy;
1904
1905    if ( pI2cCallbacks->readSwNoAddr )
1906        pI2cDevice->asyncReg.BREG_I2C_ReadSwNoAddr_Func = pI2cCallbacks->readSwNoAddr;
1907    else
1908        pI2cDevice->asyncReg.BREG_I2C_ReadSwNoAddr_Func = NEXUS_I2c_P_ReadNoAddrDummy;
1909
1910    if ( pI2cCallbacks->readEDDC )
1911        pI2cDevice->asyncReg.BREG_I2C_ReadEDDC_Func = pI2cCallbacks->readEDDC;
1912    else
1913        pI2cDevice->asyncReg.BREG_I2C_ReadEDDC_Func = NEXUS_I2c_P_ReadEDDCDummy;
1914
1915    if ( pI2cCallbacks->readSwEDDC )
1916        pI2cDevice->asyncReg.BREG_I2C_ReadSwEDDC_Func = pI2cCallbacks->readSwEDDC;
1917    else
1918        pI2cDevice->asyncReg.BREG_I2C_ReadSwEDDC_Func = NEXUS_I2c_P_ReadEDDCDummy;
1919
1920    if ( pI2cCallbacks->writeEDDC )
1921        pI2cDevice->asyncReg.BREG_I2C_WriteEDDC_Func = pI2cCallbacks->writeEDDC;
1922    else
1923        pI2cDevice->asyncReg.BREG_I2C_WriteEDDC_Func = NEXUS_I2c_P_WriteEDDCDummy;
1924
1925    NEXUS_I2c_P_FillSyncRegHandle(pI2cDevice, moduleHandle);
1926
1927    /* Success */
1928    return pI2cDevice;
1929}
1930
1931/***************************************************************************
1932Summary:
1933    Destroy a handle created with NEXUS_I2c_CreateHandle.
1934
1935See Also:
1936    NEXUS_I2c_CreateHandle()
1937****************************************************************************/
1938void NEXUS_I2c_DestroyHandle(
1939    NEXUS_I2cHandle i2cHandle
1940    )
1941{
1942    BDBG_OBJECT_ASSERT(i2cHandle, NEXUS_I2c);
1943    BDBG_ASSERT(NULL == i2cHandle->channel);   /* Can't destroy a local channel, call close for that. */
1944    BDBG_OBJECT_DESTROY(i2cHandle, NEXUS_I2c);
1945    BKNI_Free(i2cHandle);
1946}
1947
1948NEXUS_Error NEXUS_I2c_SwReset( NEXUS_I2cHandle i2cHandle )
1949{
1950    BERR_Code rc;
1951
1952    BDBG_OBJECT_ASSERT(i2cHandle, NEXUS_I2c);
1953    rc = BI2C_SwReset(i2cHandle->channel);
1954    if (rc) return BERR_TRACE(rc);
1955
1956    return 0;
1957}
1958
1959NEXUS_Error NEXUS_I2cModule_Standby_priv(bool enabled, const NEXUS_StandbySettings *pSettings)
1960{
1961#if NEXUS_POWER_MANAGEMENT
1962    BI2C_ChannelSettings channelSettings;
1963    BERR_Code rc;
1964    unsigned i;
1965
1966    if (enabled) {
1967        if (pSettings->mode==NEXUS_StandbyMode_eDeepSleep) { /* S3 */
1968
1969            /* some I2C buses are part of the AON block and some are not. for the AON ones,
1970               the BI2C_Channel should not be closed/re-opened. however, nothing is currently
1971               using I2C during S3 standby, so we can treat them all the same for now */
1972            for (i=0; i<NEXUS_NUM_I2C_CHANNELS; i++) {
1973                NEXUS_I2cHandle i2cHandle = &g_localI2cChannels[i];
1974                if (!i2cHandle->channel) { continue; }
1975                BI2C_CloseChannel(i2cHandle->channel);
1976                i2cHandle->channel = NULL;
1977                i2cHandle->s3standby = true; /* we can't rely on i2cHandle->channel being NULL and must keep track of which channels we close, because a platform may not open all i2c channels to begin with */
1978            }
1979        }
1980    }
1981    else {
1982        for (i=0; i<NEXUS_NUM_I2C_CHANNELS; i++) {
1983            NEXUS_I2cHandle i2cHandle = &g_localI2cChannels[i];
1984            if (i2cHandle->channel || !i2cHandle->s3standby) { continue; }
1985            channelSettings.clkRate = i2cHandle->settings.clockRate;
1986            channelSettings.intMode = i2cHandle->settings.interruptMode;
1987            channelSettings.timeoutMs = i2cHandle->settings.timeout;
1988            channelSettings.burstMode = i2cHandle->settings.burstMode;
1989            channelSettings.softI2c = i2cHandle->settings.softI2c;
1990            /* BI2C handle can be closed/re-opened, but the BREG_I2C handle must NOT be destroyed/re-created,
1991               because other magnum modules (e.g. HDM) will keep using that handle */
1992            rc = BI2C_OpenChannel(g_NEXUS_i2cHandle, &i2cHandle->channel, i, &channelSettings);
1993            if (rc) { return BERR_TRACE(rc); }
1994
1995            /* asyncReg.context is normally set to the BI2C_ChannelHandle via BI2C_CreateI2cRegHandle and must be updated
1996               syncReg.context is always set to NEXUS_I2CHandle, so should not be touched */           
1997            i2cHandle->asyncReg.context = i2cHandle->channel;
1998        }
1999    }
2000   
2001    return NEXUS_SUCCESS;
2002#else
2003    BSTD_UNUSED(enabled);
2004    BSTD_UNUSED(pSettings);
2005    return NEXUS_SUCCESS;
2006#endif
2007}
2008
Note: See TracBrowser for help on using the repository browser.