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