mirror of
https://github.com/zephyrproject-rtos/zephyr
synced 2025-09-01 16:42:39 +00:00
We have been combining imported mcux drivers into a flattened directory structure to maximize driver reuse, but the introduction of additional nxp soc families (lpc and imx) to zephyr has introduced driver naming conflicts. This caused us to rename and modify imported files, such as fsl_gpio.c/h, to make them unique across all three nxp soc families. This makes updating the the mcux drivers complicated, especially for the lpc family. Reoganize the mcux drivers into soc family subfolders, so we can just copy all the drivers from an mcux distribution (which is done on an soc-basis) into the appropriate soc family folder. Undo all of the naming changes that occurred when lpc and imx drivers were originally imported. Undo the accidental squashing of the kinetis watchdog and dcdc drivers that occurred when the imx drivers were introduced. The drawback to this approach is that we have duplicate files when the same hw ip modules exist in multiple soc families, however there are only few cases where this occurs, such as fsl_lpuart and fsl_trng. Signed-off-by: Maureen Helm <maureen.helm@nxp.com>
151 lines
3.8 KiB
C
151 lines
3.8 KiB
C
/*
|
|
* Copyright (c) 2017, NXP
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
/** @file
|
|
* @brief GPIO driver for LPC54XXX family
|
|
*
|
|
* Note:
|
|
* - Only basic GPIO features sufficient to blinky functionality
|
|
* are currently implemented.
|
|
* - Interrupt mode is not implemented.
|
|
*/
|
|
|
|
#include <errno.h>
|
|
#include <device.h>
|
|
#include <gpio.h>
|
|
#include <soc.h>
|
|
#include <fsl_common.h>
|
|
#include "gpio_utils.h"
|
|
#include <fsl_gpio.h>
|
|
#include <fsl_device_registers.h>
|
|
|
|
#define PORT0_IDX 0u
|
|
#define PORT1_IDX 1u
|
|
|
|
struct gpio_mcux_lpc_config {
|
|
GPIO_Type *gpio_base;
|
|
u32_t port_no;
|
|
clock_ip_name_t clock_ip_name;
|
|
};
|
|
|
|
struct gpio_mcux_lpc_data {
|
|
/* port ISR callback routine address */
|
|
sys_slist_t callbacks;
|
|
/* pin callback routine enable flags, by pin number */
|
|
u32_t pin_callback_enables;
|
|
};
|
|
|
|
static int gpio_mcux_lpc_configure(struct device *dev,
|
|
int access_op, u32_t pin, int flags)
|
|
{
|
|
const struct gpio_mcux_lpc_config *config = dev->config->config_info;
|
|
GPIO_Type *gpio_base = config->gpio_base;
|
|
|
|
/* Check for an invalid pin configuration */
|
|
if ((flags & GPIO_INT) && (flags & GPIO_DIR_OUT)) {
|
|
return -EINVAL;
|
|
}
|
|
/* Check if GPIO port supports interrupts */
|
|
if (flags & GPIO_INT) {
|
|
return -EINVAL;
|
|
}
|
|
/* supports access by pin now,you can add access by port when needed */
|
|
if (access_op == GPIO_ACCESS_BY_PIN) {
|
|
/* input-0,output-1 */
|
|
if ((flags & GPIO_DIR_MASK) == GPIO_DIR_IN) {
|
|
gpio_base->DIR[config->port_no] &= ~(BIT(pin));
|
|
} else {
|
|
gpio_base->SET[config->port_no] = BIT(pin);
|
|
gpio_base->DIR[config->port_no] |= BIT(pin);
|
|
}
|
|
} else {
|
|
|
|
return -EINVAL;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int gpio_mcux_lpc_write(struct device *dev,
|
|
int access_op, u32_t pin, u32_t value)
|
|
{
|
|
const struct gpio_mcux_lpc_config *config = dev->config->config_info;
|
|
GPIO_Type *gpio_base = config->gpio_base;
|
|
|
|
if (access_op == GPIO_ACCESS_BY_PIN) {
|
|
/* Set/Clear the data output for the respective pin */
|
|
gpio_base->B[config->port_no][pin] = value;
|
|
} else { /* return an error for all other options */
|
|
return -EINVAL;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int gpio_mcux_lpc_read(struct device *dev,
|
|
int access_op, u32_t pin, u32_t *value)
|
|
{
|
|
const struct gpio_mcux_lpc_config *config = dev->config->config_info;
|
|
GPIO_Type *gpio_base = config->gpio_base;
|
|
|
|
*value = gpio_base->PIN[config->port_no];
|
|
|
|
if (access_op == GPIO_ACCESS_BY_PIN) {
|
|
*value = (*value & BIT(pin)) >> pin;
|
|
} else { /* return an error for all other options */
|
|
return -EINVAL;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int gpio_mcux_lpc_init(struct device *dev)
|
|
{
|
|
const struct gpio_mcux_lpc_config *config = dev->config->config_info;
|
|
|
|
CLOCK_EnableClock(config->clock_ip_name);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static const struct gpio_driver_api gpio_mcux_lpc_driver_api = {
|
|
.config = gpio_mcux_lpc_configure,
|
|
.write = gpio_mcux_lpc_write,
|
|
.read = gpio_mcux_lpc_read,
|
|
};
|
|
|
|
#ifdef CONFIG_GPIO_MCUX_LPC_PORT0
|
|
static const struct gpio_mcux_lpc_config gpio_mcux_lpc_port0_config = {
|
|
.gpio_base = GPIO,
|
|
.port_no = PORT0_IDX,
|
|
.clock_ip_name = kCLOCK_Gpio0,
|
|
};
|
|
|
|
static struct gpio_mcux_lpc_data gpio_mcux_lpc_port0_data;
|
|
|
|
DEVICE_AND_API_INIT(gpio_mcux_lpc_port0, CONFIG_GPIO_MCUX_LPC_PORT0_NAME,
|
|
gpio_mcux_lpc_init,
|
|
&gpio_mcux_lpc_port0_data, &gpio_mcux_lpc_port0_config,
|
|
POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
|
|
&gpio_mcux_lpc_driver_api);
|
|
#endif /* CONFIG_GPIO_MCUX_LPC_PORT0 */
|
|
|
|
#ifdef CONFIG_GPIO_MCUX_LPC_PORT1
|
|
static const struct gpio_mcux_lpc_config gpio_mcux_lpc_port1_config = {
|
|
.gpio_base = GPIO,
|
|
.port_no = PORT1_IDX,
|
|
.clock_ip_name = kCLOCK_Gpio1,
|
|
};
|
|
|
|
static struct gpio_mcux_lpc_data gpio_mcux_lpc_port1_data;
|
|
|
|
DEVICE_AND_API_INIT(gpio_mcux_lpc_port1, CONFIG_GPIO_MCUX_LPC_PORT1_NAME,
|
|
gpio_mcux_lpc_init,
|
|
&gpio_mcux_lpc_port1_data, &gpio_mcux_lpc_port1_config,
|
|
POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
|
|
&gpio_mcux_lpc_driver_api);
|
|
#endif /* CONFIG_GPIO_MCUX_LPC_PORT1 */
|