diff options
Diffstat (limited to 'drivers/pinctrl/stm32')
| -rw-r--r-- | drivers/pinctrl/stm32/pinctrl-stm32.c | 61 | 
1 files changed, 56 insertions, 5 deletions
| diff --git a/drivers/pinctrl/stm32/pinctrl-stm32.c b/drivers/pinctrl/stm32/pinctrl-stm32.c index 2d5e0435af0a..a657cd829ce6 100644 --- a/drivers/pinctrl/stm32/pinctrl-stm32.c +++ b/drivers/pinctrl/stm32/pinctrl-stm32.c @@ -92,6 +92,7 @@ struct stm32_gpio_bank {  	u32 bank_nr;  	u32 bank_ioport_nr;  	u32 pin_backup[STM32_GPIO_PINS_PER_BANK]; +	u8 irq_type[STM32_GPIO_PINS_PER_BANK];  };  struct stm32_pinctrl { @@ -283,9 +284,9 @@ static int stm32_gpio_get_direction(struct gpio_chip *chip, unsigned int offset)  	stm32_pmx_get_mode(bank, pin, &mode, &alt);  	if ((alt == 0) && (mode == 0)) -		ret = 1; +		ret = GPIO_LINE_DIRECTION_IN;  	else if ((alt == 0) && (mode == 1)) -		ret = 0; +		ret = GPIO_LINE_DIRECTION_OUT;  	else  		ret = -EINVAL; @@ -303,6 +304,50 @@ static const struct gpio_chip stm32_gpio_template = {  	.get_direction		= stm32_gpio_get_direction,  }; +static void stm32_gpio_irq_trigger(struct irq_data *d) +{ +	struct stm32_gpio_bank *bank = d->domain->host_data; +	int level; + +	/* If level interrupt type then retrig */ +	level = stm32_gpio_get(&bank->gpio_chip, d->hwirq); +	if ((level == 0 && bank->irq_type[d->hwirq] == IRQ_TYPE_LEVEL_LOW) || +	    (level == 1 && bank->irq_type[d->hwirq] == IRQ_TYPE_LEVEL_HIGH)) +		irq_chip_retrigger_hierarchy(d); +} + +static void stm32_gpio_irq_eoi(struct irq_data *d) +{ +	irq_chip_eoi_parent(d); +	stm32_gpio_irq_trigger(d); +}; + +static int stm32_gpio_set_type(struct irq_data *d, unsigned int type) +{ +	struct stm32_gpio_bank *bank = d->domain->host_data; +	u32 parent_type; + +	switch (type) { +	case IRQ_TYPE_EDGE_RISING: +	case IRQ_TYPE_EDGE_FALLING: +	case IRQ_TYPE_EDGE_BOTH: +		parent_type = type; +		break; +	case IRQ_TYPE_LEVEL_HIGH: +		parent_type = IRQ_TYPE_EDGE_RISING; +		break; +	case IRQ_TYPE_LEVEL_LOW: +		parent_type = IRQ_TYPE_EDGE_FALLING; +		break; +	default: +		return -EINVAL; +	} + +	bank->irq_type[d->hwirq] = type; + +	return irq_chip_set_type_parent(d, parent_type); +}; +  static int stm32_gpio_irq_request_resources(struct irq_data *irq_data)  {  	struct stm32_gpio_bank *bank = irq_data->domain->host_data; @@ -330,13 +375,19 @@ static void stm32_gpio_irq_release_resources(struct irq_data *irq_data)  	gpiochip_unlock_as_irq(&bank->gpio_chip, irq_data->hwirq);  } +static void stm32_gpio_irq_unmask(struct irq_data *d) +{ +	irq_chip_unmask_parent(d); +	stm32_gpio_irq_trigger(d); +} +  static struct irq_chip stm32_gpio_irq_chip = {  	.name		= "stm32gpio", -	.irq_eoi	= irq_chip_eoi_parent, +	.irq_eoi	= stm32_gpio_irq_eoi,  	.irq_ack	= irq_chip_ack_parent,  	.irq_mask	= irq_chip_mask_parent, -	.irq_unmask	= irq_chip_unmask_parent, -	.irq_set_type	= irq_chip_set_type_parent, +	.irq_unmask	= stm32_gpio_irq_unmask, +	.irq_set_type	= stm32_gpio_set_type,  	.irq_set_wake	= irq_chip_set_wake_parent,  	.irq_request_resources = stm32_gpio_irq_request_resources,  	.irq_release_resources = stm32_gpio_irq_release_resources, |