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