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 <tdas@codeaurora.org> Change-Id: Ia672130c6ca938d9284cae5071307637709480d1 Reviewed-on: https://review.coreboot.org/c/coreboot/+/55076 Reviewed-by: Shelley Chen <shchen@google.com> Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
This commit is contained in:
parent
414b4269be
commit
017c59096a
|
@ -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(®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;
|
||||
}
|
|
@ -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_ */
|
Loading…
Reference in New Issue