1 /* 2 * Copyright (c) 2020-2022, 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 <drivers/gpio.h> 11 #include <lib/mmio.h> 12 #include <mtgpio.h> 13 #include <platform_def.h> 14 15 /****************************************************************************** 16 *Macro Definition 17 ******************************************************************************/ 18 #define GPIO_MODE_BITS 4 19 #define MAX_GPIO_MODE_PER_REG 8 20 #define MAX_GPIO_REG_BITS 32 21 #define DIR_BASE (GPIO_BASE + 0x000) 22 #define DOUT_BASE (GPIO_BASE + 0x100) 23 #define DIN_BASE (GPIO_BASE + 0x200) 24 #define MODE_BASE (GPIO_BASE + 0x300) 25 #define SET 0x4 26 #define CLR 0x8 27 28 static void mt_set_gpio_dir_chip(uint32_t pin, int dir) 29 { 30 uint32_t pos, bit; 31 32 assert(pin < MAX_GPIO_PIN); 33 assert(dir < MT_GPIO_DIR_MAX); 34 35 pos = pin / MAX_GPIO_REG_BITS; 36 bit = pin % MAX_GPIO_REG_BITS; 37 38 if (dir == MT_GPIO_DIR_IN) { 39 mmio_write_32(DIR_BASE + 0x10U * pos + CLR, 1U << bit); 40 } else { 41 mmio_write_32(DIR_BASE + 0x10U * pos + SET, 1U << bit); 42 } 43 } 44 45 static int mt_get_gpio_dir_chip(uint32_t pin) 46 { 47 uint32_t pos, bit; 48 uint32_t reg; 49 50 assert(pin < MAX_GPIO_PIN); 51 52 pos = pin / MAX_GPIO_REG_BITS; 53 bit = pin % MAX_GPIO_REG_BITS; 54 55 reg = mmio_read_32(DIR_BASE + 0x10U * pos); 56 return (((reg & (1U << bit)) != 0U) ? MT_GPIO_DIR_OUT : MT_GPIO_DIR_IN); 57 } 58 59 static void mt_set_gpio_out_chip(uint32_t pin, int output) 60 { 61 uint32_t pos, bit; 62 63 assert(pin < MAX_GPIO_PIN); 64 assert(output < MT_GPIO_OUT_MAX); 65 66 pos = pin / MAX_GPIO_REG_BITS; 67 bit = pin % MAX_GPIO_REG_BITS; 68 69 if (output == MT_GPIO_OUT_ZERO) { 70 mmio_write_32(DOUT_BASE + 0x10U * pos + CLR, 1U << bit); 71 } else { 72 mmio_write_32(DOUT_BASE + 0x10U * pos + SET, 1U << bit); 73 } 74 } 75 76 static int mt_get_gpio_in_chip(uint32_t pin) 77 { 78 uint32_t pos, bit; 79 uint32_t reg; 80 81 assert(pin < MAX_GPIO_PIN); 82 83 pos = pin / MAX_GPIO_REG_BITS; 84 bit = pin % MAX_GPIO_REG_BITS; 85 86 reg = mmio_read_32(DIN_BASE + 0x10U * pos); 87 return (((reg & (1U << bit)) != 0U) ? 1 : 0); 88 } 89 90 static void mt_gpio_set_spec_pull_pupd(uint32_t pin, int enable, 91 int select) 92 { 93 uintptr_t reg1; 94 uintptr_t reg2; 95 struct mt_pin_info gpio_info; 96 97 gpio_info = mt_pin_infos[pin]; 98 uint32_t bit = gpio_info.bit; 99 100 reg1 = mt_gpio_find_reg_addr(pin) + gpio_info.offset; 101 reg2 = reg1 + (gpio_info.base & 0xf0); 102 if (enable == MT_GPIO_PULL_ENABLE) { 103 mmio_write_32(reg2 + SET, (1U << bit)); 104 if (select == MT_GPIO_PULL_DOWN) { 105 mmio_write_32(reg1 + SET, (1U << bit)); 106 } else { 107 mmio_write_32(reg1 + CLR, (1U << bit)); 108 } 109 } else { 110 mmio_write_32(reg2 + CLR, (1U << bit)); 111 mmio_write_32((reg2 + 0x010U) + CLR, (1U << bit)); 112 } 113 } 114 115 static void mt_gpio_set_pull_pu_pd(uint32_t pin, int enable, 116 int select) 117 { 118 uintptr_t reg1; 119 uintptr_t reg2; 120 struct mt_pin_info gpio_info; 121 122 gpio_info = mt_pin_infos[pin]; 123 uint32_t bit = gpio_info.bit; 124 125 reg1 = mt_gpio_find_reg_addr(pin) + gpio_info.offset; 126 reg2 = reg1 - (gpio_info.base & 0xf0); 127 128 if (enable == MT_GPIO_PULL_ENABLE) { 129 if (select == MT_GPIO_PULL_DOWN) { 130 mmio_write_32(reg1 + CLR, (1U << bit)); 131 mmio_write_32(reg2 + SET, (1U << bit)); 132 } else { 133 mmio_write_32(reg2 + CLR, (1U << bit)); 134 mmio_write_32(reg1 + SET, (1U << bit)); 135 } 136 } else { 137 mmio_write_32(reg1 + CLR, (1U << bit)); 138 mmio_write_32(reg2 + CLR, (1U << bit)); 139 } 140 } 141 142 static void mt_gpio_set_pull_chip(uint32_t pin, int enable, 143 int select) 144 { 145 struct mt_pin_info gpio_info; 146 147 gpio_info = mt_pin_infos[pin]; 148 if (gpio_info.flag) { 149 mt_gpio_set_spec_pull_pupd(pin, enable, select); 150 } else { 151 mt_gpio_set_pull_pu_pd(pin, enable, select); 152 } 153 } 154 155 static int mt_gpio_get_spec_pull_pupd(uint32_t pin) 156 { 157 uintptr_t reg1; 158 uintptr_t reg2; 159 uint32_t r0; 160 uint32_t r1; 161 162 struct mt_pin_info gpio_info; 163 164 gpio_info = mt_pin_infos[pin]; 165 uint32_t bit = gpio_info.bit; 166 167 reg1 = mt_gpio_find_reg_addr(pin) + gpio_info.offset; 168 reg2 = reg1 + (gpio_info.base & 0xf0); 169 170 r0 = (mmio_read_32(reg2) >> bit) & 1U; 171 r1 = (mmio_read_32(reg2 + 0x010) >> bit) & 1U; 172 if (r0 == 0U && r1 == 0U) { 173 return MT_GPIO_PULL_NONE; 174 } else { 175 if (mmio_read_32(reg1) & (1U << bit)) { 176 return MT_GPIO_PULL_DOWN; 177 } else { 178 return MT_GPIO_PULL_UP; 179 } 180 } 181 } 182 183 static int mt_gpio_get_pull_pu_pd(uint32_t pin) 184 { 185 uintptr_t reg1; 186 uintptr_t reg2; 187 uint32_t pu; 188 uint32_t pd; 189 190 struct mt_pin_info gpio_info; 191 192 gpio_info = mt_pin_infos[pin]; 193 uint32_t bit = gpio_info.bit; 194 195 reg1 = mt_gpio_find_reg_addr(pin) + gpio_info.offset; 196 reg2 = reg1 - (gpio_info.base & 0xf0); 197 pu = (mmio_read_32(reg1) >> bit) & 1U; 198 pd = (mmio_read_32(reg2) >> bit) & 1U; 199 if (pu == 1U) { 200 return MT_GPIO_PULL_UP; 201 } else if (pd == 1U) { 202 return MT_GPIO_PULL_DOWN; 203 } else { 204 return MT_GPIO_PULL_NONE; 205 } 206 } 207 208 static int mt_gpio_get_pull_chip(uint32_t pin) 209 { 210 struct mt_pin_info gpio_info; 211 212 gpio_info = mt_pin_infos[pin]; 213 if (gpio_info.flag) { 214 return mt_gpio_get_spec_pull_pupd(pin); 215 } else { 216 return mt_gpio_get_pull_pu_pd(pin); 217 } 218 } 219 220 static void mt_set_gpio_pull_select_chip(uint32_t pin, int sel) 221 { 222 assert(pin < MAX_GPIO_PIN); 223 224 if (sel == MT_GPIO_PULL_NONE) { 225 mt_gpio_set_pull_chip(pin, MT_GPIO_PULL_DISABLE, MT_GPIO_PULL_DOWN); 226 } else if (sel == MT_GPIO_PULL_UP) { 227 mt_gpio_set_pull_chip(pin, MT_GPIO_PULL_ENABLE, MT_GPIO_PULL_UP); 228 } else if (sel == MT_GPIO_PULL_DOWN) { 229 mt_gpio_set_pull_chip(pin, MT_GPIO_PULL_ENABLE, MT_GPIO_PULL_DOWN); 230 } 231 } 232 233 /* get pull-up or pull-down, regardless of resistor value */ 234 static int mt_get_gpio_pull_select_chip(uint32_t pin) 235 { 236 assert(pin < MAX_GPIO_PIN); 237 238 return mt_gpio_get_pull_chip(pin); 239 } 240 241 static void mt_set_gpio_dir(int gpio, int direction) 242 { 243 mt_set_gpio_dir_chip((uint32_t)gpio, direction); 244 } 245 246 static int mt_get_gpio_dir(int gpio) 247 { 248 uint32_t pin; 249 250 pin = (uint32_t)gpio; 251 return mt_get_gpio_dir_chip(pin); 252 } 253 254 static void mt_set_gpio_pull(int gpio, int pull) 255 { 256 uint32_t pin; 257 258 pin = (uint32_t)gpio; 259 mt_set_gpio_pull_select_chip(pin, pull); 260 } 261 262 static int mt_get_gpio_pull(int gpio) 263 { 264 uint32_t pin; 265 266 pin = (uint32_t)gpio; 267 return mt_get_gpio_pull_select_chip(pin); 268 } 269 270 static void mt_set_gpio_out(int gpio, int value) 271 { 272 uint32_t pin; 273 274 pin = (uint32_t)gpio; 275 mt_set_gpio_out_chip(pin, value); 276 } 277 278 static int mt_get_gpio_in(int gpio) 279 { 280 uint32_t pin; 281 282 pin = (uint32_t)gpio; 283 return mt_get_gpio_in_chip(pin); 284 } 285 286 const gpio_ops_t mtgpio_ops = { 287 .get_direction = mt_get_gpio_dir, 288 .set_direction = mt_set_gpio_dir, 289 .get_value = mt_get_gpio_in, 290 .set_value = mt_set_gpio_out, 291 .set_pull = mt_set_gpio_pull, 292 .get_pull = mt_get_gpio_pull, 293 }; 294 295 void mt_gpio_init(void) 296 { 297 gpio_init(&mtgpio_ops); 298 } 299