116c13b4dSManish Tomar // SPDX-License-Identifier: BSD-2-Clause 216c13b4dSManish Tomar /* 316c13b4dSManish Tomar * Copyright 2021 NXP 416c13b4dSManish Tomar * 516c13b4dSManish Tomar * Driver for GPIO Controller 616c13b4dSManish Tomar * 716c13b4dSManish Tomar */ 816c13b4dSManish Tomar 916c13b4dSManish Tomar #include <assert.h> 1016c13b4dSManish Tomar #include <drivers/ls_gpio.h> 1116c13b4dSManish Tomar #include <io.h> 1216c13b4dSManish Tomar #include <kernel/boot.h> 1316c13b4dSManish Tomar #include <kernel/dt.h> 1416c13b4dSManish Tomar #include <libfdt.h> 1516c13b4dSManish Tomar #include <mm/core_memprot.h> 1616c13b4dSManish Tomar 1716c13b4dSManish Tomar static const char * const gpio_controller_map[] = { 1816c13b4dSManish Tomar "/soc/gpio@2300000", 1916c13b4dSManish Tomar "/soc/gpio@2310000", 2016c13b4dSManish Tomar "/soc/gpio@2320000", 2116c13b4dSManish Tomar "/soc/gpio@2330000" 2216c13b4dSManish Tomar }; 2316c13b4dSManish Tomar 2416c13b4dSManish Tomar /* 2516c13b4dSManish Tomar * Get value from GPIO controller 2616c13b4dSManish Tomar * chip: pointer to GPIO controller chip instance 2716c13b4dSManish Tomar * gpio_pin: pin from which value needs to be read 2816c13b4dSManish Tomar */ 29*4bb7a11eSClément Léger static enum gpio_level ls_gpio_get_value(struct gpio_chip *chip, 3016c13b4dSManish Tomar unsigned int gpio_pin) 3116c13b4dSManish Tomar { 3216c13b4dSManish Tomar vaddr_t gpio_data_addr = 0; 3316c13b4dSManish Tomar uint32_t data = 0; 3416c13b4dSManish Tomar struct ls_gpio_chip_data *gc_data = container_of(chip, 3516c13b4dSManish Tomar struct ls_gpio_chip_data, 3616c13b4dSManish Tomar chip); 3716c13b4dSManish Tomar 3816c13b4dSManish Tomar assert(gpio_pin <= MAX_GPIO_PINS); 3916c13b4dSManish Tomar 4016c13b4dSManish Tomar gpio_data_addr = gc_data->gpio_base + GPIODAT; 4116c13b4dSManish Tomar data = io_read32(gpio_data_addr); 4216c13b4dSManish Tomar 4316c13b4dSManish Tomar if (data & PIN_SHIFT(gpio_pin)) 4416c13b4dSManish Tomar return GPIO_LEVEL_HIGH; 4516c13b4dSManish Tomar else 4616c13b4dSManish Tomar return GPIO_LEVEL_LOW; 4716c13b4dSManish Tomar } 4816c13b4dSManish Tomar 4916c13b4dSManish Tomar /* 5016c13b4dSManish Tomar * Set value for GPIO controller 5116c13b4dSManish Tomar * chip: pointer to GPIO controller chip instance 5216c13b4dSManish Tomar * gpio_pin: pin to which value needs to be write 5316c13b4dSManish Tomar * value: value needs to be written to the pin 5416c13b4dSManish Tomar */ 55*4bb7a11eSClément Léger static void ls_gpio_set_value(struct gpio_chip *chip, unsigned int gpio_pin, 5616c13b4dSManish Tomar enum gpio_level value) 5716c13b4dSManish Tomar { 5816c13b4dSManish Tomar vaddr_t gpio_data_addr = 0; 5916c13b4dSManish Tomar struct ls_gpio_chip_data *gc_data = container_of(chip, 6016c13b4dSManish Tomar struct ls_gpio_chip_data, 6116c13b4dSManish Tomar chip); 6216c13b4dSManish Tomar 6316c13b4dSManish Tomar assert(gpio_pin <= MAX_GPIO_PINS); 6416c13b4dSManish Tomar 6516c13b4dSManish Tomar gpio_data_addr = gc_data->gpio_base + GPIODAT; 6616c13b4dSManish Tomar 6716c13b4dSManish Tomar if (value == GPIO_LEVEL_HIGH) 6816c13b4dSManish Tomar /* if value is high then set pin value */ 6916c13b4dSManish Tomar io_setbits32(gpio_data_addr, PIN_SHIFT(gpio_pin)); 7016c13b4dSManish Tomar else 7116c13b4dSManish Tomar /* if value is low then clear pin value */ 7216c13b4dSManish Tomar io_clrbits32(gpio_data_addr, PIN_SHIFT(gpio_pin)); 7316c13b4dSManish Tomar } 7416c13b4dSManish Tomar 7516c13b4dSManish Tomar /* 7616c13b4dSManish Tomar * Get direction from GPIO controller 7716c13b4dSManish Tomar * chip: pointer to GPIO controller chip instance 7816c13b4dSManish Tomar * gpio_pin: pin from which direction needs to be read 7916c13b4dSManish Tomar */ 80*4bb7a11eSClément Léger static enum gpio_dir ls_gpio_get_direction(struct gpio_chip *chip, 8116c13b4dSManish Tomar unsigned int gpio_pin) 8216c13b4dSManish Tomar { 8316c13b4dSManish Tomar vaddr_t gpio_dir_addr = 0; 8416c13b4dSManish Tomar uint32_t data = 0; 8516c13b4dSManish Tomar struct ls_gpio_chip_data *gc_data = container_of(chip, 8616c13b4dSManish Tomar struct ls_gpio_chip_data, 8716c13b4dSManish Tomar chip); 8816c13b4dSManish Tomar 8916c13b4dSManish Tomar assert(gpio_pin <= MAX_GPIO_PINS); 9016c13b4dSManish Tomar 9116c13b4dSManish Tomar gpio_dir_addr = gc_data->gpio_base + GPIODIR; 9216c13b4dSManish Tomar data = io_read32(gpio_dir_addr); 9316c13b4dSManish Tomar 9416c13b4dSManish Tomar if (data & PIN_SHIFT(gpio_pin)) 9516c13b4dSManish Tomar return GPIO_DIR_OUT; 9616c13b4dSManish Tomar else 9716c13b4dSManish Tomar return GPIO_DIR_IN; 9816c13b4dSManish Tomar } 9916c13b4dSManish Tomar 10016c13b4dSManish Tomar /* 10116c13b4dSManish Tomar * Set direction for GPIO controller 10216c13b4dSManish Tomar * chip: pointer to GPIO controller chip instance 10316c13b4dSManish Tomar * gpio_pin: pin on which direction needs to be set 10416c13b4dSManish Tomar * direction: direction which needs to be set on pin 10516c13b4dSManish Tomar */ 106*4bb7a11eSClément Léger static void ls_gpio_set_direction(struct gpio_chip *chip, unsigned int gpio_pin, 10716c13b4dSManish Tomar enum gpio_dir direction) 10816c13b4dSManish Tomar { 10916c13b4dSManish Tomar vaddr_t gpio_dir_addr = 0; 11016c13b4dSManish Tomar struct ls_gpio_chip_data *gc_data = container_of(chip, 11116c13b4dSManish Tomar struct ls_gpio_chip_data, 11216c13b4dSManish Tomar chip); 11316c13b4dSManish Tomar 11416c13b4dSManish Tomar assert(gpio_pin <= MAX_GPIO_PINS); 11516c13b4dSManish Tomar 11616c13b4dSManish Tomar gpio_dir_addr = gc_data->gpio_base + GPIODIR; 11716c13b4dSManish Tomar 11816c13b4dSManish Tomar if (direction == GPIO_DIR_OUT) 11916c13b4dSManish Tomar io_setbits32(gpio_dir_addr, PIN_SHIFT(gpio_pin)); 12016c13b4dSManish Tomar else 12116c13b4dSManish Tomar io_clrbits32(gpio_dir_addr, PIN_SHIFT(gpio_pin)); 12216c13b4dSManish Tomar } 12316c13b4dSManish Tomar 12416c13b4dSManish Tomar /* 12516c13b4dSManish Tomar * Get interrupt from GPIO controller 12616c13b4dSManish Tomar * chip: pointer to GPIO controller chip instance 12716c13b4dSManish Tomar * gpio_pin: pin from which interrupt value needs to be read 12816c13b4dSManish Tomar */ 12916c13b4dSManish Tomar static enum gpio_interrupt gpio_get_interrupt(struct gpio_chip *chip, 13016c13b4dSManish Tomar unsigned int gpio_pin) 13116c13b4dSManish Tomar { 13216c13b4dSManish Tomar vaddr_t gpio_ier_addr = 0; 13316c13b4dSManish Tomar uint32_t data = 0; 13416c13b4dSManish Tomar struct ls_gpio_chip_data *gc_data = container_of(chip, 13516c13b4dSManish Tomar struct ls_gpio_chip_data, 13616c13b4dSManish Tomar chip); 13716c13b4dSManish Tomar 13816c13b4dSManish Tomar assert(gpio_pin <= MAX_GPIO_PINS); 13916c13b4dSManish Tomar 14016c13b4dSManish Tomar gpio_ier_addr = gc_data->gpio_base + GPIOIER; 14116c13b4dSManish Tomar data = io_read32(gpio_ier_addr); 14216c13b4dSManish Tomar 14316c13b4dSManish Tomar if (data & PIN_SHIFT(gpio_pin)) 14416c13b4dSManish Tomar return GPIO_INTERRUPT_ENABLE; 14516c13b4dSManish Tomar else 14616c13b4dSManish Tomar return GPIO_INTERRUPT_DISABLE; 14716c13b4dSManish Tomar } 14816c13b4dSManish Tomar 14916c13b4dSManish Tomar /* 15016c13b4dSManish Tomar * Set interrupt event for GPIO controller 15116c13b4dSManish Tomar * chip: pointer to GPIO controller chip instance 15216c13b4dSManish Tomar * gpio_pin: pin on which interrupt value needs to be set 15316c13b4dSManish Tomar * interrupt: interrupt valie which needs to be set on pin 15416c13b4dSManish Tomar */ 15516c13b4dSManish Tomar static void gpio_set_interrupt(struct gpio_chip *chip, unsigned int gpio_pin, 15616c13b4dSManish Tomar enum gpio_interrupt interrupt) 15716c13b4dSManish Tomar { 15816c13b4dSManish Tomar vaddr_t gpio_ier_addr = 0; 15916c13b4dSManish Tomar struct ls_gpio_chip_data *gc_data = container_of(chip, 16016c13b4dSManish Tomar struct ls_gpio_chip_data, 16116c13b4dSManish Tomar chip); 16216c13b4dSManish Tomar 16316c13b4dSManish Tomar assert(gpio_pin <= MAX_GPIO_PINS); 16416c13b4dSManish Tomar 16516c13b4dSManish Tomar gpio_ier_addr = gc_data->gpio_base + GPIOIER; 16616c13b4dSManish Tomar 16716c13b4dSManish Tomar if (interrupt == GPIO_INTERRUPT_ENABLE) 16816c13b4dSManish Tomar io_setbits32(gpio_ier_addr, PIN_SHIFT(gpio_pin)); 16916c13b4dSManish Tomar else 17016c13b4dSManish Tomar io_clrbits32(gpio_ier_addr, PIN_SHIFT(gpio_pin)); 17116c13b4dSManish Tomar } 17216c13b4dSManish Tomar 17316c13b4dSManish Tomar /* 17416c13b4dSManish Tomar * Extract information for GPIO Controller from the DTB 17516c13b4dSManish Tomar * gpio_data: GPIO controller chip instance 17616c13b4dSManish Tomar */ 17716c13b4dSManish Tomar static TEE_Result get_info_from_device_tree(struct ls_gpio_chip_data *gpio_data) 17816c13b4dSManish Tomar { 17916c13b4dSManish Tomar size_t size = 0; 18016c13b4dSManish Tomar int node = 0; 18116c13b4dSManish Tomar vaddr_t ctrl_base = 0; 18216c13b4dSManish Tomar void *fdt = NULL; 18316c13b4dSManish Tomar 18416c13b4dSManish Tomar /* 18516c13b4dSManish Tomar * First get the GPIO Controller base address from the DTB 18616c13b4dSManish Tomar * if DTB present and if the GPIO Controller defined in it. 18716c13b4dSManish Tomar */ 18816c13b4dSManish Tomar fdt = get_embedded_dt(); 18916c13b4dSManish Tomar if (!fdt) { 19016c13b4dSManish Tomar EMSG("Unable to get the Embedded DTB, GPIO init failed\n"); 19116c13b4dSManish Tomar return TEE_ERROR_GENERIC; 19216c13b4dSManish Tomar } 19316c13b4dSManish Tomar 19416c13b4dSManish Tomar node = fdt_path_offset(fdt, gpio_controller_map 19516c13b4dSManish Tomar [gpio_data->gpio_controller]); 19616c13b4dSManish Tomar if (node > 0) { 197a5d5bbc8SVesa Jääskeläinen if (dt_map_dev(fdt, node, &ctrl_base, &size, 198a5d5bbc8SVesa Jääskeläinen DT_MAP_AUTO) < 0) { 19916c13b4dSManish Tomar EMSG("Unable to get virtual address"); 20016c13b4dSManish Tomar return TEE_ERROR_GENERIC; 20116c13b4dSManish Tomar } 20216c13b4dSManish Tomar } else { 20316c13b4dSManish Tomar EMSG("Unable to get gpio offset node"); 20416c13b4dSManish Tomar return TEE_ERROR_ITEM_NOT_FOUND; 20516c13b4dSManish Tomar } 20616c13b4dSManish Tomar 20716c13b4dSManish Tomar gpio_data->gpio_base = ctrl_base; 20816c13b4dSManish Tomar 20916c13b4dSManish Tomar return TEE_SUCCESS; 21016c13b4dSManish Tomar } 21116c13b4dSManish Tomar 21216c13b4dSManish Tomar static const struct gpio_ops ls_gpio_ops = { 213*4bb7a11eSClément Léger .get_direction = ls_gpio_get_direction, 214*4bb7a11eSClément Léger .set_direction = ls_gpio_set_direction, 215*4bb7a11eSClément Léger .get_value = ls_gpio_get_value, 216*4bb7a11eSClément Léger .set_value = ls_gpio_set_value, 21716c13b4dSManish Tomar .get_interrupt = gpio_get_interrupt, 21816c13b4dSManish Tomar .set_interrupt = gpio_set_interrupt, 21916c13b4dSManish Tomar }; 22016c13b4dSManish Tomar DECLARE_KEEP_PAGER(ls_gpio_ops); 22116c13b4dSManish Tomar 22216c13b4dSManish Tomar TEE_Result ls_gpio_init(struct ls_gpio_chip_data *gpio_data) 22316c13b4dSManish Tomar { 22416c13b4dSManish Tomar TEE_Result status = TEE_ERROR_GENERIC; 22516c13b4dSManish Tomar 22616c13b4dSManish Tomar /* 22716c13b4dSManish Tomar * First get the GPIO Controller base address from the DTB, 22816c13b4dSManish Tomar * if DTB present and if the GPIO Controller defined in it. 22916c13b4dSManish Tomar */ 23016c13b4dSManish Tomar status = get_info_from_device_tree(gpio_data); 23116c13b4dSManish Tomar if (status == TEE_SUCCESS) { 23216c13b4dSManish Tomar /* set GPIO Input Buffer Enable register */ 23316c13b4dSManish Tomar io_setbits32(gpio_data->gpio_base + GPIOIBE, UINT32_MAX); 23416c13b4dSManish Tomar 23516c13b4dSManish Tomar /* generic GPIO chip handle */ 23616c13b4dSManish Tomar gpio_data->chip.ops = &ls_gpio_ops; 23716c13b4dSManish Tomar } else { 23816c13b4dSManish Tomar EMSG("Unable to get info from device tree"); 23916c13b4dSManish Tomar } 24016c13b4dSManish Tomar 24116c13b4dSManish Tomar return status; 24216c13b4dSManish Tomar } 243