1*e61fc00fSSandeep Tripathy // SPDX-License-Identifier: BSD-2-Clause 2*e61fc00fSSandeep Tripathy /* 3*e61fc00fSSandeep Tripathy * Copyright 2019 Broadcom. 4*e61fc00fSSandeep Tripathy */ 5*e61fc00fSSandeep Tripathy #include <assert.h> 6*e61fc00fSSandeep Tripathy #include <drivers/bcm_gpio.h> 7*e61fc00fSSandeep Tripathy #include <initcall.h> 8*e61fc00fSSandeep Tripathy #include <io.h> 9*e61fc00fSSandeep Tripathy #include <mm/core_memprot.h> 10*e61fc00fSSandeep Tripathy #include <platform_config.h> 11*e61fc00fSSandeep Tripathy #include <trace.h> 12*e61fc00fSSandeep Tripathy 13*e61fc00fSSandeep Tripathy #define IPROC_GPIO_DATA_IN_OFFSET 0x00 14*e61fc00fSSandeep Tripathy #define IPROC_GPIO_DATA_OUT_OFFSET 0x04 15*e61fc00fSSandeep Tripathy #define IPROC_GPIO_OUT_EN_OFFSET 0x08 16*e61fc00fSSandeep Tripathy #define IPROC_GPIO_INT_MSK_OFFSET 0x18 17*e61fc00fSSandeep Tripathy 18*e61fc00fSSandeep Tripathy #define GPIO_BANK_SIZE 0x200 19*e61fc00fSSandeep Tripathy #define NGPIOS_PER_BANK 32 20*e61fc00fSSandeep Tripathy #define GPIO_BANK(pin) ((pin) / NGPIOS_PER_BANK) 21*e61fc00fSSandeep Tripathy 22*e61fc00fSSandeep Tripathy #define IPROC_GPIO_REG(pin, reg) ((reg) + \ 23*e61fc00fSSandeep Tripathy GPIO_BANK(pin) * GPIO_BANK_SIZE) 24*e61fc00fSSandeep Tripathy 25*e61fc00fSSandeep Tripathy #define IPROC_GPIO_SHIFT(pin) ((pin) % NGPIOS_PER_BANK) 26*e61fc00fSSandeep Tripathy 27*e61fc00fSSandeep Tripathy static SLIST_HEAD(, bcm_gpio_chip) gclist = SLIST_HEAD_INITIALIZER(gclist); 28*e61fc00fSSandeep Tripathy 29*e61fc00fSSandeep Tripathy struct bcm_gpio_chip *bcm_gpio_pin_to_chip(unsigned int pin) 30*e61fc00fSSandeep Tripathy { 31*e61fc00fSSandeep Tripathy struct bcm_gpio_chip *gc = NULL; 32*e61fc00fSSandeep Tripathy 33*e61fc00fSSandeep Tripathy SLIST_FOREACH(gc, &gclist, link) 34*e61fc00fSSandeep Tripathy if ((pin >= gc->gpio_base) && 35*e61fc00fSSandeep Tripathy (pin < (gc->gpio_base + gc->ngpios))) 36*e61fc00fSSandeep Tripathy return gc; 37*e61fc00fSSandeep Tripathy return NULL; 38*e61fc00fSSandeep Tripathy } 39*e61fc00fSSandeep Tripathy 40*e61fc00fSSandeep Tripathy static bool __maybe_unused gpio_is_range_overlap(unsigned int start, 41*e61fc00fSSandeep Tripathy unsigned int end) 42*e61fc00fSSandeep Tripathy { 43*e61fc00fSSandeep Tripathy struct bcm_gpio_chip *gc = NULL; 44*e61fc00fSSandeep Tripathy 45*e61fc00fSSandeep Tripathy SLIST_FOREACH(gc, &gclist, link) 46*e61fc00fSSandeep Tripathy if ((start < (gc->gpio_base + gc->ngpios)) && 47*e61fc00fSSandeep Tripathy (end > gc->gpio_base)) 48*e61fc00fSSandeep Tripathy return true; 49*e61fc00fSSandeep Tripathy return false; 50*e61fc00fSSandeep Tripathy } 51*e61fc00fSSandeep Tripathy 52*e61fc00fSSandeep Tripathy static void iproc_set_bit(unsigned int reg, unsigned int gpio) 53*e61fc00fSSandeep Tripathy { 54*e61fc00fSSandeep Tripathy unsigned int offset = IPROC_GPIO_REG(gpio, reg); 55*e61fc00fSSandeep Tripathy unsigned int shift = IPROC_GPIO_SHIFT(gpio); 56*e61fc00fSSandeep Tripathy struct bcm_gpio_chip *gc = bcm_gpio_pin_to_chip(gpio); 57*e61fc00fSSandeep Tripathy 58*e61fc00fSSandeep Tripathy assert(gc); 59*e61fc00fSSandeep Tripathy io_setbits32(gc->base + offset, BIT(shift)); 60*e61fc00fSSandeep Tripathy } 61*e61fc00fSSandeep Tripathy 62*e61fc00fSSandeep Tripathy static void iproc_clr_bit(unsigned int reg, unsigned int gpio) 63*e61fc00fSSandeep Tripathy { 64*e61fc00fSSandeep Tripathy unsigned int offset = IPROC_GPIO_REG(gpio, reg); 65*e61fc00fSSandeep Tripathy unsigned int shift = IPROC_GPIO_SHIFT(gpio); 66*e61fc00fSSandeep Tripathy struct bcm_gpio_chip *gc = bcm_gpio_pin_to_chip(gpio); 67*e61fc00fSSandeep Tripathy 68*e61fc00fSSandeep Tripathy assert(gc); 69*e61fc00fSSandeep Tripathy io_clrbits32(gc->base + offset, BIT(shift)); 70*e61fc00fSSandeep Tripathy } 71*e61fc00fSSandeep Tripathy 72*e61fc00fSSandeep Tripathy static void iproc_gpio_set(unsigned int gpio, enum gpio_level val) 73*e61fc00fSSandeep Tripathy { 74*e61fc00fSSandeep Tripathy if (val == GPIO_LEVEL_HIGH) 75*e61fc00fSSandeep Tripathy iproc_set_bit(IPROC_GPIO_DATA_OUT_OFFSET, gpio); 76*e61fc00fSSandeep Tripathy else 77*e61fc00fSSandeep Tripathy iproc_clr_bit(IPROC_GPIO_DATA_OUT_OFFSET, gpio); 78*e61fc00fSSandeep Tripathy } 79*e61fc00fSSandeep Tripathy 80*e61fc00fSSandeep Tripathy static enum gpio_level iproc_gpio_get(unsigned int gpio) 81*e61fc00fSSandeep Tripathy { 82*e61fc00fSSandeep Tripathy unsigned int offset = IPROC_GPIO_REG(gpio, IPROC_GPIO_DATA_IN_OFFSET); 83*e61fc00fSSandeep Tripathy unsigned int shift = IPROC_GPIO_SHIFT(gpio); 84*e61fc00fSSandeep Tripathy struct bcm_gpio_chip *gc = bcm_gpio_pin_to_chip(gpio); 85*e61fc00fSSandeep Tripathy 86*e61fc00fSSandeep Tripathy assert(gc); 87*e61fc00fSSandeep Tripathy 88*e61fc00fSSandeep Tripathy if (io_read32(gc->base + offset) & BIT(shift)) 89*e61fc00fSSandeep Tripathy return GPIO_LEVEL_HIGH; 90*e61fc00fSSandeep Tripathy else 91*e61fc00fSSandeep Tripathy return GPIO_LEVEL_LOW; 92*e61fc00fSSandeep Tripathy } 93*e61fc00fSSandeep Tripathy 94*e61fc00fSSandeep Tripathy static void iproc_gpio_set_dir(unsigned int gpio, enum gpio_dir dir) 95*e61fc00fSSandeep Tripathy { 96*e61fc00fSSandeep Tripathy if (dir == GPIO_DIR_OUT) 97*e61fc00fSSandeep Tripathy iproc_set_bit(IPROC_GPIO_OUT_EN_OFFSET, gpio); 98*e61fc00fSSandeep Tripathy else 99*e61fc00fSSandeep Tripathy iproc_clr_bit(IPROC_GPIO_OUT_EN_OFFSET, gpio); 100*e61fc00fSSandeep Tripathy } 101*e61fc00fSSandeep Tripathy 102*e61fc00fSSandeep Tripathy static enum gpio_dir iproc_gpio_get_dir(unsigned int gpio) 103*e61fc00fSSandeep Tripathy { 104*e61fc00fSSandeep Tripathy unsigned int offset = IPROC_GPIO_REG(gpio, IPROC_GPIO_OUT_EN_OFFSET); 105*e61fc00fSSandeep Tripathy unsigned int shift = IPROC_GPIO_SHIFT(gpio); 106*e61fc00fSSandeep Tripathy struct bcm_gpio_chip *gc = bcm_gpio_pin_to_chip(gpio); 107*e61fc00fSSandeep Tripathy 108*e61fc00fSSandeep Tripathy assert(gc); 109*e61fc00fSSandeep Tripathy 110*e61fc00fSSandeep Tripathy if (io_read32(gc->base + offset) & BIT(shift)) 111*e61fc00fSSandeep Tripathy return GPIO_DIR_OUT; 112*e61fc00fSSandeep Tripathy else 113*e61fc00fSSandeep Tripathy return GPIO_DIR_IN; 114*e61fc00fSSandeep Tripathy } 115*e61fc00fSSandeep Tripathy 116*e61fc00fSSandeep Tripathy static enum gpio_interrupt iproc_gpio_get_itr(unsigned int gpio) 117*e61fc00fSSandeep Tripathy { 118*e61fc00fSSandeep Tripathy unsigned int offset = IPROC_GPIO_REG(gpio, IPROC_GPIO_INT_MSK_OFFSET); 119*e61fc00fSSandeep Tripathy unsigned int shift = IPROC_GPIO_SHIFT(gpio); 120*e61fc00fSSandeep Tripathy struct bcm_gpio_chip *gc = bcm_gpio_pin_to_chip(gpio); 121*e61fc00fSSandeep Tripathy 122*e61fc00fSSandeep Tripathy assert(gc); 123*e61fc00fSSandeep Tripathy 124*e61fc00fSSandeep Tripathy if (io_read32(gc->base + offset) & BIT(shift)) 125*e61fc00fSSandeep Tripathy return GPIO_INTERRUPT_ENABLE; 126*e61fc00fSSandeep Tripathy else 127*e61fc00fSSandeep Tripathy return GPIO_INTERRUPT_DISABLE; 128*e61fc00fSSandeep Tripathy } 129*e61fc00fSSandeep Tripathy 130*e61fc00fSSandeep Tripathy static void iproc_gpio_set_itr(unsigned int gpio, 131*e61fc00fSSandeep Tripathy enum gpio_interrupt ena_dis) 132*e61fc00fSSandeep Tripathy { 133*e61fc00fSSandeep Tripathy if (ena_dis == GPIO_INTERRUPT_ENABLE) 134*e61fc00fSSandeep Tripathy iproc_set_bit(IPROC_GPIO_OUT_EN_OFFSET, gpio); 135*e61fc00fSSandeep Tripathy else 136*e61fc00fSSandeep Tripathy iproc_clr_bit(IPROC_GPIO_OUT_EN_OFFSET, gpio); 137*e61fc00fSSandeep Tripathy } 138*e61fc00fSSandeep Tripathy 139*e61fc00fSSandeep Tripathy static const struct gpio_ops bcm_gpio_ops = { 140*e61fc00fSSandeep Tripathy .get_direction = iproc_gpio_get_dir, 141*e61fc00fSSandeep Tripathy .set_direction = iproc_gpio_set_dir, 142*e61fc00fSSandeep Tripathy .get_value = iproc_gpio_get, 143*e61fc00fSSandeep Tripathy .set_value = iproc_gpio_set, 144*e61fc00fSSandeep Tripathy .get_interrupt = iproc_gpio_get_itr, 145*e61fc00fSSandeep Tripathy .set_interrupt = iproc_gpio_set_itr, 146*e61fc00fSSandeep Tripathy }; 147*e61fc00fSSandeep Tripathy KEEP_PAGER(bcm_gpio_ops); 148*e61fc00fSSandeep Tripathy 149*e61fc00fSSandeep Tripathy static void iproc_gpio_init(struct bcm_gpio_chip *gc, unsigned int paddr, 150*e61fc00fSSandeep Tripathy unsigned int gpio_base, unsigned int ngpios) 151*e61fc00fSSandeep Tripathy { 152*e61fc00fSSandeep Tripathy assert(!gpio_is_range_overlap(gpio_base, gpio_base + gc->ngpios)); 153*e61fc00fSSandeep Tripathy 154*e61fc00fSSandeep Tripathy gc->base = core_mmu_get_va(paddr, MEM_AREA_IO_SEC); 155*e61fc00fSSandeep Tripathy gc->chip.ops = &bcm_gpio_ops; 156*e61fc00fSSandeep Tripathy gc->gpio_base = gpio_base; 157*e61fc00fSSandeep Tripathy gc->ngpios = ngpios; 158*e61fc00fSSandeep Tripathy 159*e61fc00fSSandeep Tripathy SLIST_INSERT_HEAD(&gclist, gc, link); 160*e61fc00fSSandeep Tripathy 161*e61fc00fSSandeep Tripathy DMSG("gpio chip for <%u - %u>", gpio_base, gpio_base + ngpios); 162*e61fc00fSSandeep Tripathy } 163*e61fc00fSSandeep Tripathy 164*e61fc00fSSandeep Tripathy static TEE_Result bcm_gpio_init(void) 165*e61fc00fSSandeep Tripathy { 166*e61fc00fSSandeep Tripathy struct bcm_gpio_chip *gc = NULL; 167*e61fc00fSSandeep Tripathy 168*e61fc00fSSandeep Tripathy #ifdef SECURE_GPIO_BASE0 169*e61fc00fSSandeep Tripathy gc = malloc(sizeof(*gc)); 170*e61fc00fSSandeep Tripathy if (gc == NULL) 171*e61fc00fSSandeep Tripathy return TEE_ERROR_OUT_OF_MEMORY; 172*e61fc00fSSandeep Tripathy 173*e61fc00fSSandeep Tripathy iproc_gpio_init(gc, SECURE_GPIO_BASE0, GPIO_NUM_START0, NUM_GPIOS0); 174*e61fc00fSSandeep Tripathy #endif 175*e61fc00fSSandeep Tripathy #ifdef SECURE_GPIO_BASE1 176*e61fc00fSSandeep Tripathy gc = malloc(sizeof(*gc)); 177*e61fc00fSSandeep Tripathy if (gc == NULL) 178*e61fc00fSSandeep Tripathy return TEE_ERROR_OUT_OF_MEMORY; 179*e61fc00fSSandeep Tripathy 180*e61fc00fSSandeep Tripathy iproc_gpio_init(gc, SECURE_GPIO_BASE1, GPIO_NUM_START1, NUM_GPIOS1); 181*e61fc00fSSandeep Tripathy #endif 182*e61fc00fSSandeep Tripathy return TEE_SUCCESS; 183*e61fc00fSSandeep Tripathy } 184*e61fc00fSSandeep Tripathy driver_init(bcm_gpio_init); 185