diff options
-rw-r--r-- | Documentation/devicetree/bindings/gpio/gpio-omap.txt | 36 | ||||
-rw-r--r-- | drivers/gpio/gpio-omap.c | 121 |
2 files changed, 148 insertions, 9 deletions
diff --git a/Documentation/devicetree/bindings/gpio/gpio-omap.txt b/Documentation/devicetree/bindings/gpio/gpio-omap.txt new file mode 100644 index 000000000000..bff51a2fee1e --- /dev/null +++ b/Documentation/devicetree/bindings/gpio/gpio-omap.txt | |||
@@ -0,0 +1,36 @@ | |||
1 | OMAP GPIO controller bindings | ||
2 | |||
3 | Required properties: | ||
4 | - compatible: | ||
5 | - "ti,omap2-gpio" for OMAP2 controllers | ||
6 | - "ti,omap3-gpio" for OMAP3 controllers | ||
7 | - "ti,omap4-gpio" for OMAP4 controllers | ||
8 | - #gpio-cells : Should be two. | ||
9 | - first cell is the pin number | ||
10 | - second cell is used to specify optional parameters (unused) | ||
11 | - gpio-controller : Marks the device node as a GPIO controller. | ||
12 | - #interrupt-cells : Should be 2. | ||
13 | - interrupt-controller: Mark the device node as an interrupt controller | ||
14 | The first cell is the GPIO number. | ||
15 | The second cell is used to specify flags: | ||
16 | bits[3:0] trigger type and level flags: | ||
17 | 1 = low-to-high edge triggered. | ||
18 | 2 = high-to-low edge triggered. | ||
19 | 4 = active high level-sensitive. | ||
20 | 8 = active low level-sensitive. | ||
21 | |||
22 | OMAP specific properties: | ||
23 | - ti,hwmods: Name of the hwmod associated to the GPIO: | ||
24 | "gpio<X>", <X> being the 1-based instance number from the HW spec | ||
25 | |||
26 | |||
27 | Example: | ||
28 | |||
29 | gpio4: gpio4 { | ||
30 | compatible = "ti,omap4-gpio"; | ||
31 | ti,hwmods = "gpio4"; | ||
32 | #gpio-cells = <2>; | ||
33 | gpio-controller; | ||
34 | #interrupt-cells = <2>; | ||
35 | interrupt-controller; | ||
36 | }; | ||
diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index c3a9dc8fe732..bc2bd698ff2a 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c | |||
@@ -22,6 +22,9 @@ | |||
22 | #include <linux/device.h> | 22 | #include <linux/device.h> |
23 | #include <linux/pm_runtime.h> | 23 | #include <linux/pm_runtime.h> |
24 | #include <linux/pm.h> | 24 | #include <linux/pm.h> |
25 | #include <linux/of.h> | ||
26 | #include <linux/of_device.h> | ||
27 | #include <linux/irqdomain.h> | ||
25 | 28 | ||
26 | #include <mach/hardware.h> | 29 | #include <mach/hardware.h> |
27 | #include <asm/irq.h> | 30 | #include <asm/irq.h> |
@@ -52,7 +55,8 @@ struct gpio_bank { | |||
52 | struct list_head node; | 55 | struct list_head node; |
53 | void __iomem *base; | 56 | void __iomem *base; |
54 | u16 irq; | 57 | u16 irq; |
55 | u16 virtual_irq_start; | 58 | int irq_base; |
59 | struct irq_domain *domain; | ||
56 | u32 suspend_wakeup; | 60 | u32 suspend_wakeup; |
57 | u32 saved_wakeup; | 61 | u32 saved_wakeup; |
58 | u32 non_wakeup_gpios; | 62 | u32 non_wakeup_gpios; |
@@ -669,7 +673,7 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc) | |||
669 | if (!isr) | 673 | if (!isr) |
670 | break; | 674 | break; |
671 | 675 | ||
672 | gpio_irq = bank->virtual_irq_start; | 676 | gpio_irq = bank->irq_base; |
673 | for (; isr != 0; isr >>= 1, gpio_irq++) { | 677 | for (; isr != 0; isr >>= 1, gpio_irq++) { |
674 | gpio_index = GPIO_INDEX(bank, irq_to_gpio(gpio_irq)); | 678 | gpio_index = GPIO_INDEX(bank, irq_to_gpio(gpio_irq)); |
675 | 679 | ||
@@ -915,7 +919,7 @@ static int gpio_2irq(struct gpio_chip *chip, unsigned offset) | |||
915 | struct gpio_bank *bank; | 919 | struct gpio_bank *bank; |
916 | 920 | ||
917 | bank = container_of(chip, struct gpio_bank, chip); | 921 | bank = container_of(chip, struct gpio_bank, chip); |
918 | return bank->virtual_irq_start + offset; | 922 | return bank->irq_base + offset; |
919 | } | 923 | } |
920 | 924 | ||
921 | /*---------------------------------------------------------------------*/ | 925 | /*---------------------------------------------------------------------*/ |
@@ -1028,8 +1032,7 @@ static void __devinit omap_gpio_chip_init(struct gpio_bank *bank) | |||
1028 | 1032 | ||
1029 | gpiochip_add(&bank->chip); | 1033 | gpiochip_add(&bank->chip); |
1030 | 1034 | ||
1031 | for (j = bank->virtual_irq_start; | 1035 | for (j = bank->irq_base; j < bank->irq_base + bank->width; j++) { |
1032 | j < bank->virtual_irq_start + bank->width; j++) { | ||
1033 | irq_set_lockdep_class(j, &gpio_lock_class); | 1036 | irq_set_lockdep_class(j, &gpio_lock_class); |
1034 | irq_set_chip_data(j, bank); | 1037 | irq_set_chip_data(j, bank); |
1035 | if (bank->is_mpuio) { | 1038 | if (bank->is_mpuio) { |
@@ -1044,15 +1047,22 @@ static void __devinit omap_gpio_chip_init(struct gpio_bank *bank) | |||
1044 | irq_set_handler_data(bank->irq, bank); | 1047 | irq_set_handler_data(bank->irq, bank); |
1045 | } | 1048 | } |
1046 | 1049 | ||
1050 | static const struct of_device_id omap_gpio_match[]; | ||
1051 | |||
1047 | static int __devinit omap_gpio_probe(struct platform_device *pdev) | 1052 | static int __devinit omap_gpio_probe(struct platform_device *pdev) |
1048 | { | 1053 | { |
1049 | struct device *dev = &pdev->dev; | 1054 | struct device *dev = &pdev->dev; |
1055 | struct device_node *node = dev->of_node; | ||
1056 | const struct of_device_id *match; | ||
1050 | struct omap_gpio_platform_data *pdata; | 1057 | struct omap_gpio_platform_data *pdata; |
1051 | struct resource *res; | 1058 | struct resource *res; |
1052 | struct gpio_bank *bank; | 1059 | struct gpio_bank *bank; |
1053 | int ret = 0; | 1060 | int ret = 0; |
1054 | 1061 | ||
1055 | if (!dev->platform_data) | 1062 | match = of_match_device(of_match_ptr(omap_gpio_match), dev); |
1063 | |||
1064 | pdata = match ? match->data : dev->platform_data; | ||
1065 | if (!pdata) | ||
1056 | return -EINVAL; | 1066 | return -EINVAL; |
1057 | 1067 | ||
1058 | bank = devm_kzalloc(&pdev->dev, sizeof(struct gpio_bank), GFP_KERNEL); | 1068 | bank = devm_kzalloc(&pdev->dev, sizeof(struct gpio_bank), GFP_KERNEL); |
@@ -1068,9 +1078,6 @@ static int __devinit omap_gpio_probe(struct platform_device *pdev) | |||
1068 | } | 1078 | } |
1069 | 1079 | ||
1070 | bank->irq = res->start; | 1080 | bank->irq = res->start; |
1071 | |||
1072 | pdata = pdev->dev.platform_data; | ||
1073 | bank->virtual_irq_start = pdata->virtual_irq_start; | ||
1074 | bank->dev = dev; | 1081 | bank->dev = dev; |
1075 | bank->dbck_flag = pdata->dbck_flag; | 1082 | bank->dbck_flag = pdata->dbck_flag; |
1076 | bank->stride = pdata->bank_stride; | 1083 | bank->stride = pdata->bank_stride; |
@@ -1080,6 +1087,18 @@ static int __devinit omap_gpio_probe(struct platform_device *pdev) | |||
1080 | bank->loses_context = pdata->loses_context; | 1087 | bank->loses_context = pdata->loses_context; |
1081 | bank->get_context_loss_count = pdata->get_context_loss_count; | 1088 | bank->get_context_loss_count = pdata->get_context_loss_count; |
1082 | bank->regs = pdata->regs; | 1089 | bank->regs = pdata->regs; |
1090 | #ifdef CONFIG_OF_GPIO | ||
1091 | bank->chip.of_node = of_node_get(node); | ||
1092 | #endif | ||
1093 | |||
1094 | bank->irq_base = irq_alloc_descs(-1, 0, bank->width, 0); | ||
1095 | if (bank->irq_base < 0) { | ||
1096 | dev_err(dev, "Couldn't allocate IRQ numbers\n"); | ||
1097 | return -ENODEV; | ||
1098 | } | ||
1099 | |||
1100 | bank->domain = irq_domain_add_legacy(node, bank->width, bank->irq_base, | ||
1101 | 0, &irq_domain_simple_ops, NULL); | ||
1083 | 1102 | ||
1084 | if (bank->regs->set_dataout && bank->regs->clr_dataout) | 1103 | if (bank->regs->set_dataout && bank->regs->clr_dataout) |
1085 | bank->set_dataout = _set_gpio_dataout_reg; | 1104 | bank->set_dataout = _set_gpio_dataout_reg; |
@@ -1387,11 +1406,95 @@ static const struct dev_pm_ops gpio_pm_ops = { | |||
1387 | NULL) | 1406 | NULL) |
1388 | }; | 1407 | }; |
1389 | 1408 | ||
1409 | #if defined(CONFIG_OF) | ||
1410 | static struct omap_gpio_reg_offs omap2_gpio_regs = { | ||
1411 | .revision = OMAP24XX_GPIO_REVISION, | ||
1412 | .direction = OMAP24XX_GPIO_OE, | ||
1413 | .datain = OMAP24XX_GPIO_DATAIN, | ||
1414 | .dataout = OMAP24XX_GPIO_DATAOUT, | ||
1415 | .set_dataout = OMAP24XX_GPIO_SETDATAOUT, | ||
1416 | .clr_dataout = OMAP24XX_GPIO_CLEARDATAOUT, | ||
1417 | .irqstatus = OMAP24XX_GPIO_IRQSTATUS1, | ||
1418 | .irqstatus2 = OMAP24XX_GPIO_IRQSTATUS2, | ||
1419 | .irqenable = OMAP24XX_GPIO_IRQENABLE1, | ||
1420 | .irqenable2 = OMAP24XX_GPIO_IRQENABLE2, | ||
1421 | .set_irqenable = OMAP24XX_GPIO_SETIRQENABLE1, | ||
1422 | .clr_irqenable = OMAP24XX_GPIO_CLEARIRQENABLE1, | ||
1423 | .debounce = OMAP24XX_GPIO_DEBOUNCE_VAL, | ||
1424 | .debounce_en = OMAP24XX_GPIO_DEBOUNCE_EN, | ||
1425 | .ctrl = OMAP24XX_GPIO_CTRL, | ||
1426 | .wkup_en = OMAP24XX_GPIO_WAKE_EN, | ||
1427 | .leveldetect0 = OMAP24XX_GPIO_LEVELDETECT0, | ||
1428 | .leveldetect1 = OMAP24XX_GPIO_LEVELDETECT1, | ||
1429 | .risingdetect = OMAP24XX_GPIO_RISINGDETECT, | ||
1430 | .fallingdetect = OMAP24XX_GPIO_FALLINGDETECT, | ||
1431 | }; | ||
1432 | |||
1433 | static struct omap_gpio_reg_offs omap4_gpio_regs = { | ||
1434 | .revision = OMAP4_GPIO_REVISION, | ||
1435 | .direction = OMAP4_GPIO_OE, | ||
1436 | .datain = OMAP4_GPIO_DATAIN, | ||
1437 | .dataout = OMAP4_GPIO_DATAOUT, | ||
1438 | .set_dataout = OMAP4_GPIO_SETDATAOUT, | ||
1439 | .clr_dataout = OMAP4_GPIO_CLEARDATAOUT, | ||
1440 | .irqstatus = OMAP4_GPIO_IRQSTATUS0, | ||
1441 | .irqstatus2 = OMAP4_GPIO_IRQSTATUS1, | ||
1442 | .irqenable = OMAP4_GPIO_IRQSTATUSSET0, | ||
1443 | .irqenable2 = OMAP4_GPIO_IRQSTATUSSET1, | ||
1444 | .set_irqenable = OMAP4_GPIO_IRQSTATUSSET0, | ||
1445 | .clr_irqenable = OMAP4_GPIO_IRQSTATUSCLR0, | ||
1446 | .debounce = OMAP4_GPIO_DEBOUNCINGTIME, | ||
1447 | .debounce_en = OMAP4_GPIO_DEBOUNCENABLE, | ||
1448 | .ctrl = OMAP4_GPIO_CTRL, | ||
1449 | .wkup_en = OMAP4_GPIO_IRQWAKEN0, | ||
1450 | .leveldetect0 = OMAP4_GPIO_LEVELDETECT0, | ||
1451 | .leveldetect1 = OMAP4_GPIO_LEVELDETECT1, | ||
1452 | .risingdetect = OMAP4_GPIO_RISINGDETECT, | ||
1453 | .fallingdetect = OMAP4_GPIO_FALLINGDETECT, | ||
1454 | }; | ||
1455 | |||
1456 | static struct omap_gpio_platform_data omap2_pdata = { | ||
1457 | .regs = &omap2_gpio_regs, | ||
1458 | .bank_width = 32, | ||
1459 | .dbck_flag = false, | ||
1460 | }; | ||
1461 | |||
1462 | static struct omap_gpio_platform_data omap3_pdata = { | ||
1463 | .regs = &omap2_gpio_regs, | ||
1464 | .bank_width = 32, | ||
1465 | .dbck_flag = true, | ||
1466 | }; | ||
1467 | |||
1468 | static struct omap_gpio_platform_data omap4_pdata = { | ||
1469 | .regs = &omap4_gpio_regs, | ||
1470 | .bank_width = 32, | ||
1471 | .dbck_flag = true, | ||
1472 | }; | ||
1473 | |||
1474 | static const struct of_device_id omap_gpio_match[] = { | ||
1475 | { | ||
1476 | .compatible = "ti,omap4-gpio", | ||
1477 | .data = &omap4_pdata, | ||
1478 | }, | ||
1479 | { | ||
1480 | .compatible = "ti,omap3-gpio", | ||
1481 | .data = &omap3_pdata, | ||
1482 | }, | ||
1483 | { | ||
1484 | .compatible = "ti,omap2-gpio", | ||
1485 | .data = &omap2_pdata, | ||
1486 | }, | ||
1487 | { }, | ||
1488 | }; | ||
1489 | MODULE_DEVICE_TABLE(of, omap_gpio_match); | ||
1490 | #endif | ||
1491 | |||
1390 | static struct platform_driver omap_gpio_driver = { | 1492 | static struct platform_driver omap_gpio_driver = { |
1391 | .probe = omap_gpio_probe, | 1493 | .probe = omap_gpio_probe, |
1392 | .driver = { | 1494 | .driver = { |
1393 | .name = "omap_gpio", | 1495 | .name = "omap_gpio", |
1394 | .pm = &gpio_pm_ops, | 1496 | .pm = &gpio_pm_ops, |
1497 | .of_match_table = of_match_ptr(omap_gpio_match), | ||
1395 | }, | 1498 | }, |
1396 | }; | 1499 | }; |
1397 | 1500 | ||