diff options
author | Tristan Shieh <tristan.shieh@mediatek.com> | 2018-07-09 18:59:32 +0800 |
---|---|---|
committer | Patrick Georgi <pgeorgi@google.com> | 2018-07-20 13:50:54 +0000 |
commit | 71d227b1085b5f54b11a6fcfa9419597ee5c9f56 (patch) | |
tree | 49ba7259011ef038a6b8f9aa1808523b650115fe /src/soc/mediatek/common/gpio.c | |
parent | ccb62960db3eff2d4c2905710ba99ba90f24bcdc (diff) | |
download | coreboot-71d227b1085b5f54b11a6fcfa9419597ee5c9f56.tar.xz |
mediatek: Share GPIO code among similar SOCs
Refactor GPIO code which will be reused among similar SOCs.
BUG=b:80501386
BRANCH=none
TEST=Boots correctly on Elm
Change-Id: Icdd1f2a1dd1bd64a7218bf9c63bd4a0af1acbcc0
Signed-off-by: Tristan Shieh <tristan.shieh@mediatek.com>
Reviewed-on: https://review.coreboot.org/27416
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Julius Werner <jwerner@chromium.org>
Diffstat (limited to 'src/soc/mediatek/common/gpio.c')
-rw-r--r-- | src/soc/mediatek/common/gpio.c | 128 |
1 files changed, 128 insertions, 0 deletions
diff --git a/src/soc/mediatek/common/gpio.c b/src/soc/mediatek/common/gpio.c new file mode 100644 index 0000000000..590f8ea461 --- /dev/null +++ b/src/soc/mediatek/common/gpio.c @@ -0,0 +1,128 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2018 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <arch/io.h> +#include <gpio.h> + +enum { + GPIO_DIRECTION_IN = 0, + GPIO_DIRECTION_OUT = 1, +}; + +enum { + GPIO_MODE = 0, +}; + +static void pos_bit_calc(gpio_t gpio, u32 *pos, u32 *bit) +{ + *pos = gpio.id / MAX_GPIO_REG_BITS; + *bit = gpio.id % MAX_GPIO_REG_BITS; +} + +static void pos_bit_calc_for_mode(gpio_t gpio, u32 *pos, u32 *bit) +{ + *pos = gpio.id / MAX_GPIO_MODE_PER_REG; + *bit = (gpio.id % MAX_GPIO_MODE_PER_REG) * GPIO_MODE_BITS; +} + +static s32 gpio_set_dir(gpio_t gpio, u32 dir) +{ + u32 pos; + u32 bit; + u32 *reg; + + pos_bit_calc(gpio, &pos, &bit); + + if (dir == GPIO_DIRECTION_IN) + reg = &mtk_gpio->dir[pos].rst; + else + reg = &mtk_gpio->dir[pos].set; + + write32(reg, 1L << bit); + + return 0; +} + +void gpio_set_mode(gpio_t gpio, int mode) +{ + u32 pos; + u32 bit; + u32 mask = (1L << GPIO_MODE_BITS) - 1; + + pos_bit_calc_for_mode(gpio, &pos, &bit); + + clrsetbits_le32(&mtk_gpio->mode[pos].val, + mask << bit, mode << bit); +} + +int gpio_get(gpio_t gpio) +{ + u32 pos; + u32 bit; + u32 *reg; + u32 data; + + pos_bit_calc(gpio, &pos, &bit); + + reg = &mtk_gpio->din[pos].val; + data = read32(reg); + + return (data & (1L << bit)) ? 1 : 0; +} + +void gpio_set(gpio_t gpio, int output) +{ + u32 pos; + u32 bit; + u32 *reg; + + pos_bit_calc(gpio, &pos, &bit); + + if (output == 0) + reg = &mtk_gpio->dout[pos].rst; + else + reg = &mtk_gpio->dout[pos].set; + + write32(reg, 1L << bit); +} + +void gpio_input_pulldown(gpio_t gpio) +{ + gpio_set_pull(gpio, GPIO_PULL_ENABLE, GPIO_PULL_DOWN); + gpio_set_dir(gpio, GPIO_DIRECTION_IN); + gpio_set_mode(gpio, GPIO_MODE); +} + +void gpio_input_pullup(gpio_t gpio) +{ + gpio_set_pull(gpio, GPIO_PULL_ENABLE, GPIO_PULL_UP); + gpio_set_dir(gpio, GPIO_DIRECTION_IN); + gpio_set_mode(gpio, GPIO_MODE); +} + +void gpio_input(gpio_t gpio) +{ + gpio_set_pull(gpio, GPIO_PULL_DISABLE, GPIO_PULL_DOWN); + gpio_set_dir(gpio, GPIO_DIRECTION_IN); + gpio_set_mode(gpio, GPIO_MODE); +} + +void gpio_output(gpio_t gpio, int value) +{ + gpio_set_pull(gpio, GPIO_PULL_DISABLE, GPIO_PULL_DOWN); + gpio_set(gpio, value); + gpio_set_dir(gpio, GPIO_DIRECTION_OUT); + gpio_set_mode(gpio, GPIO_MODE); +} |