| /* |
| * 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 <drivers/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 -ENOTSUP; |
| } |
| |
| /* 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; |
| |
| /* Check for an invalid pin number */ |
| if (pin >= ARRAY_SIZE(gpio_base->B[config->port_no])) { |
| return -EINVAL; |
| } |
| |
| 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 */ |