1 /* 2 * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are met: 6 * 7 * Redistributions of source code must retain the above copyright notice, this 8 * list of conditions and the following disclaimer. 9 * 10 * Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * 14 * Neither the name of ARM nor the names of its contributors may be used 15 * to endorse or promote products derived from this software without specific 16 * prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * POSSIBILITY OF SUCH DAMAGE. 29 */ 30 #include <assert.h> 31 #include <debug.h> 32 #include <delay_timer.h> 33 #include <errno.h> 34 #include <gpio.h> 35 #include <mmio.h> 36 #include <platform.h> 37 #include <platform_def.h> 38 #include <plat_private.h> 39 #include <soc.h> 40 41 uint32_t gpio_port[] = { 42 GPIO0_BASE, 43 GPIO1_BASE, 44 GPIO2_BASE, 45 GPIO3_BASE, 46 GPIO4_BASE, 47 }; 48 49 #define SWPORTA_DR 0x00 50 #define SWPORTA_DDR 0x04 51 #define EXT_PORTA 0x50 52 53 #define PMU_GPIO_PORT0 0 54 #define PMU_GPIO_PORT1 1 55 #define GPIO_PORT2 2 56 #define GPIO_PORT3 3 57 #define GPIO_PORT4 4 58 59 #define PMU_GRF_GPIO0A_P 0x40 60 #define GRF_GPIO2A_P 0xe040 61 #define GPIO_P_MASK 0x03 62 63 #define GET_GPIO_PORT(pin) (pin / 32) 64 #define GET_GPIO_NUM(pin) (pin % 32) 65 #define GET_GPIO_BANK(pin) ((pin % 32) / 8) 66 #define GET_GPIO_ID(pin) ((pin % 32) % 8) 67 68 /* returns old clock state, enables clock, in order to do GPIO access */ 69 static int gpio_get_clock(uint32_t gpio_number) 70 { 71 uint32_t port = GET_GPIO_PORT(gpio_number); 72 uint32_t clock_state = 0; 73 74 assert(port < 5); 75 76 switch (port) { 77 case PMU_GPIO_PORT0: 78 clock_state = (mmio_read_32(PMUCRU_BASE + 79 CRU_PMU_CLKGATE_CON(1)) >> 80 PCLK_GPIO0_GATE_SHIFT) & 0x01; 81 mmio_write_32(PMUCRU_BASE + CRU_PMU_CLKGATE_CON(1), 82 BITS_WITH_WMASK(0, CLK_GATE_MASK, 83 PCLK_GPIO0_GATE_SHIFT)); 84 break; 85 case PMU_GPIO_PORT1: 86 clock_state = (mmio_read_32(PMUCRU_BASE + 87 CRU_PMU_CLKGATE_CON(1)) >> 88 PCLK_GPIO1_GATE_SHIFT) & 0x01; 89 mmio_write_32(PMUCRU_BASE + CRU_PMU_CLKGATE_CON(1), 90 BITS_WITH_WMASK(0, CLK_GATE_MASK, 91 PCLK_GPIO1_GATE_SHIFT)); 92 break; 93 case GPIO_PORT2: 94 clock_state = (mmio_read_32(CRU_BASE + 95 CRU_CLKGATE_CON(31)) >> 96 PCLK_GPIO2_GATE_SHIFT) & 0x01; 97 mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(31), 98 BITS_WITH_WMASK(0, CLK_GATE_MASK, 99 PCLK_GPIO2_GATE_SHIFT)); 100 break; 101 case GPIO_PORT3: 102 clock_state = (mmio_read_32(CRU_BASE + 103 CRU_CLKGATE_CON(31)) >> 104 PCLK_GPIO3_GATE_SHIFT) & 0x01; 105 mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(31), 106 BITS_WITH_WMASK(0, CLK_GATE_MASK, 107 PCLK_GPIO3_GATE_SHIFT)); 108 break; 109 case GPIO_PORT4: 110 clock_state = (mmio_read_32(CRU_BASE + 111 CRU_CLKGATE_CON(31)) >> 112 PCLK_GPIO4_GATE_SHIFT) & 0x01; 113 mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(31), 114 BITS_WITH_WMASK(0, CLK_GATE_MASK, 115 PCLK_GPIO4_GATE_SHIFT)); 116 break; 117 default: 118 break; 119 } 120 121 return clock_state; 122 } 123 124 /* restores old state of gpio clock */ 125 void gpio_put_clock(uint32_t gpio_number, uint32_t clock_state) 126 { 127 uint32_t port = GET_GPIO_PORT(gpio_number); 128 129 switch (port) { 130 case PMU_GPIO_PORT0: 131 mmio_write_32(PMUCRU_BASE + CRU_PMU_CLKGATE_CON(1), 132 BITS_WITH_WMASK(clock_state, CLK_GATE_MASK, 133 PCLK_GPIO0_GATE_SHIFT)); 134 break; 135 case PMU_GPIO_PORT1: 136 mmio_write_32(PMUCRU_BASE + CRU_PMU_CLKGATE_CON(1), 137 BITS_WITH_WMASK(clock_state, CLK_GATE_MASK, 138 PCLK_GPIO1_GATE_SHIFT)); 139 break; 140 case GPIO_PORT2: 141 mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(31), 142 BITS_WITH_WMASK(clock_state, CLK_GATE_MASK, 143 PCLK_GPIO2_GATE_SHIFT)); 144 break; 145 case GPIO_PORT3: 146 mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(31), 147 BITS_WITH_WMASK(clock_state, CLK_GATE_MASK, 148 PCLK_GPIO3_GATE_SHIFT)); 149 150 break; 151 case GPIO_PORT4: 152 mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(31), 153 BITS_WITH_WMASK(clock_state, CLK_GATE_MASK, 154 PCLK_GPIO4_GATE_SHIFT)); 155 break; 156 default: 157 break; 158 } 159 } 160 161 static int get_pull(int gpio) 162 { 163 uint32_t port = GET_GPIO_PORT(gpio); 164 uint32_t bank = GET_GPIO_BANK(gpio); 165 uint32_t id = GET_GPIO_ID(gpio); 166 uint32_t val, clock_state; 167 168 assert((port < 5) && (bank < 4)); 169 170 clock_state = gpio_get_clock(gpio); 171 172 if (port == PMU_GPIO_PORT0 || port == PMU_GPIO_PORT1) { 173 val = mmio_read_32(PMUGRF_BASE + PMU_GRF_GPIO0A_P + 174 port * 16 + bank * 4); 175 val = (val >> (id * 2)) & GPIO_P_MASK; 176 } else { 177 val = mmio_read_32(GRF_BASE + GRF_GPIO2A_P + 178 (port - 2) * 16 + bank * 4); 179 val = (val >> (id * 2)) & GPIO_P_MASK; 180 } 181 gpio_put_clock(gpio, clock_state); 182 183 /* 184 * in gpio0a, gpio0b, gpio2c, gpio2d, 185 * 00: Z 186 * 01: pull down 187 * 10: Z 188 * 11: pull up 189 * different with other gpio, so need to correct it 190 */ 191 if (((port == 0) && (bank < 2)) || ((port == 2) && (bank > 1))) { 192 if (val == 3) 193 val = GPIO_PULL_UP; 194 else if (val == 1) 195 val = GPIO_PULL_DOWN; 196 else 197 val = 0; 198 } 199 200 return val; 201 } 202 203 static void set_pull(int gpio, int pull) 204 { 205 uint32_t port = GET_GPIO_PORT(gpio); 206 uint32_t bank = GET_GPIO_BANK(gpio); 207 uint32_t id = GET_GPIO_ID(gpio); 208 uint32_t clock_state; 209 210 assert((port < 5) && (bank < 4)); 211 212 clock_state = gpio_get_clock(gpio); 213 214 /* 215 * in gpio0a, gpio0b, gpio2c, gpio2d, 216 * 00: Z 217 * 01: pull down 218 * 10: Z 219 * 11: pull up 220 * different with other gpio, so need to correct it 221 */ 222 if (((port == 0) && (bank < 2)) || ((port == 2) && (bank > 1))) { 223 if (pull == GPIO_PULL_UP) 224 pull = 3; 225 else if (pull == GPIO_PULL_DOWN) 226 pull = 1; 227 else 228 pull = 0; 229 } 230 231 if (port == PMU_GPIO_PORT0 || port == PMU_GPIO_PORT1) { 232 mmio_write_32(PMUGRF_BASE + PMU_GRF_GPIO0A_P + 233 port * 16 + bank * 4, 234 BITS_WITH_WMASK(pull, GPIO_P_MASK, id * 2)); 235 } else { 236 mmio_write_32(GRF_BASE + GRF_GPIO2A_P + 237 (port - 2) * 16 + bank * 4, 238 BITS_WITH_WMASK(pull, GPIO_P_MASK, id * 2)); 239 } 240 gpio_put_clock(gpio, clock_state); 241 } 242 243 static void set_direction(int gpio, int direction) 244 { 245 uint32_t port = GET_GPIO_PORT(gpio); 246 uint32_t num = GET_GPIO_NUM(gpio); 247 uint32_t clock_state; 248 249 assert((port < 5) && (num < 32)); 250 251 clock_state = gpio_get_clock(gpio); 252 253 /* 254 * in gpio.h 255 * #define GPIO_DIR_OUT 0 256 * #define GPIO_DIR_IN 1 257 * but rk3399 gpio direction 1: output, 0: input 258 * so need to revert direction value 259 */ 260 mmio_setbits_32(gpio_port[port] + SWPORTA_DDR, !direction << num); 261 gpio_put_clock(gpio, clock_state); 262 } 263 264 static int get_direction(int gpio) 265 { 266 uint32_t port = GET_GPIO_PORT(gpio); 267 uint32_t num = GET_GPIO_NUM(gpio); 268 int direction, clock_state; 269 270 assert((port < 5) && (num < 32)); 271 272 clock_state = gpio_get_clock(gpio); 273 274 /* 275 * in gpio.h 276 * #define GPIO_DIR_OUT 0 277 * #define GPIO_DIR_IN 1 278 * but rk3399 gpio direction 1: output, 0: input 279 * so need to revert direction value 280 */ 281 direction = !((mmio_read_32(gpio_port[port] + 282 SWPORTA_DDR) >> num) & 0x1); 283 gpio_put_clock(gpio, clock_state); 284 285 return direction; 286 } 287 288 static int get_value(int gpio) 289 { 290 uint32_t port = GET_GPIO_PORT(gpio); 291 uint32_t num = GET_GPIO_NUM(gpio); 292 int value, clock_state; 293 294 assert((port < 5) && (num < 32)); 295 296 clock_state = gpio_get_clock(gpio); 297 value = (mmio_read_32(gpio_port[port] + EXT_PORTA) >> num) & 0x1; 298 gpio_put_clock(gpio, clock_state); 299 300 return value; 301 } 302 303 static void set_value(int gpio, int value) 304 { 305 uint32_t port = GET_GPIO_PORT(gpio); 306 uint32_t num = GET_GPIO_NUM(gpio); 307 uint32_t clock_state; 308 309 assert((port < 5) && (num < 32)); 310 311 clock_state = gpio_get_clock(gpio); 312 mmio_clrsetbits_32(gpio_port[port] + SWPORTA_DR, 1 << num, 313 !!value << num); 314 gpio_put_clock(gpio, clock_state); 315 } 316 317 const gpio_ops_t rk3399_gpio_ops = { 318 .get_direction = get_direction, 319 .set_direction = set_direction, 320 .get_value = get_value, 321 .set_value = set_value, 322 .set_pull = set_pull, 323 .get_pull = get_pull, 324 }; 325 326 void plat_rockchip_gpio_init(void) 327 { 328 gpio_init(&rk3399_gpio_ops); 329 } 330