1 /* 2 * Copyright (c) 2019, MediaTek Inc. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <assert.h> 8 #include <common/debug.h> 9 #include <drivers/delay_timer.h> 10 #include <gpio/mtgpio.h> 11 #include <gpio/mtgpio_cfg.h> 12 #include <drivers/gpio.h> 13 #include <mcucfg.h> 14 #include <lib/mmio.h> 15 #include <platform_def.h> 16 #include <spm.h> 17 #include <stdbool.h> 18 19 /****************************************************************************** 20 *Macro Definition 21 ******************************************************************************/ 22 #define GPIO_MODE_BITS 4 23 #define MAX_GPIO_MODE_PER_REG 8 24 #define MAX_GPIO_REG_BITS 32 25 #define DIR_BASE (GPIO_BASE + 0x000) 26 #define DOUT_BASE (GPIO_BASE + 0x100) 27 #define DIN_BASE (GPIO_BASE + 0x200) 28 #define MODE_BASE (GPIO_BASE + 0x300) 29 #define SET 0x4 30 #define CLR 0x8 31 #define PULLEN_ADDR_OFFSET 0x060 32 #define PULLSEL_ADDR_OFFSET 0x080 33 34 void mt_set_gpio_dir_chip(uint32_t pin, int dir) 35 { 36 uint32_t pos, bit; 37 38 assert(pin < MAX_GPIO_PIN); 39 assert(dir < GPIO_DIR_MAX); 40 41 pos = pin / MAX_GPIO_REG_BITS; 42 bit = pin % MAX_GPIO_REG_BITS; 43 44 if (dir == GPIO_DIR_IN) 45 mmio_write_32(DIR_BASE + 0x10 * pos + CLR, 1U << bit); 46 else 47 mmio_write_32(DIR_BASE + 0x10 * pos + SET, 1U << bit); 48 } 49 50 int mt_get_gpio_dir_chip(uint32_t pin) 51 { 52 uint32_t pos, bit; 53 uint32_t reg; 54 55 assert(pin < MAX_GPIO_PIN); 56 57 pos = pin / MAX_GPIO_REG_BITS; 58 bit = pin % MAX_GPIO_REG_BITS; 59 60 reg = mmio_read_32(DIR_BASE + 0x10 * pos); 61 return (((reg & (1U << bit)) != 0) ? GPIO_DIR_OUT : GPIO_DIR_IN); 62 } 63 64 void mt_set_gpio_out_chip(uint32_t pin, int output) 65 { 66 uint32_t pos, bit; 67 68 assert(pin < MAX_GPIO_PIN); 69 assert(output < GPIO_OUT_MAX); 70 71 pos = pin / MAX_GPIO_REG_BITS; 72 bit = pin % MAX_GPIO_REG_BITS; 73 74 if (output == GPIO_OUT_ZERO) 75 mmio_write_32(DOUT_BASE + 0x10 * pos + CLR, 1U << bit); 76 else 77 mmio_write_32(DOUT_BASE + 0x10 * pos + SET, 1U << bit); 78 } 79 80 int mt_get_gpio_out_chip(uint32_t pin) 81 { 82 uint32_t pos, bit; 83 uint32_t reg; 84 85 assert(pin < MAX_GPIO_PIN); 86 87 pos = pin / MAX_GPIO_REG_BITS; 88 bit = pin % MAX_GPIO_REG_BITS; 89 90 reg = mmio_read_32(DOUT_BASE + 0x10 * pos); 91 return (((reg & (1U << bit)) != 0) ? 1 : 0); 92 } 93 94 int mt_get_gpio_in_chip(uint32_t pin) 95 { 96 uint32_t pos, bit; 97 uint32_t reg; 98 99 assert(pin < MAX_GPIO_PIN); 100 101 pos = pin / MAX_GPIO_REG_BITS; 102 bit = pin % MAX_GPIO_REG_BITS; 103 104 reg = mmio_read_32(DIN_BASE + 0x10 * pos); 105 return (((reg & (1U << bit)) != 0) ? 1 : 0); 106 } 107 108 void mt_set_gpio_mode_chip(uint32_t pin, int mode) 109 { 110 uint32_t pos, bit; 111 uint32_t data; 112 uint32_t mask; 113 114 assert(pin < MAX_GPIO_PIN); 115 assert(mode < GPIO_MODE_MAX); 116 117 mask = (1U << GPIO_MODE_BITS) - 1; 118 119 mode = mode & mask; 120 pos = pin / MAX_GPIO_MODE_PER_REG; 121 bit = (pin % MAX_GPIO_MODE_PER_REG) * GPIO_MODE_BITS; 122 123 data = mmio_read_32(MODE_BASE + 0x10 * pos); 124 data &= (~(mask << bit)); 125 data |= (mode << bit); 126 mmio_write_32(MODE_BASE + 0x10 * pos, data); 127 } 128 129 int mt_get_gpio_mode_chip(uint32_t pin) 130 { 131 uint32_t pos, bit; 132 uint32_t data; 133 uint32_t mask; 134 135 assert(pin < MAX_GPIO_PIN); 136 137 mask = (1U << GPIO_MODE_BITS) - 1; 138 139 pos = pin / MAX_GPIO_MODE_PER_REG; 140 bit = (pin % MAX_GPIO_MODE_PER_REG) * GPIO_MODE_BITS; 141 142 data = mmio_read_32(MODE_BASE + 0x10 * pos); 143 return (data >> bit) & mask; 144 } 145 146 int32_t gpio_get_pull_iocfg(uint32_t pin) 147 { 148 switch (pin) { 149 case 0 ... 10: 150 return IOCFG_5_BASE; 151 case 11 ... 12: 152 return IOCFG_0_BASE; 153 case 13 ... 28: 154 return IOCFG_1_BASE; 155 case 43 ... 49: 156 return IOCFG_2_BASE; 157 case 50 ... 60: 158 return IOCFG_3_BASE; 159 case 61 ... 88: 160 return IOCFG_4_BASE; 161 case 89 ... 90: 162 return IOCFG_5_BASE; 163 case 95 ... 106: 164 return IOCFG_5_BASE; 165 case 107 ... 121: 166 return IOCFG_6_BASE; 167 case 134 ... 160: 168 return IOCFG_0_BASE; 169 case 161 ... 166: 170 return IOCFG_1_BASE; 171 case 167 ... 176: 172 return IOCFG_3_BASE; 173 case 177 ... 179: 174 return IOCFG_5_BASE; 175 default: 176 return -1; 177 } 178 } 179 180 int32_t gpio_get_pupd_iocfg(uint32_t pin) 181 { 182 const int32_t offset = 0x0c0; 183 184 switch (pin) { 185 case 29 ... 34: 186 return IOCFG_1_BASE + offset; 187 case 35 ... 42: 188 return IOCFG_2_BASE + offset; 189 case 91 ... 94: 190 return IOCFG_5_BASE + offset; 191 case 122 ... 133: 192 return IOCFG_7_BASE + offset; 193 default: 194 return -1; 195 } 196 } 197 198 int gpio_get_pupd_offset(uint32_t pin) 199 { 200 switch (pin) { 201 case 29 ... 34: 202 return (pin - 29) * 4 % 32; 203 case 35 ... 42: 204 return (pin - 35) * 4 % 32; 205 case 91 ... 94: 206 return (pin - 91) * 4 % 32; 207 case 122 ... 129: 208 return (pin - 122) * 4 % 32; 209 case 130 ... 133: 210 return (pin - 130) * 4 % 32; 211 default: 212 return -1; 213 } 214 } 215 216 void mt_set_gpio_pull_enable_chip(uint32_t pin, int en) 217 { 218 int pullen_addr = gpio_get_pull_iocfg(pin) + PULLEN_ADDR_OFFSET; 219 int pupd_addr = gpio_get_pupd_iocfg(pin); 220 int pupd_offset = gpio_get_pupd_offset(pin); 221 222 assert(pin < MAX_GPIO_PIN); 223 224 assert(!((PULL_offset[pin].offset == (int8_t)-1) && 225 (pupd_offset == (int8_t)-1))); 226 227 if (en == GPIO_PULL_DISABLE) { 228 if (PULL_offset[pin].offset == (int8_t)-1) 229 mmio_clrbits_32(pupd_addr, 3U << pupd_offset); 230 else 231 mmio_clrbits_32(pullen_addr, 232 1U << PULL_offset[pin].offset); 233 } else if (en == GPIO_PULL_ENABLE) { 234 if (PULL_offset[pin].offset == (int8_t)-1) { 235 /* For PUPD+R0+R1 Type, mt_set_gpio_pull_enable 236 * does not know 237 * which one between PU and PD shall be enabled. 238 * Use R0 to guarantee at one resistor is set when lk 239 * apply default setting 240 */ 241 mmio_setbits_32(pupd_addr, 1U << pupd_offset); 242 mmio_clrbits_32(pupd_addr, 1U << (pupd_offset + 1)); 243 } else { 244 /* For PULLEN + PULLSEL Type */ 245 mmio_setbits_32(pullen_addr, 246 1U << PULL_offset[pin].offset); 247 } 248 } else if (en == GPIO_PULL_ENABLE_R0) { 249 assert(!(pupd_offset == (int8_t)-1)); 250 mmio_setbits_32(pupd_addr, 1U << pupd_offset); 251 mmio_clrbits_32(pupd_addr, 1U << (pupd_offset + 1)); 252 } else if (en == GPIO_PULL_ENABLE_R1) { 253 assert(!(pupd_offset == (int8_t)-1)); 254 255 mmio_clrbits_32(pupd_addr, 1U << pupd_offset); 256 mmio_setbits_32(pupd_addr, 1U << (pupd_offset + 1)); 257 } else if (en == GPIO_PULL_ENABLE_R0R1) { 258 assert(!(pupd_offset == (int8_t)-1)); 259 mmio_setbits_32(pupd_addr, 3U << pupd_offset); 260 } 261 } 262 263 int mt_get_gpio_pull_enable_chip(uint32_t pin) 264 { 265 uint32_t reg; 266 267 int pullen_addr = gpio_get_pull_iocfg(pin) + PULLEN_ADDR_OFFSET; 268 int pupd_addr = gpio_get_pupd_iocfg(pin); 269 int pupd_offset = gpio_get_pupd_offset(pin); 270 271 assert(pin < MAX_GPIO_PIN); 272 273 assert(!((PULL_offset[pin].offset == (int8_t)-1) && 274 (pupd_offset == (int8_t)-1))); 275 276 if (PULL_offset[pin].offset == (int8_t)-1) { 277 reg = mmio_read_32(pupd_addr); 278 return ((reg & (3U << pupd_offset)) ? 1 : 0); 279 } else if (pupd_offset == (int8_t)-1) { 280 reg = mmio_read_32(pullen_addr); 281 return ((reg & (1U << PULL_offset[pin].offset)) ? 1 : 0); 282 } 283 284 return -ERINVAL; 285 } 286 287 void mt_set_gpio_pull_select_chip(uint32_t pin, int sel) 288 { 289 int pullsel_addr = gpio_get_pull_iocfg(pin) + PULLSEL_ADDR_OFFSET; 290 int pupd_addr = gpio_get_pupd_iocfg(pin); 291 int pupd_offset = gpio_get_pupd_offset(pin); 292 293 assert(pin < MAX_GPIO_PIN); 294 295 assert(!((PULL_offset[pin].offset == (int8_t) -1) && 296 (pupd_offset == (int8_t)-1))); 297 298 if (sel == GPIO_PULL_NONE) { 299 /* Regard No PULL as PULL disable + pull down */ 300 mt_set_gpio_pull_enable_chip(pin, GPIO_PULL_DISABLE); 301 if (PULL_offset[pin].offset == (int8_t)-1) 302 mmio_setbits_32(pupd_addr, 1U << (pupd_offset + 2)); 303 else 304 mmio_clrbits_32(pullsel_addr, 305 1U << PULL_offset[pin].offset); 306 } else if (sel == GPIO_PULL_UP) { 307 mt_set_gpio_pull_enable_chip(pin, GPIO_PULL_ENABLE); 308 if (PULL_offset[pin].offset == (int8_t)-1) 309 mmio_clrbits_32(pupd_addr, 1U << (pupd_offset + 2)); 310 else 311 mmio_setbits_32(pullsel_addr, 312 1U << PULL_offset[pin].offset); 313 } else if (sel == GPIO_PULL_DOWN) { 314 mt_set_gpio_pull_enable_chip(pin, GPIO_PULL_ENABLE); 315 if (PULL_offset[pin].offset == -1) 316 mmio_setbits_32(pupd_addr, 1U << (pupd_offset + 2)); 317 else 318 mmio_clrbits_32(pullsel_addr, 319 1U << PULL_offset[pin].offset); 320 } 321 } 322 323 /* get pull-up or pull-down, regardless of resistor value */ 324 int mt_get_gpio_pull_select_chip(uint32_t pin) 325 { 326 uint32_t reg; 327 328 int pullen_addr = gpio_get_pull_iocfg(pin) + PULLEN_ADDR_OFFSET; 329 int pullsel_addr = gpio_get_pull_iocfg(pin) + PULLSEL_ADDR_OFFSET; 330 int pupd_addr = gpio_get_pupd_iocfg(pin); 331 int pupd_offset = gpio_get_pupd_offset(pin); 332 333 assert(pin < MAX_GPIO_PIN); 334 335 assert(!((PULL_offset[pin].offset == (int8_t)-1) && 336 (pupd_offset == (int8_t)-1))); 337 338 if (PULL_offset[pin].offset == (int8_t)-1) { 339 reg = mmio_read_32(pupd_addr); 340 if (reg & (3U << pupd_offset)) { 341 reg = mmio_read_32(pupd_addr); 342 /* Reg value: 0 for PU, 1 for PD --> 343 * reverse return value */ 344 return ((reg & (1U << (pupd_offset + 2))) ? 345 GPIO_PULL_DOWN : GPIO_PULL_UP); 346 } else { 347 return GPIO_PULL_NONE; 348 } 349 } else if (pupd_offset == (int8_t)-1) { 350 reg = mmio_read_32(pullen_addr); 351 if ((reg & (1U << PULL_offset[pin].offset))) { 352 reg = mmio_read_32(pullsel_addr); 353 return ((reg & (1U << PULL_offset[pin].offset)) ? 354 GPIO_PULL_UP : GPIO_PULL_DOWN); 355 } else { 356 return GPIO_PULL_NONE; 357 } 358 } 359 360 return -ERINVAL; 361 } 362 363 void mt_set_gpio_dir(int gpio, int direction) 364 { 365 mt_set_gpio_dir_chip((uint32_t)gpio, direction); 366 } 367 368 int mt_get_gpio_dir(int gpio) 369 { 370 uint32_t pin; 371 372 pin = (uint32_t)gpio; 373 return mt_get_gpio_dir_chip(pin); 374 } 375 376 void mt_set_gpio_pull(int gpio, int pull) 377 { 378 uint32_t pin; 379 380 pin = (uint32_t)gpio; 381 mt_set_gpio_pull_select_chip(pin, pull); 382 } 383 384 int mt_get_gpio_pull(int gpio) 385 { 386 uint32_t pin; 387 388 pin = (uint32_t)gpio; 389 return mt_get_gpio_pull_select_chip(pin); 390 } 391 392 void mt_set_gpio_out(int gpio, int value) 393 { 394 uint32_t pin; 395 396 pin = (uint32_t)gpio; 397 mt_set_gpio_out_chip(pin, value); 398 } 399 400 int mt_get_gpio_out(int gpio) 401 { 402 uint32_t pin; 403 404 pin = (uint32_t)gpio; 405 return mt_get_gpio_out_chip(pin); 406 } 407 408 int mt_get_gpio_in(int gpio) 409 { 410 uint32_t pin; 411 412 pin = (uint32_t)gpio; 413 return mt_get_gpio_in_chip(pin); 414 } 415 416 void mt_set_gpio_mode(int gpio, int mode) 417 { 418 uint32_t pin; 419 420 pin = (uint32_t)gpio; 421 mt_set_gpio_mode_chip(pin, mode); 422 } 423 424 int mt_get_gpio_mode(int gpio) 425 { 426 uint32_t pin; 427 428 pin = (uint32_t)gpio; 429 return mt_get_gpio_mode_chip(pin); 430 } 431 432 const gpio_ops_t mtgpio_ops = { 433 .get_direction = mt_get_gpio_dir, 434 .set_direction = mt_set_gpio_dir, 435 .get_value = mt_get_gpio_in, 436 .set_value = mt_set_gpio_out, 437 .set_pull = mt_set_gpio_pull, 438 .get_pull = mt_get_gpio_pull, 439 }; 440