liangzhanggb commented on a change in pull request #2669: URL: https://github.com/apache/incubator-nuttx/pull/2669#discussion_r556390285
########## File path: boards/risc-v/bl602/bl602evb/src/bl602_gpio.c ########## @@ -0,0 +1,648 @@ +/**************************************************************************** + * board/risc-v/bl602/bl602evb/src/bl602_gpio.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> +#include <stdint.h> +#include <stdio.h> +#include <stdbool.h> +#include <assert.h> +#include <debug.h> +#include <nuttx/arch.h> +#include <nuttx/ioexpander/gpio.h> +#include <arch/board/board.h> +#include "riscv_arch.h" +#include "bl602_gpio.h" + +#if defined(CONFIG_DEV_GPIO) && !defined(CONFIG_GPIO_LOWER_HALF) + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define BOARD_GPIO_PIN(mode, pupd, func, pin) (mode | pupd | func | pin) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct bl602_gpio_dev_s +{ + struct gpio_dev_s gpio; + uint8_t id; +}; + +struct bl602_gpint_dev_s +{ + struct bl602_gpio_dev_s bl602gpio; + pin_interrupt_t callback; +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int gpin_read(FAR struct gpio_dev_s *dev, FAR bool *value); +static int gpout_read(FAR struct gpio_dev_s *dev, FAR bool *value); +static int gpout_write(FAR struct gpio_dev_s *dev, bool value); +static int gpint_read(FAR struct gpio_dev_s *dev, FAR bool *value); +static int gpint_attach(FAR struct gpio_dev_s *dev, + pin_interrupt_t callback); +static int gpint_enable(FAR struct gpio_dev_s *dev, bool enable); +static int gpio_setpintype(FAR struct gpio_dev_s *dev, + enum gpio_pintype_e gp_pintype); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct gpio_operations_s gpin_ops = +{ + .go_read = gpin_read, + .go_write = NULL, + .go_attach = NULL, + .go_enable = NULL, + .go_setpintype = gpio_setpintype, +}; + +static const struct gpio_operations_s gpout_ops = +{ + .go_read = gpout_read, + .go_write = gpout_write, + .go_attach = NULL, + .go_enable = NULL, + .go_setpintype = gpio_setpintype, +}; + +static const struct gpio_operations_s gpint_ops = +{ + .go_read = gpint_read, + .go_write = NULL, + .go_attach = gpint_attach, + .go_enable = gpint_enable, + .go_setpintype = gpio_setpintype, +}; + +#if BOARD_NGPIOIN > 0 +/* This array maps the GPIO pins used as INPUT */ + +static const uint32_t g_gpioinputs[BOARD_NGPIOIN] = +{ + BOARD_GPIO_IN1, +}; + +static struct bl602_gpio_dev_s g_gpin[BOARD_NGPIOIN]; +#endif + +#if BOARD_NGPIOOUT +/* This array maps the GPIO pins used as OUTPUT */ + +static const uint32_t g_gpiooutputs[BOARD_NGPIOOUT] = +{ + BOARD_GPIO_OUT1, +}; + +static struct bl602_gpio_dev_s g_gpout[BOARD_NGPIOOUT]; +#endif + +#if BOARD_NGPIOINT > 0 +/* This array maps the GPIO pins used as INTERRUPT INPUTS */ + +static const uint32_t g_gpiointinputs[BOARD_NGPIOINT] = +{ + BOARD_GPIO_INT1, +}; + +static struct bl602_gpint_dev_s g_gpint[BOARD_NGPIOINT]; +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: bl602_gpio_intmask + * + * Description: + * intmask a gpio pin. + * + ****************************************************************************/ + +static void bl602_gpio_intmask(int pin, int intmask) +{ + uint32_t tmp_val; + + if (pin < 28) + { + tmp_val = getreg32(BL602_GPIO_INT_MASK1); + if (intmask == 1) + { + tmp_val |= (1 << pin); + } + else + { + tmp_val &= ~(1 << pin); + } + + putreg32(tmp_val, BL602_GPIO_INT_MASK1); + } +} + +/**************************************************************************** + * Name: bl602_gpio_set_intmod + * + * Description: + * set gpio intmod. + * + ****************************************************************************/ + +static void bl602_gpio_set_intmod(uint8_t gpio_pin, + uint8_t int_ctlmod, uint8_t int_trgmod) +{ + uint32_t tmp_val; + + if (gpio_pin < GPIO_PIN10) + { + /* GPIO0 ~ GPIO9 */ + + tmp_val = gpio_pin; + modifyreg32(BL602_GPIO_INT_MODE_SET1, + 0x7 << (3 * tmp_val), + ((int_ctlmod << 2) | int_trgmod) << (3 * tmp_val)); + } + else if (gpio_pin < GPIO_PIN20) + { + /* GPIO10 ~ GPIO19 */ + + tmp_val = gpio_pin - GPIO_PIN10; + modifyreg32(BL602_GPIO_INT_MODE_SET2, + 0x7 << (3 * tmp_val), + ((int_ctlmod << 2) | int_trgmod) << (3 * tmp_val)); + } + else + { + /* GPIO20 ~ GPIO29 */ + + tmp_val = gpio_pin - GPIO_PIN20; + modifyreg32(BL602_GPIO_INT_MODE_SET3, + 0x7 << (3 * tmp_val), + ((int_ctlmod << 2) | int_trgmod) << (3 * tmp_val)); + } +} + +/**************************************************************************** + * Name: bl602_gpio_get_intstatus + * + * Description: + * get gpio intstatus. + * + ****************************************************************************/ + +static int bl602_gpio_get_intstatus(uint8_t gpio_pin) +{ + uint32_t tmp_val = 0; + + if (gpio_pin < 28) + { + /* GPIO0 ~ GPIO27 */ + + tmp_val = getreg32(BL602_GPIO_INT_STAT1); + } + + return (tmp_val & (1 << gpio_pin)) ? 1 : 0; +} + +/**************************************************************************** + * Name: bl602_gpio_intclear + * + * Description: + * clear gpio int. + * + ****************************************************************************/ + +static void bl602_gpio_intclear(uint8_t gpio_pin, uint8_t int_clear) +{ + if (gpio_pin < 28) + { + /* GPIO0 ~ GPIO27 */ + + modifyreg32(BL602_GPIO_INT_CLR1, + int_clear ? 0 : (1 << gpio_pin), + int_clear ? (1 << gpio_pin) : 0); + } +} + +/**************************************************************************** + * Name: bl602_gpio_interrupt + * + * Description: + * gpio interrupt. + * + ****************************************************************************/ + +static int bl602_gpio_interrupt(int irq, void *context, void *arg) +{ + FAR struct bl602_gpint_dev_s *bl602xgpint = + (FAR struct bl602_gpint_dev_s *)arg; + + uint32_t time_out = 0; + uint8_t gpio_pin; + + DEBUGASSERT(bl602xgpint != NULL && bl602xgpint->callback != NULL); + gpioinfo("Interrupt! callback=%p\n", bl602xgpint->callback); + + gpio_pin = (g_gpiointinputs[bl602xgpint->bl602gpio.id] & GPIO_PIN_MASK) >> + GPIO_PIN_SHIFT; + + if (1 == bl602_gpio_get_intstatus(gpio_pin)) + { + bl602_gpio_intclear(gpio_pin, 1); + + /* timeout check */ + + time_out = 32; + do + { + time_out--; + } + while ((1 == bl602_gpio_get_intstatus(gpio_pin)) && time_out); + if (!time_out) + { + printf("WARNING: Clear GPIO interrupt status fail.\r\n"); + } + + /* if time_out==0, GPIO interrupt status not cleared */ + + bl602_gpio_intclear(gpio_pin, 0); + } + + bl602xgpint->callback(&bl602xgpint->bl602gpio.gpio, + gpio_pin); + + return OK; +} + +/**************************************************************************** + * Name: gpio_setpintype + * + * Description: + * set gpio pintype. + * + ****************************************************************************/ + +static int gpio_setpintype(FAR struct gpio_dev_s *dev, + enum gpio_pintype_e gp_pintype) +{ + FAR struct bl602_gpint_dev_s *bl602xgpint = + (FAR struct bl602_gpint_dev_s *)dev; + uint8_t gpio_pin; + uint8_t pintype = bl602xgpint->bl602gpio.gpio.gp_pintype; + + DEBUGASSERT(bl602xgpint != NULL); + gpioinfo("setpintype...\n"); + + if (pintype <= GPIO_INPUT_PIN_PULLDOWN) + { + gpio_pin = + (g_gpioinputs[bl602xgpint->bl602gpio.id] & GPIO_PIN_MASK) >> + GPIO_PIN_SHIFT; + } + else if (pintype <= GPIO_OUTPUT_PIN_OPENDRAIN) + { + gpio_pin = + (g_gpiooutputs[bl602xgpint->bl602gpio.id] & GPIO_PIN_MASK) >> + GPIO_PIN_SHIFT; + } + else if (pintype < GPIO_NPINTYPES) + { + gpio_pin = + (g_gpiointinputs[bl602xgpint->bl602gpio.id] & GPIO_PIN_MASK) >> + GPIO_PIN_SHIFT; + } + else + { + printf("pintype error\r\n"); + return -1; + } + + switch (gp_pintype) + { + case GPIO_INPUT_PIN: + bl602_configgpio( + BOARD_GPIO_PIN(GPIO_INPUT, GPIO_FLOAT, GPIO_FUNC_SWGPIO, gpio_pin)); + break; + case GPIO_INPUT_PIN_PULLUP: + bl602_configgpio( + BOARD_GPIO_PIN(GPIO_INPUT, GPIO_PULLUP, GPIO_FUNC_SWGPIO, gpio_pin)); + break; + case GPIO_INPUT_PIN_PULLDOWN: + bl602_configgpio( + BOARD_GPIO_PIN(GPIO_INPUT, GPIO_PULLDOWN, GPIO_FUNC_SWGPIO, gpio_pin)); + break; + case GPIO_OUTPUT_PIN: + bl602_configgpio( + BOARD_GPIO_PIN(GPIO_OUTPUT, GPIO_PULLUP, GPIO_FUNC_SWGPIO, gpio_pin)); + break; + case GPIO_OUTPUT_PIN_OPENDRAIN: + bl602_configgpio( + BOARD_GPIO_PIN(GPIO_OUTPUT, GPIO_FLOAT, GPIO_FUNC_SWGPIO, gpio_pin)); + break; + case GPIO_INTERRUPT_RISING_PIN: + bl602_gpio_set_intmod(gpio_pin, 1, GLB_GPIO_INT_TRIG_POS_PULSE); + bl602_configgpio( + BOARD_GPIO_PIN(GPIO_INPUT, GPIO_PULLUP, GPIO_FUNC_SWGPIO, gpio_pin)); + break; + case GPIO_INTERRUPT_FALLING_PIN: + bl602_gpio_set_intmod(gpio_pin, 1, GLB_GPIO_INT_TRIG_NEG_PULSE); + bl602_configgpio( + BOARD_GPIO_PIN(GPIO_INPUT, GPIO_PULLUP, GPIO_FUNC_SWGPIO, gpio_pin)); + break; + default: + break; + } + + return 0; +} + +/**************************************************************************** + * Name: gpin_read + * + * Description: + * read gpio input. + * + ****************************************************************************/ + +static int gpin_read(FAR struct gpio_dev_s *dev, FAR bool *value) +{ + FAR struct bl602_gpio_dev_s *bl602xgpio = + (FAR struct bl602_gpio_dev_s *)dev; + + DEBUGASSERT(bl602xgpio != NULL && value != NULL); + gpioinfo("Reading...\n"); + *value = bl602_gpioread(g_gpioinputs[bl602xgpio->id]); + + return OK; +} + +/**************************************************************************** + * Name: gpout_read + * + * Description: + * read gpio output. + * + ****************************************************************************/ + +static int gpout_read(FAR struct gpio_dev_s *dev, FAR bool *value) +{ + FAR struct bl602_gpio_dev_s *bl602xgpio = + (FAR struct bl602_gpio_dev_s *)dev; + + DEBUGASSERT(bl602xgpio != NULL && value != NULL); + DEBUGASSERT(bl602xgpio->id < BOARD_NGPIOOUT); + gpioinfo("Reading...\n"); + + uint8_t gpio_pin = (g_gpiooutputs[bl602xgpio->id] & GPIO_PIN_MASK) >> + GPIO_PIN_SHIFT; + uint32_t *p = (uint32_t *)(BL602_GPIO_CFGCTL32 + ((gpio_pin >> 5) << 2)); + uint32_t pos = gpio_pin % 32; + + if ((*p) & (1 << pos)) + { + *value = 1; + } + else + { + *value = 0; + } + + return OK; +} + +/**************************************************************************** + * Name: gpout_write + * + * Description: + * write gpio. + * + ****************************************************************************/ + +static int gpout_write(FAR struct gpio_dev_s *dev, bool value) +{ + FAR struct bl602_gpio_dev_s *bl602xgpio = + (FAR struct bl602_gpio_dev_s *)dev; + + DEBUGASSERT(bl602xgpio != NULL); + DEBUGASSERT(bl602xgpio->id < BOARD_NGPIOOUT); + gpioinfo("Writing %d\n", (int)value); + + uint8_t gpio_pin = (g_gpiooutputs[bl602xgpio->id] & GPIO_PIN_MASK) >> + GPIO_PIN_SHIFT; + uint32_t *p_out = (uint32_t *)(BL602_GPIO_CFGCTL32 + + ((gpio_pin >> 5) << 2)); + uint32_t pos = gpio_pin % 32; Review comment: I have fixed it ,Thanks. ---------------------------------------------------------------- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. For queries about this service, please contact Infrastructure at: us...@infra.apache.org