source: svn/trunk/newcon3bcm2_21bu/nexus/modules/pwm/7552/src/nexus_pwm.c

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

first commit

  • Property svn:executable set to *
File size: 15.3 KB
Line 
1/***************************************************************************
2 *     (c)2007-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_pwm.c $
39 * $brcm_Revision: 12 $
40 * $brcm_Date: 11/22/11 6:16p $
41 *
42 * Module Description:
43 *
44 * Revision History:
45 *
46 * $brcm_Log: /nexus/modules/pwm/7425/src/nexus_pwm.c $
47 *
48 * 12   11/22/11 6:16p jtna
49 * SW7425-1708: fix s3 resume
50 *
51 * 11   11/18/11 4:20p jtna
52 * SW7425-1708: add s3 power management for pwm
53 *
54 * 10   6/7/11 1:21p nickh
55 * SW7425-685: Set max number of PWM's according to the defines in the PWM
56 *  PI
57 *
58 * 9   6/16/10 1:26p erickson
59 * SW7405-4444: refactor NEXUS_Pwm_OpenChannel for kernel mode support
60 *
61 * 8   2/10/10 3:13p erickson
62 * SW3548-2769: added NEXUS_Pwm_GetPeriodInterval_isr
63 *
64 * 7   8/4/09 1:28p erickson
65 * PR57259: add NEXUS_Pwm_RampOnInterval
66 *
67 * 6   3/6/09 10:25a erickson
68 * PR52855: fix possible NULL dereference in NEXUS_Pwm_OpenChannel, remove
69 *  unused static default structures
70 *
71 * 5   1/27/09 10:55a erickson
72 * PR50367: added memset and BDBG_OBJECT safeguards
73 *
74 * 4   1/26/09 11:29a erickson
75 * PR51468: global variable naming convention
76 *
77 * 3   9/5/08 1:11p erickson
78 * PR45897: added NEXUS_Pwm_SetOnInterval_isr in private API
79 *
80 * 2   2/7/08 11:18p vsilyaev
81 * PR 38682: Fixed _Close function to follow Nexus guidelines
82 *
83 * 1   1/18/08 2:20p jgarrett
84 * PR 38808: Merging to main branch
85 *
86 * Nexus_Devel/3   12/28/07 5:19p erickson
87 * PR38470: move conversion functions to core
88 *
89 * Nexus_Devel/2   11/15/07 1:57p erickson
90 * PR37136: move PWM from display to its own module
91 *
92 **************************************************************************/
93
94#include "bstd.h"
95#include "bkni.h"
96#include "bpwm.h"
97#include "bkni_multi.h"
98
99#include "nexus_pwm_module.h"
100#include "priv/nexus_pwm_standby_priv.h"
101#include "nexus_platform_features.h"
102
103#include "priv/nexus_core.h"
104
105BDBG_MODULE(nexus_pwm);
106BDBG_OBJECT_ID(NEXUS_PwmChannel);
107
108struct NEXUS_Pwm_P_ChannelContext
109{
110    BDBG_OBJECT(NEXUS_PwmChannel)
111    BPWM_ChannelHandle             hPwmChn;
112    NEXUS_PwmChannelSettings    stSettings;
113    struct {
114        uint16_t controlWord;
115        NEXUS_PwmFreqModeType frequencyMode;
116        uint16_t onInterval;
117        uint16_t periodInterval;
118    } standby;
119};
120
121struct NEXUS_Pwm_P_Context
122{
123    BPWM_Handle         hPwm;
124    struct NEXUS_Pwm_P_ChannelContext hChannel[MAX_PWM_CHANNELS];
125    bool s3standby[MAX_PWM_CHANNELS];
126};
127
128static struct NEXUS_Pwm_P_Context g_PwmData;
129NEXUS_ModuleHandle g_NEXUS_pwmModule;
130
131/***************************************************************************
132
133Pwm Module functions
134
135***************************************************************************/
136void NEXUS_PwmModule_GetDefaultSettings(NEXUS_PwmModuleSettings *pSettings)
137{
138    BKNI_Memset(pSettings, 0, sizeof(*pSettings));
139}
140
141NEXUS_ModuleHandle NEXUS_PwmModule_Init(const NEXUS_PwmModuleSettings *pSettings)
142{
143    NEXUS_ModuleSettings moduleSettings;
144    BERR_Code rc;
145    BPWM_Settings pwmSettings;
146
147    BDBG_ASSERT(!g_NEXUS_pwmModule);
148    BSTD_UNUSED(pSettings);
149
150    /* init global module handle */
151    NEXUS_Module_GetDefaultSettings(&moduleSettings);
152    g_NEXUS_pwmModule = NEXUS_Module_Create("pwm", &moduleSettings);
153    if (!g_NEXUS_pwmModule) {
154        return NULL;
155    }
156
157    /* bring up PWM PI */
158    BKNI_Memset(&g_PwmData,0,sizeof(g_PwmData));
159
160    BPWM_GetDefaultSettings(&pwmSettings, g_pCoreHandles->chp);
161    pwmSettings.hInterrupt = g_pCoreHandles->bint;
162    rc=BPWM_Open(&g_PwmData.hPwm, (BCHP_Handle)g_pCoreHandles->chp,g_pCoreHandles->reg, &pwmSettings);
163    if (rc) { BERR_TRACE(NEXUS_UNKNOWN); return NULL;}
164
165    return g_NEXUS_pwmModule;
166}
167
168void NEXUS_PwmModule_Uninit(void)
169{
170    if (g_PwmData.hPwm != NULL)
171    {
172        BERR_Code rc;
173        rc=BPWM_Close(g_PwmData.hPwm);
174        if (rc) { BERR_TRACE(NEXUS_UNKNOWN);}
175        g_PwmData.hPwm = NULL;
176    }
177    NEXUS_Module_Destroy(g_NEXUS_pwmModule);
178    g_NEXUS_pwmModule = NULL;
179}
180
181NEXUS_PwmChannelHandle NEXUS_Pwm_OpenChannel(unsigned index, const NEXUS_PwmChannelSettings *pSettings)
182{
183     BERR_Code rc;
184     NEXUS_PwmChannelSettings defaultSettings;
185     BPWM_ChannelSettings pwmChannelSettings;
186     NEXUS_PwmChannelHandle pwm;
187
188     if (!g_PwmData.hPwm) {
189         BDBG_ERR(("PWM module not initialized"));
190         return NULL;
191    }
192    if (index >= MAX_PWM_CHANNELS) {
193         BERR_TRACE(NEXUS_INVALID_PARAMETER);
194         return NULL;
195    }
196
197    /* Init PWM_Channel setting */
198    if (!pSettings) {
199        NEXUS_Pwm_GetDefaultChannelSettings(&defaultSettings);
200        pSettings = &defaultSettings;
201    }
202
203    pwm = &g_PwmData.hChannel[index];
204    if (pwm->hPwmChn) {
205         BDBG_ERR(("PWM channel %d already opened", index));
206         return NULL;
207    }
208    BKNI_Memset(pwm, 0, sizeof(*pwm));
209    BDBG_OBJECT_SET(pwm, NEXUS_PwmChannel);
210    pwm->stSettings = *pSettings;
211
212    /* Open PWM_Channel context */
213    rc = BPWM_GetChannelDefaultSettings(g_PwmData.hPwm, index, &pwmChannelSettings);
214    if (rc) {BERR_TRACE(NEXUS_UNKNOWN); return NULL;}
215
216    pwmChannelSettings.FreqMode = pSettings->eFreqMode;
217    pwmChannelSettings.openDrainb = pSettings->openDrain;
218
219    rc = BPWM_OpenChannel(g_PwmData.hPwm, &pwm->hPwmChn, index, &pwmChannelSettings);
220    if (rc) {BERR_TRACE(NEXUS_UNKNOWN); return NULL;}
221
222    return pwm;
223}
224
225void NEXUS_Pwm_CloseChannel(NEXUS_PwmChannelHandle hChn)
226{
227    BERR_Code rc;
228
229    BDBG_OBJECT_ASSERT(hChn, NEXUS_PwmChannel);
230
231    rc = BPWM_CloseChannel(hChn->hPwmChn);
232    if (rc!=BERR_SUCCESS) {rc = BERR_TRACE(rc);}
233
234    BDBG_OBJECT_DESTROY(hChn, NEXUS_PwmChannel);
235    hChn->hPwmChn = NULL; /* must NULL out this for re-open test */
236}
237
238void NEXUS_Pwm_GetDefaultChannelSettings(NEXUS_PwmChannelSettings *pSettings)
239{
240    BPWM_ChannelSettings ChannelSettings;
241
242    (void)BPWM_GetChannelDefaultSettings(g_PwmData.hPwm, 0, &ChannelSettings);
243
244    BKNI_Memset(pSettings, 0, sizeof(*pSettings));
245    pSettings->openDrain=ChannelSettings.openDrainb;
246    pSettings->eFreqMode=ChannelSettings.FreqMode;
247}
248
249NEXUS_Error NEXUS_Pwm_SetControlWord(NEXUS_PwmChannelHandle hChn,
250    uint16_t cWord)
251{
252    BERR_Code rc = BERR_SUCCESS;
253
254    BDBG_OBJECT_ASSERT(hChn, NEXUS_PwmChannel);
255
256    rc=BPWM_SetControlWord(hChn->hPwmChn,cWord);
257    if (rc) return BERR_TRACE(rc);
258
259    return NEXUS_SUCCESS;
260}
261
262NEXUS_Error NEXUS_Pwm_GetControlWord(NEXUS_PwmChannelHandle hChn,
263    uint16_t *cWord)
264{
265    BERR_Code rc = BERR_SUCCESS;
266
267    BDBG_OBJECT_ASSERT(hChn, NEXUS_PwmChannel);
268
269    rc=BPWM_GetControlWord(hChn->hPwmChn,cWord);
270    if (rc) return BERR_TRACE(rc);
271
272    return NEXUS_SUCCESS;
273}
274
275NEXUS_Error NEXUS_Pwm_SetFreqMode(NEXUS_PwmChannelHandle hChn,
276    NEXUS_PwmFreqModeType frequencyMode)
277{
278    BERR_Code rc = BERR_SUCCESS;
279
280    BDBG_OBJECT_ASSERT(hChn, NEXUS_PwmChannel);
281
282    rc=BPWM_SetFreqMode(hChn->hPwmChn,frequencyMode);
283    if (rc) return BERR_TRACE(rc);
284
285    return NEXUS_SUCCESS;
286}
287
288NEXUS_Error NEXUS_Pwm_GetFreqMode(NEXUS_PwmChannelHandle hChn,
289    NEXUS_PwmFreqModeType *pFrequencyMode)
290{
291    BERR_Code rc = BERR_SUCCESS;
292    BPWM_FreqModeType cfg_frequencyMode;
293
294    BDBG_OBJECT_ASSERT(hChn, NEXUS_PwmChannel);
295
296    rc=BPWM_GetFreqMode(hChn->hPwmChn,&cfg_frequencyMode);
297    if (rc) return BERR_TRACE(rc);
298
299    *pFrequencyMode=cfg_frequencyMode;
300
301    return NEXUS_SUCCESS;
302}
303
304NEXUS_Error NEXUS_Pwm_SetOnInterval(NEXUS_PwmChannelHandle hChn, uint16_t OnInterval)
305{
306    BERR_Code rc;
307
308    BDBG_OBJECT_ASSERT(hChn, NEXUS_PwmChannel);
309
310    rc = BPWM_SetOnInterval(hChn->hPwmChn, OnInterval);
311    if (rc) return BERR_TRACE(rc);
312
313    return NEXUS_SUCCESS;
314}
315
316NEXUS_Error NEXUS_Pwm_SetOnInterval_isr(NEXUS_PwmChannelHandle hChn, uint16_t OnInterval)
317{
318    BERR_Code rc;
319
320    BDBG_OBJECT_ASSERT(hChn, NEXUS_PwmChannel);
321
322    rc = BPWM_SetOnInterval_isr(hChn->hPwmChn, OnInterval);
323    if (rc) return BERR_TRACE(rc);
324
325    return NEXUS_SUCCESS;
326}
327
328NEXUS_Error NEXUS_Pwm_RampOnInterval( NEXUS_PwmChannelHandle hChn, uint16_t onInterval )
329{
330    BERR_Code rc;
331
332    BDBG_OBJECT_ASSERT(hChn, NEXUS_PwmChannel);
333
334    rc = BPWM_RampOnInterval(hChn->hPwmChn, onInterval);
335    if (rc) return BERR_TRACE(rc);
336
337    return NEXUS_SUCCESS;
338}
339
340NEXUS_Error NEXUS_Pwm_GetOnInterval(NEXUS_PwmChannelHandle hChn,
341    uint16_t *OnInterval)
342{
343    BERR_Code rc = BERR_SUCCESS;
344
345    BDBG_OBJECT_ASSERT(hChn, NEXUS_PwmChannel);
346
347    rc=BPWM_GetOnInterval(hChn->hPwmChn,OnInterval);
348    if (rc) return BERR_TRACE(rc);
349
350    return NEXUS_SUCCESS;
351}
352
353NEXUS_Error NEXUS_Pwm_SetPeriodInterval(NEXUS_PwmChannelHandle hChn,
354    uint16_t PeriodInterval)
355{
356    BERR_Code rc = BERR_SUCCESS;
357
358    BDBG_OBJECT_ASSERT(hChn, NEXUS_PwmChannel);
359
360    rc=BPWM_SetPeriodInterval(hChn->hPwmChn,PeriodInterval);
361    if (rc) return BERR_TRACE(rc);
362
363    return NEXUS_SUCCESS;
364}
365
366NEXUS_Error NEXUS_Pwm_GetPeriodInterval(NEXUS_PwmChannelHandle hChn,
367    uint16_t *pPeriodInterval)
368{
369    BERR_Code rc = BERR_SUCCESS;
370
371    BDBG_OBJECT_ASSERT(hChn, NEXUS_PwmChannel);
372
373    rc=BPWM_GetPeriodInterval(hChn->hPwmChn,pPeriodInterval);
374    if (rc) return BERR_TRACE(rc);
375
376    return NEXUS_SUCCESS;
377}
378
379NEXUS_Error NEXUS_Pwm_GetPeriodInterval_isr( NEXUS_PwmChannelHandle hChn, uint16_t *pPeriodInterval )
380{
381    BERR_Code rc = BERR_SUCCESS;
382
383    BDBG_OBJECT_ASSERT(hChn, NEXUS_PwmChannel);
384
385    rc=BPWM_GetPeriodInterval_isr(hChn->hPwmChn,pPeriodInterval);
386    if (rc) return BERR_TRACE(rc);
387
388    return NEXUS_SUCCESS;
389}
390
391NEXUS_Error NEXUS_Pwm_SetOnAndPeriodInterval(NEXUS_PwmChannelHandle hChn,
392    uint16_t OnInterval,
393    uint16_t PeriodInterval)
394{
395    BERR_Code rc = BERR_SUCCESS;
396
397    BDBG_OBJECT_ASSERT(hChn, NEXUS_PwmChannel);
398
399    rc=BPWM_SetOnAndPeriodInterval(hChn->hPwmChn,OnInterval,PeriodInterval);
400    if (rc) return BERR_TRACE(rc);
401
402    return NEXUS_SUCCESS;
403}
404
405NEXUS_Error NEXUS_Pwm_GetOnAndPeriodInterval(NEXUS_PwmChannelHandle hChn,
406    uint16_t *OnInterval,
407    uint16_t *PeriodInterval)
408{
409    BERR_Code rc = BERR_SUCCESS;
410
411    BDBG_OBJECT_ASSERT(hChn, NEXUS_PwmChannel);
412
413    rc=BPWM_GetOnAndPeriodInterval(hChn->hPwmChn,OnInterval,PeriodInterval);
414    if (rc) return BERR_TRACE(rc);
415
416    return NEXUS_SUCCESS;
417}
418
419NEXUS_Error NEXUS_Pwm_Start(NEXUS_PwmChannelHandle hChn)
420{
421    BERR_Code rc = BERR_SUCCESS;
422
423    BDBG_OBJECT_ASSERT(hChn, NEXUS_PwmChannel);
424
425    rc=BPWM_Start(hChn->hPwmChn);
426    if (rc) return BERR_TRACE(rc);
427
428    return NEXUS_SUCCESS;
429}
430
431NEXUS_Error NEXUS_Pwm_Stop(NEXUS_PwmChannelHandle hChn)
432{
433    BERR_Code rc = BERR_SUCCESS;
434
435    BDBG_OBJECT_ASSERT(hChn, NEXUS_PwmChannel);
436
437    rc=BPWM_Stop(hChn->hPwmChn);
438    if (rc) return BERR_TRACE(rc);
439
440    return NEXUS_SUCCESS;
441}
442
443NEXUS_Error NEXUS_PwmModule_Standby_priv(bool enabled, const NEXUS_StandbySettings *pSettings)
444{
445#if NEXUS_POWER_MANAGEMENT
446    unsigned i;
447    NEXUS_Error rc;
448    BSTD_UNUSED(pSettings);
449
450    if (!g_PwmData.hPwm) { /* module not initialized */
451        return NEXUS_SUCCESS;
452    }
453
454    /* pwm has no (known) clocks to shutdown. we only need to save and restore state for S3 */
455    for (i=0; i<MAX_PWM_CHANNELS; i++) {
456        NEXUS_PwmChannelHandle p = &g_PwmData.hChannel[i];
457        if (!p->hPwmChn) { continue; } /* channel not opened by app */
458
459        if (enabled) {
460            BPWM_ChannelHandle pwm = p->hPwmChn;
461            BPWM_Stop(pwm); /* always force a stop. app must re-start, if needed */
462
463            if (pSettings->mode==NEXUS_StandbyMode_eDeepSleep) { /* S3 */
464                /* save channel settings before closing */
465                BPWM_GetControlWord(pwm, &p->standby.controlWord);
466                BPWM_GetFreqMode(pwm, (BPWM_FreqModeType*)&p->standby.frequencyMode);
467                BPWM_GetOnInterval(pwm, &p->standby.onInterval);
468                BPWM_GetPeriodInterval(pwm, &p->standby.periodInterval);
469                BPWM_CloseChannel(pwm);
470                g_PwmData.s3standby[i] = true;
471            }
472        }
473        else {
474            if (g_PwmData.s3standby[i]) { /* S3 */
475                BPWM_ChannelHandle pwm = NULL;
476                BPWM_ChannelSettings pwmChannelSettings;
477                rc = BPWM_GetChannelDefaultSettings(g_PwmData.hPwm, i, &pwmChannelSettings);
478                if (rc) {return BERR_TRACE(NEXUS_UNKNOWN);}
479                pwmChannelSettings.FreqMode = p->stSettings.eFreqMode;
480                pwmChannelSettings.openDrainb = p->stSettings.openDrain;
481
482                rc = BPWM_OpenChannel(g_PwmData.hPwm, &p->hPwmChn, i, &pwmChannelSettings);
483                if (rc) {return BERR_TRACE(NEXUS_UNKNOWN);}
484
485                /* restore channel settings after opening */
486                pwm = p->hPwmChn;
487                rc = BPWM_SetControlWord(pwm, p->standby.controlWord);
488                if (rc) {rc = BERR_TRACE(NEXUS_UNKNOWN);} /* keep going */
489                rc = BPWM_SetFreqMode(pwm, p->standby.frequencyMode);
490                if (rc) {rc = BERR_TRACE(NEXUS_UNKNOWN);} /* keep going */
491                rc = BPWM_SetOnInterval(pwm, p->standby.onInterval);
492                if (rc) {rc = BERR_TRACE(NEXUS_UNKNOWN);} /* keep going */
493                rc = BPWM_SetPeriodInterval(pwm, p->standby.periodInterval);
494                if (rc) {rc = BERR_TRACE(NEXUS_UNKNOWN);} /* keep going */
495            }
496        }
497    }
498   
499    return NEXUS_SUCCESS;
500#else
501    BSTD_UNUSED(pSettings);
502    BSTD_UNUSED(enabled);
503    return NEXUS_SUCCESS;
504#endif
505
506}
507
Note: See TracBrowser for help on using the repository browser.