irq; support irq revert trigger type and get gpio level

Change-Id: Ib897bb37c518429c595903bb8f2cfd9fcea9aa78
Signed-off-by: Joseph Chen <chenjh@rock-chips.com>
This commit is contained in:
Joseph Chen 2018-01-30 15:24:21 +08:00
parent bb9827924e
commit c234b81e6a
3 changed files with 113 additions and 0 deletions

View File

@ -162,6 +162,28 @@ int irq_set_irq_type(int irq, unsigned int type)
return gpio_irq_chip->irq_set_type(irq, type);
}
int irq_revert_irq_type(int irq)
{
if (irq_bad(irq))
return -EINVAL;
if (irq < PLATFORM_GIC_IRQS_NR)
return 0;
else
return gpio_irq_chip->irq_revert_type(irq);
}
int irq_get_gpio_level(int irq)
{
if (irq_bad(irq))
return -EINVAL;
if (irq < PLATFORM_GIC_IRQS_NR)
return 0;
else
return gpio_irq_chip->irq_get_gpio_level(irq);
}
void irq_install_handler(int irq, interrupt_handler_t *handler, void *data)
{
if (irq_bad(irq))

View File

@ -62,6 +62,11 @@ static void gpio_bit_op(void __iomem *regbase, unsigned int offset,
writel(val, regbase + offset);
}
static int gpio_bit_rd(void __iomem *regbase, unsigned int offset, u32 bit)
{
return readl(regbase + offset) & bit ? 1 : 0;
}
static void gpio_irq_unmask(void __iomem *regbase, unsigned int bit)
{
gpio_bit_op(regbase, GPIO_INTEN, bit, 1);
@ -137,6 +142,34 @@ static void gpio_set_intr_type(void __iomem *regbase,
}
}
static int gpio_get_intr_type(void __iomem *regbase,
unsigned int bit)
{
u32 polarity, level, magic = 0;
int type;
polarity = gpio_bit_rd(regbase, GPIO_INT_POLARITY, bit);
level = gpio_bit_rd(regbase, GPIO_INTTYPE_LEVEL, bit);
magic = (polarity << 1) | (level << 0);
switch (magic) {
case 0x00:
type = GPIOLevelLow;
break;
case 0x02:
type = GPIOLevelHigh;
break;
case 0x01:
type = GPIOEdgelFalling;
break;
case 0x03:
type = GPIOEdgelRising;
break;
}
return type;
}
static int gpio_irq_set_type(int gpio_irq, unsigned int type)
{
int gpio = irq_to_gpio(gpio_irq);
@ -175,6 +208,58 @@ static int gpio_irq_set_type(int gpio_irq, unsigned int type)
return 0;
}
static int gpio_irq_revert_type(int gpio_irq)
{
int gpio = irq_to_gpio(gpio_irq);
struct gpio_bank *bank = gpio_to_bank(gpio);
eGPIOIntType_t int_type = 0;
int type;
if (!bank)
return -EINVAL;
gpio &= GPIO_PIN_MASK;
if (gpio >= bank->ngpio)
return -EINVAL;
type = gpio_get_intr_type(bank->regbase, offset_to_bit(gpio));
switch (type) {
case GPIOEdgelFalling:
int_type = GPIOEdgelRising;
break;
case GPIOEdgelRising:
int_type = GPIOEdgelFalling;
break;
case GPIOLevelHigh:
int_type = GPIOLevelLow;
break;
case GPIOLevelLow:
int_type = GPIOLevelHigh;
break;
default:
return -EINVAL;
}
gpio_set_intr_type(bank->regbase, offset_to_bit(gpio), int_type);
return 0;
}
static int gpio_irq_get_gpio_level(int gpio_irq)
{
int gpio = irq_to_gpio(gpio_irq);
struct gpio_bank *bank = gpio_to_bank(gpio);
if (!bank)
return -EINVAL;
gpio &= GPIO_PIN_MASK;
if (gpio >= bank->ngpio)
return -EINVAL;
return gpio_bit_rd(bank->regbase, GPIO_EXT_PORT, offset_to_bit(gpio));
}
static int gpio_irq_enable(int gpio_irq)
{
int gpio = irq_to_gpio(gpio_irq);
@ -238,6 +323,8 @@ static struct irq_chip gpio_irq_chip = {
.irq_enable = gpio_irq_enable,
.irq_disable = gpio_irq_disable,
.irq_set_type = gpio_irq_set_type,
.irq_revert_type = gpio_irq_revert_type,
.irq_get_gpio_level = gpio_irq_get_gpio_level,
};
struct irq_chip *arch_gpio_irq_init(void)

View File

@ -55,14 +55,18 @@ struct irq_chip {
void (*irq_ack)(int irq);
void (*irq_eoi)(int irq);
int (*irq_set_type)(int irq, unsigned int flow_type);
int (*irq_revert_type)(int irq);
int (*irq_get_gpio_level)(int irq);
};
/* APIs for irqs */
void irq_install_handler(int irq, interrupt_handler_t *handler, void *data);
void irq_free_handler(int irq);
int irq_set_irq_type(int irq, unsigned int type);
int irq_revert_irq_type(int irq);
int irq_handler_enable(int irq);
int irq_handler_disable(int irq);
int irq_get_gpio_level(int irq);
int irqs_suspend(void);
int irqs_resume(void);
int gpio_to_irq(struct gpio_desc *gpio);