@@ -43,6 +43,8 @@ struct gpio_rcar_priv {
bool has_outdtsel;
bool has_both_edge_trigger;
struct gpio_rcar_bank_info bank_info;
+ int intmsk;
+ int mskclr;
};
#define IOINTSEL 0x00 /* General IO/Interrupt Switching Register */
@@ -56,6 +58,8 @@ struct gpio_rcar_priv {
#define POSNEG 0x20 /* Positive/Negative Logic Select Register */
#define EDGLEVEL 0x24 /* Edge/level Select Register */
#define FILONOFF 0x28 /* Chattering Prevention On/Off Register */
+#define INTMSKS 0x38 /* Interrupt Sub Mask Register */
+#define MSKCLRS 0x3c /* Interrupt Sub Mask Clear Register */
#define OUTDTSEL 0x40 /* Output Data Select Register */
#define BOTHEDGE 0x4c /* One Edge/Both Edge Select Register */
@@ -90,7 +94,7 @@ static void gpio_rcar_irq_disable(struct irq_data *d)
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct gpio_rcar_priv *p = gpiochip_get_data(gc);
- gpio_rcar_write(p, INTMSK, ~BIT(irqd_to_hwirq(d)));
+ gpio_rcar_write(p, p->intmsk, ~BIT(irqd_to_hwirq(d)));
}
static void gpio_rcar_irq_enable(struct irq_data *d)
@@ -98,7 +102,7 @@ static void gpio_rcar_irq_enable(struct irq_data *d)
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct gpio_rcar_priv *p = gpiochip_get_data(gc);
- gpio_rcar_write(p, MSKCLR, BIT(irqd_to_hwirq(d)));
+ gpio_rcar_write(p, p->mskclr, BIT(irqd_to_hwirq(d)));
}
static void gpio_rcar_config_interrupt_input_mode(struct gpio_rcar_priv *p,
@@ -203,7 +207,7 @@ static irqreturn_t gpio_rcar_irq_handler(int irq, void *dev_id)
unsigned int offset, irqs_handled = 0;
while ((pending = gpio_rcar_read(p, INTDT) &
- gpio_rcar_read(p, INTMSK))) {
+ gpio_rcar_read(p, p->intmsk))) {
offset = __ffs(pending);
gpio_rcar_write(p, INTCLR, BIT(offset));
generic_handle_irq(irq_find_mapping(p->gpio_chip.irq.domain,
@@ -427,6 +431,14 @@ static int gpio_rcar_parse_dt(struct gpio_rcar_priv *p, unsigned int *npins)
*npins = RCAR_MAX_GPIO_PER_BANK;
}
+ if (of_get_property(np, "use-alternative-interrupt", NULL)) {
+ p->intmsk = INTMSKS;
+ p->mskclr = MSKCLRS;
+ } else {
+ p->intmsk = INTMSK;
+ p->mskclr = MSKCLR;
+ }
+
return 0;
}
@@ -544,7 +556,7 @@ static int gpio_rcar_suspend(struct device *dev)
p->bank_info.iointsel = gpio_rcar_read(p, IOINTSEL);
p->bank_info.inoutsel = gpio_rcar_read(p, INOUTSEL);
p->bank_info.outdt = gpio_rcar_read(p, OUTDT);
- p->bank_info.intmsk = gpio_rcar_read(p, INTMSK);
+ p->bank_info.intmsk = gpio_rcar_read(p, p->intmsk);
p->bank_info.posneg = gpio_rcar_read(p, POSNEG);
p->bank_info.edglevel = gpio_rcar_read(p, EDGLEVEL);
if (p->has_both_edge_trigger)
@@ -586,7 +598,7 @@ static int gpio_rcar_resume(struct device *dev)
!!(p->bank_info.bothedge & mask));
if (p->bank_info.intmsk & mask)
- gpio_rcar_write(p, MSKCLR, mask);
+ gpio_rcar_write(p, p->mskclr, mask);
}
}