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