gpio: Update mcux igpio driver to use new gpio api
Updates the mcux igpio driver and all associated boards to use new device tree compatible gpio configuration flags. Implements new port get/set/clear/toggle and pin_interrupt_configure functions recently added to the gpio api. Assumes the gpio api layer handles translating logical flags to physical flags. Removes port configuration support since that feature is deprecated in the new gpio api. Tested with: - samples/basic/blinky - samples/basic/button - tests/drivers/gpio/gpio_api_1pin On boards: - mimxrt1015_evk - mimxrt1020_evk - mimxrt1050_evk - mimxrt1060_evk - mimxrt1064_evk Signed-off-by: Maureen Helm <maureen.helm@nxp.com>
This commit is contained in:
parent
ba18a7d6d0
commit
5f09966380
6 changed files with 139 additions and 55 deletions
|
@ -25,7 +25,7 @@
|
||||||
leds {
|
leds {
|
||||||
compatible = "gpio-leds";
|
compatible = "gpio-leds";
|
||||||
green_led: led-1 {
|
green_led: led-1 {
|
||||||
gpios = <&gpio3 21 GPIO_INT_ACTIVE_LOW>;
|
gpios = <&gpio3 21 GPIO_ACTIVE_LOW>;
|
||||||
label = "User LD1";
|
label = "User LD1";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -34,7 +34,7 @@
|
||||||
compatible = "gpio-keys";
|
compatible = "gpio-keys";
|
||||||
user_button: button-1 {
|
user_button: button-1 {
|
||||||
label = "User SW4";
|
label = "User SW4";
|
||||||
gpios = <&gpio2 9 GPIO_INT_ACTIVE_LOW>;
|
gpios = <&gpio2 9 GPIO_ACTIVE_LOW>;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,7 @@
|
||||||
leds {
|
leds {
|
||||||
compatible = "gpio-leds";
|
compatible = "gpio-leds";
|
||||||
green_led: led-1 {
|
green_led: led-1 {
|
||||||
gpios = <&gpio1 5 GPIO_INT_ACTIVE_LOW>;
|
gpios = <&gpio1 5 GPIO_ACTIVE_LOW>;
|
||||||
label = "User LD1";
|
label = "User LD1";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -41,7 +41,7 @@
|
||||||
compatible = "gpio-keys";
|
compatible = "gpio-keys";
|
||||||
user_button: button-1 {
|
user_button: button-1 {
|
||||||
label = "User SW8";
|
label = "User SW8";
|
||||||
gpios = <&gpio5 0 GPIO_INT_ACTIVE_LOW>;
|
gpios = <&gpio5 0 GPIO_ACTIVE_LOW>;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,7 @@
|
||||||
leds {
|
leds {
|
||||||
compatible = "gpio-leds";
|
compatible = "gpio-leds";
|
||||||
green_led: led_0 {
|
green_led: led_0 {
|
||||||
gpios = <&gpio1 9 0>;
|
gpios = <&gpio1 9 GPIO_ACTIVE_LOW>;
|
||||||
label = "User LD1";
|
label = "User LD1";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -41,7 +41,7 @@
|
||||||
compatible = "gpio-keys";
|
compatible = "gpio-keys";
|
||||||
user_button: button_0 {
|
user_button: button_0 {
|
||||||
label = "User SW8";
|
label = "User SW8";
|
||||||
gpios = <&gpio5 0 GPIO_INT_ACTIVE_LOW>;
|
gpios = <&gpio5 0 GPIO_ACTIVE_LOW>;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,7 @@
|
||||||
leds {
|
leds {
|
||||||
compatible = "gpio-leds";
|
compatible = "gpio-leds";
|
||||||
green_led: led-1 {
|
green_led: led-1 {
|
||||||
gpios = <&gpio1 9 GPIO_INT_ACTIVE_LOW>;
|
gpios = <&gpio1 9 GPIO_ACTIVE_LOW>;
|
||||||
label = "User LD1";
|
label = "User LD1";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -41,7 +41,7 @@
|
||||||
compatible = "gpio-keys";
|
compatible = "gpio-keys";
|
||||||
user_button: button-1 {
|
user_button: button-1 {
|
||||||
label = "User SW8";
|
label = "User SW8";
|
||||||
gpios = <&gpio5 0 GPIO_INT_ACTIVE_LOW>;
|
gpios = <&gpio5 0 GPIO_ACTIVE_LOW>;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,7 @@
|
||||||
leds {
|
leds {
|
||||||
compatible = "gpio-leds";
|
compatible = "gpio-leds";
|
||||||
green_led: led-1 {
|
green_led: led-1 {
|
||||||
gpios = <&gpio1 9 GPIO_INT_ACTIVE_LOW>;
|
gpios = <&gpio1 9 GPIO_ACTIVE_LOW>;
|
||||||
label = "User LD1";
|
label = "User LD1";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -50,7 +50,7 @@
|
||||||
compatible = "gpio-keys";
|
compatible = "gpio-keys";
|
||||||
user_button: button-1 {
|
user_button: button-1 {
|
||||||
label = "User SW8";
|
label = "User SW8";
|
||||||
gpios = <&gpio5 0 GPIO_INT_ACTIVE_LOW>;
|
gpios = <&gpio5 0 GPIO_ACTIVE_LOW>;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,8 @@ struct mcux_igpio_config {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct mcux_igpio_data {
|
struct mcux_igpio_data {
|
||||||
|
/* gpio_driver_data needs to be first */
|
||||||
|
struct gpio_driver_data general;
|
||||||
/* port ISR callback routine address */
|
/* port ISR callback routine address */
|
||||||
sys_slist_t callbacks;
|
sys_slist_t callbacks;
|
||||||
/* pin callback routine enable flags, by pin number */
|
/* pin callback routine enable flags, by pin number */
|
||||||
|
@ -28,49 +30,34 @@ static int mcux_igpio_configure(struct device *dev,
|
||||||
int access_op, u32_t pin, int flags)
|
int access_op, u32_t pin, int flags)
|
||||||
{
|
{
|
||||||
const struct mcux_igpio_config *config = dev->config->config_info;
|
const struct mcux_igpio_config *config = dev->config->config_info;
|
||||||
gpio_pin_config_t pin_config;
|
GPIO_Type *base = config->base;
|
||||||
u32_t i;
|
|
||||||
|
|
||||||
/* Check for an invalid pin configuration */
|
if (((flags & GPIO_INPUT) != 0) && ((flags & GPIO_OUTPUT) != 0)) {
|
||||||
if ((flags & GPIO_INT) && (flags & GPIO_DIR_OUT)) {
|
return -ENOTSUP;
|
||||||
return -EINVAL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pin_config.direction = ((flags & GPIO_DIR_MASK) == GPIO_DIR_IN)
|
if ((flags & GPIO_SINGLE_ENDED) != 0) {
|
||||||
? kGPIO_DigitalInput : kGPIO_DigitalOutput;
|
return -ENOTSUP;
|
||||||
|
|
||||||
pin_config.outputLogic = 0;
|
|
||||||
|
|
||||||
if (flags & GPIO_INT) {
|
|
||||||
if (flags & GPIO_INT_EDGE) {
|
|
||||||
if (flags & GPIO_INT_ACTIVE_HIGH) {
|
|
||||||
pin_config.interruptMode = kGPIO_IntRisingEdge;
|
|
||||||
} else if (flags & GPIO_INT_DOUBLE_EDGE) {
|
|
||||||
pin_config.interruptMode =
|
|
||||||
kGPIO_IntRisingOrFallingEdge;
|
|
||||||
} else {
|
|
||||||
pin_config.interruptMode =
|
|
||||||
kGPIO_IntFallingEdge;
|
|
||||||
}
|
|
||||||
} else { /* GPIO_INT_LEVEL */
|
|
||||||
if (flags & GPIO_INT_ACTIVE_HIGH) {
|
|
||||||
pin_config.interruptMode = kGPIO_IntHighLevel;
|
|
||||||
} else {
|
|
||||||
pin_config.interruptMode = kGPIO_IntLowLevel;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
pin_config.interruptMode = kGPIO_NoIntmode;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (access_op == GPIO_ACCESS_BY_PIN) {
|
if (((flags & GPIO_PULL_UP) != 0) || ((flags & GPIO_PULL_DOWN) != 0)) {
|
||||||
GPIO_PinInit(config->base, pin, &pin_config);
|
return -ENOTSUP;
|
||||||
} else { /* GPIO_ACCESS_BY_PORT */
|
|
||||||
for (i = 0U; i < 32; i++) {
|
|
||||||
GPIO_PinInit(config->base, i, &pin_config);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (access_op == GPIO_ACCESS_BY_PORT) {
|
||||||
|
return -ENOTSUP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (flags & GPIO_OUTPUT_INIT_HIGH) {
|
||||||
|
base->DR_SET = BIT(pin);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags & GPIO_OUTPUT_INIT_LOW) {
|
||||||
|
base->DR_CLEAR = BIT(pin);
|
||||||
|
}
|
||||||
|
|
||||||
|
WRITE_BIT(base->GDIR, pin, flags & GPIO_OUTPUT);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,6 +89,103 @@ static int mcux_igpio_read(struct device *dev,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int mcux_igpio_port_get_raw(struct device *dev, u32_t *value)
|
||||||
|
{
|
||||||
|
const struct mcux_igpio_config *config = dev->config->config_info;
|
||||||
|
GPIO_Type *base = config->base;
|
||||||
|
|
||||||
|
*value = base->DR;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mcux_igpio_port_set_masked_raw(struct device *dev, u32_t mask,
|
||||||
|
u32_t value)
|
||||||
|
{
|
||||||
|
const struct mcux_igpio_config *config = dev->config->config_info;
|
||||||
|
GPIO_Type *base = config->base;
|
||||||
|
|
||||||
|
base->DR = (base->DR & ~mask) | (mask & value);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mcux_igpio_port_set_bits_raw(struct device *dev, u32_t mask)
|
||||||
|
{
|
||||||
|
const struct mcux_igpio_config *config = dev->config->config_info;
|
||||||
|
GPIO_Type *base = config->base;
|
||||||
|
|
||||||
|
base->DR_SET = mask;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mcux_igpio_port_clear_bits_raw(struct device *dev, u32_t mask)
|
||||||
|
{
|
||||||
|
const struct mcux_igpio_config *config = dev->config->config_info;
|
||||||
|
GPIO_Type *base = config->base;
|
||||||
|
|
||||||
|
base->DR_CLEAR = mask;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mcux_igpio_port_toggle_bits(struct device *dev, u32_t mask)
|
||||||
|
{
|
||||||
|
const struct mcux_igpio_config *config = dev->config->config_info;
|
||||||
|
GPIO_Type *base = config->base;
|
||||||
|
|
||||||
|
base->DR_TOGGLE = mask;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mcux_igpio_pin_interrupt_configure(struct device *dev,
|
||||||
|
unsigned int pin, enum gpio_int_mode mode,
|
||||||
|
enum gpio_int_trig trig)
|
||||||
|
{
|
||||||
|
const struct mcux_igpio_config *config = dev->config->config_info;
|
||||||
|
struct mcux_igpio_data *data = dev->driver_data;
|
||||||
|
GPIO_Type *base = config->base;
|
||||||
|
unsigned int key;
|
||||||
|
u8_t icr;
|
||||||
|
int shift;
|
||||||
|
|
||||||
|
if ((mode == GPIO_INT_MODE_EDGE) && (trig == GPIO_INT_TRIG_LOW)) {
|
||||||
|
icr = 3;
|
||||||
|
} else if ((mode == GPIO_INT_MODE_EDGE) &&
|
||||||
|
(trig == GPIO_INT_TRIG_HIGH)) {
|
||||||
|
icr = 2;
|
||||||
|
} else if ((mode == GPIO_INT_MODE_LEVEL) &&
|
||||||
|
(trig == GPIO_INT_TRIG_HIGH)) {
|
||||||
|
icr = 1;
|
||||||
|
} else {
|
||||||
|
icr = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pin < 16) {
|
||||||
|
shift = 2 * pin;
|
||||||
|
base->ICR1 = (base->ICR1 & ~(3 << shift)) | (icr << shift);
|
||||||
|
} else if (pin < 32) {
|
||||||
|
shift = 2 * (pin - 16);
|
||||||
|
base->ICR2 = (base->ICR2 & ~(3 << shift)) | (icr << shift);
|
||||||
|
} else {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
key = irq_lock();
|
||||||
|
|
||||||
|
WRITE_BIT(base->EDGE_SEL, pin, trig == GPIO_INT_TRIG_BOTH);
|
||||||
|
WRITE_BIT(base->ISR, pin, mode != GPIO_INT_MODE_DISABLED);
|
||||||
|
WRITE_BIT(base->IMR, pin, mode != GPIO_INT_MODE_DISABLED);
|
||||||
|
WRITE_BIT(data->pin_callback_enables, pin,
|
||||||
|
mode != GPIO_INT_MODE_DISABLED);
|
||||||
|
|
||||||
|
irq_unlock(key);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int mcux_igpio_manage_callback(struct device *dev,
|
static int mcux_igpio_manage_callback(struct device *dev,
|
||||||
struct gpio_callback *callback, bool set)
|
struct gpio_callback *callback, bool set)
|
||||||
{
|
{
|
||||||
|
@ -113,15 +197,12 @@ static int mcux_igpio_manage_callback(struct device *dev,
|
||||||
static int mcux_igpio_enable_callback(struct device *dev,
|
static int mcux_igpio_enable_callback(struct device *dev,
|
||||||
int access_op, u32_t pin)
|
int access_op, u32_t pin)
|
||||||
{
|
{
|
||||||
const struct mcux_igpio_config *config = dev->config->config_info;
|
|
||||||
struct mcux_igpio_data *data = dev->driver_data;
|
struct mcux_igpio_data *data = dev->driver_data;
|
||||||
|
|
||||||
if (access_op == GPIO_ACCESS_BY_PIN) {
|
if (access_op == GPIO_ACCESS_BY_PIN) {
|
||||||
data->pin_callback_enables |= BIT(pin);
|
data->pin_callback_enables |= BIT(pin);
|
||||||
GPIO_PortEnableInterrupts(config->base, BIT(pin));
|
|
||||||
} else {
|
} else {
|
||||||
data->pin_callback_enables = 0xFFFFFFFF;
|
data->pin_callback_enables = 0xFFFFFFFF;
|
||||||
GPIO_PortEnableInterrupts(config->base, 0xFFFFFFFF);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -130,14 +211,11 @@ static int mcux_igpio_enable_callback(struct device *dev,
|
||||||
static int mcux_igpio_disable_callback(struct device *dev,
|
static int mcux_igpio_disable_callback(struct device *dev,
|
||||||
int access_op, u32_t pin)
|
int access_op, u32_t pin)
|
||||||
{
|
{
|
||||||
const struct mcux_igpio_config *config = dev->config->config_info;
|
|
||||||
struct mcux_igpio_data *data = dev->driver_data;
|
struct mcux_igpio_data *data = dev->driver_data;
|
||||||
|
|
||||||
if (access_op == GPIO_ACCESS_BY_PIN) {
|
if (access_op == GPIO_ACCESS_BY_PIN) {
|
||||||
GPIO_PortDisableInterrupts(config->base, BIT(pin));
|
|
||||||
data->pin_callback_enables &= ~BIT(pin);
|
data->pin_callback_enables &= ~BIT(pin);
|
||||||
} else {
|
} else {
|
||||||
GPIO_PortDisableInterrupts(config->base, 0);
|
|
||||||
data->pin_callback_enables = 0U;
|
data->pin_callback_enables = 0U;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,20 +227,26 @@ static void mcux_igpio_port_isr(void *arg)
|
||||||
struct device *dev = (struct device *)arg;
|
struct device *dev = (struct device *)arg;
|
||||||
const struct mcux_igpio_config *config = dev->config->config_info;
|
const struct mcux_igpio_config *config = dev->config->config_info;
|
||||||
struct mcux_igpio_data *data = dev->driver_data;
|
struct mcux_igpio_data *data = dev->driver_data;
|
||||||
|
GPIO_Type *base = config->base;
|
||||||
u32_t enabled_int, int_flags;
|
u32_t enabled_int, int_flags;
|
||||||
|
|
||||||
int_flags = GPIO_PortGetInterruptFlags(config->base);
|
int_flags = base->ISR;
|
||||||
enabled_int = int_flags & data->pin_callback_enables;
|
enabled_int = int_flags & data->pin_callback_enables;
|
||||||
|
base->ISR = enabled_int;
|
||||||
|
|
||||||
gpio_fire_callbacks(&data->callbacks, dev, enabled_int);
|
gpio_fire_callbacks(&data->callbacks, dev, enabled_int);
|
||||||
|
|
||||||
GPIO_ClearPinsInterruptFlags(config->base, enabled_int);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct gpio_driver_api mcux_igpio_driver_api = {
|
static const struct gpio_driver_api mcux_igpio_driver_api = {
|
||||||
.config = mcux_igpio_configure,
|
.config = mcux_igpio_configure,
|
||||||
.write = mcux_igpio_write,
|
.write = mcux_igpio_write,
|
||||||
.read = mcux_igpio_read,
|
.read = mcux_igpio_read,
|
||||||
|
.port_get_raw = mcux_igpio_port_get_raw,
|
||||||
|
.port_set_masked_raw = mcux_igpio_port_set_masked_raw,
|
||||||
|
.port_set_bits_raw = mcux_igpio_port_set_bits_raw,
|
||||||
|
.port_clear_bits_raw = mcux_igpio_port_clear_bits_raw,
|
||||||
|
.port_toggle_bits = mcux_igpio_port_toggle_bits,
|
||||||
|
.pin_interrupt_configure = mcux_igpio_pin_interrupt_configure,
|
||||||
.manage_callback = mcux_igpio_manage_callback,
|
.manage_callback = mcux_igpio_manage_callback,
|
||||||
.enable_callback = mcux_igpio_enable_callback,
|
.enable_callback = mcux_igpio_enable_callback,
|
||||||
.disable_callback = mcux_igpio_disable_callback,
|
.disable_callback = mcux_igpio_disable_callback,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue