aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpio/gpiolib.c
diff options
context:
space:
mode:
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/**