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 */
ls_gpio_get_value(struct gpio_chip * chip,unsigned int gpio_pin)294bb7a11eSClé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 */
ls_gpio_set_value(struct gpio_chip * chip,unsigned int gpio_pin,enum gpio_level value)554bb7a11eSClé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 */
ls_gpio_get_direction(struct gpio_chip * chip,unsigned int gpio_pin)804bb7a11eSClé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 */
ls_gpio_set_direction(struct gpio_chip * chip,unsigned int gpio_pin,enum gpio_dir direction)1064bb7a11eSClé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 */
gpio_get_interrupt(struct gpio_chip * chip,unsigned int gpio_pin)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 */
gpio_set_interrupt(struct gpio_chip * chip,unsigned int gpio_pin,enum gpio_interrupt interrupt)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 */
get_info_from_device_tree(struct ls_gpio_chip_data * gpio_data)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) {
190*bce2f88aSVincent Mailhol EMSG("Unable to get the Embedded DTB, GPIO init failed");
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 = {
2134bb7a11eSClément Léger .get_direction = ls_gpio_get_direction,
2144bb7a11eSClément Léger .set_direction = ls_gpio_set_direction,
2154bb7a11eSClément Léger .get_value = ls_gpio_get_value,
2164bb7a11eSClé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
ls_gpio_init(struct ls_gpio_chip_data * gpio_data)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