common/util/hal_gpio.c (171 lines of code) (raw):

#include <zephyr.h> #include <stdio.h> #include "hal_gpio.h" #include "pal.h" #include "util_sys.h" #define STACK_SIZE 1024 static const struct device *dev_gpio[GPIO_GROUP_NUM]; static struct gpio_callback callbacks[total_gpio_num]; static struct k_work_q gpio_work_queue; static K_THREAD_STACK_DEFINE(gpio_work_stack, STACK_SIZE); struct k_work gpio_work[total_gpio_num]; uint8_t gpio_ind_to_num_table[200]; uint8_t gpio_ind_to_num_table_cnt; __weak const char *const gpio_name[] = {}; GPIO_CFG gpio_cfg[GPIO_CFG_SIZE] = { // chip, number, is_init, direction, status, property, int_type, int_cb // Defalut DISABLE GPIO_INPUT LOW PUSH_PULL GPIO_INT_DISABLE NULL }; void irq_callback(const struct device *dev, struct gpio_callback *cb, uint32_t pins) { uint8_t group, index, gpio_num; if (dev == dev_gpio[gpio_a_d]) { group = gpio_a_d; } else if (dev == dev_gpio[gpio_e_h]) { group = gpio_e_h; } else if (dev == dev_gpio[gpio_i_l]) { group = gpio_i_l; } else if (dev == dev_gpio[gpio_m_p]) { group = gpio_m_p; } else if (dev == dev_gpio[gpio_q_t]) { group = gpio_q_t; } else if (dev == dev_gpio[gpio_u_v]) { group = gpio_u_v; } else { printk("invalid dev group for isr cb\n"); return; } for (index = 0; index < GPIO_GROUP_SIZE; index++) { if ((pins >> index) & 0x1) { pins = index; break; } } if (index == GPIO_GROUP_SIZE) { printk("irq_callback: pin %x not found\n", pins); return; } gpio_num = (group * GPIO_GROUP_SIZE) + pins; if (gpio_cfg[gpio_num].int_cb == NULL) { printk("CB func pointer NULL for gpio num %d\n", gpio_num); return; } k_work_submit_to_queue(&gpio_work_queue, &gpio_work[gpio_num]); } static void gpio_init_cb(uint8_t gpio_num) { gpio_init_callback(&callbacks[gpio_num], irq_callback, BIT(gpio_num % GPIO_GROUP_SIZE)); return; } static int gpio_add_cb(uint8_t gpio_num) { return gpio_add_callback(dev_gpio[gpio_num / GPIO_GROUP_SIZE], &callbacks[gpio_num]); } /* interrupt type: GPIO_INT_DISABLE GPIO_INT_EDGE_RISING GPIO_INT_EDGE_FALLING GPIO_INT_EDGE_BOTH GPIO_INT_LEVEL_LOW GPIO_INT_LEVEL_HIGH */ int gpio_interrupt_conf(uint8_t gpio_num, gpio_flags_t flags) { return gpio_pin_interrupt_configure(dev_gpio[gpio_num / GPIO_GROUP_SIZE], (gpio_num % GPIO_GROUP_SIZE), flags); } void gpio_cb_irq_init(uint8_t gpio_num, gpio_flags_t flags) { gpio_init_cb(gpio_num); gpio_add_cb(gpio_num); gpio_interrupt_conf(gpio_num, flags); k_work_init(&gpio_work[gpio_num], gpio_cfg[gpio_num].int_cb); } uint8_t gpio_conf(uint8_t gpio_num, int dir) { return gpio_pin_configure(dev_gpio[gpio_num / GPIO_GROUP_SIZE], (gpio_num % GPIO_GROUP_SIZE), dir); } int gpio_get(uint8_t gpio_num) { if (gpio_num >= total_gpio_num) { printf("getting invalid gpio num %d", gpio_num); return false; } return gpio_pin_get(dev_gpio[gpio_num / GPIO_GROUP_SIZE], (gpio_num % GPIO_GROUP_SIZE)); // return gpio[0].get(&gpio[0], gpio_num); } int gpio_set(uint8_t gpio_num, uint8_t status) { if (gpio_num >= total_gpio_num) { printf("setting invalid gpio num %d", gpio_num); return false; } if (gpio_cfg[gpio_num].property == OPEN_DRAIN) { // should release gpio ctrl for OD high if (status) { return gpio_conf(gpio_num, GPIO_INPUT); } else { gpio_conf(gpio_num, GPIO_OUTPUT); return gpio_pin_set(dev_gpio[gpio_num / GPIO_GROUP_SIZE], (gpio_num % GPIO_GROUP_SIZE), status); } } else { return gpio_pin_set(dev_gpio[gpio_num / GPIO_GROUP_SIZE], (gpio_num % GPIO_GROUP_SIZE), status); } } /*void gpio_show(void) { uint8_t i, j, status; char direction[6]; printf("Number: Group Status Direction Name\n"); for(i = 0; i < total_gpio_num; i++) { if (gpio_cfg[i].is_init == ENABLE) { printf("%02d: %c%d %d %s %s\n", j++, ((i/8)+65), (i%8), gpio[0].get(&gpio[0], i), gpio[0].get_direction(&gpio[0], i) == 1 ? "Output" : "Input ", gpio_name[i]); } } printf("\n"); return; }*/ void gpio_index_to_num(void) { uint8_t i = 0; for (uint8_t j = 0; j < total_gpio_num; j++) { if (gpio_cfg[j].is_init == ENABLE) { gpio_ind_to_num_table[i++] = gpio_cfg[j].number; } } gpio_ind_to_num_table_cnt = i; } void init_gpio_dev(void) { #ifdef DEV_GPIO_A_D dev_gpio[gpio_a_d] = device_get_binding("GPIO0_A_D"); #endif #ifdef DEV_GPIO_E_H dev_gpio[gpio_e_h] = device_get_binding("GPIO0_E_H"); #endif #ifdef DEV_GPIO_I_L dev_gpio[gpio_i_l] = device_get_binding("GPIO0_I_L"); #endif #ifdef DEV_GPIO_M_P dev_gpio[gpio_m_p] = device_get_binding("GPIO0_M_P"); #endif #ifdef DEV_GPIO_Q_T dev_gpio[gpio_q_t] = device_get_binding("GPIO0_Q_T"); #endif #ifdef DEV_GPIO_U_V dev_gpio[gpio_u_v] = device_get_binding("GPIO0_U_V"); #endif } void gpio_init(void) { uint8_t i; pal_load_gpio_config(); init_gpio_dev(); gpio_index_to_num(); // gpio init is much earily than main init seq // set boot source here to skip gpio init for latched gpios set_boot_source(); k_work_queue_start(&gpio_work_queue, gpio_work_stack, STACK_SIZE, K_PRIO_PREEMPT(CONFIG_MAIN_THREAD_PRIORITY), NULL); k_thread_name_set(&gpio_work_queue.thread, "gpio_workq"); for (i = 0; i < total_gpio_num; i++) { if (gpio_cfg[i].is_init == ENABLE) { if (gpio_cfg[i].is_latch == ENABLE && !get_boot_source_ACon()) { continue; } if (gpio_cfg[i].chip == chip_gpio) { gpio_set(gpio_cfg[i].number, gpio_cfg[i].status); if (gpio_cfg[i].property == PUSH_PULL) { // OD config is set during status set gpio_conf(gpio_cfg[i].number, gpio_cfg[i].direction); } gpio_set(gpio_cfg[i].number, gpio_cfg[i].status); if ((gpio_cfg[i].int_type == GPIO_INT_EDGE_RISING) || (gpio_cfg[i].int_type == GPIO_INT_EDGE_FALLING) || (gpio_cfg[i].int_type == GPIO_INT_EDGE_BOTH) || (gpio_cfg[i].int_type == GPIO_INT_LEVEL_LOW) || (gpio_cfg[i].int_type == GPIO_INT_LEVEL_HIGH)) { gpio_cb_irq_init(gpio_cfg[i].number, gpio_cfg[i].int_type); } } else { printf("TODO: add sgpio handler\n"); } } } }