summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/soc/qualcomm/common/gpio.c87
-rw-r--r--src/soc/qualcomm/common/include/soc/gpio_common.h102
2 files changed, 189 insertions, 0 deletions
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 <assert.h>
+#include <device/mmio.h>
+#include <gpio.h>
+
+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(&regs->cfg, reg_val);
+}
+
+void gpio_set(gpio_t gpio, int value)
+{
+ struct tlmm_gpio *regs = (void *)(uintptr_t)gpio.addr;
+
+ write32(&regs->in_out, (!!value) << GPIO_IO_OUT_SHFT);
+}
+
+int gpio_get(gpio_t gpio)
+{
+ struct tlmm_gpio *regs = (void *)(uintptr_t)gpio.addr;
+
+ return ((read32(&regs->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(&regs->intr_cfg, GPIO_INTR_DECT_CTL_MASK <<
+ GPIO_INTR_DECT_CTL_SHFT, type << GPIO_INTR_DECT_CTL_SHFT);
+ clrsetbits32(&regs->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(&regs->intr_status) & GPIO_INTR_STATUS_MASK))
+ return GPIO_INTR_STATUS_DISABLE;
+
+ write32(&regs->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 <soc/gpio.h>
+#include <soc/addressmap.h>
+
+#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_ */