1 /* 2 * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 #include <assert.h> 7 #include <debug.h> 8 #include <delay_timer.h> 9 #include <errno.h> 10 #include <gpio.h> 11 #include <mmio.h> 12 #include <platform.h> 13 #include <platform_def.h> 14 #include <plat_private.h> 15 #include <soc.h> 16 17 uint32_t gpio_port[] = { 18 GPIO0_BASE, 19 GPIO1_BASE, 20 GPIO2_BASE, 21 GPIO3_BASE, 22 GPIO4_BASE, 23 }; 24 25 #define SWPORTA_DR 0x00 26 #define SWPORTA_DDR 0x04 27 #define EXT_PORTA 0x50 28 29 #define PMU_GPIO_PORT0 0 30 #define PMU_GPIO_PORT1 1 31 #define GPIO_PORT2 2 32 #define GPIO_PORT3 3 33 #define GPIO_PORT4 4 34 35 #define PMU_GRF_GPIO0A_P 0x40 36 #define GRF_GPIO2A_P 0xe040 37 #define GPIO_P_MASK 0x03 38 39 #define GET_GPIO_PORT(pin) (pin / 32) 40 #define GET_GPIO_NUM(pin) (pin % 32) 41 #define GET_GPIO_BANK(pin) ((pin % 32) / 8) 42 #define GET_GPIO_ID(pin) ((pin % 32) % 8) 43 44 /* returns old clock state, enables clock, in order to do GPIO access */ 45 static int gpio_get_clock(uint32_t gpio_number) 46 { 47 uint32_t port = GET_GPIO_PORT(gpio_number); 48 uint32_t clock_state = 0; 49 50 assert(port < 5); 51 52 switch (port) { 53 case PMU_GPIO_PORT0: 54 clock_state = (mmio_read_32(PMUCRU_BASE + 55 CRU_PMU_CLKGATE_CON(1)) >> 56 PCLK_GPIO0_GATE_SHIFT) & 0x01; 57 mmio_write_32(PMUCRU_BASE + CRU_PMU_CLKGATE_CON(1), 58 BITS_WITH_WMASK(0, CLK_GATE_MASK, 59 PCLK_GPIO0_GATE_SHIFT)); 60 break; 61 case PMU_GPIO_PORT1: 62 clock_state = (mmio_read_32(PMUCRU_BASE + 63 CRU_PMU_CLKGATE_CON(1)) >> 64 PCLK_GPIO1_GATE_SHIFT) & 0x01; 65 mmio_write_32(PMUCRU_BASE + CRU_PMU_CLKGATE_CON(1), 66 BITS_WITH_WMASK(0, CLK_GATE_MASK, 67 PCLK_GPIO1_GATE_SHIFT)); 68 break; 69 case GPIO_PORT2: 70 clock_state = (mmio_read_32(CRU_BASE + 71 CRU_CLKGATE_CON(31)) >> 72 PCLK_GPIO2_GATE_SHIFT) & 0x01; 73 mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(31), 74 BITS_WITH_WMASK(0, CLK_GATE_MASK, 75 PCLK_GPIO2_GATE_SHIFT)); 76 break; 77 case GPIO_PORT3: 78 clock_state = (mmio_read_32(CRU_BASE + 79 CRU_CLKGATE_CON(31)) >> 80 PCLK_GPIO3_GATE_SHIFT) & 0x01; 81 mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(31), 82 BITS_WITH_WMASK(0, CLK_GATE_MASK, 83 PCLK_GPIO3_GATE_SHIFT)); 84 break; 85 case GPIO_PORT4: 86 clock_state = (mmio_read_32(CRU_BASE + 87 CRU_CLKGATE_CON(31)) >> 88 PCLK_GPIO4_GATE_SHIFT) & 0x01; 89 mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(31), 90 BITS_WITH_WMASK(0, CLK_GATE_MASK, 91 PCLK_GPIO4_GATE_SHIFT)); 92 break; 93 default: 94 break; 95 } 96 97 return clock_state; 98 } 99 100 /* restores old state of gpio clock */ 101 void gpio_put_clock(uint32_t gpio_number, uint32_t clock_state) 102 { 103 uint32_t port = GET_GPIO_PORT(gpio_number); 104 105 switch (port) { 106 case PMU_GPIO_PORT0: 107 mmio_write_32(PMUCRU_BASE + CRU_PMU_CLKGATE_CON(1), 108 BITS_WITH_WMASK(clock_state, CLK_GATE_MASK, 109 PCLK_GPIO0_GATE_SHIFT)); 110 break; 111 case PMU_GPIO_PORT1: 112 mmio_write_32(PMUCRU_BASE + CRU_PMU_CLKGATE_CON(1), 113 BITS_WITH_WMASK(clock_state, CLK_GATE_MASK, 114 PCLK_GPIO1_GATE_SHIFT)); 115 break; 116 case GPIO_PORT2: 117 mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(31), 118 BITS_WITH_WMASK(clock_state, CLK_GATE_MASK, 119 PCLK_GPIO2_GATE_SHIFT)); 120 break; 121 case GPIO_PORT3: 122 mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(31), 123 BITS_WITH_WMASK(clock_state, CLK_GATE_MASK, 124 PCLK_GPIO3_GATE_SHIFT)); 125 126 break; 127 case GPIO_PORT4: 128 mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(31), 129 BITS_WITH_WMASK(clock_state, CLK_GATE_MASK, 130 PCLK_GPIO4_GATE_SHIFT)); 131 break; 132 default: 133 break; 134 } 135 } 136 137 static int get_pull(int gpio) 138 { 139 uint32_t port = GET_GPIO_PORT(gpio); 140 uint32_t bank = GET_GPIO_BANK(gpio); 141 uint32_t id = GET_GPIO_ID(gpio); 142 uint32_t val, clock_state; 143 144 assert((port < 5) && (bank < 4)); 145 146 clock_state = gpio_get_clock(gpio); 147 148 if (port == PMU_GPIO_PORT0 || port == PMU_GPIO_PORT1) { 149 val = mmio_read_32(PMUGRF_BASE + PMU_GRF_GPIO0A_P + 150 port * 16 + bank * 4); 151 val = (val >> (id * 2)) & GPIO_P_MASK; 152 } else { 153 val = mmio_read_32(GRF_BASE + GRF_GPIO2A_P + 154 (port - 2) * 16 + bank * 4); 155 val = (val >> (id * 2)) & GPIO_P_MASK; 156 } 157 gpio_put_clock(gpio, clock_state); 158 159 /* 160 * in gpio0a, gpio0b, gpio2c, gpio2d, 161 * 00: Z 162 * 01: pull down 163 * 10: Z 164 * 11: pull up 165 * different with other gpio, so need to correct it 166 */ 167 if (((port == 0) && (bank < 2)) || ((port == 2) && (bank > 1))) { 168 if (val == 3) 169 val = GPIO_PULL_UP; 170 else if (val == 1) 171 val = GPIO_PULL_DOWN; 172 else 173 val = 0; 174 } 175 176 return val; 177 } 178 179 static void set_pull(int gpio, int pull) 180 { 181 uint32_t port = GET_GPIO_PORT(gpio); 182 uint32_t bank = GET_GPIO_BANK(gpio); 183 uint32_t id = GET_GPIO_ID(gpio); 184 uint32_t clock_state; 185 186 assert((port < 5) && (bank < 4)); 187 188 clock_state = gpio_get_clock(gpio); 189 190 /* 191 * in gpio0a, gpio0b, gpio2c, gpio2d, 192 * 00: Z 193 * 01: pull down 194 * 10: Z 195 * 11: pull up 196 * different with other gpio, so need to correct it 197 */ 198 if (((port == 0) && (bank < 2)) || ((port == 2) && (bank > 1))) { 199 if (pull == GPIO_PULL_UP) 200 pull = 3; 201 else if (pull == GPIO_PULL_DOWN) 202 pull = 1; 203 else 204 pull = 0; 205 } 206 207 if (port == PMU_GPIO_PORT0 || port == PMU_GPIO_PORT1) { 208 mmio_write_32(PMUGRF_BASE + PMU_GRF_GPIO0A_P + 209 port * 16 + bank * 4, 210 BITS_WITH_WMASK(pull, GPIO_P_MASK, id * 2)); 211 } else { 212 mmio_write_32(GRF_BASE + GRF_GPIO2A_P + 213 (port - 2) * 16 + bank * 4, 214 BITS_WITH_WMASK(pull, GPIO_P_MASK, id * 2)); 215 } 216 gpio_put_clock(gpio, clock_state); 217 } 218 219 static void set_direction(int gpio, int direction) 220 { 221 uint32_t port = GET_GPIO_PORT(gpio); 222 uint32_t num = GET_GPIO_NUM(gpio); 223 uint32_t clock_state; 224 225 assert((port < 5) && (num < 32)); 226 227 clock_state = gpio_get_clock(gpio); 228 229 /* 230 * in gpio.h 231 * #define GPIO_DIR_OUT 0 232 * #define GPIO_DIR_IN 1 233 * but rk3399 gpio direction 1: output, 0: input 234 * so need to revert direction value 235 */ 236 mmio_setbits_32(gpio_port[port] + SWPORTA_DDR, !direction << num); 237 gpio_put_clock(gpio, clock_state); 238 } 239 240 static int get_direction(int gpio) 241 { 242 uint32_t port = GET_GPIO_PORT(gpio); 243 uint32_t num = GET_GPIO_NUM(gpio); 244 int direction, clock_state; 245 246 assert((port < 5) && (num < 32)); 247 248 clock_state = gpio_get_clock(gpio); 249 250 /* 251 * in gpio.h 252 * #define GPIO_DIR_OUT 0 253 * #define GPIO_DIR_IN 1 254 * but rk3399 gpio direction 1: output, 0: input 255 * so need to revert direction value 256 */ 257 direction = !((mmio_read_32(gpio_port[port] + 258 SWPORTA_DDR) >> num) & 0x1); 259 gpio_put_clock(gpio, clock_state); 260 261 return direction; 262 } 263 264 static int get_value(int gpio) 265 { 266 uint32_t port = GET_GPIO_PORT(gpio); 267 uint32_t num = GET_GPIO_NUM(gpio); 268 int value, clock_state; 269 270 assert((port < 5) && (num < 32)); 271 272 clock_state = gpio_get_clock(gpio); 273 value = (mmio_read_32(gpio_port[port] + EXT_PORTA) >> num) & 0x1; 274 gpio_put_clock(gpio, clock_state); 275 276 return value; 277 } 278 279 static void set_value(int gpio, int value) 280 { 281 uint32_t port = GET_GPIO_PORT(gpio); 282 uint32_t num = GET_GPIO_NUM(gpio); 283 uint32_t clock_state; 284 285 assert((port < 5) && (num < 32)); 286 287 clock_state = gpio_get_clock(gpio); 288 mmio_clrsetbits_32(gpio_port[port] + SWPORTA_DR, 1 << num, 289 !!value << num); 290 gpio_put_clock(gpio, clock_state); 291 } 292 293 const gpio_ops_t rk3399_gpio_ops = { 294 .get_direction = get_direction, 295 .set_direction = set_direction, 296 .get_value = get_value, 297 .set_value = set_value, 298 .set_pull = set_pull, 299 .get_pull = get_pull, 300 }; 301 302 void plat_rockchip_gpio_init(void) 303 { 304 gpio_init(&rk3399_gpio_ops); 305 } 306