1*cd495a5aSJorge Ramirez-Ortiz // SPDX-License-Identifier: MIT 2*cd495a5aSJorge Ramirez-Ortiz /* 3*cd495a5aSJorge Ramirez-Ortiz * Copyright (C) 2002 - 2021 Xilinx, Inc. All rights reserved. 4*cd495a5aSJorge Ramirez-Ortiz * Copyright (c) 2022 Foundries.io Ltd. (jorge@foundries.io) 5*cd495a5aSJorge Ramirez-Ortiz */ 6*cd495a5aSJorge Ramirez-Ortiz #include <arm.h> 7*cd495a5aSJorge Ramirez-Ortiz #include <assert.h> 8*cd495a5aSJorge Ramirez-Ortiz #include <crypto/crypto.h> 9*cd495a5aSJorge Ramirez-Ortiz #include <initcall.h> 10*cd495a5aSJorge Ramirez-Ortiz #include <io.h> 11*cd495a5aSJorge Ramirez-Ortiz #include <kernel/panic.h> 12*cd495a5aSJorge Ramirez-Ortiz #include <mm/core_mmu.h> 13*cd495a5aSJorge Ramirez-Ortiz #include <platform_config.h> 14*cd495a5aSJorge Ramirez-Ortiz #include <stdlib.h> 15*cd495a5aSJorge Ramirez-Ortiz #include <string.h> 16*cd495a5aSJorge Ramirez-Ortiz #include <tee/tee_cryp_utl.h> 17*cd495a5aSJorge Ramirez-Ortiz 18*cd495a5aSJorge Ramirez-Ortiz #include "drivers/versal_gpio.h" 19*cd495a5aSJorge Ramirez-Ortiz 20*cd495a5aSJorge Ramirez-Ortiz #define VERSAL_GPIO_LEN 0x10000 21*cd495a5aSJorge Ramirez-Ortiz 22*cd495a5aSJorge Ramirez-Ortiz #define DATA_LSW_OFFSET(__bank) (0x000 + 0x08 * (__bank)) 23*cd495a5aSJorge Ramirez-Ortiz #define DATA_MSW_OFFSET(__bank) (0x004 + 0x08 * (__bank)) 24*cd495a5aSJorge Ramirez-Ortiz #define DATA_RO_OFFSET(__bank) (0x060 + 0x04 * (__bank)) 25*cd495a5aSJorge Ramirez-Ortiz #define DIRM_OFFSET(__bank) (0x204 + 0x40 * (__bank)) 26*cd495a5aSJorge Ramirez-Ortiz #define OUTEN_OFFSET(__bank) (0x208 + 0x40 * (__bank)) 27*cd495a5aSJorge Ramirez-Ortiz 28*cd495a5aSJorge Ramirez-Ortiz #define VERSAL_GPIO_MID_PIN 16 29*cd495a5aSJorge Ramirez-Ortiz #define VERSAL_GPIO_UPPER_MASK 0xFFFF0000 30*cd495a5aSJorge Ramirez-Ortiz 31*cd495a5aSJorge Ramirez-Ortiz /* Max pins in the PMC_GPIO devices 32*cd495a5aSJorge Ramirez-Ortiz * 00 - 025, Bank 0 33*cd495a5aSJorge Ramirez-Ortiz * 26 - 051, Bank 1 34*cd495a5aSJorge Ramirez-Ortiz * 52 - 083, Bank 3 35*cd495a5aSJorge Ramirez-Ortiz * 84 - 115, Bank 4 36*cd495a5aSJorge Ramirez-Ortiz */ 37*cd495a5aSJorge Ramirez-Ortiz #define VERSAL_GPIO_PMC_BASE 0xf1020000 38*cd495a5aSJorge Ramirez-Ortiz #define VERSAL_GPIO_PMC_NR_GPIOS 116 39*cd495a5aSJorge Ramirez-Ortiz #define VERSAL_GPIO_PMC_MAX_BANK 5 40*cd495a5aSJorge Ramirez-Ortiz 41*cd495a5aSJorge Ramirez-Ortiz static const struct versal_gpio_platform_data versal_gpio_pmc_def = { 42*cd495a5aSJorge Ramirez-Ortiz .max_bank = VERSAL_GPIO_PMC_MAX_BANK, 43*cd495a5aSJorge Ramirez-Ortiz .ngpio = VERSAL_GPIO_PMC_NR_GPIOS, 44*cd495a5aSJorge Ramirez-Ortiz .label = "versal_pmc_gpio", 45*cd495a5aSJorge Ramirez-Ortiz .bank_min[0] = 0, 46*cd495a5aSJorge Ramirez-Ortiz .bank_max[0] = 25, 47*cd495a5aSJorge Ramirez-Ortiz .bank_min[1] = 26, 48*cd495a5aSJorge Ramirez-Ortiz .bank_max[1] = 51, 49*cd495a5aSJorge Ramirez-Ortiz .bank_min[3] = 52, 50*cd495a5aSJorge Ramirez-Ortiz .bank_max[3] = 83, 51*cd495a5aSJorge Ramirez-Ortiz .bank_min[4] = 84, 52*cd495a5aSJorge Ramirez-Ortiz .bank_max[4] = 115, 53*cd495a5aSJorge Ramirez-Ortiz }; 54*cd495a5aSJorge Ramirez-Ortiz 55*cd495a5aSJorge Ramirez-Ortiz /* Max pins in the PS_GPIO devices 56*cd495a5aSJorge Ramirez-Ortiz * 00 - 25, Bank 0 57*cd495a5aSJorge Ramirez-Ortiz * 26 - 57, Bank 3 58*cd495a5aSJorge Ramirez-Ortiz */ 59*cd495a5aSJorge Ramirez-Ortiz #define VERSAL_GPIO_PS_BASE 0xff0b0000 60*cd495a5aSJorge Ramirez-Ortiz #define VERSAL_GPIO_PS_NR_GPIOS 58 61*cd495a5aSJorge Ramirez-Ortiz #define VERSAL_GPIO_PS_MAX_BANK 4 62*cd495a5aSJorge Ramirez-Ortiz 63*cd495a5aSJorge Ramirez-Ortiz static const struct versal_gpio_platform_data versal_gpio_ps_def = { 64*cd495a5aSJorge Ramirez-Ortiz .max_bank = VERSAL_GPIO_PS_MAX_BANK, 65*cd495a5aSJorge Ramirez-Ortiz .ngpio = VERSAL_GPIO_PS_NR_GPIOS, 66*cd495a5aSJorge Ramirez-Ortiz .label = "versal_ps_gpio", 67*cd495a5aSJorge Ramirez-Ortiz .bank_min[0] = 0, 68*cd495a5aSJorge Ramirez-Ortiz .bank_max[0] = 25, 69*cd495a5aSJorge Ramirez-Ortiz .bank_min[3] = 26, 70*cd495a5aSJorge Ramirez-Ortiz .bank_max[3] = 57, 71*cd495a5aSJorge Ramirez-Ortiz }; 72*cd495a5aSJorge Ramirez-Ortiz 73*cd495a5aSJorge Ramirez-Ortiz static void versal_gpio_get_pin(struct versal_gpio_chip *chip, uint32_t gpio, 74*cd495a5aSJorge Ramirez-Ortiz uint32_t *bank, uint32_t *pin) 75*cd495a5aSJorge Ramirez-Ortiz { 76*cd495a5aSJorge Ramirez-Ortiz struct versal_gpio_platdata *platdata = &chip->plat; 77*cd495a5aSJorge Ramirez-Ortiz uint32_t bnk = 0; 78*cd495a5aSJorge Ramirez-Ortiz 79*cd495a5aSJorge Ramirez-Ortiz assert(gpio < platdata->p_data->ngpio); 80*cd495a5aSJorge Ramirez-Ortiz 81*cd495a5aSJorge Ramirez-Ortiz for (bnk = 0; bnk < platdata->p_data->max_bank; bnk++) { 82*cd495a5aSJorge Ramirez-Ortiz if (gpio < platdata->p_data->bank_min[bnk]) 83*cd495a5aSJorge Ramirez-Ortiz continue; 84*cd495a5aSJorge Ramirez-Ortiz 85*cd495a5aSJorge Ramirez-Ortiz if (gpio > platdata->p_data->bank_max[bnk]) 86*cd495a5aSJorge Ramirez-Ortiz continue; 87*cd495a5aSJorge Ramirez-Ortiz 88*cd495a5aSJorge Ramirez-Ortiz *bank = bnk; 89*cd495a5aSJorge Ramirez-Ortiz *pin = gpio - platdata->p_data->bank_min[bnk]; 90*cd495a5aSJorge Ramirez-Ortiz 91*cd495a5aSJorge Ramirez-Ortiz return; 92*cd495a5aSJorge Ramirez-Ortiz } 93*cd495a5aSJorge Ramirez-Ortiz 94*cd495a5aSJorge Ramirez-Ortiz EMSG("GPIO_%d not found", gpio); 95*cd495a5aSJorge Ramirez-Ortiz panic(); 96*cd495a5aSJorge Ramirez-Ortiz } 97*cd495a5aSJorge Ramirez-Ortiz 98*cd495a5aSJorge Ramirez-Ortiz static enum gpio_level gpio_get_value(struct versal_gpio_chip *chip, 99*cd495a5aSJorge Ramirez-Ortiz uint32_t gpio) 100*cd495a5aSJorge Ramirez-Ortiz { 101*cd495a5aSJorge Ramirez-Ortiz uint32_t bank = 0; 102*cd495a5aSJorge Ramirez-Ortiz uint32_t pin = 0; 103*cd495a5aSJorge Ramirez-Ortiz 104*cd495a5aSJorge Ramirez-Ortiz versal_gpio_get_pin(chip, gpio, &bank, &pin); 105*cd495a5aSJorge Ramirez-Ortiz 106*cd495a5aSJorge Ramirez-Ortiz return (io_read32(chip->base + DATA_RO_OFFSET(bank)) >> pin) & 1; 107*cd495a5aSJorge Ramirez-Ortiz } 108*cd495a5aSJorge Ramirez-Ortiz 109*cd495a5aSJorge Ramirez-Ortiz static void gpio_set_value(struct versal_gpio_chip *chip, uint32_t gpio, 110*cd495a5aSJorge Ramirez-Ortiz enum gpio_level val) 111*cd495a5aSJorge Ramirez-Ortiz { 112*cd495a5aSJorge Ramirez-Ortiz uint32_t bank = 0; 113*cd495a5aSJorge Ramirez-Ortiz uint32_t off = 0; 114*cd495a5aSJorge Ramirez-Ortiz uint32_t pin = 0; 115*cd495a5aSJorge Ramirez-Ortiz 116*cd495a5aSJorge Ramirez-Ortiz versal_gpio_get_pin(chip, gpio, &bank, &pin); 117*cd495a5aSJorge Ramirez-Ortiz 118*cd495a5aSJorge Ramirez-Ortiz if (bank >= VERSAL_GPIO_MID_PIN) { 119*cd495a5aSJorge Ramirez-Ortiz bank -= VERSAL_GPIO_MID_PIN; 120*cd495a5aSJorge Ramirez-Ortiz off = DATA_MSW_OFFSET(bank); 121*cd495a5aSJorge Ramirez-Ortiz } else { 122*cd495a5aSJorge Ramirez-Ortiz off = DATA_LSW_OFFSET(bank); 123*cd495a5aSJorge Ramirez-Ortiz } 124*cd495a5aSJorge Ramirez-Ortiz 125*cd495a5aSJorge Ramirez-Ortiz /* 126*cd495a5aSJorge Ramirez-Ortiz * get the 32 bit value to be written to the mask/data register where 127*cd495a5aSJorge Ramirez-Ortiz * the upper 16 bits is the mask and lower 16 bits is the data 128*cd495a5aSJorge Ramirez-Ortiz */ 129*cd495a5aSJorge Ramirez-Ortiz val = !!val; 130*cd495a5aSJorge Ramirez-Ortiz val = ~BIT32(pin + VERSAL_GPIO_MID_PIN) & 131*cd495a5aSJorge Ramirez-Ortiz (SHIFT_U32(val, pin) | VERSAL_GPIO_UPPER_MASK); 132*cd495a5aSJorge Ramirez-Ortiz 133*cd495a5aSJorge Ramirez-Ortiz io_write32(chip->base + off, val); 134*cd495a5aSJorge Ramirez-Ortiz } 135*cd495a5aSJorge Ramirez-Ortiz 136*cd495a5aSJorge Ramirez-Ortiz static void gpio_set_direction(struct versal_gpio_chip *chip, uint32_t gpio, 137*cd495a5aSJorge Ramirez-Ortiz enum gpio_dir direction) 138*cd495a5aSJorge Ramirez-Ortiz { 139*cd495a5aSJorge Ramirez-Ortiz uint32_t bank = 0; 140*cd495a5aSJorge Ramirez-Ortiz uint32_t reg = 0; 141*cd495a5aSJorge Ramirez-Ortiz uint32_t pin = 0; 142*cd495a5aSJorge Ramirez-Ortiz 143*cd495a5aSJorge Ramirez-Ortiz versal_gpio_get_pin(chip, gpio, &bank, &pin); 144*cd495a5aSJorge Ramirez-Ortiz 145*cd495a5aSJorge Ramirez-Ortiz if (direction == GPIO_DIR_OUT) { 146*cd495a5aSJorge Ramirez-Ortiz /* set the GPIO pin as output */ 147*cd495a5aSJorge Ramirez-Ortiz reg = io_read32(chip->base + DIRM_OFFSET(bank)); 148*cd495a5aSJorge Ramirez-Ortiz reg |= BIT(pin); 149*cd495a5aSJorge Ramirez-Ortiz io_write32(chip->base + DIRM_OFFSET(bank), reg); 150*cd495a5aSJorge Ramirez-Ortiz 151*cd495a5aSJorge Ramirez-Ortiz /* configure the output enable reg for the pin */ 152*cd495a5aSJorge Ramirez-Ortiz reg = io_read32(chip->base + OUTEN_OFFSET(bank)); 153*cd495a5aSJorge Ramirez-Ortiz 154*cd495a5aSJorge Ramirez-Ortiz reg |= BIT(pin); 155*cd495a5aSJorge Ramirez-Ortiz io_write32(chip->base + OUTEN_OFFSET(bank), reg); 156*cd495a5aSJorge Ramirez-Ortiz 157*cd495a5aSJorge Ramirez-Ortiz /* set the state of the pin */ 158*cd495a5aSJorge Ramirez-Ortiz gpio_set_value(chip, gpio, GPIO_LEVEL_LOW); 159*cd495a5aSJorge Ramirez-Ortiz } else { 160*cd495a5aSJorge Ramirez-Ortiz /* bnk 0 pins 7 and 8 cannot be used as inputs */ 161*cd495a5aSJorge Ramirez-Ortiz assert(!(bank == 0 && (pin == 7 || pin == 8))); 162*cd495a5aSJorge Ramirez-Ortiz 163*cd495a5aSJorge Ramirez-Ortiz reg = io_read32(chip->base + DIRM_OFFSET(bank)); 164*cd495a5aSJorge Ramirez-Ortiz reg &= ~BIT(pin); 165*cd495a5aSJorge Ramirez-Ortiz io_write32(chip->base + DIRM_OFFSET(bank), reg); 166*cd495a5aSJorge Ramirez-Ortiz } 167*cd495a5aSJorge Ramirez-Ortiz } 168*cd495a5aSJorge Ramirez-Ortiz 169*cd495a5aSJorge Ramirez-Ortiz static enum gpio_dir gpio_get_direction(struct versal_gpio_chip *chip, 170*cd495a5aSJorge Ramirez-Ortiz uint32_t gpio) 171*cd495a5aSJorge Ramirez-Ortiz { 172*cd495a5aSJorge Ramirez-Ortiz uint32_t pin = 0; 173*cd495a5aSJorge Ramirez-Ortiz uint32_t bank = 0; 174*cd495a5aSJorge Ramirez-Ortiz 175*cd495a5aSJorge Ramirez-Ortiz versal_gpio_get_pin(chip, gpio, &bank, &pin); 176*cd495a5aSJorge Ramirez-Ortiz 177*cd495a5aSJorge Ramirez-Ortiz if (io_read32(chip->base + DIRM_OFFSET(bank)) & BIT(pin)) 178*cd495a5aSJorge Ramirez-Ortiz return GPIO_DIR_OUT; 179*cd495a5aSJorge Ramirez-Ortiz 180*cd495a5aSJorge Ramirez-Ortiz return GPIO_DIR_IN; 181*cd495a5aSJorge Ramirez-Ortiz } 182*cd495a5aSJorge Ramirez-Ortiz 183*cd495a5aSJorge Ramirez-Ortiz static enum gpio_level do_get_value(struct gpio_chip *chip, uint32_t gpio) 184*cd495a5aSJorge Ramirez-Ortiz { 185*cd495a5aSJorge Ramirez-Ortiz struct versal_gpio_chip *p = container_of(chip, 186*cd495a5aSJorge Ramirez-Ortiz struct versal_gpio_chip, chip); 187*cd495a5aSJorge Ramirez-Ortiz return gpio_get_value(p, gpio); 188*cd495a5aSJorge Ramirez-Ortiz } 189*cd495a5aSJorge Ramirez-Ortiz 190*cd495a5aSJorge Ramirez-Ortiz static void do_set_value(struct gpio_chip *chip, uint32_t gpio, 191*cd495a5aSJorge Ramirez-Ortiz enum gpio_level val) 192*cd495a5aSJorge Ramirez-Ortiz { 193*cd495a5aSJorge Ramirez-Ortiz struct versal_gpio_chip *p = container_of(chip, 194*cd495a5aSJorge Ramirez-Ortiz struct versal_gpio_chip, chip); 195*cd495a5aSJorge Ramirez-Ortiz return gpio_set_value(p, gpio, val); 196*cd495a5aSJorge Ramirez-Ortiz } 197*cd495a5aSJorge Ramirez-Ortiz 198*cd495a5aSJorge Ramirez-Ortiz static void do_set_dir(struct gpio_chip *chip, uint32_t gpio, 199*cd495a5aSJorge Ramirez-Ortiz enum gpio_dir direction) 200*cd495a5aSJorge Ramirez-Ortiz { 201*cd495a5aSJorge Ramirez-Ortiz struct versal_gpio_chip *p = container_of(chip, 202*cd495a5aSJorge Ramirez-Ortiz struct versal_gpio_chip, chip); 203*cd495a5aSJorge Ramirez-Ortiz return gpio_set_direction(p, gpio, direction); 204*cd495a5aSJorge Ramirez-Ortiz } 205*cd495a5aSJorge Ramirez-Ortiz 206*cd495a5aSJorge Ramirez-Ortiz static enum gpio_dir do_get_dir(struct gpio_chip *chip, uint32_t gpio) 207*cd495a5aSJorge Ramirez-Ortiz { 208*cd495a5aSJorge Ramirez-Ortiz struct versal_gpio_chip *p = container_of(chip, 209*cd495a5aSJorge Ramirez-Ortiz struct versal_gpio_chip, chip); 210*cd495a5aSJorge Ramirez-Ortiz return gpio_get_direction(p, gpio); 211*cd495a5aSJorge Ramirez-Ortiz } 212*cd495a5aSJorge Ramirez-Ortiz 213*cd495a5aSJorge Ramirez-Ortiz static const struct gpio_ops versal_gpio_ops = { 214*cd495a5aSJorge Ramirez-Ortiz .get_direction = do_get_dir, 215*cd495a5aSJorge Ramirez-Ortiz .set_direction = do_set_dir, 216*cd495a5aSJorge Ramirez-Ortiz .get_value = do_get_value, 217*cd495a5aSJorge Ramirez-Ortiz .set_value = do_set_value, 218*cd495a5aSJorge Ramirez-Ortiz .get_interrupt = NULL, 219*cd495a5aSJorge Ramirez-Ortiz .set_interrupt = NULL, 220*cd495a5aSJorge Ramirez-Ortiz }; 221*cd495a5aSJorge Ramirez-Ortiz 222*cd495a5aSJorge Ramirez-Ortiz TEE_Result versal_gpio_pmc_init(struct versal_gpio_chip *chip) 223*cd495a5aSJorge Ramirez-Ortiz { 224*cd495a5aSJorge Ramirez-Ortiz if (chip->base) 225*cd495a5aSJorge Ramirez-Ortiz return TEE_SUCCESS; 226*cd495a5aSJorge Ramirez-Ortiz 227*cd495a5aSJorge Ramirez-Ortiz chip->plat.p_data = &versal_gpio_pmc_def; 228*cd495a5aSJorge Ramirez-Ortiz chip->plat.base = VERSAL_GPIO_PMC_BASE; 229*cd495a5aSJorge Ramirez-Ortiz chip->chip.ops = &versal_gpio_ops; 230*cd495a5aSJorge Ramirez-Ortiz 231*cd495a5aSJorge Ramirez-Ortiz chip->base = (vaddr_t)core_mmu_add_mapping(MEM_AREA_IO_SEC, 232*cd495a5aSJorge Ramirez-Ortiz VERSAL_GPIO_PMC_BASE, 233*cd495a5aSJorge Ramirez-Ortiz VERSAL_GPIO_LEN); 234*cd495a5aSJorge Ramirez-Ortiz if (!chip->base) { 235*cd495a5aSJorge Ramirez-Ortiz EMSG("Failed to map gpio"); 236*cd495a5aSJorge Ramirez-Ortiz chip->chip.ops = NULL; 237*cd495a5aSJorge Ramirez-Ortiz return TEE_ERROR_GENERIC; 238*cd495a5aSJorge Ramirez-Ortiz } 239*cd495a5aSJorge Ramirez-Ortiz 240*cd495a5aSJorge Ramirez-Ortiz return TEE_SUCCESS; 241*cd495a5aSJorge Ramirez-Ortiz } 242*cd495a5aSJorge Ramirez-Ortiz 243*cd495a5aSJorge Ramirez-Ortiz TEE_Result versal_gpio_ps_init(struct versal_gpio_chip *chip) 244*cd495a5aSJorge Ramirez-Ortiz { 245*cd495a5aSJorge Ramirez-Ortiz if (chip->base) 246*cd495a5aSJorge Ramirez-Ortiz return TEE_SUCCESS; 247*cd495a5aSJorge Ramirez-Ortiz 248*cd495a5aSJorge Ramirez-Ortiz chip->plat.p_data = &versal_gpio_ps_def; 249*cd495a5aSJorge Ramirez-Ortiz chip->plat.base = VERSAL_GPIO_PS_BASE; 250*cd495a5aSJorge Ramirez-Ortiz chip->chip.ops = &versal_gpio_ops; 251*cd495a5aSJorge Ramirez-Ortiz 252*cd495a5aSJorge Ramirez-Ortiz chip->base = (vaddr_t)core_mmu_add_mapping(MEM_AREA_IO_SEC, 253*cd495a5aSJorge Ramirez-Ortiz VERSAL_GPIO_PS_BASE, 254*cd495a5aSJorge Ramirez-Ortiz VERSAL_GPIO_LEN); 255*cd495a5aSJorge Ramirez-Ortiz if (!chip->base) { 256*cd495a5aSJorge Ramirez-Ortiz EMSG("Failed to map gpio"); 257*cd495a5aSJorge Ramirez-Ortiz chip->chip.ops = NULL; 258*cd495a5aSJorge Ramirez-Ortiz return TEE_ERROR_GENERIC; 259*cd495a5aSJorge Ramirez-Ortiz } 260*cd495a5aSJorge Ramirez-Ortiz 261*cd495a5aSJorge Ramirez-Ortiz return TEE_SUCCESS; 262*cd495a5aSJorge Ramirez-Ortiz } 263