source: svn/trunk/newcon3bcm2_21bu/nexus/modules/gpio/7552/src/nexus_gpio.c

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

first commit

  • Property svn:executable set to *
File size: 21.0 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_gpio.c $
39 * $brcm_Revision: 25 $
40 * $brcm_Date: 7/14/11 2:11p $
41 *
42 * Module Description:
43 *
44 * Revision History:
45 *
46 * $brcm_Log: /nexus/modules/gpio/7400/src/nexus_gpio.c $
47 *
48 * 25   7/14/11 2:11p jtna
49 * SW7405-5414: added NEXUS_GpioSettings.maskEdgeInterrupts
50 *
51 * 24   5/25/11 3:50p shyi
52 * SWDTV-7058: Added support for TVM GPIO interrupt
53 *
54 * 23   2/22/11 4:52p randyjew
55 * SW7344-25: Creating seperate callback handle for AONGpios.
56 *
57 * 22   2/16/11 4:57p randyjew
58 * SW7344-25:Fixed compile warning
59 *
60 * 21   2/16/11 3:17p randyjew
61 * SW7344-25:Add Gpio register abstraction to support AON Gpio's and other
62 *  Gpio register ranges.
63 *
64 * 20   12/6/10 12:08p erickson
65 * SW7408-146: add NEXUS_Gpio_GetPinMux
66 *
67 * 19   11/17/10 1:27p VISHK
68 * SW7422-71: Add support for GPIO interrupts to 3112 frontend tuners.
69 *
70 * 18   10/11/10 3:52p erickson
71 * SW7422-75: deprecate NEXUS_GpioType. convert from sparse array to
72 *  linked list. nexus_gpio_table.c is now responsible for bounds check.
73 *  this allows us to avoid updating generic code for chip-specific GPIO
74 *  blocks.
75 *
76 * 17   10/11/10 1:06p nickh
77 * SW7422-73: Add 7422 support
78 *
79 * 16   9/14/10 6:47p hongtaoz
80 * SW7425-9: compile for 7425;
81 *
82 * 15   9/8/10 10:52a erickson
83 * SW7550-560: fix interrupt safety of NEXUS_Gpio_SetSettings
84 *
85 * 14   4/21/10 4:17p erickson
86 * SW7405-4228: fix logic in NEXUS_Gpio_OpenAux
87 *
88 * 13   4/19/10 4:29p erickson
89 * SW7405-4228: use NEXUS_Gpio_Open macro and
90 *  NEXUS_Gpio_OpenAux(typeAndPin) implementation to fix linux kernel mode
91 *  proxy callbacks for GPIO
92 *
93 * 12   4/5/10 4:26p shyi
94 * SW35230-124: NEXUS GPIO for 35230 (merging to main branch)
95 *
96 * 11   1/6/10 12:15p jhaberf
97 * SW35230-1: Added 35230 DTV chip support
98 *
99 * 10   7/10/09 4:08p jhaberf
100 * PR53796: Adding 35130 #define in order to get gpio module to build for
101 *  the 35130 software development environment
102 *
103 * 9   3/12/09 2:13p jgarrett
104 * PR 50409: Disabling interrupt before setting mask/edge/... registers to
105 *  avoid spurious interrupts
106 *
107 * 8   1/26/09 12:05p erickson
108 * PR51468: global variable naming convention
109 *
110 * 7   1/26/09 11:29a erickson
111 * PR51468: global variable naming convention
112 *
113 * 6   8/18/08 10:28a katrep
114 * PR45674: Compiler warnings in DEBUG=n builds
115 *
116 * 5   2/28/08 10:42p vsilyaev
117 * PR 40103: Added interfaceHandle and settings for the
118 *  NEXUS_IsrCallbackCreate
119 *
120 * 4   2/26/08 11:40a jgarrett
121 * PR 39016: Fixing open sequencing if interrupt is enabled
122 *
123 * 3   2/25/08 8:10p jgarrett
124 * PR 39610: Masking level interrupts after interrupt is received
125 *
126 * 2   1/25/08 2:30p erickson
127 * PR39016: fix interrupt enable
128 *
129 * 1   1/18/08 2:21p jgarrett
130 * PR 38808: Merging to main branch
131 *
132 * Nexus_Devel/6   11/30/07 11:08a jgarrett
133 * PR 37801: Adjusting register offsets
134 *
135 * Nexus_Devel/5   11/26/07 10:57a erickson
136 * PR37423: support other name of gpio interrupt
137 *
138 * Nexus_Devel/4   11/26/07 9:45a erickson
139 * PR37423: gpio update
140 *
141 * Nexus_Devel/3   11/21/07 11:12a erickson
142 * PR37423: update
143 *
144 * Nexus_Devel/2   11/20/07 2:22p erickson
145 * PR37423: simplify module init
146 *
147 * Nexus_Devel/1   11/20/07 1:28p erickson
148 * PR37423: added uart, gpio, spi modules
149 *
150 **************************************************************************/
151#include "nexus_gpio_module.h"
152#include "priv/nexus_core.h"
153#include "priv/nexus_gpio_priv.h"
154#include "bint.h"
155#include "bchp_int_id_irq0.h"
156#include "bchp_gio.h"
157
158#ifdef BCHP_INT_ID_aon_gio_irqen
159#error "BCHP_INT_ID_aon_gio_irqen should not be defined previously"
160#endif
161
162#if NEXUS_NUM_AON_GPIO_PINS > 0
163#include "bchp_int_id_irq0_aon.h"
164#include "bchp_gio_aon.h"
165#define BCHP_INT_ID_aon_gio_irqen BCHP_INT_ID_IRQ0_AON_gio_irqen
166#endif
167#if NEXUS_NUM_TGPIO_PINS > 0
168#include "bchp_int_id_tvm.h"
169#include "bchp_tvm.h"
170#define BCHP_INT_ID_aon_gio_irqen BCHP_INT_ID_TVM_GPIO_INT
171#endif
172
173/**
174The Nexus Gpio module does not use the Magnum GIO porting interface.
175Interrupts are requested directly from INT. GPIO registers are accessed directly.
176**/
177
178BDBG_MODULE(nexus_gpio);
179
180NEXUS_ModuleHandle g_NEXUS_gpioModule;
181struct {
182    NEXUS_GpioModuleSettings settings;
183    BINT_CallbackHandle intCallback;
184    #ifdef BCHP_INT_ID_aon_gio_irqen
185    BINT_CallbackHandle intAonCallback;
186    #endif
187    BLST_S_HEAD(NEXUS_GpioList, NEXUS_Gpio) list;
188} g_NEXUS_gpio;
189static void NEXUS_Gpio_P_isr(void *context, int param);
190
191BDBG_OBJECT_ID(NEXUS_Gpio);
192
193
194
195/****************************************
196* Module functions
197***************/
198
199void NEXUS_GpioModule_GetDefaultSettings(NEXUS_GpioModuleSettings *pSettings)
200{
201    BKNI_Memset(pSettings, 0, sizeof(*pSettings));
202}
203
204NEXUS_ModuleHandle NEXUS_GpioModule_Init(const NEXUS_GpioModuleSettings *pSettings)
205{
206    BERR_Code rc;
207
208    BDBG_ASSERT(!g_NEXUS_gpioModule);
209    g_NEXUS_gpioModule = NEXUS_Module_Create("gpio", NULL);
210    BKNI_Memset(&g_NEXUS_gpio, 0, sizeof(g_NEXUS_gpio));
211    if (pSettings) {
212        g_NEXUS_gpio.settings = *pSettings;
213    }
214    else {
215        NEXUS_GpioModule_GetDefaultSettings(&g_NEXUS_gpio.settings);
216    }
217    BLST_S_INIT(&g_NEXUS_gpio.list);
218
219    /* Prior to installing L2 callback, we must ensure that all GPIO interrupts are masked. */
220    BREG_Write32(g_pCoreHandles->reg, BCHP_GIO_MASK_LO, 0);
221    BREG_Write32(g_pCoreHandles->reg, BCHP_GIO_STAT_LO, 0xFFFFFFFF);
222    #ifdef BCHP_GIO_MASK_HI
223    BREG_Write32(g_pCoreHandles->reg, BCHP_GIO_MASK_HI, 0);
224    BREG_Write32(g_pCoreHandles->reg, BCHP_GIO_STAT_HI, 0xFFFFFFFF);
225    #endif
226    #ifdef BCHP_GIO_MASK_EXT
227    BREG_Write32(g_pCoreHandles->reg, BCHP_GIO_MASK_EXT, 0);
228    BREG_Write32(g_pCoreHandles->reg, BCHP_GIO_STAT_EXT, 0xFFFFFFFF);
229    #endif
230   #ifdef BCHP_GIO_AON_MASK_LO
231    BREG_Write32(g_pCoreHandles->reg, BCHP_GIO_AON_MASK_LO, 0);
232    BREG_Write32(g_pCoreHandles->reg, BCHP_GIO_AON_STAT_LO, 0xFFFFFFFF);
233    #endif
234    #ifdef BCHP_GIO_AON_MASK_EXT
235    BREG_Write32(g_pCoreHandles->reg, BCHP_GIO_AON_MASK_EXT, 0);
236    BREG_Write32(g_pCoreHandles->reg, BCHP_GIO_AON_STAT_EXT, 0xFFFFFFFF);
237    #endif
238    #ifdef BCHP_GIO_MASK_EXT_HI
239    BREG_Write32(g_pCoreHandles->reg, BCHP_GIO_MASK_EXT_HI, 0);
240    BREG_Write32(g_pCoreHandles->reg, BCHP_GIO_STAT_EXT_HI, 0xFFFFFFFF);
241    #endif
242    #ifdef BCHP_GIO_MASK_EXT2
243    BREG_Write32(g_pCoreHandles->reg, BCHP_GIO_MASK_EXT2, 0);
244    BREG_Write32(g_pCoreHandles->reg, BCHP_GIO_STAT_EXT2, 0xFFFFFFFF);
245    #endif
246    #ifdef BCHP_TVM_GPIO_MASK_0
247    BREG_Write32(g_pCoreHandles->reg, BCHP_TVM_GPIO_MASK_0, 0);
248    BREG_Write32(g_pCoreHandles->reg, BCHP_TVM_GPIO_STAT_0, 0xFFFFFFFF);
249    #endif
250    #ifdef BCHP_TVM_GPIO_MASK_1
251    BREG_Write32(g_pCoreHandles->reg, BCHP_TVM_GPIO_MASK_1, 0);
252    BREG_Write32(g_pCoreHandles->reg, BCHP_TVM_GPIO_STAT_1, 0xFFFFFFFF);
253    #endif
254    #ifdef BCHP_TVM_GPIO_MASK_2
255    BREG_Write32(g_pCoreHandles->reg, BCHP_TVM_GPIO_MASK_2, 0);
256    BREG_Write32(g_pCoreHandles->reg, BCHP_TVM_GPIO_STAT_2, 0xFFFFFFFF);
257    #endif
258
259#ifndef BCHP_INT_ID_gio_irqen
260#ifdef BCHP_INT_ID_IRQ0_gio_irqen
261#define BCHP_INT_ID_gio_irqen BCHP_INT_ID_IRQ0_gio_irqen
262#else
263#define BCHP_INT_ID_gio_irqen BCHP_INT_ID_gio
264#endif
265#endif
266    rc = BINT_CreateCallback(&g_NEXUS_gpio.intCallback, g_pCoreHandles->bint, BCHP_INT_ID_gio_irqen, NEXUS_Gpio_P_isr, NULL, 0);
267    if (rc) {rc=BERR_TRACE(rc); return NULL;}
268    rc = BINT_EnableCallback(g_NEXUS_gpio.intCallback);
269    if (rc) {rc=BERR_TRACE(rc); return NULL;}
270    #ifdef BCHP_INT_ID_aon_gio_irqen
271    rc = BINT_CreateCallback(&g_NEXUS_gpio.intAonCallback, g_pCoreHandles->bint, BCHP_INT_ID_aon_gio_irqen, NEXUS_Gpio_P_isr, NULL, 0);
272    if (rc) {rc=BERR_TRACE(rc); return NULL;}
273    rc = BINT_EnableCallback(g_NEXUS_gpio.intAonCallback);
274    if (rc) {rc=BERR_TRACE(rc); return NULL;}
275    #endif
276
277    return g_NEXUS_gpioModule;
278}
279
280void NEXUS_GpioModule_Uninit()
281{
282    NEXUS_GpioHandle gpio;
283
284    BINT_DisableCallback(g_NEXUS_gpio.intCallback);
285    BINT_DestroyCallback(g_NEXUS_gpio.intCallback);
286    #ifdef BCHP_INT_ID_aon_gio_irqen
287    BINT_DisableCallback(g_NEXUS_gpio.intAonCallback);
288    BINT_DestroyCallback(g_NEXUS_gpio.intAonCallback);
289    #endif
290    while ((gpio = BLST_S_FIRST(&g_NEXUS_gpio.list))) {
291        BDBG_ERR(("automatically closing gpio[%d], type %d", gpio->pin, gpio->type));
292        NEXUS_Gpio_Close(gpio);
293    }
294
295    NEXUS_Module_Destroy(g_NEXUS_gpioModule);
296    g_NEXUS_gpioModule = NULL;
297}
298
299/****************************************
300* API functions
301***************/
302
303void NEXUS_Gpio_GetDefaultSettings(NEXUS_GpioType type, NEXUS_GpioSettings *pSettings)
304{
305    BSTD_UNUSED(type);
306    BKNI_Memset(pSettings, 0, sizeof(*pSettings));
307}
308
309NEXUS_GpioHandle NEXUS_Gpio_OpenAux(unsigned typeAndPin, const NEXUS_GpioSettings *pSettings)
310{
311    NEXUS_GpioHandle gpio;
312    BERR_Code rc;
313    NEXUS_GpioSettings defaultSettings;
314#ifndef NEXUS_GPIO_REGISTER_ABSTRACTION
315    uint32_t address;
316#endif
317#define NEXUS_GPIO_TYPE(typeAndPin) (typeAndPin >> 16)
318#define NEXUS_GPIO_PIN(typeAndPin) (typeAndPin & 0xFFFF)
319    NEXUS_GpioType type = NEXUS_GPIO_TYPE(typeAndPin);
320    unsigned pin = NEXUS_GPIO_PIN(typeAndPin);
321
322    /* There is no bounds check for type or pin in this generic file.
323    When the general eMax was extended from 2 to 3, no existing copies of nexus_gpio_table.c were updated to handle it.
324    The worst case is that type>1 is handled as if type==0.
325    If more rigorous checking is needed, it must be done in each chip's nexus_gpio_table.c. */
326
327    /* chip-specific sanity check */
328    rc = NEXUS_Gpio_P_CheckPinmux(type, pin);
329    if ( rc!=NEXUS_SUCCESS ) { rc = BERR_TRACE(rc); goto err_pinmux;}
330
331    gpio = BKNI_Malloc(sizeof(*gpio));
332    if(!gpio) { rc = BERR_TRACE(BERR_OUT_OF_SYSTEM_MEMORY);goto err_alloc;}
333    BKNI_Memset(gpio, 0, sizeof(*gpio));
334    BDBG_OBJECT_SET(gpio, NEXUS_Gpio);
335
336    if (!pSettings) {
337        NEXUS_Gpio_GetDefaultSettings(type, &defaultSettings);
338        pSettings = &defaultSettings;
339    }
340
341    gpio->pin = pin;
342    gpio->type = type;
343#if NEXUS_GPIO_REGISTER_ABSTRACTION
344    rc = NEXUS_Gpio_P_GetPinData(gpio);
345    if ( rc!=NEXUS_SUCCESS) { rc = BERR_TRACE(rc); goto err_pindata;}
346#else
347    rc = NEXUS_Gpio_P_GetPinData(type, pin, &address, &gpio->shift);
348    if ( rc!=NEXUS_SUCCESS) { rc = BERR_TRACE(rc); goto err_pindata;}
349
350        /* populate the addresses */
351    {
352        unsigned offset = address - BCHP_GIO_ODEN_LO;
353        gpio->addr.iodir=BCHP_GIO_IODIR_LO+offset;
354        gpio->addr.data=BCHP_GIO_DATA_LO+offset;
355        gpio->addr.oden=BCHP_GIO_ODEN_LO+offset;
356        gpio->addr.mask=BCHP_GIO_MASK_LO+offset;
357        gpio->addr.ec= BCHP_GIO_EC_LO+offset;
358        gpio->addr.ei= BCHP_GIO_EI_LO+offset;
359        gpio->addr.level=BCHP_GIO_LEVEL_LO+offset;
360        gpio->addr.stat=BCHP_GIO_STAT_LO+offset;       
361        }
362#endif
363    gpio->isrCallback = NEXUS_IsrCallback_Create(gpio,NULL);
364    if(!gpio->isrCallback) { rc = BERR_TRACE(BERR_OUT_OF_SYSTEM_MEMORY);goto err_callback;}
365
366    BKNI_EnterCriticalSection();
367    BLST_S_INSERT_HEAD(&g_NEXUS_gpio.list, gpio, link);
368    BKNI_LeaveCriticalSection();
369
370    rc = NEXUS_Gpio_SetSettings(gpio, pSettings);
371    if (rc) {rc=BERR_TRACE(rc); goto err_gpio;}
372
373    return gpio;
374
375err_pindata:
376err_callback:
377err_gpio:
378    NEXUS_Gpio_Close(gpio);
379err_alloc:
380err_pinmux:
381    return NULL;
382}
383
384void NEXUS_Gpio_Close(NEXUS_GpioHandle gpio)
385{
386    BDBG_OBJECT_ASSERT(gpio, NEXUS_Gpio);
387    if (gpio->isrCallback) {
388        NEXUS_IsrCallback_Destroy(gpio->isrCallback);
389    }
390    BKNI_EnterCriticalSection();
391    BLST_S_REMOVE(&g_NEXUS_gpio.list, gpio, NEXUS_Gpio, link);
392    BKNI_LeaveCriticalSection();
393    BDBG_OBJECT_DESTROY(gpio, NEXUS_Gpio);
394    BKNI_Free(gpio);
395}
396
397void NEXUS_Gpio_GetSettings(NEXUS_GpioHandle gpio, NEXUS_GpioSettings *pSettings)
398{
399    BDBG_OBJECT_ASSERT(gpio, NEXUS_Gpio);
400    *pSettings = gpio->settings;
401}
402
403static void NEXUS_Gpio_P_SetBit_isr(uint32_t addr, unsigned shift, bool set)
404{
405    uint32_t val = BREG_Read32(g_pCoreHandles->reg, addr);
406    if (set) {
407        val |= (1 << shift);
408    }
409    else{
410        val &= ~(1 << shift);
411    }
412    BREG_Write32(g_pCoreHandles->reg, addr, val);
413}
414
415static unsigned NEXUS_Gpio_P_GetBit(uint32_t addr, unsigned shift)
416{
417    /* No critical section because its an atomic read. */
418    return (BREG_Read32(g_pCoreHandles->reg, addr) >> shift) & 0x1;
419}
420
421void NEXUS_Gpio_SetInterruptEnabled_isr(NEXUS_GpioHandle gpio, bool enabled)
422{
423      NEXUS_Gpio_P_SetBit_isr(gpio->addr.mask, gpio->shift, enabled); /* The MASK register is a misnomer. MASK = 1 is unmasked. */
424}
425
426NEXUS_Error NEXUS_Gpio_SetSettings(NEXUS_GpioHandle gpio, const NEXUS_GpioSettings *pSettings)
427{
428    unsigned edge_conf = 0, edge_insensitive = 0, edge_level = 0, enabled = 1;
429
430    BDBG_OBJECT_ASSERT(gpio, NEXUS_Gpio);
431
432    switch (pSettings->interruptMode){
433    case NEXUS_GpioInterrupt_eRisingEdge:
434        edge_conf = 1;
435        edge_insensitive = 0;
436        edge_level = 0;
437        break;
438    case NEXUS_GpioInterrupt_eFallingEdge:
439        edge_conf = 0;
440        edge_insensitive = 0;
441        edge_level = 0;
442        break;
443    case NEXUS_GpioInterrupt_eEdge:
444        edge_conf = 0;
445        edge_insensitive = 1;
446        edge_level = 0;
447        break;
448    case NEXUS_GpioInterrupt_eHigh:
449        edge_conf = 1;
450        edge_insensitive = 0;
451        edge_level = 1;
452        break;
453    case NEXUS_GpioInterrupt_eLow:
454        edge_conf = 0;
455        edge_insensitive = 0;
456        edge_level = 1;
457        break;
458    default: /* NEXUS_GpioInterrupt_eDisabled */
459        enabled = 0;
460        break;
461    }
462
463    NEXUS_IsrCallback_Set(gpio->isrCallback, &pSettings->interrupt);
464
465    BKNI_EnterCriticalSection();
466
467    NEXUS_Gpio_P_SetBit_isr(gpio->addr.iodir, gpio->shift, pSettings->mode == NEXUS_GpioMode_eInput);
468   
469    if (pSettings->mode != NEXUS_GpioMode_eInput) {
470        NEXUS_Gpio_P_SetBit_isr(gpio->addr.data, gpio->shift, pSettings->value);
471    }
472   
473    NEXUS_Gpio_P_SetBit_isr(gpio->addr.oden, gpio->shift, pSettings->mode == NEXUS_GpioMode_eOutputOpenDrain);
474
475    if (!enabled) {
476        /* Mask before resetting interrupt condition bits to avoid a re-trigger */
477        NEXUS_Gpio_P_SetBit_isr(gpio->addr.mask, gpio->shift, 0); /* The MASK register is a misnomer. MASK = 1 is unmasked. */
478    }
479
480    NEXUS_Gpio_P_SetBit_isr(gpio->addr.ec, gpio->shift, edge_conf);
481    NEXUS_Gpio_P_SetBit_isr(gpio->addr.ei, gpio->shift, edge_insensitive);
482    NEXUS_Gpio_P_SetBit_isr(gpio->addr.level, gpio->shift, edge_level);
483
484    gpio->settings = *pSettings;
485   
486    if (enabled) {
487        NEXUS_Gpio_P_SetBit_isr(gpio->addr.mask, gpio->shift, enabled); /* The MASK register is a misnomer. MASK = 1 is unmasked. */
488    }
489    BKNI_LeaveCriticalSection();
490
491    return 0;
492}
493
494NEXUS_Error NEXUS_Gpio_GetStatus(NEXUS_GpioHandle gpio, NEXUS_GpioStatus *pStatus)
495{
496    BDBG_OBJECT_ASSERT(gpio, NEXUS_Gpio);
497    BKNI_EnterCriticalSection();
498    pStatus->value = NEXUS_Gpio_P_GetBit(gpio->addr.data, gpio->shift);
499    pStatus->interruptPending = NEXUS_Gpio_P_GetBit(gpio->addr.stat, gpio->shift);
500    BKNI_LeaveCriticalSection();
501    return 0;
502}
503
504NEXUS_Error NEXUS_Gpio_ClearInterrupt(NEXUS_GpioHandle gpio)
505{
506    BDBG_OBJECT_ASSERT(gpio, NEXUS_Gpio);
507    BKNI_EnterCriticalSection();
508    BREG_Write32(g_pCoreHandles->reg, gpio->addr.stat, 1 << gpio->shift);
509    if ( gpio->settings.interruptMode != NEXUS_GpioInterrupt_eDisabled )
510    {
511        /* Re-enable interrupts.  May be a masked level interrupt */
512        NEXUS_Gpio_P_SetBit_isr(gpio->addr.mask, gpio->shift, 1); /* The MASK register is a misnomer. MASK = 1 is unmasked. */
513    }
514    BKNI_LeaveCriticalSection();
515    return 0;
516}
517
518void NEXUS_Gpio_SetInterruptCallback_priv(NEXUS_GpioHandle gpio, NEXUS_GpioIsrCallback callback_isr, void *context, int param)
519{
520    BKNI_EnterCriticalSection();
521    gpio->directIsrCallback.callback_isr = callback_isr;
522    gpio->directIsrCallback.context = context;
523    gpio->directIsrCallback.param = param;
524    BKNI_LeaveCriticalSection();
525}
526
527static bool NEXUS_Gpio_P_Dispatch_isr(NEXUS_GpioHandle gpio)
528{
529    if (NEXUS_Gpio_P_GetBit(gpio->addr.stat, gpio->shift) &
530        NEXUS_Gpio_P_GetBit(gpio->addr.mask, gpio->shift))
531    {
532        /* clear status immediately */
533        BREG_Write32(g_pCoreHandles->reg,gpio->addr.stat, 1 << gpio->shift);
534        if ( gpio->settings.maskEdgeInterrupts || 
535             gpio->settings.interruptMode == NEXUS_GpioInterrupt_eLow ||
536             gpio->settings.interruptMode == NEXUS_GpioInterrupt_eHigh )
537        {
538            /* Mask a level interrupt */
539            NEXUS_Gpio_P_SetBit_isr(gpio->addr.mask, gpio->shift, 0);
540            /* The MASK register is a misnomer. MASK = 1 is unmasked. */
541        }
542        if(gpio->isrCallback) {
543            NEXUS_IsrCallback_Fire_isr(gpio->isrCallback);
544        }
545       
546        if(gpio->directIsrCallback.callback_isr){
547            gpio->directIsrCallback.callback_isr(gpio->directIsrCallback.context, gpio->directIsrCallback.param);
548        }
549           
550        return true;
551    }
552
553    return false;
554}
555
556static void NEXUS_Gpio_P_isr(void *context, int param)
557{
558    NEXUS_GpioHandle gpio;
559    BDBG_MSG(("NEXUS_Gpio_P_isr"));
560
561    BSTD_UNUSED(context);
562    BSTD_UNUSED(param);
563
564#if 0 /* Useful for debugging flood scenarios */
565    BDBG_MSG(("GIO_MASK_LO 0x%08x GIO_STAT_LO 0x%08x", BREG_Read32(g_pCoreHandles->reg, BCHP_GIO_MASK_LO), BREG_Read32(g_pCoreHandles->reg, BCHP_GIO_STAT_LO)));
566    #ifdef BCHP_GIO_MASK_HI
567    BDBG_MSG(("GIO_MASK_HI 0x%08x GIO_STAT_HI 0x%08x", BREG_Read32(g_pCoreHandles->reg, BCHP_GIO_MASK_HI), BREG_Read32(g_pCoreHandles->reg, BCHP_GIO_STAT_HI)));
568    #endif
569    #ifdef BCHP_GIO_MASK_EXT
570    BDBG_MSG(("GIO_MASK_EXT 0x%08x GIO_STAT_EXT 0x%08x", BREG_Read32(g_pCoreHandles->reg, BCHP_GIO_MASK_EXT), BREG_Read32(g_pCoreHandles->reg, BCHP_GIO_STAT_EXT)));
571    #endif
572    #ifdef BCHP_GIO_MASK_EXT_HI
573    BDBG_MSG(("GIO_MASK_EXT_HI 0x%08x GIO_STAT_EXT_HI 0x%08x", BREG_Read32(g_pCoreHandles->reg, BCHP_GIO_MASK_EXT_HI), BREG_Read32(g_pCoreHandles->reg, BCHP_GIO_MASK_EXT_HI)));
574    #endif
575    #ifdef BCHP_GIO_MASK_EXT2
576    BDBG_MSG(("GIO_MASK_EXT2 0x%08x GIO_STAT_EXT2 0x%08x", BREG_Read32(g_pCoreHandles->reg, BCHP_GIO_MASK_EXT2), BREG_Read32(g_pCoreHandles->reg, BCHP_GIO_MASK_EXT2)));
577    #endif
578    #ifdef BCHP_TVM_GPIO_MASK_0
579    BDBG_MSG(("TVM_GPIO_MASK_0 0x%08x TVM_GPIO_STAT_0 0x%08x", BREG_Read32(g_pCoreHandles->reg, BCHP_TVM_GPIO_MASK_0), BREG_Read32(g_pCoreHandles->reg, BCHP_TVM_GPIO_STAT_0)));
580    #endif
581    #ifdef BCHP_TVM_GPIO_MASK_1
582    BDBG_MSG(("TVM_GPIO_MASK_1 0x%08x TVM_GPIO_STAT_1 0x%08x", BREG_Read32(g_pCoreHandles->reg, BCHP_TVM_GPIO_MASK_1), BREG_Read32(g_pCoreHandles->reg, BCHP_TVM_GPIO_STAT_1)));
583    #endif
584#endif
585
586    for (gpio=BLST_S_FIRST(&g_NEXUS_gpio.list); gpio; gpio = BLST_S_NEXT(gpio, link)) {
587        if (NEXUS_Gpio_P_Dispatch_isr(gpio)) {
588            BDBG_MSG(("Dispatched GPIO interrupt %u, type %u", gpio->pin, gpio->type));
589        }
590    }
591}
592
593NEXUS_Error NEXUS_Gpio_GetPinMux( unsigned typeAndPin, uint32_t *pAddr, uint32_t *pMask, unsigned *pShift )
594{
595    NEXUS_GpioType type = NEXUS_GPIO_TYPE(typeAndPin);
596    unsigned pin = NEXUS_GPIO_PIN(typeAndPin);
597    return NEXUS_Gpio_P_GetPinMux(type, pin, pAddr, pMask, pShift );
598}
Note: See TracBrowser for help on using the repository browser.