aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pinctrl/intel
diff options
context:
space:
mode:
authorMika Westerberg <mika.westerberg@linux.intel.com>2015-05-12 06:35:37 -0400
committerLinus Walleij <linus.walleij@linaro.org>2015-05-12 07:54:32 -0400
commite6c906dedb8a332ece0e789980eef340fdcd9e20 (patch)
treefeb3ee45359a9c96a45309887066c4b315d8f16e /drivers/pinctrl/intel
parent030bbdbf4c833bc69f502eae58498bc5572db736 (diff)
pinctrl: cherryview: Read triggering type from HW if not set when requested
If a driver does not set interrupt triggering type when it calls request_irq(), it means use the pin as the hardware/firmware has configured it. There are some drivers doing this. One example is drivers/input/serio/i8042.c that requests the interrupt like: error = request_irq(I8042_KBD_IRQ, i8042_interrupt, IRQF_SHARED, "i8042", i8042_platform_device); It assumes the interrupt is already properly configured. This is true in case of interrupts connected to the IO-APIC. However, some Intel Braswell/Cherryview based machines use a GPIO here instead for the internal keyboard controller. This is a problem because even if the pin/interrupt is properly configured, the irqchip ->irq_set_type() will never be called as the triggering flags are 0. Because of that we do not have correct interrupt flow handler set for the interrupt. Fix this by adding a custom ->irq_startup() that checks if the interrupt has no triggering type set and in that case read the type directly from the hardware and install correct flow handler along with the mapping. Reported-by: Jagadish Krishnamoorthy <jagadish.krishnamoorthy@intel.com> Reported-by: Freddy Paul <freddy.paul@intel.com> Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/pinctrl/intel')
-rw-r--r--drivers/pinctrl/intel/pinctrl-cherryview.c44
1 files changed, 44 insertions, 0 deletions
diff --git a/drivers/pinctrl/intel/pinctrl-cherryview.c b/drivers/pinctrl/intel/pinctrl-cherryview.c
index 82f691eeeec4..732ff757a95f 100644
--- a/drivers/pinctrl/intel/pinctrl-cherryview.c
+++ b/drivers/pinctrl/intel/pinctrl-cherryview.c
@@ -1292,6 +1292,49 @@ static void chv_gpio_irq_unmask(struct irq_data *d)
1292 chv_gpio_irq_mask_unmask(d, false); 1292 chv_gpio_irq_mask_unmask(d, false);
1293} 1293}
1294 1294
1295static unsigned chv_gpio_irq_startup(struct irq_data *d)
1296{
1297 /*
1298 * Check if the interrupt has been requested with 0 as triggering
1299 * type. In that case it is assumed that the current values
1300 * programmed to the hardware are used (e.g BIOS configured
1301 * defaults).
1302 *
1303 * In that case ->irq_set_type() will never be called so we need to
1304 * read back the values from hardware now, set correct flow handler
1305 * and update mappings before the interrupt is being used.
1306 */
1307 if (irqd_get_trigger_type(d) == IRQ_TYPE_NONE) {
1308 struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
1309 struct chv_pinctrl *pctrl = gpiochip_to_pinctrl(gc);
1310 unsigned offset = irqd_to_hwirq(d);
1311 int pin = chv_gpio_offset_to_pin(pctrl, offset);
1312 irq_flow_handler_t handler;
1313 unsigned long flags;
1314 u32 intsel, value;
1315
1316 intsel = readl(chv_padreg(pctrl, pin, CHV_PADCTRL0));
1317 intsel &= CHV_PADCTRL0_INTSEL_MASK;
1318 intsel >>= CHV_PADCTRL0_INTSEL_SHIFT;
1319
1320 value = readl(chv_padreg(pctrl, pin, CHV_PADCTRL1));
1321 if (value & CHV_PADCTRL1_INTWAKECFG_LEVEL)
1322 handler = handle_level_irq;
1323 else
1324 handler = handle_edge_irq;
1325
1326 spin_lock_irqsave(&pctrl->lock, flags);
1327 if (!pctrl->intr_lines[intsel]) {
1328 __irq_set_handler_locked(d->irq, handler);
1329 pctrl->intr_lines[intsel] = offset;
1330 }
1331 spin_unlock_irqrestore(&pctrl->lock, flags);
1332 }
1333
1334 chv_gpio_irq_unmask(d);
1335 return 0;
1336}
1337
1295static int chv_gpio_irq_type(struct irq_data *d, unsigned type) 1338static int chv_gpio_irq_type(struct irq_data *d, unsigned type)
1296{ 1339{
1297 struct gpio_chip *gc = irq_data_get_irq_chip_data(d); 1340 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)
1357 1400
1358static struct irq_chip chv_gpio_irqchip = { 1401static struct irq_chip chv_gpio_irqchip = {
1359 .name = "chv-gpio", 1402 .name = "chv-gpio",
1403 .irq_startup = chv_gpio_irq_startup,
1360 .irq_ack = chv_gpio_irq_ack, 1404 .irq_ack = chv_gpio_irq_ack,
1361 .irq_mask = chv_gpio_irq_mask, 1405 .irq_mask = chv_gpio_irq_mask,
1362 .irq_unmask = chv_gpio_irq_unmask, 1406 .irq_unmask = chv_gpio_irq_unmask,