123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343 |
- /*
- * Copyright (c) 2006-2023, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Email: opensource_embedded@phytium.com.cn
- *
- * Change Logs:
- * Date Author Notes
- * 2023/7/24 liqiaozhong first add, support intr
- *
- */
- #include "rtconfig.h"
- #include <rtthread.h>
- #include <rtdevice.h>
- #include "interrupt.h"
- #define LOG_TAG "gpio_drv"
- #include "drv_log.h"
- #ifdef RT_USING_SMART
- #include "ioremap.h"
- #endif
- #include <string.h>
- #if defined(TARGET_E2000)
- #include "fparameters.h"
- #endif
- #include "fkernel.h"
- #include "fcpu_info.h"
- #include "ftypes.h"
- #include "fio_mux.h"
- #include "board.h"
- #include "fiopad.h"
- #include "fgpio.h"
- #include "drv_gpio.h"
- /**************************** Type Definitions *******************************/
- typedef void (*FGpioOpsIrqHandler)(s32 vector, void *param);
- typedef struct
- {
- FGpioDirection direction;
- boolean en_irq;
- FGpioIrqType irq_type;
- FGpioOpsIrqHandler irq_handler;
- void *irq_args;
- } FGpioOpsPinConfig;
- typedef struct
- {
- FGpio ctrl;
- FGpioPin pins[FGPIO_PORT_NUM][FGPIO_PIN_NUM];
- FGpioOpsPinConfig pin_config[FGPIO_PORT_NUM][FGPIO_PIN_NUM];
- boolean init_ok;
- } FGpioOps;
- /***************** Macros (Inline Functions) Definitions *********************/
- #if defined(TARGET_E2000)
- #define FGPIO_VERSION_2
- #endif
- /************************** Variable Definitions *****************************/
- static FGpioOps gpio[FGPIO_NUM];
- extern FIOPadCtrl iopad_ctrl;
- /*******************************Api Functions*********************************/
- static void FGpioOpsSetupCtrlIRQ(FGpio *ctrl)
- {
- u32 cpu_id;
- u32 irq_num = ctrl->config.irq_num[0];
- GetCpuId(&cpu_id);
- LOG_D("In FGpioOpsSetupCtrlIRQ() -> cpu_id %d, irq_num %d\r\n", cpu_id, irq_num);
- rt_hw_interrupt_set_target_cpus(irq_num, cpu_id);
- rt_hw_interrupt_set_priority(irq_num, ctrl->config.irq_priority); /* setup interrupt */
- rt_hw_interrupt_install(irq_num, FGpioInterruptHandler, ctrl, NULL); /* register intr handler */
- rt_hw_interrupt_umask(irq_num);
- return;
- }
- /* setup gpio pin interrupt */
- static void FGpioOpsSetupPinIRQ(FGpio *ctrl, FGpioPin *const pin, FGpioOpsPinConfig *config)
- {
- u32 cpu_id;
- u32 irq_num = ctrl->config.irq_num[pin->index.pin];
- GetCpuId(&cpu_id);
- LOG_D("in FGpioOpsSetupPinIRQ() -> cpu_id %d, irq_num %d", cpu_id, irq_num);
- rt_hw_interrupt_set_target_cpus(irq_num, cpu_id);
- rt_hw_interrupt_set_priority(irq_num, ctrl->config.irq_priority); /* setup interrupt */
- rt_hw_interrupt_install(irq_num, FGpioInterruptHandler, config->irq_args, NULL); /* register intr handler */
- rt_hw_interrupt_umask(irq_num);
- return;
- }
- /* on E2000, if u want use GPIO-4-11, set pin = FGPIO_OPS_PIN_INDEX(4, 0, 11) */
- static void drv_pin_mode(struct rt_device *device, rt_base_t pin, rt_uint8_t mode)
- {
- u32 ctrl_id = FGPIO_OPS_PIN_CTRL_ID(pin);
- u32 port_id = FGPIO_OPS_PIN_PORT_ID(pin);
- u32 pin_id = FGPIO_OPS_PIN_ID(pin);
- FGpioPinId gpio_pin_id;
- FError err = FGPIO_SUCCESS;
- FGpio *instance = &gpio[ctrl_id].ctrl;
- FGpioPin *pin_instance = &gpio[ctrl_id].pins[port_id][pin_id];
- FGpioOpsPinConfig *pin_config = &gpio[ctrl_id].pin_config[port_id][pin_id];
- if (ctrl_id >= FGPIO_NUM)
- {
- LOG_E("ctrl_id too large!!!");
- return;
- }
- if (FALSE == gpio[ctrl_id].init_ok) /* init ctrl if needed */
- {
- FGpioConfig input_cfg = *FGpioLookupConfig(ctrl_id);
- memset(instance, 0, sizeof(*instance));
- #ifdef RT_USING_SMART
- input_cfg.base_addr = (uintptr)rt_ioremap((void *)input_cfg.base_addr, 0x1000);
- #endif
- err = FGpioCfgInitialize(instance, &input_cfg);
- if (FGPIO_SUCCESS != err)
- {
- LOG_E("Ctrl: %d init fail!!!\n", ctrl_id);
- return;
- }
- gpio[ctrl_id].init_ok = TRUE;
- }
- FIOPadSetGpioMux(ctrl_id, pin_id);
- if (FT_COMPONENT_IS_READY == pin_instance->is_ready)
- {
- FGpioPinDeInitialize(pin_instance);
- }
- gpio_pin_id.ctrl = ctrl_id;
- gpio_pin_id.port = port_id;
- gpio_pin_id.pin = pin_id;
- err = FGpioPinInitialize(instance, pin_instance, gpio_pin_id);
- if (FGPIO_SUCCESS != err)
- {
- LOG_E("Pin %d-%c-%d init fail!!!\n",
- ctrl_id,
- port_id == 0 ? 'a' : 'b',
- pin_id);
- return;
- }
- switch (mode)
- {
- case PIN_MODE_OUTPUT:
- pin_config->direction = FGPIO_DIR_OUTPUT;
- pin_config->en_irq = FALSE;
- break;
- case PIN_MODE_INPUT:
- pin_config->direction = FGPIO_DIR_INPUT;
- pin_config->en_irq = TRUE;
- pin_config->irq_type = FGPIO_IRQ_TYPE_EDGE_RISING;
- break;
- default:
- rt_kprintf("Not support mode %d!!!\n", mode);
- break;
- }
- FGpioSetDirection(pin_instance, pin_config->direction);
- rt_kprintf("Init GPIO-%d-%c-%d as an %sput pin\r\n",
- ctrl_id,
- port_id,
- pin_id, pin_config->direction == FGPIO_DIR_OUTPUT ? "out" : "in");
- }
- void drv_pin_write(struct rt_device *device, rt_base_t pin, rt_uint8_t value)
- {
- u32 ctrl_id = FGPIO_OPS_PIN_CTRL_ID(pin);
- u32 port_id = FGPIO_OPS_PIN_PORT_ID(pin);
- u32 pin_id = FGPIO_OPS_PIN_ID(pin);
- FGpioPin *pin_instance = &gpio[ctrl_id].pins[port_id][pin_id];
- if (pin_instance == RT_NULL)
- {
- rt_kprintf("Pin %d-%c-%d not set mode\n",
- ctrl_id,
- port_id == 0 ? 'a' : 'b',
- pin_id);
- return;
- }
- FGpioSetOutputValue(pin_instance, (value == PIN_HIGH) ? FGPIO_PIN_HIGH : FGPIO_PIN_LOW);
- }
- rt_ssize_t drv_pin_read(struct rt_device *device, rt_base_t pin)
- {
- u32 ctrl_id = FGPIO_OPS_PIN_CTRL_ID(pin);
- u32 port_id = FGPIO_OPS_PIN_PORT_ID(pin);
- u32 pin_id = FGPIO_OPS_PIN_ID(pin);
- FGpioPin *pin_instance = &gpio[ctrl_id].pins[port_id][pin_id];
- if (pin_instance == RT_NULL)
- {
- rt_kprintf("Pin %d-%c-%d not set mode\n",
- ctrl_id,
- port_id == 0 ? 'a' : 'b',
- pin_id);
- return -RT_ERROR;
- }
- return FGpioGetInputValue(pin_instance) == FGPIO_PIN_HIGH ? PIN_HIGH : PIN_LOW;
- }
- rt_err_t drv_pin_attach_irq(struct rt_device *device, rt_base_t pin,
- rt_uint8_t mode, void (*hdr)(void *args), void *args)
- {
- u32 ctrl_id = FGPIO_OPS_PIN_CTRL_ID(pin);
- u32 port_id = FGPIO_OPS_PIN_PORT_ID(pin);
- u32 pin_id = FGPIO_OPS_PIN_ID(pin);
- rt_base_t level;
- FGpio *instance = &gpio[ctrl_id].ctrl;
- FGpioPin *pin_instance = &gpio[ctrl_id].pins[port_id][pin_id];
- FGpioOpsPinConfig *pin_config = &gpio[ctrl_id].pin_config[port_id][pin_id];
- level = rt_hw_interrupt_disable();
- pin_config->irq_handler = (FGpioOpsIrqHandler)hdr;
- pin_config->irq_args = args;
- if (pin_instance == RT_NULL)
- {
- LOG_E("GPIO%d-%c-%d not init yet.\n", ctrl_id, port_id == 0 ? 'a' : 'b', pin_id);
- return -RT_ERROR;
- }
- if (pin_config->en_irq)
- {
- FGpioSetInterruptMask(pin_instance, FALSE);
- FGpioPinId pin_of_ctrl =
- {
- .ctrl = ctrl_id,
- .port = FGPIO_PORT_A,
- .pin = FGPIO_PIN_0
- };
- if (FGPIO_IRQ_BY_CONTROLLER == FGpioGetPinIrqSourceType(pin_of_ctrl)) /* setup for ctrl report interrupt */
- {
- FGpioOpsSetupCtrlIRQ(instance);
- LOG_I("GPIO-%d report irq by controller", ctrl_id);
- }
- else if (FGPIO_IRQ_BY_PIN == FGpioGetPinIrqSourceType(pin_of_ctrl))
- {
- FGpioOpsSetupPinIRQ(instance, pin_instance, pin_config);
- LOG_I("GPIO-%d report irq by pin", ctrl_id);
- }
- switch (mode)
- {
- case PIN_IRQ_MODE_RISING:
- pin_config->irq_type = FGPIO_IRQ_TYPE_EDGE_RISING;
- break;
- case PIN_IRQ_MODE_FALLING:
- pin_config->irq_type = FGPIO_IRQ_TYPE_EDGE_FALLING;
- break;
- case PIN_IRQ_MODE_LOW_LEVEL:
- pin_config->irq_type = FGPIO_IRQ_TYPE_LEVEL_LOW;
- break;
- case PIN_IRQ_MODE_HIGH_LEVEL:
- pin_config->irq_type = FGPIO_IRQ_TYPE_LEVEL_HIGH;
- break;
- default:
- LOG_E("Do not spport irq_mode: %d\n", mode);
- break;
- }
- FGpioSetInterruptType(pin_instance, pin_config->irq_type);
- FGpioRegisterInterruptCB(pin_instance, pin_config->irq_handler,
- pin_config->irq_args, TRUE); /* register intr callback */
- }
- rt_hw_interrupt_enable(level);
- return RT_EOK;
- }
- rt_err_t drv_pin_detach_irq(struct rt_device *device, rt_base_t pin)
- {
- u32 ctrl_id = FGPIO_OPS_PIN_CTRL_ID(pin);
- u32 port_id = FGPIO_OPS_PIN_PORT_ID(pin);
- u32 pin_id = FGPIO_OPS_PIN_ID(pin);
- rt_base_t level;
- FGpioPin *pin_instance = &gpio[ctrl_id].pins[port_id][pin_id];
- FGpioOpsPinConfig *pin_config = &gpio[ctrl_id].pin_config[port_id][pin_id];
- if (pin_instance == RT_NULL)
- {
- rt_kprintf("pin %d-%c-%d not set mode\n",
- ctrl_id,
- port_id == 0 ? 'a' : 'b',
- pin_id);
- return -RT_ERROR;
- }
- level = rt_hw_interrupt_disable();
- pin_config->irq_handler = RT_NULL;
- pin_config->irq_args = RT_NULL;
- rt_hw_interrupt_enable(level);
- return RT_EOK;
- }
- rt_err_t drv_pin_irq_enable(struct rt_device *device, rt_base_t pin, rt_uint8_t enabled)
- {
- u32 ctrl_id = FGPIO_OPS_PIN_CTRL_ID(pin);
- u32 port_id = FGPIO_OPS_PIN_PORT_ID(pin);
- u32 pin_id = FGPIO_OPS_PIN_ID(pin);
- FGpioPin *pin_instance = &gpio[ctrl_id].pins[port_id][pin_id];
- if (pin_instance == RT_NULL)
- {
- rt_kprintf("Pin %d-%c-%d not set mode\n",
- ctrl_id,
- port_id == 0 ? 'a' : 'b',
- pin_id);
- return -RT_ERROR;
- }
- FGpioSetInterruptMask(pin_instance, enabled);
- return RT_EOK;
- }
- const struct rt_pin_ops drv_pin_ops =
- {
- .pin_mode = drv_pin_mode,
- .pin_write = drv_pin_write,
- .pin_read = drv_pin_read,
- .pin_attach_irq = drv_pin_attach_irq,
- .pin_detach_irq = drv_pin_detach_irq,
- .pin_irq_enable = drv_pin_irq_enable,
- .pin_get = RT_NULL
- };
- int ft_pin_init(void)
- {
- rt_err_t ret = RT_EOK;
- ret = rt_device_pin_register("pin", &drv_pin_ops, RT_NULL);
- rt_kprintf("Register pin with return: %d\n", ret);
- return ret;
- }
- INIT_DEVICE_EXPORT(ft_pin_init);
|