From 017c59096abb02e53538e0693f02738d5abc98ec Mon Sep 17 00:00:00 2001 From: Taniya Das Date: Fri, 7 May 2021 10:20:19 +0530 Subject: soc: common: gpio: Add support for common GPIO driver Add common gpio functionalities across qualcomm soc targets. This common gpio driver would allow the consumers to be able to configure gpio function, set/get gpio direction as input/output, configure the gpio as pull-up/pull-down, configure the gpio as an IRQ and also query the gpio irq status. The GPIO pin definition would be SoC specific. BUG=b:182963902 TEST=Validated on qualcomm sc7180 and sc7280 development board Signed-off-by: Taniya Das Change-Id: Ia672130c6ca938d9284cae5071307637709480d1 Reviewed-on: https://review.coreboot.org/c/coreboot/+/55076 Reviewed-by: Shelley Chen Tested-by: build bot (Jenkins) --- src/soc/qualcomm/common/gpio.c | 87 ++++++++++++++++++ src/soc/qualcomm/common/include/soc/gpio_common.h | 102 ++++++++++++++++++++++ 2 files changed, 189 insertions(+) create mode 100644 src/soc/qualcomm/common/gpio.c create mode 100644 src/soc/qualcomm/common/include/soc/gpio_common.h (limited to 'src/soc/qualcomm') diff --git a/src/soc/qualcomm/common/gpio.c b/src/soc/qualcomm/common/gpio.c new file mode 100644 index 0000000000..1ed8e8a04b --- /dev/null +++ b/src/soc/qualcomm/common/gpio.c @@ -0,0 +1,87 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include +#include +#include + +void gpio_configure(gpio_t gpio, uint32_t func, uint32_t pull, + uint32_t drive_str, uint32_t enable) +{ + struct tlmm_gpio *regs = (void *)(uintptr_t)gpio.addr; + uint32_t reg_val; + + /* gpio pull only PULLNONE, PULLUP, KEEPER, PULLDOWN status */ + assert(pull <= GPIO_PULL_UP); + + reg_val = ((enable & GPIO_BMSK) << GPIO_CFG_OE_SHFT) | + ((drive_str & GPIO_CFG_DRV_BMSK) << GPIO_CFG_DRV_SHFT) | + ((func & GPIO_CFG_FUNC_BMSK) << GPIO_CFG_FUNC_SHFT) | + ((pull & GPIO_CFG_PULL_BMSK) << GPIO_CFG_PULL_SHFT); + + write32(®s->cfg, reg_val); +} + +void gpio_set(gpio_t gpio, int value) +{ + struct tlmm_gpio *regs = (void *)(uintptr_t)gpio.addr; + + write32(®s->in_out, (!!value) << GPIO_IO_OUT_SHFT); +} + +int gpio_get(gpio_t gpio) +{ + struct tlmm_gpio *regs = (void *)(uintptr_t)gpio.addr; + + return ((read32(®s->in_out) >> GPIO_IO_IN_SHFT) & GPIO_BMSK); +} + +void gpio_input_pulldown(gpio_t gpio) +{ + gpio_configure(gpio, GPIO_FUNC_GPIO, + GPIO_PULL_DOWN, GPIO_2MA, GPIO_INPUT); +} + +void gpio_input_pullup(gpio_t gpio) +{ + gpio_configure(gpio, GPIO_FUNC_GPIO, + GPIO_PULL_UP, GPIO_2MA, GPIO_INPUT); +} + +void gpio_input(gpio_t gpio) +{ + gpio_configure(gpio, GPIO_FUNC_GPIO, + GPIO_NO_PULL, GPIO_2MA, GPIO_INPUT); +} + +void gpio_output(gpio_t gpio, int value) +{ + gpio_set(gpio, value); + gpio_configure(gpio, GPIO_FUNC_GPIO, + GPIO_NO_PULL, GPIO_2MA, GPIO_OUTPUT); +} + +void gpio_input_irq(gpio_t gpio, enum gpio_irq_type type, uint32_t pull) +{ + struct tlmm_gpio *regs = (void *)(uintptr_t)gpio.addr; + + gpio_configure(gpio, GPIO_FUNC_GPIO, + pull, GPIO_2MA, GPIO_INPUT); + + clrsetbits32(®s->intr_cfg, GPIO_INTR_DECT_CTL_MASK << + GPIO_INTR_DECT_CTL_SHFT, type << GPIO_INTR_DECT_CTL_SHFT); + clrsetbits32(®s->intr_cfg, GPIO_INTR_STATUS_ENABLE + << GPIO_INTR_RAW_STATUS_EN_SHFT, GPIO_INTR_STATUS_ENABLE + << GPIO_INTR_RAW_STATUS_EN_SHFT); +} + +int gpio_irq_status(gpio_t gpio) +{ + struct tlmm_gpio *regs = (void *)(uintptr_t)gpio.addr; + + if (!(read32(®s->intr_status) & GPIO_INTR_STATUS_MASK)) + return GPIO_INTR_STATUS_DISABLE; + + write32(®s->intr_status, GPIO_INTR_STATUS_DISABLE); + + return GPIO_INTR_STATUS_ENABLE; +} diff --git a/src/soc/qualcomm/common/include/soc/gpio_common.h b/src/soc/qualcomm/common/include/soc/gpio_common.h new file mode 100644 index 0000000000..0ad582de60 --- /dev/null +++ b/src/soc/qualcomm/common/include/soc/gpio_common.h @@ -0,0 +1,102 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef _SOC_QUALCOMM_COMMON_GPIO_H_ +#define _SOC_QUALCOMM_COMMON_GPIO_H_ + +#include +#include + +#define GPIO_FUNC_GPIO 0 + +/* GPIO TLMM INTR: Mask */ +enum gpio_tlmm_intr_bmsk { + GPIO_INTR_STATUS_MASK = 0x1, + GPIO_INTR_DECT_CTL_MASK = 0x3, +}; + +/* GPIO TLMM: Mask */ +enum gpio_tlmm_bmsk { + GPIO_BMSK = 0x1, + GPIO_CFG_PULL_BMSK = 0x3, + GPIO_CFG_FUNC_BMSK = 0xF, + GPIO_CFG_DRV_BMSK = 0x7, +}; + +/* GPIO TLMM INTR: Shift */ +enum gpio_tlmm_intr_shft { + GPIO_INTR_DECT_CTL_SHFT = 2, + GPIO_INTR_RAW_STATUS_EN_SHFT = 4, +}; + +/* GPIO TLMM: Shift */ +enum gpio_tlmm_shft { + GPIO_CFG_PULL_SHFT = 0, + GPIO_CFG_FUNC_SHFT = 2, + GPIO_CFG_DRV_SHFT = 6, + GPIO_CFG_OE_SHFT = 9, +}; + +/* GPIO IO: Shift */ +enum gpio_io_shft { + GPIO_IO_IN_SHFT, + GPIO_IO_OUT_SHFT, +}; + +/* GPIO INTR STATUS */ +enum gpio_irq_status { + GPIO_INTR_STATUS_DISABLE, + GPIO_INTR_STATUS_ENABLE, +}; + +/* GPIO TLMM: Direction */ +enum gpio_direction { + GPIO_INPUT, + GPIO_OUTPUT, +}; + +/* GPIO TLMM: Pullup/Pulldown */ +enum gpio_pull { + GPIO_NO_PULL, + GPIO_PULL_DOWN, + GPIO_KEEPER, + GPIO_PULL_UP, +}; + +/* GPIO TLMM: Drive Strength */ +enum gpio_drv_str { + GPIO_2MA, + GPIO_4MA, + GPIO_6MA, + GPIO_8MA, + GPIO_10MA, + GPIO_12MA, + GPIO_14MA, + GPIO_16MA, +}; + +enum gpio_irq_type { + IRQ_TYPE_LEVEL, + IRQ_TYPE_RISING_EDGE, + IRQ_TYPE_FALLING_EDGE, + IRQ_TYPE_DUAL_EDGE, +}; + +typedef struct { + u32 addr; +} gpio_t; + +struct tlmm_gpio { + uint32_t cfg; + uint32_t in_out; + uint32_t intr_cfg; + uint32_t intr_status; +}; + +#define GPIO(num) ((gpio_t){.addr = GPIO##num##_ADDR}) + +void gpio_configure(gpio_t gpio, uint32_t func, uint32_t pull, + uint32_t drive_str, uint32_t enable); +void gpio_input_irq(gpio_t gpio, enum gpio_irq_type type, uint32_t pull); +int gpio_irq_status(gpio_t gpio); + +#endif /* _SOC_QUALCOMM_COMMON_GPIO_H_ */ -- cgit v1.2.3