From 12d614d0b805f8ea42d3e69c2d008cba0d73adb8 Mon Sep 17 00:00:00 2001 From: Ramakrishna Pallala Date: Sat, 16 Dec 2017 14:55:09 +0530 Subject: [PATCH] drivers: gpio: add support for Altera Nios-II PIO controller The PIO cores on Altera Nios-II processors can be used for GPIOs and each PIO core can be configured as Input only, Output only or as Bidirectional port from the Qsys tool. The present Nios-II softcpu image on the Zephyr only has the support for Output only port and the PIOs[0:3] are wired to LED[0:3] on the Altera MAX10 board. Signed-off-by: Ramakrishna Pallala --- .../nios2/soc/nios2f-zephyr/Kconfig.defconfig | 7 + drivers/gpio/CMakeLists.txt | 1 + drivers/gpio/Kconfig | 2 + drivers/gpio/Kconfig.altera_nios2 | 34 ++++ drivers/gpio/gpio_altera_nios2.c | 162 ++++++++++++++++++ 5 files changed, 206 insertions(+) create mode 100644 drivers/gpio/Kconfig.altera_nios2 create mode 100644 drivers/gpio/gpio_altera_nios2.c diff --git a/arch/nios2/soc/nios2f-zephyr/Kconfig.defconfig b/arch/nios2/soc/nios2f-zephyr/Kconfig.defconfig index 89a8d9c35ab..e570b037703 100644 --- a/arch/nios2/soc/nios2f-zephyr/Kconfig.defconfig +++ b/arch/nios2/soc/nios2f-zephyr/Kconfig.defconfig @@ -11,6 +11,13 @@ config SYS_CLOCK_HW_CYCLES_PER_SEC config ALTERA_AVALON_SYSID def_bool y +if GPIO_ALTERA_NIOS2 + +config ALTERA_AVALON_PIO + def_bool y + +endif # GPIO_ALTERA_NIOS2 + if UART_NS16550 config UART_NS16550_PCI diff --git a/drivers/gpio/CMakeLists.txt b/drivers/gpio/CMakeLists.txt index 3eab6b09133..56623eac37e 100644 --- a/drivers/gpio/CMakeLists.txt +++ b/drivers/gpio/CMakeLists.txt @@ -1,3 +1,4 @@ +zephyr_sources_ifdef(CONFIG_GPIO_ALTERA_NIOS2 gpio_altera_nios2.c) zephyr_sources_ifdef(CONFIG_GPIO_ATMEL_SAM3 gpio_atmel_sam3.c) zephyr_sources_ifdef(CONFIG_GPIO_CC2650 gpio_cc2650.c) zephyr_sources_ifdef(CONFIG_GPIO_CC32XX gpio_cc32xx.c) diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 706897fe28a..e3eb119b88b 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -69,4 +69,6 @@ source "drivers/gpio/Kconfig.esp32" source "drivers/gpio/Kconfig.gecko" +source "drivers/gpio/Kconfig.altera_nios2" + endif # GPIO diff --git a/drivers/gpio/Kconfig.altera_nios2 b/drivers/gpio/Kconfig.altera_nios2 new file mode 100644 index 00000000000..475b40b8b67 --- /dev/null +++ b/drivers/gpio/Kconfig.altera_nios2 @@ -0,0 +1,34 @@ +# Kconfig.altera_nios2 - Altera Nios-II GPIO configuration options +# +# +# Copyright (c) 2017 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 +# + +menuconfig GPIO_ALTERA_NIOS2 + bool "Altera Nios-II PIO Controllers" + depends on GPIO && HAS_ALTERA_HAL + default n + help + Enable config options to support the PIO controllers + on Altera Nios-II family processors. + + Says n if not sure. + +if GPIO_ALTERA_NIOS2 + +config GPIO_ALTERA_NIOS2_OUTPUT + bool "Enable driver for Altera Nios-II PIO Output Port" + default n + help + Build the driver to utilize PIO controller Output Port. + +config GPIO_ALTERA_NIOS2_OUTPUT_DEV_NAME + string "Device name for Output Port" + depends on GPIO_ALTERA_NIOS2_OUTPUT + default "PIO_OUTPUT" + help + Device name for Output Port. + +endif # GPIO_ALTERA_NIOS2 diff --git a/drivers/gpio/gpio_altera_nios2.c b/drivers/gpio/gpio_altera_nios2.c new file mode 100644 index 00000000000..14b0b6c4518 --- /dev/null +++ b/drivers/gpio/gpio_altera_nios2.c @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2017 Intel Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file Driver for the Altera Nios-II PIO Core. + */ + +#include +#include +#include +#include +#include +#include + +#include "gpio_utils.h" +#include "altera_avalon_pio_regs.h" + +typedef int (*config_func_t)(struct device *dev, int access_op, + u32_t pin, int flags); + +/* Configuration data */ +struct gpio_nios2_config { + u32_t pio_base; + config_func_t config_func; +}; + +static int gpio_nios2_config_oput_port(struct device *dev, int access_op, + u32_t pin, int flags) +{ + if ((flags & GPIO_DIR_IN) || (flags & GPIO_INT)) { + return -ENOTSUP; + } + + if (access_op == GPIO_ACCESS_BY_PIN) { + return -ENOTSUP; + } + + return 0; +} + +/** + * @brief Configure pin or port + * + * @param dev Device struct + * @param access_op Access operation (pin or port) + * @param pin The pin number + * @param flags Flags of pin or port + * + * @return 0 if successful, failed otherwise + */ +static int gpio_nios2_config(struct device *dev, int access_op, + u32_t pin, int flags) +{ + const struct gpio_nios2_config *cfg = dev->config->config_info; + + if (cfg->config_func) { + return cfg->config_func(dev, access_op, pin, flags); + } + + return 0; +} + +/** + * @brief Set the pin or port output + * + * @param dev Device struct + * @param access_op Access operation (pin or port) + * @param pin The pin number + * @param value Value to set (0 or 1) + * + * @return 0 if successful, failed otherwise + */ +static int gpio_nios2_write(struct device *dev, int access_op, + u32_t pin, u32_t value) +{ + const struct gpio_nios2_config *cfg = dev->config->config_info; + + switch (access_op) { + case GPIO_ACCESS_BY_PIN: + if (value) { + /* set the pin */ + IOWR_ALTERA_AVALON_PIO_SET_BITS(cfg->pio_base, + BIT(pin)); + } else { + /* clear the pin */ + IOWR_ALTERA_AVALON_PIO_CLEAR_BITS(cfg->pio_base, + BIT(pin)); + } + break; + case GPIO_ACCESS_BY_PORT: + IOWR_ALTERA_AVALON_PIO_DATA(cfg->pio_base, value); + break; + default: + return -ENOTSUP; + } + + return 0; +} + +/** + * @brief Read the pin or port status + * + * @param dev Device struct + * @param access_op Access operation (pin or port) + * @param pin The pin number + * @param value Value of input pin(s) + * + * @return 0 if successful, failed otherwise + */ +static int gpio_nios2_read(struct device *dev, int access_op, + u32_t pin, u32_t *value) +{ + const struct gpio_nios2_config *cfg = dev->config->config_info; + + *value = IORD_ALTERA_AVALON_PIO_DATA(cfg->pio_base); + + switch (access_op) { + case GPIO_ACCESS_BY_PIN: + *value = (*value >> pin) & 0x01; + break; + case GPIO_ACCESS_BY_PORT: + break; + default: + return -ENOTSUP; + } + + return 0; +} + +static const struct gpio_driver_api gpio_nios2_drv_api_funcs = { + .config = gpio_nios2_config, + .write = gpio_nios2_write, + .read = gpio_nios2_read, +}; + +/* Output only Port */ +#ifdef CONFIG_GPIO_ALTERA_NIOS2_OUTPUT +static const struct gpio_nios2_config gpio_nios2_oput_cfg = { + .pio_base = LED_BASE, + .config_func = gpio_nios2_config_oput_port, +}; + +/** + * @brief Initialization function of PIO + * + * @param dev Device struct + * @return 0 if successful, failed otherwise. + */ +static int gpio_nios2_oput_init(struct device *dev) +{ + return 0; +} + +DEVICE_AND_API_INIT(gpio_nios2_oput, CONFIG_GPIO_ALTERA_NIOS2_OUTPUT_DEV_NAME, + gpio_nios2_oput_init, NULL, &gpio_nios2_oput_cfg, + POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, + &gpio_nios2_drv_api_funcs); + +#endif /* CONFIG_GPIO_ALTERA_NIOS2_OUTPUT */