1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright (c) 2016-2021, ARM Limited and Contributors. All rights reserved. 3*91f16700Schasinglulu * 4*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause 5*91f16700Schasinglulu */ 6*91f16700Schasinglulu 7*91f16700Schasinglulu #include <assert.h> 8*91f16700Schasinglulu #include <errno.h> 9*91f16700Schasinglulu 10*91f16700Schasinglulu #include <platform_def.h> 11*91f16700Schasinglulu 12*91f16700Schasinglulu #include <common/debug.h> 13*91f16700Schasinglulu #include <drivers/delay_timer.h> 14*91f16700Schasinglulu #include <drivers/gpio.h> 15*91f16700Schasinglulu #include <lib/mmio.h> 16*91f16700Schasinglulu #include <plat/common/platform.h> 17*91f16700Schasinglulu 18*91f16700Schasinglulu #include <plat_private.h> 19*91f16700Schasinglulu #include <soc.h> 20*91f16700Schasinglulu 21*91f16700Schasinglulu struct gpio_save { 22*91f16700Schasinglulu uint32_t swporta_dr; 23*91f16700Schasinglulu uint32_t swporta_ddr; 24*91f16700Schasinglulu uint32_t inten; 25*91f16700Schasinglulu uint32_t intmask; 26*91f16700Schasinglulu uint32_t inttype_level; 27*91f16700Schasinglulu uint32_t int_polarity; 28*91f16700Schasinglulu uint32_t debounce; 29*91f16700Schasinglulu uint32_t ls_sync; 30*91f16700Schasinglulu } store_gpio[3]; 31*91f16700Schasinglulu 32*91f16700Schasinglulu static uint32_t store_grf_gpio[(GRF_GPIO2D_HE - GRF_GPIO2A_IOMUX) / 4 + 1]; 33*91f16700Schasinglulu 34*91f16700Schasinglulu #define SWPORTA_DR 0x00 35*91f16700Schasinglulu #define SWPORTA_DDR 0x04 36*91f16700Schasinglulu #define INTEN 0x30 37*91f16700Schasinglulu #define INTMASK 0x34 38*91f16700Schasinglulu #define INTTYPE_LEVEL 0x38 39*91f16700Schasinglulu #define INT_POLARITY 0x3c 40*91f16700Schasinglulu #define DEBOUNCE 0x48 41*91f16700Schasinglulu #define LS_SYNC 0x60 42*91f16700Schasinglulu 43*91f16700Schasinglulu #define EXT_PORTA 0x50 44*91f16700Schasinglulu #define PMU_GPIO_PORT0 0 45*91f16700Schasinglulu #define PMU_GPIO_PORT1 1 46*91f16700Schasinglulu #define GPIO_PORT2 2 47*91f16700Schasinglulu #define GPIO_PORT3 3 48*91f16700Schasinglulu #define GPIO_PORT4 4 49*91f16700Schasinglulu 50*91f16700Schasinglulu #define PMU_GRF_GPIO0A_P 0x40 51*91f16700Schasinglulu #define GRF_GPIO2A_P 0xe040 52*91f16700Schasinglulu #define GPIO_P_MASK 0x03 53*91f16700Schasinglulu 54*91f16700Schasinglulu #define GET_GPIO_PORT(pin) (pin / 32) 55*91f16700Schasinglulu #define GET_GPIO_NUM(pin) (pin % 32) 56*91f16700Schasinglulu #define GET_GPIO_BANK(pin) ((pin % 32) / 8) 57*91f16700Schasinglulu #define GET_GPIO_ID(pin) ((pin % 32) % 8) 58*91f16700Schasinglulu 59*91f16700Schasinglulu enum { 60*91f16700Schasinglulu ENC_ZDZU, 61*91f16700Schasinglulu ENC_ZUDR, 62*91f16700Schasinglulu ENC_ZUDZ, 63*91f16700Schasinglulu NUM_ENC 64*91f16700Schasinglulu }; 65*91f16700Schasinglulu 66*91f16700Schasinglulu static const struct port_info { 67*91f16700Schasinglulu uint32_t clkgate_reg; 68*91f16700Schasinglulu uint32_t pull_base; 69*91f16700Schasinglulu uint32_t port_base; 70*91f16700Schasinglulu /* 71*91f16700Schasinglulu * Selects the pull mode encoding per bank, 72*91f16700Schasinglulu * first index for pull_type_{hw2sw,sw2hw} 73*91f16700Schasinglulu */ 74*91f16700Schasinglulu uint8_t pull_enc[4]; 75*91f16700Schasinglulu uint8_t clkgate_bit; 76*91f16700Schasinglulu uint8_t max_bank; 77*91f16700Schasinglulu } port_info[] = { 78*91f16700Schasinglulu { 79*91f16700Schasinglulu .clkgate_reg = PMUCRU_BASE + CRU_PMU_CLKGATE_CON(1), 80*91f16700Schasinglulu .pull_base = PMUGRF_BASE + PMUGRF_GPIO0A_P, 81*91f16700Schasinglulu .port_base = GPIO0_BASE, 82*91f16700Schasinglulu .pull_enc = {ENC_ZDZU, ENC_ZDZU}, 83*91f16700Schasinglulu .clkgate_bit = PCLK_GPIO0_GATE_SHIFT, 84*91f16700Schasinglulu .max_bank = 1, 85*91f16700Schasinglulu }, { 86*91f16700Schasinglulu .clkgate_reg = PMUCRU_BASE + CRU_PMU_CLKGATE_CON(1), 87*91f16700Schasinglulu .pull_base = PMUGRF_BASE + PMUGRF_GPIO1A_P, 88*91f16700Schasinglulu .port_base = GPIO1_BASE, 89*91f16700Schasinglulu .pull_enc = {ENC_ZUDR, ENC_ZUDR, ENC_ZUDR, ENC_ZUDR}, 90*91f16700Schasinglulu .clkgate_bit = PCLK_GPIO1_GATE_SHIFT, 91*91f16700Schasinglulu .max_bank = 3, 92*91f16700Schasinglulu }, { 93*91f16700Schasinglulu .clkgate_reg = CRU_BASE + CRU_CLKGATE_CON(31), 94*91f16700Schasinglulu .pull_base = GRF_BASE + GRF_GPIO2A_P, 95*91f16700Schasinglulu .port_base = GPIO2_BASE, 96*91f16700Schasinglulu .pull_enc = {ENC_ZUDR, ENC_ZUDR, ENC_ZDZU, ENC_ZDZU}, 97*91f16700Schasinglulu .clkgate_bit = PCLK_GPIO2_GATE_SHIFT, 98*91f16700Schasinglulu .max_bank = 3, 99*91f16700Schasinglulu }, { 100*91f16700Schasinglulu .clkgate_reg = CRU_BASE + CRU_CLKGATE_CON(31), 101*91f16700Schasinglulu .pull_base = GRF_BASE + GRF_GPIO3A_P, 102*91f16700Schasinglulu .port_base = GPIO3_BASE, 103*91f16700Schasinglulu .pull_enc = {ENC_ZUDR, ENC_ZUDR, ENC_ZUDR, ENC_ZUDR}, 104*91f16700Schasinglulu .clkgate_bit = PCLK_GPIO3_GATE_SHIFT, 105*91f16700Schasinglulu .max_bank = 3, 106*91f16700Schasinglulu }, { 107*91f16700Schasinglulu .clkgate_reg = CRU_BASE + CRU_CLKGATE_CON(31), 108*91f16700Schasinglulu .pull_base = GRF_BASE + GRF_GPIO4A_P, 109*91f16700Schasinglulu .port_base = GPIO4_BASE, 110*91f16700Schasinglulu .pull_enc = {ENC_ZUDR, ENC_ZUDR, ENC_ZUDR, ENC_ZUDR}, 111*91f16700Schasinglulu .clkgate_bit = PCLK_GPIO4_GATE_SHIFT, 112*91f16700Schasinglulu .max_bank = 3, 113*91f16700Schasinglulu } 114*91f16700Schasinglulu }; 115*91f16700Schasinglulu 116*91f16700Schasinglulu /* 117*91f16700Schasinglulu * Mappings between TF-A constants and hardware encodings: 118*91f16700Schasinglulu * there are 3 different encoding schemes that may differ between 119*91f16700Schasinglulu * banks of the same port: the corresponding value of the pull_enc array 120*91f16700Schasinglulu * in port_info is used as the first index 121*91f16700Schasinglulu */ 122*91f16700Schasinglulu static const uint8_t pull_type_hw2sw[NUM_ENC][4] = { 123*91f16700Schasinglulu [ENC_ZDZU] = {GPIO_PULL_NONE, GPIO_PULL_DOWN, GPIO_PULL_NONE, GPIO_PULL_UP}, 124*91f16700Schasinglulu [ENC_ZUDR] = {GPIO_PULL_NONE, GPIO_PULL_UP, GPIO_PULL_DOWN, GPIO_PULL_REPEATER}, 125*91f16700Schasinglulu [ENC_ZUDZ] = {GPIO_PULL_NONE, GPIO_PULL_UP, GPIO_PULL_DOWN, GPIO_PULL_NONE} 126*91f16700Schasinglulu }; 127*91f16700Schasinglulu static const uint8_t pull_type_sw2hw[NUM_ENC][4] = { 128*91f16700Schasinglulu [ENC_ZDZU] = { 129*91f16700Schasinglulu [GPIO_PULL_NONE] = 0, 130*91f16700Schasinglulu [GPIO_PULL_DOWN] = 1, 131*91f16700Schasinglulu [GPIO_PULL_UP] = 3, 132*91f16700Schasinglulu [GPIO_PULL_REPEATER] = -1 133*91f16700Schasinglulu }, 134*91f16700Schasinglulu [ENC_ZUDR] = { 135*91f16700Schasinglulu [GPIO_PULL_NONE] = 0, 136*91f16700Schasinglulu [GPIO_PULL_DOWN] = 2, 137*91f16700Schasinglulu [GPIO_PULL_UP] = 1, 138*91f16700Schasinglulu [GPIO_PULL_REPEATER] = 3 139*91f16700Schasinglulu }, 140*91f16700Schasinglulu [ENC_ZUDZ] = { 141*91f16700Schasinglulu [GPIO_PULL_NONE] = 0, 142*91f16700Schasinglulu [GPIO_PULL_DOWN] = 2, 143*91f16700Schasinglulu [GPIO_PULL_UP] = 1, 144*91f16700Schasinglulu [GPIO_PULL_REPEATER] = -1 145*91f16700Schasinglulu } 146*91f16700Schasinglulu }; 147*91f16700Schasinglulu 148*91f16700Schasinglulu /* Return old clock state, enables clock, in order to do GPIO access */ 149*91f16700Schasinglulu static int gpio_get_clock(uint32_t gpio_number) 150*91f16700Schasinglulu { 151*91f16700Schasinglulu uint32_t port = GET_GPIO_PORT(gpio_number); 152*91f16700Schasinglulu assert(port < 5U); 153*91f16700Schasinglulu 154*91f16700Schasinglulu const struct port_info *info = &port_info[port]; 155*91f16700Schasinglulu 156*91f16700Schasinglulu if ((mmio_read_32(info->clkgate_reg) & (1U << info->clkgate_bit)) == 0U) { 157*91f16700Schasinglulu return 0; 158*91f16700Schasinglulu } 159*91f16700Schasinglulu mmio_write_32( 160*91f16700Schasinglulu info->clkgate_reg, 161*91f16700Schasinglulu BITS_WITH_WMASK(0, 1, info->clkgate_bit) 162*91f16700Schasinglulu ); 163*91f16700Schasinglulu return 1; 164*91f16700Schasinglulu } 165*91f16700Schasinglulu 166*91f16700Schasinglulu /* Restore old state of gpio clock, assuming it is running now */ 167*91f16700Schasinglulu void gpio_put_clock(uint32_t gpio_number, uint32_t clock_state) 168*91f16700Schasinglulu { 169*91f16700Schasinglulu if (clock_state == 0) { 170*91f16700Schasinglulu return; 171*91f16700Schasinglulu } 172*91f16700Schasinglulu uint32_t port = GET_GPIO_PORT(gpio_number); 173*91f16700Schasinglulu const struct port_info *info = &port_info[port]; 174*91f16700Schasinglulu 175*91f16700Schasinglulu mmio_write_32(info->clkgate_reg, BITS_WITH_WMASK(1, 1, info->clkgate_bit)); 176*91f16700Schasinglulu } 177*91f16700Schasinglulu 178*91f16700Schasinglulu static int get_pull(int gpio) 179*91f16700Schasinglulu { 180*91f16700Schasinglulu uint32_t port = GET_GPIO_PORT(gpio); 181*91f16700Schasinglulu uint32_t bank = GET_GPIO_BANK(gpio); 182*91f16700Schasinglulu uint32_t id = GET_GPIO_ID(gpio); 183*91f16700Schasinglulu uint32_t val, clock_state; 184*91f16700Schasinglulu 185*91f16700Schasinglulu assert(port < 5U); 186*91f16700Schasinglulu const struct port_info *info = &port_info[port]; 187*91f16700Schasinglulu 188*91f16700Schasinglulu assert(bank <= info->max_bank); 189*91f16700Schasinglulu 190*91f16700Schasinglulu clock_state = gpio_get_clock(gpio); 191*91f16700Schasinglulu val = (mmio_read_32(info->pull_base + 4 * bank) >> (id * 2)) & GPIO_P_MASK; 192*91f16700Schasinglulu gpio_put_clock(gpio, clock_state); 193*91f16700Schasinglulu 194*91f16700Schasinglulu return pull_type_hw2sw[info->pull_enc[bank]][val]; 195*91f16700Schasinglulu } 196*91f16700Schasinglulu 197*91f16700Schasinglulu static void set_pull(int gpio, int pull) 198*91f16700Schasinglulu { 199*91f16700Schasinglulu uint32_t port = GET_GPIO_PORT(gpio); 200*91f16700Schasinglulu uint32_t bank = GET_GPIO_BANK(gpio); 201*91f16700Schasinglulu uint32_t id = GET_GPIO_ID(gpio); 202*91f16700Schasinglulu uint32_t clock_state; 203*91f16700Schasinglulu 204*91f16700Schasinglulu assert(port < 5U); 205*91f16700Schasinglulu const struct port_info *info = &port_info[port]; 206*91f16700Schasinglulu 207*91f16700Schasinglulu assert(bank <= info->max_bank); 208*91f16700Schasinglulu 209*91f16700Schasinglulu uint8_t val = pull_type_sw2hw[info->pull_enc[bank]][pull]; 210*91f16700Schasinglulu 211*91f16700Schasinglulu assert(val != (uint8_t)-1); 212*91f16700Schasinglulu 213*91f16700Schasinglulu clock_state = gpio_get_clock(gpio); 214*91f16700Schasinglulu mmio_write_32( 215*91f16700Schasinglulu info->pull_base + 4 * bank, 216*91f16700Schasinglulu BITS_WITH_WMASK(val, GPIO_P_MASK, id * 2) 217*91f16700Schasinglulu ); 218*91f16700Schasinglulu gpio_put_clock(gpio, clock_state); 219*91f16700Schasinglulu } 220*91f16700Schasinglulu 221*91f16700Schasinglulu static void set_direction(int gpio, int direction) 222*91f16700Schasinglulu { 223*91f16700Schasinglulu uint32_t port = GET_GPIO_PORT(gpio); 224*91f16700Schasinglulu uint32_t num = GET_GPIO_NUM(gpio); 225*91f16700Schasinglulu uint32_t clock_state; 226*91f16700Schasinglulu 227*91f16700Schasinglulu assert((port < 5) && (num < 32)); 228*91f16700Schasinglulu 229*91f16700Schasinglulu clock_state = gpio_get_clock(gpio); 230*91f16700Schasinglulu 231*91f16700Schasinglulu /* 232*91f16700Schasinglulu * in gpio.h 233*91f16700Schasinglulu * #define GPIO_DIR_OUT 0 234*91f16700Schasinglulu * #define GPIO_DIR_IN 1 235*91f16700Schasinglulu * but rk3399 gpio direction 1: output, 0: input 236*91f16700Schasinglulu * so need to revert direction value 237*91f16700Schasinglulu */ 238*91f16700Schasinglulu mmio_setbits_32( 239*91f16700Schasinglulu port_info[port].port_base + SWPORTA_DDR, 240*91f16700Schasinglulu ((direction == 0) ? 1 : 0) << num 241*91f16700Schasinglulu ); 242*91f16700Schasinglulu gpio_put_clock(gpio, clock_state); 243*91f16700Schasinglulu } 244*91f16700Schasinglulu 245*91f16700Schasinglulu static int get_direction(int gpio) 246*91f16700Schasinglulu { 247*91f16700Schasinglulu uint32_t port = GET_GPIO_PORT(gpio); 248*91f16700Schasinglulu uint32_t num = GET_GPIO_NUM(gpio); 249*91f16700Schasinglulu int direction, clock_state; 250*91f16700Schasinglulu 251*91f16700Schasinglulu assert((port < 5U) && (num < 32U)); 252*91f16700Schasinglulu 253*91f16700Schasinglulu clock_state = gpio_get_clock(gpio); 254*91f16700Schasinglulu 255*91f16700Schasinglulu /* 256*91f16700Schasinglulu * in gpio.h 257*91f16700Schasinglulu * #define GPIO_DIR_OUT 0 258*91f16700Schasinglulu * #define GPIO_DIR_IN 1 259*91f16700Schasinglulu * but rk3399 gpio direction 1: output, 0: input 260*91f16700Schasinglulu * so need to revert direction value 261*91f16700Schasinglulu */ 262*91f16700Schasinglulu direction = (((mmio_read_32( 263*91f16700Schasinglulu port_info[port].port_base + SWPORTA_DDR 264*91f16700Schasinglulu ) >> num) & 1U) == 0) ? 1 : 0; 265*91f16700Schasinglulu gpio_put_clock(gpio, clock_state); 266*91f16700Schasinglulu 267*91f16700Schasinglulu return direction; 268*91f16700Schasinglulu } 269*91f16700Schasinglulu 270*91f16700Schasinglulu static int get_value(int gpio) 271*91f16700Schasinglulu { 272*91f16700Schasinglulu uint32_t port = GET_GPIO_PORT(gpio); 273*91f16700Schasinglulu uint32_t num = GET_GPIO_NUM(gpio); 274*91f16700Schasinglulu int value, clock_state; 275*91f16700Schasinglulu 276*91f16700Schasinglulu assert((port < 5) && (num < 32)); 277*91f16700Schasinglulu 278*91f16700Schasinglulu clock_state = gpio_get_clock(gpio); 279*91f16700Schasinglulu value = (mmio_read_32(port_info[port].port_base + EXT_PORTA) >> num) & 280*91f16700Schasinglulu 0x1U; 281*91f16700Schasinglulu gpio_put_clock(gpio, clock_state); 282*91f16700Schasinglulu 283*91f16700Schasinglulu return value; 284*91f16700Schasinglulu } 285*91f16700Schasinglulu 286*91f16700Schasinglulu static void set_value(int gpio, int value) 287*91f16700Schasinglulu { 288*91f16700Schasinglulu uint32_t port = GET_GPIO_PORT(gpio); 289*91f16700Schasinglulu uint32_t num = GET_GPIO_NUM(gpio); 290*91f16700Schasinglulu uint32_t clock_state; 291*91f16700Schasinglulu 292*91f16700Schasinglulu assert((port < 5U) && (num < 32U)); 293*91f16700Schasinglulu 294*91f16700Schasinglulu clock_state = gpio_get_clock(gpio); 295*91f16700Schasinglulu mmio_clrsetbits_32( 296*91f16700Schasinglulu port_info[port].port_base + SWPORTA_DR, 297*91f16700Schasinglulu 1 << num, 298*91f16700Schasinglulu ((value == 0) ? 0 : 1) << num 299*91f16700Schasinglulu ); 300*91f16700Schasinglulu gpio_put_clock(gpio, clock_state); 301*91f16700Schasinglulu } 302*91f16700Schasinglulu 303*91f16700Schasinglulu void plat_rockchip_save_gpio(void) 304*91f16700Schasinglulu { 305*91f16700Schasinglulu unsigned int i; 306*91f16700Schasinglulu uint32_t cru_gate_save; 307*91f16700Schasinglulu 308*91f16700Schasinglulu cru_gate_save = mmio_read_32(CRU_BASE + CRU_CLKGATE_CON(31)); 309*91f16700Schasinglulu 310*91f16700Schasinglulu /* 311*91f16700Schasinglulu * when shutdown logic, we need to save gpio2 ~ gpio4 register, 312*91f16700Schasinglulu * we need to enable gpio2 ~ gpio4 clock here, since it may be gating, 313*91f16700Schasinglulu * and we do not care gpio0 and gpio1 clock gate, since we never 314*91f16700Schasinglulu * gating them 315*91f16700Schasinglulu */ 316*91f16700Schasinglulu mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(31), 317*91f16700Schasinglulu BITS_WITH_WMASK(0, 0x07, PCLK_GPIO2_GATE_SHIFT)); 318*91f16700Schasinglulu 319*91f16700Schasinglulu /* 320*91f16700Schasinglulu * since gpio0, gpio1 are pmugpio, they will keep ther value 321*91f16700Schasinglulu * when shutdown logic power rail, so only need to save gpio2 ~ gpio4 322*91f16700Schasinglulu * register value 323*91f16700Schasinglulu */ 324*91f16700Schasinglulu for (i = 2; i < 5; i++) { 325*91f16700Schasinglulu uint32_t base = port_info[i].port_base; 326*91f16700Schasinglulu 327*91f16700Schasinglulu store_gpio[i - 2] = (struct gpio_save) { 328*91f16700Schasinglulu .swporta_dr = mmio_read_32(base + SWPORTA_DR), 329*91f16700Schasinglulu .swporta_ddr = mmio_read_32(base + SWPORTA_DDR), 330*91f16700Schasinglulu .inten = mmio_read_32(base + INTEN), 331*91f16700Schasinglulu .intmask = mmio_read_32(base + INTMASK), 332*91f16700Schasinglulu .inttype_level = mmio_read_32(base + INTTYPE_LEVEL), 333*91f16700Schasinglulu .int_polarity = mmio_read_32(base + INT_POLARITY), 334*91f16700Schasinglulu .debounce = mmio_read_32(base + DEBOUNCE), 335*91f16700Schasinglulu .ls_sync = mmio_read_32(base + LS_SYNC), 336*91f16700Schasinglulu }; 337*91f16700Schasinglulu } 338*91f16700Schasinglulu mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(31), 339*91f16700Schasinglulu cru_gate_save | REG_SOC_WMSK); 340*91f16700Schasinglulu 341*91f16700Schasinglulu /* 342*91f16700Schasinglulu * gpio0, gpio1 in pmuiomux, they will keep ther value 343*91f16700Schasinglulu * when shutdown logic power rail, so only need to save gpio2 ~ gpio4 344*91f16700Schasinglulu * iomux register value 345*91f16700Schasinglulu */ 346*91f16700Schasinglulu for (i = 0; i < ARRAY_SIZE(store_grf_gpio); i++) 347*91f16700Schasinglulu store_grf_gpio[i] = 348*91f16700Schasinglulu mmio_read_32(GRF_BASE + GRF_GPIO2A_IOMUX + i * 4); 349*91f16700Schasinglulu } 350*91f16700Schasinglulu 351*91f16700Schasinglulu void plat_rockchip_restore_gpio(void) 352*91f16700Schasinglulu { 353*91f16700Schasinglulu int i; 354*91f16700Schasinglulu uint32_t cru_gate_save; 355*91f16700Schasinglulu 356*91f16700Schasinglulu for (i = 0; i < ARRAY_SIZE(store_grf_gpio); i++) 357*91f16700Schasinglulu mmio_write_32(GRF_BASE + GRF_GPIO2A_IOMUX + i * 4, 358*91f16700Schasinglulu REG_SOC_WMSK | store_grf_gpio[i]); 359*91f16700Schasinglulu 360*91f16700Schasinglulu cru_gate_save = mmio_read_32(CRU_BASE + CRU_CLKGATE_CON(31)); 361*91f16700Schasinglulu 362*91f16700Schasinglulu /* 363*91f16700Schasinglulu * when shutdown logic, we need to save gpio2 ~ gpio4 register, 364*91f16700Schasinglulu * we need to enable gpio2 ~ gpio4 clock here, since it may be gating, 365*91f16700Schasinglulu * and we do not care gpio0 and gpio1 clock gate, since we never 366*91f16700Schasinglulu * gating them 367*91f16700Schasinglulu */ 368*91f16700Schasinglulu mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(31), 369*91f16700Schasinglulu BITS_WITH_WMASK(0, 0x07, PCLK_GPIO2_GATE_SHIFT)); 370*91f16700Schasinglulu 371*91f16700Schasinglulu for (i = 2; i < 5; i++) { 372*91f16700Schasinglulu uint32_t base = port_info[i].port_base; 373*91f16700Schasinglulu const struct gpio_save *save = &store_gpio[i - 2]; 374*91f16700Schasinglulu 375*91f16700Schasinglulu mmio_write_32(base + SWPORTA_DR, save->swporta_dr); 376*91f16700Schasinglulu mmio_write_32(base + SWPORTA_DDR, save->swporta_ddr); 377*91f16700Schasinglulu mmio_write_32(base + INTEN, save->inten); 378*91f16700Schasinglulu mmio_write_32(base + INTMASK, save->intmask); 379*91f16700Schasinglulu mmio_write_32(base + INTTYPE_LEVEL, save->inttype_level); 380*91f16700Schasinglulu mmio_write_32(base + INT_POLARITY, save->int_polarity); 381*91f16700Schasinglulu mmio_write_32(base + DEBOUNCE, save->debounce); 382*91f16700Schasinglulu mmio_write_32(base + LS_SYNC, save->ls_sync); 383*91f16700Schasinglulu } 384*91f16700Schasinglulu mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(31), 385*91f16700Schasinglulu cru_gate_save | REG_SOC_WMSK); 386*91f16700Schasinglulu } 387*91f16700Schasinglulu 388*91f16700Schasinglulu const gpio_ops_t rk3399_gpio_ops = { 389*91f16700Schasinglulu .get_direction = get_direction, 390*91f16700Schasinglulu .set_direction = set_direction, 391*91f16700Schasinglulu .get_value = get_value, 392*91f16700Schasinglulu .set_value = set_value, 393*91f16700Schasinglulu .set_pull = set_pull, 394*91f16700Schasinglulu .get_pull = get_pull, 395*91f16700Schasinglulu }; 396*91f16700Schasinglulu 397*91f16700Schasinglulu void plat_rockchip_gpio_init(void) 398*91f16700Schasinglulu { 399*91f16700Schasinglulu gpio_init(&rk3399_gpio_ops); 400*91f16700Schasinglulu } 401