rockbox/firmware/target/arm/imx31/gpio-imx31.h
Michael Sevakis 2220a4b695 Improve imx31 interrupt code for PMIC and GPIO
Fix stuff that was bugging me about the way I did it at first.

While messing around I found RDS code wasn't masking its GPIO
ISR as it should, which might lead to two different interrupts
messing with the static data.

Change-Id: I54626809ea3039a842af0cc9e3e42853326c4193
2017-01-29 19:07:55 -05:00

218 lines
6 KiB
C

/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (c) 2008 by Michael Sevakis
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#ifndef GPIO_IMX31_H
#define GPIO_IMX31_H
/* Static registration mechanism for imx31 GPIO interrupts */
#define USE_GPIO1_EVENTS (1 << 0)
#define USE_GPIO2_EVENTS (1 << 1)
#define USE_GPIO3_EVENTS (1 << 2)
/* Module logical indexes */
enum gpio_module_number
{
GPIO1_NUM, /* ID 0..31 */
GPIO2_NUM, /* ID 32..63 */
GPIO3_NUM, /* ID 64..95 */
GPIO_NUM_GPIO,
};
enum gpio_id
{
/* GPIO1 */
GPIO1_0_ID = 0,
GPIO1_1_ID,
GPIO1_2_ID,
GPIO1_3_ID,
GPIO1_4_ID,
GPIO1_5_ID,
GPIO1_6_ID,
GPIO1_7_ID,
GPIO1_8_ID,
GPIO1_9_ID,
GPIO1_10_ID,
GPIO1_11_ID,
GPIO1_12_ID,
GPIO1_13_ID,
GPIO1_14_ID,
GPIO1_15_ID,
GPIO1_16_ID,
GPIO1_17_ID,
GPIO1_18_ID,
GPIO1_19_ID,
GPIO1_20_ID,
GPIO1_21_ID,
GPIO1_22_ID,
GPIO1_23_ID,
GPIO1_24_ID,
GPIO1_25_ID,
GPIO1_26_ID,
GPIO1_27_ID,
GPIO1_28_ID,
GPIO1_29_ID,
GPIO1_30_ID,
GPIO1_31_ID,
/* GPIO2 */
GPIO2_0_ID = 32,
GPIO2_1_ID,
GPIO2_2_ID,
GPIO2_3_ID,
GPIO2_4_ID,
GPIO2_5_ID,
GPIO2_6_ID,
GPIO2_7_ID,
GPIO2_8_ID,
GPIO2_9_ID,
GPIO2_10_ID,
GPIO2_11_ID,
GPIO2_12_ID,
GPIO2_13_ID,
GPIO2_14_ID,
GPIO2_15_ID,
GPIO2_16_ID,
GPIO2_17_ID,
GPIO2_18_ID,
GPIO2_19_ID,
GPIO2_20_ID,
GPIO2_21_ID,
GPIO2_22_ID,
GPIO2_23_ID,
GPIO2_24_ID,
GPIO2_25_ID,
GPIO2_26_ID,
GPIO2_27_ID,
GPIO2_28_ID,
GPIO2_29_ID,
GPIO2_30_ID,
GPIO2_31_ID,
/* GPIO3 */
GPIO3_0_ID = 64,
GPIO3_1_ID,
GPIO3_2_ID,
GPIO3_3_ID,
GPIO3_4_ID,
GPIO3_5_ID,
GPIO3_6_ID,
GPIO3_7_ID,
GPIO3_8_ID,
GPIO3_9_ID,
GPIO3_10_ID,
GPIO3_11_ID,
GPIO3_12_ID,
GPIO3_13_ID,
GPIO3_14_ID,
GPIO3_15_ID,
GPIO3_16_ID,
GPIO3_17_ID,
GPIO3_18_ID,
GPIO3_19_ID,
GPIO3_20_ID,
GPIO3_21_ID,
GPIO3_22_ID,
GPIO3_23_ID,
GPIO3_24_ID,
GPIO3_25_ID,
GPIO3_26_ID,
GPIO3_27_ID,
GPIO3_28_ID,
GPIO3_29_ID,
GPIO3_30_ID,
GPIO3_31_ID,
};
/* Possible values for gpio interrupt line config */
enum gpio_int_sense
{
GPIO_SENSE_LOW_LEVEL, /* High-level sensitive */
GPIO_SENSE_HIGH_LEVEL, /* Low-level sensitive */
GPIO_SENSE_RISING, /* Rising-edge sensitive */
GPIO_SENSE_FALLING, /* Falling-edge sensitive */
GPIO_SENSE_EDGE_SEL, /* Detect any edge */
};
/* Handlers will be called in declared order for a given module
Handlers of same module should be grouped together; module order
doesn't matter */
#ifdef DEFINE_GPIO_VECTOR_TABLE
/* Describes a single event for a pin */
struct gpio_event
{
uint8_t id; /* GPIOx_y_ID */
uint8_t sense; /* GPIO_SENSE_x */
void (*callback)(void); /* GPIOx_y_EVENT_CB */
};
#define GPIO_VECTOR_TBL_START() \
static FORCE_INLINE uintptr_t __gpio_event_vector_tbl(int __what) \
{ \
static const struct gpio_event __tbl[] = {
#define GPIO_EVENT_VECTOR(__name, __sense) \
{ .id = (__name##_ID), \
.sense = (__sense), \
.callback = ({ void __name##_EVENT_CB(void); \
__name##_EVENT_CB; }) },
#define GPIO_VECTOR_TBL_END() \
}; \
switch (__what) \
{ \
default: return (uintptr_t)__tbl; \
case 1: return (uintptr_t)ARRAYLEN(__tbl); \
} \
}
#define gpio_event_vector_tbl \
((const struct gpio_event *)__gpio_event_vector_tbl(0))
#define gpio_event_vector_tbl_len \
((unsigned int)__gpio_event_vector_tbl(1))
#endif /* DEFINE_GPIO_VECTOR_TABLE */
#define GPIO_BASE_ADDR \
(volatile unsigned long * const [GPIO_NUM_GPIO]) { \
(volatile unsigned long *)GPIO1_BASE_ADDR, \
(volatile unsigned long *)GPIO2_BASE_ADDR, \
(volatile unsigned long *)GPIO3_BASE_ADDR }
#define GPIO_DR (0x00 / sizeof (unsigned long)) /* 00h */
#define GPIO_GDIR (0x04 / sizeof (unsigned long)) /* 04h */
#define GPIO_PSR (0x08 / sizeof (unsigned long)) /* 08h */
#define GPIO_ICR (0x0C / sizeof (unsigned long)) /* 0Ch ICR1,2 */
#define GPIO_IMR (0x14 / sizeof (unsigned long)) /* 14h */
#define GPIO_ISR (0x18 / sizeof (unsigned long)) /* 18h */
#define GPIO_EDGE_SEL (0x1C / sizeof (unsigned long)) /* 1Ch */
void gpio_init(void);
bool gpio_enable_event(enum gpio_id id, bool enable);
static FORCE_INLINE void gpio_int_clear(enum gpio_id id)
{ GPIO_BASE_ADDR[id / 32][GPIO_ISR] = 1ul << (id % 32); }
static FORCE_INLINE void gpio_int_enable(enum gpio_id id)
{ bitset32(&GPIO_BASE_ADDR[id / 32][GPIO_IMR], 1ul << (id % 32)); }
static FORCE_INLINE void gpio_int_disable(enum gpio_id id)
{ bitclr32(&GPIO_BASE_ADDR[id / 32][GPIO_IMR], 1ul << (id % 32)); }
#endif /* GPIO_IMX31_H */