aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpio/gpiolib.c
diff options
context:
space:
mode:
authorLinus Walleij <linus.walleij@linaro.org>2014-03-25 05:40:18 -0400
committerLinus Walleij <linus.walleij@linaro.org>2014-03-26 05:31:21 -0400
commit1425052097b53de841e064dc190a9009480c208c (patch)
tree828f6a7bf6e5903149ea1d34ae9c7ba14a9a6fd8 /drivers/gpio/gpiolib.c
parent8f18bcfcd2bc30cb9a5924a6b4af49c8388bc785 (diff)
gpio: add IRQ chip helpers in gpiolib
This provides a function gpiochip_irqchip_add() to set up an irqchip for a GPIO controller, and a function gpiochip_set_chained_irqchip() to chain it to a parent irqchip. Most GPIOs are of the type where a number of lines form a cascaded interrupt controller chained onto the primary system interrupt controller (or further down the chain) so let's add this helper and factor the code to request the lines to be used as IRQs, the .to_irq() function and the irqdomain into the core as well. Acked-by: Thomas Gleixner <tglx@linutronix.de> Acked-by: Alexandre Courbot <acourbot@nvidia.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/gpio/gpiolib.c')
-rw-r--r--drivers/gpio/gpiolib.c188
1 files changed, 188 insertions, 0 deletions
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 584d2b465f84..f41cb4f3d715 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -1254,6 +1254,9 @@ fail:
1254} 1254}
1255EXPORT_SYMBOL_GPL(gpiochip_add); 1255EXPORT_SYMBOL_GPL(gpiochip_add);
1256 1256
1257/* Forward-declaration */
1258static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip);
1259
1257/** 1260/**
1258 * gpiochip_remove() - unregister a gpio_chip 1261 * gpiochip_remove() - unregister a gpio_chip
1259 * @chip: the chip to unregister 1262 * @chip: the chip to unregister
@@ -1270,6 +1273,7 @@ int gpiochip_remove(struct gpio_chip *chip)
1270 1273
1271 spin_lock_irqsave(&gpio_lock, flags); 1274 spin_lock_irqsave(&gpio_lock, flags);
1272 1275
1276 gpiochip_irqchip_remove(chip);
1273 gpiochip_remove_pin_ranges(chip); 1277 gpiochip_remove_pin_ranges(chip);
1274 of_gpiochip_remove(chip); 1278 of_gpiochip_remove(chip);
1275 1279
@@ -1339,6 +1343,190 @@ static struct gpio_chip *find_chip_by_name(const char *name)
1339 return gpiochip_find((void *)name, gpiochip_match_name); 1343 return gpiochip_find((void *)name, gpiochip_match_name);
1340} 1344}
1341 1345
1346#ifdef CONFIG_GPIOLIB_IRQCHIP
1347
1348/*
1349 * The following is irqchip helper code for gpiochips.
1350 */
1351
1352/**
1353 * gpiochip_add_chained_irqchip() - adds a chained irqchip to a gpiochip
1354 * @gpiochip: the gpiochip to add the irqchip to
1355 * @irqchip: the irqchip to add to the gpiochip
1356 * @parent_irq: the irq number corresponding to the parent IRQ for this
1357 * chained irqchip
1358 * @parent_handler: the parent interrupt handler for the accumulated IRQ
1359 * coming out of the gpiochip
1360 */
1361void gpiochip_set_chained_irqchip(struct gpio_chip *gpiochip,
1362 struct irq_chip *irqchip,
1363 int parent_irq,
1364 irq_flow_handler_t parent_handler)
1365{
1366 irq_set_chained_handler(parent_irq, parent_handler);
1367 /*
1368 * The parent irqchip is already using the chip_data for this
1369 * irqchip, so our callbacks simply use the handler_data.
1370 */
1371 irq_set_handler_data(parent_irq, gpiochip);
1372}
1373EXPORT_SYMBOL_GPL(gpiochip_set_chained_irqchip);
1374
1375/**
1376 * gpiochip_irq_map() - maps an IRQ into a GPIO irqchip
1377 * @d: the irqdomain used by this irqchip
1378 * @irq: the global irq number used by this GPIO irqchip irq
1379 * @hwirq: the local IRQ/GPIO line offset on this gpiochip
1380 *
1381 * This function will set up the mapping for a certain IRQ line on a
1382 * gpiochip by assigning the gpiochip as chip data, and using the irqchip
1383 * stored inside the gpiochip.
1384 */
1385static int gpiochip_irq_map(struct irq_domain *d, unsigned int irq,
1386 irq_hw_number_t hwirq)
1387{
1388 struct gpio_chip *chip = d->host_data;
1389
1390 irq_set_chip_and_handler(irq, chip->irqchip, chip->irq_handler);
1391 irq_set_chip_data(irq, chip);
1392#ifdef CONFIG_ARM
1393 set_irq_flags(irq, IRQF_VALID);
1394#else
1395 irq_set_noprobe(irq);
1396#endif
1397 irq_set_irq_type(irq, chip->irq_default_type);
1398
1399 return 0;
1400}
1401
1402static const struct irq_domain_ops gpiochip_domain_ops = {
1403 .map = gpiochip_irq_map,
1404 /* Virtually all GPIO irqchips are twocell:ed */
1405 .xlate = irq_domain_xlate_twocell,
1406};
1407
1408static int gpiochip_irq_reqres(struct irq_data *d)
1409{
1410 struct gpio_chip *chip = irq_data_get_irq_chip_data(d);
1411
1412 if (gpio_lock_as_irq(chip, d->hwirq)) {
1413 chip_err(chip,
1414 "unable to lock HW IRQ %lu for IRQ\n",
1415 d->hwirq);
1416 return -EINVAL;
1417 }
1418 return 0;
1419}
1420
1421static void gpiochip_irq_relres(struct irq_data *d)
1422{
1423 struct gpio_chip *chip = irq_data_get_irq_chip_data(d);
1424
1425 gpio_unlock_as_irq(chip, d->hwirq);
1426}
1427
1428static int gpiochip_to_irq(struct gpio_chip *chip, unsigned offset)
1429{
1430 return irq_find_mapping(chip->irqdomain, offset);
1431}
1432
1433/**
1434 * gpiochip_irqchip_remove() - removes an irqchip added to a gpiochip
1435 * @gpiochip: the gpiochip to remove the irqchip from
1436 *
1437 * This is called only from gpiochip_remove()
1438 */
1439static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip)
1440{
1441 if (gpiochip->irqdomain)
1442 irq_domain_remove(gpiochip->irqdomain);
1443
1444 if (gpiochip->irqchip) {
1445 gpiochip->irqchip->irq_request_resources = NULL;
1446 gpiochip->irqchip->irq_release_resources = NULL;
1447 gpiochip->irqchip = NULL;
1448 }
1449}
1450
1451/**
1452 * gpiochip_irqchip_add() - adds an irqchip to a gpiochip
1453 * @gpiochip: the gpiochip to add the irqchip to
1454 * @irqchip: the irqchip to add to the gpiochip
1455 * @first_irq: if not dynamically assigned, the base (first) IRQ to
1456 * allocate gpiochip irqs from
1457 * @handler: the irq handler to use (often a predefined irq core function)
1458 * @type: the default type for IRQs on this irqchip
1459 *
1460 * This function closely associates a certain irqchip with a certain
1461 * gpiochip, providing an irq domain to translate the local IRQs to
1462 * global irqs in the gpiolib core, and making sure that the gpiochip
1463 * is passed as chip data to all related functions. Driver callbacks
1464 * need to use container_of() to get their local state containers back
1465 * from the gpiochip passed as chip data. An irqdomain will be stored
1466 * in the gpiochip that shall be used by the driver to handle IRQ number
1467 * translation. The gpiochip will need to be initialized and registered
1468 * before calling this function.
1469 *
1470 * This function will handle two cell:ed simple IRQs. Everything else
1471 * need to be open coded.
1472 */
1473int gpiochip_irqchip_add(struct gpio_chip *gpiochip,
1474 struct irq_chip *irqchip,
1475 unsigned int first_irq,
1476 irq_flow_handler_t handler,
1477 unsigned int type)
1478{
1479 struct device_node *of_node;
1480 unsigned int offset;
1481
1482 if (!gpiochip || !irqchip)
1483 return -EINVAL;
1484
1485 if (!gpiochip->dev) {
1486 pr_err("missing gpiochip .dev parent pointer\n");
1487 return -EINVAL;
1488 }
1489 of_node = gpiochip->dev->of_node;
1490#ifdef CONFIG_OF_GPIO
1491 /*
1492 * If the gpiochip has an assigned OF node this takes precendence
1493 * FIXME: get rid of this and use gpiochip->dev->of_node everywhere
1494 */
1495 if (gpiochip->of_node)
1496 of_node = gpiochip->of_node;
1497#endif
1498 gpiochip->irqchip = irqchip;
1499 gpiochip->irq_handler = handler;
1500 gpiochip->irq_default_type = type;
1501 gpiochip->to_irq = gpiochip_to_irq;
1502 gpiochip->irqdomain = irq_domain_add_simple(of_node,
1503 gpiochip->ngpio, first_irq,
1504 &gpiochip_domain_ops, gpiochip);
1505 if (!gpiochip->irqdomain) {
1506 gpiochip->irqchip = NULL;
1507 return -EINVAL;
1508 }
1509 irqchip->irq_request_resources = gpiochip_irq_reqres;
1510 irqchip->irq_release_resources = gpiochip_irq_relres;
1511
1512 /*
1513 * Prepare the mapping since the irqchip shall be orthogonal to
1514 * any gpiochip calls. If the first_irq was zero, this is
1515 * necessary to allocate descriptors for all IRQs.
1516 */
1517 for (offset = 0; offset < gpiochip->ngpio; offset++)
1518 irq_create_mapping(gpiochip->irqdomain, offset);
1519
1520 return 0;
1521}
1522EXPORT_SYMBOL_GPL(gpiochip_irqchip_add);
1523
1524#else /* CONFIG_GPIOLIB_IRQCHIP */
1525
1526static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip) {}
1527
1528#endif /* CONFIG_GPIOLIB_IRQCHIP */
1529
1342#ifdef CONFIG_PINCTRL 1530#ifdef CONFIG_PINCTRL
1343 1531
1344/** 1532/**