|
@@ -1292,6 +1292,49 @@ static void chv_gpio_irq_unmask(struct irq_data *d)
|
|
chv_gpio_irq_mask_unmask(d, false);
|
|
chv_gpio_irq_mask_unmask(d, false);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static unsigned chv_gpio_irq_startup(struct irq_data *d)
|
|
|
|
+{
|
|
|
|
+ /*
|
|
|
|
+ * Check if the interrupt has been requested with 0 as triggering
|
|
|
|
+ * type. In that case it is assumed that the current values
|
|
|
|
+ * programmed to the hardware are used (e.g BIOS configured
|
|
|
|
+ * defaults).
|
|
|
|
+ *
|
|
|
|
+ * In that case ->irq_set_type() will never be called so we need to
|
|
|
|
+ * read back the values from hardware now, set correct flow handler
|
|
|
|
+ * and update mappings before the interrupt is being used.
|
|
|
|
+ */
|
|
|
|
+ if (irqd_get_trigger_type(d) == IRQ_TYPE_NONE) {
|
|
|
|
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
|
|
|
|
+ struct chv_pinctrl *pctrl = gpiochip_to_pinctrl(gc);
|
|
|
|
+ unsigned offset = irqd_to_hwirq(d);
|
|
|
|
+ int pin = chv_gpio_offset_to_pin(pctrl, offset);
|
|
|
|
+ irq_flow_handler_t handler;
|
|
|
|
+ unsigned long flags;
|
|
|
|
+ u32 intsel, value;
|
|
|
|
+
|
|
|
|
+ intsel = readl(chv_padreg(pctrl, pin, CHV_PADCTRL0));
|
|
|
|
+ intsel &= CHV_PADCTRL0_INTSEL_MASK;
|
|
|
|
+ intsel >>= CHV_PADCTRL0_INTSEL_SHIFT;
|
|
|
|
+
|
|
|
|
+ value = readl(chv_padreg(pctrl, pin, CHV_PADCTRL1));
|
|
|
|
+ if (value & CHV_PADCTRL1_INTWAKECFG_LEVEL)
|
|
|
|
+ handler = handle_level_irq;
|
|
|
|
+ else
|
|
|
|
+ handler = handle_edge_irq;
|
|
|
|
+
|
|
|
|
+ spin_lock_irqsave(&pctrl->lock, flags);
|
|
|
|
+ if (!pctrl->intr_lines[intsel]) {
|
|
|
|
+ __irq_set_handler_locked(d->irq, handler);
|
|
|
|
+ pctrl->intr_lines[intsel] = offset;
|
|
|
|
+ }
|
|
|
|
+ spin_unlock_irqrestore(&pctrl->lock, flags);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ chv_gpio_irq_unmask(d);
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
static int chv_gpio_irq_type(struct irq_data *d, unsigned type)
|
|
static int chv_gpio_irq_type(struct irq_data *d, unsigned type)
|
|
{
|
|
{
|
|
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
|
|
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
|
|
@@ -1357,6 +1400,7 @@ static int chv_gpio_irq_type(struct irq_data *d, unsigned type)
|
|
|
|
|
|
static struct irq_chip chv_gpio_irqchip = {
|
|
static struct irq_chip chv_gpio_irqchip = {
|
|
.name = "chv-gpio",
|
|
.name = "chv-gpio",
|
|
|
|
+ .irq_startup = chv_gpio_irq_startup,
|
|
.irq_ack = chv_gpio_irq_ack,
|
|
.irq_ack = chv_gpio_irq_ack,
|
|
.irq_mask = chv_gpio_irq_mask,
|
|
.irq_mask = chv_gpio_irq_mask,
|
|
.irq_unmask = chv_gpio_irq_unmask,
|
|
.irq_unmask = chv_gpio_irq_unmask,
|