.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | * Xilinx Zynq GPIO device driver |
---|
3 | 4 | * |
---|
4 | 5 | * Copyright (C) 2009 - 2014 Xilinx, Inc. |
---|
5 | | - * |
---|
6 | | - * This program is free software; you can redistribute it and/or modify it under |
---|
7 | | - * the terms of the GNU General Public License as published by the Free Software |
---|
8 | | - * Foundation; either version 2 of the License, or (at your option) any later |
---|
9 | | - * version. |
---|
10 | 6 | */ |
---|
11 | 7 | |
---|
12 | 8 | #include <linux/bitops.h> |
---|
.. | .. |
---|
14 | 10 | #include <linux/gpio/driver.h> |
---|
15 | 11 | #include <linux/init.h> |
---|
16 | 12 | #include <linux/interrupt.h> |
---|
| 13 | +#include <linux/spinlock.h> |
---|
17 | 14 | #include <linux/io.h> |
---|
18 | 15 | #include <linux/module.h> |
---|
19 | 16 | #include <linux/platform_device.h> |
---|
.. | .. |
---|
25 | 22 | /* Maximum banks */ |
---|
26 | 23 | #define ZYNQ_GPIO_MAX_BANK 4 |
---|
27 | 24 | #define ZYNQMP_GPIO_MAX_BANK 6 |
---|
| 25 | +#define VERSAL_GPIO_MAX_BANK 4 |
---|
| 26 | +#define PMC_GPIO_MAX_BANK 5 |
---|
| 27 | +#define VERSAL_UNUSED_BANKS 2 |
---|
28 | 28 | |
---|
29 | 29 | #define ZYNQ_GPIO_BANK0_NGPIO 32 |
---|
30 | 30 | #define ZYNQ_GPIO_BANK1_NGPIO 22 |
---|
.. | .. |
---|
99 | 99 | /* set to differentiate zynq from zynqmp, 0=zynqmp, 1=zynq */ |
---|
100 | 100 | #define ZYNQ_GPIO_QUIRK_IS_ZYNQ BIT(0) |
---|
101 | 101 | #define GPIO_QUIRK_DATA_RO_BUG BIT(1) |
---|
| 102 | +#define GPIO_QUIRK_VERSAL BIT(2) |
---|
102 | 103 | |
---|
103 | 104 | struct gpio_regs { |
---|
104 | 105 | u32 datamsw[ZYNQMP_GPIO_MAX_BANK]; |
---|
.. | .. |
---|
120 | 121 | * @irq: interrupt for the GPIO device |
---|
121 | 122 | * @p_data: pointer to platform data |
---|
122 | 123 | * @context: context registers |
---|
| 124 | + * @dirlock: lock used for direction in/out synchronization |
---|
123 | 125 | */ |
---|
124 | 126 | struct zynq_gpio { |
---|
125 | 127 | struct gpio_chip chip; |
---|
.. | .. |
---|
128 | 130 | int irq; |
---|
129 | 131 | const struct zynq_platform_data *p_data; |
---|
130 | 132 | struct gpio_regs context; |
---|
| 133 | + spinlock_t dirlock; /* lock */ |
---|
131 | 134 | }; |
---|
132 | 135 | |
---|
133 | 136 | /** |
---|
.. | .. |
---|
200 | 203 | gpio->p_data->bank_min[bank]; |
---|
201 | 204 | return; |
---|
202 | 205 | } |
---|
| 206 | + if (gpio->p_data->quirks & GPIO_QUIRK_VERSAL) |
---|
| 207 | + bank = bank + VERSAL_UNUSED_BANKS; |
---|
203 | 208 | } |
---|
204 | 209 | |
---|
205 | 210 | /* default */ |
---|
.. | .. |
---|
301 | 306 | { |
---|
302 | 307 | u32 reg; |
---|
303 | 308 | unsigned int bank_num, bank_pin_num; |
---|
| 309 | + unsigned long flags; |
---|
304 | 310 | struct zynq_gpio *gpio = gpiochip_get_data(chip); |
---|
305 | 311 | |
---|
306 | 312 | zynq_gpio_get_bank_pin(pin, &bank_num, &bank_pin_num, gpio); |
---|
.. | .. |
---|
314 | 320 | return -EINVAL; |
---|
315 | 321 | |
---|
316 | 322 | /* clear the bit in direction mode reg to set the pin as input */ |
---|
| 323 | + spin_lock_irqsave(&gpio->dirlock, flags); |
---|
317 | 324 | reg = readl_relaxed(gpio->base_addr + ZYNQ_GPIO_DIRM_OFFSET(bank_num)); |
---|
318 | 325 | reg &= ~BIT(bank_pin_num); |
---|
319 | 326 | writel_relaxed(reg, gpio->base_addr + ZYNQ_GPIO_DIRM_OFFSET(bank_num)); |
---|
| 327 | + spin_unlock_irqrestore(&gpio->dirlock, flags); |
---|
320 | 328 | |
---|
321 | 329 | return 0; |
---|
322 | 330 | } |
---|
.. | .. |
---|
338 | 346 | { |
---|
339 | 347 | u32 reg; |
---|
340 | 348 | unsigned int bank_num, bank_pin_num; |
---|
| 349 | + unsigned long flags; |
---|
341 | 350 | struct zynq_gpio *gpio = gpiochip_get_data(chip); |
---|
342 | 351 | |
---|
343 | 352 | zynq_gpio_get_bank_pin(pin, &bank_num, &bank_pin_num, gpio); |
---|
344 | 353 | |
---|
345 | 354 | /* set the GPIO pin as output */ |
---|
| 355 | + spin_lock_irqsave(&gpio->dirlock, flags); |
---|
346 | 356 | reg = readl_relaxed(gpio->base_addr + ZYNQ_GPIO_DIRM_OFFSET(bank_num)); |
---|
347 | 357 | reg |= BIT(bank_pin_num); |
---|
348 | 358 | writel_relaxed(reg, gpio->base_addr + ZYNQ_GPIO_DIRM_OFFSET(bank_num)); |
---|
.. | .. |
---|
351 | 361 | reg = readl_relaxed(gpio->base_addr + ZYNQ_GPIO_OUTEN_OFFSET(bank_num)); |
---|
352 | 362 | reg |= BIT(bank_pin_num); |
---|
353 | 363 | writel_relaxed(reg, gpio->base_addr + ZYNQ_GPIO_OUTEN_OFFSET(bank_num)); |
---|
| 364 | + spin_unlock_irqrestore(&gpio->dirlock, flags); |
---|
354 | 365 | |
---|
355 | 366 | /* set the state of the pin */ |
---|
356 | 367 | zynq_gpio_set_value(chip, pin, state); |
---|
.. | .. |
---|
364 | 375 | * |
---|
365 | 376 | * This function returns the direction of the specified GPIO. |
---|
366 | 377 | * |
---|
367 | | - * Return: 0 for output, 1 for input |
---|
| 378 | + * Return: GPIO_LINE_DIRECTION_OUT or GPIO_LINE_DIRECTION_IN |
---|
368 | 379 | */ |
---|
369 | 380 | static int zynq_gpio_get_direction(struct gpio_chip *chip, unsigned int pin) |
---|
370 | 381 | { |
---|
.. | .. |
---|
376 | 387 | |
---|
377 | 388 | reg = readl_relaxed(gpio->base_addr + ZYNQ_GPIO_DIRM_OFFSET(bank_num)); |
---|
378 | 389 | |
---|
379 | | - return !(reg & BIT(bank_pin_num)); |
---|
| 390 | + if (reg & BIT(bank_pin_num)) |
---|
| 391 | + return GPIO_LINE_DIRECTION_OUT; |
---|
| 392 | + |
---|
| 393 | + return GPIO_LINE_DIRECTION_IN; |
---|
380 | 394 | } |
---|
381 | 395 | |
---|
382 | 396 | /** |
---|
.. | .. |
---|
555 | 569 | return 0; |
---|
556 | 570 | } |
---|
557 | 571 | |
---|
| 572 | +static int zynq_gpio_irq_reqres(struct irq_data *d) |
---|
| 573 | +{ |
---|
| 574 | + struct gpio_chip *chip = irq_data_get_irq_chip_data(d); |
---|
| 575 | + int ret; |
---|
| 576 | + |
---|
| 577 | + ret = pm_runtime_resume_and_get(chip->parent); |
---|
| 578 | + if (ret < 0) |
---|
| 579 | + return ret; |
---|
| 580 | + |
---|
| 581 | + return gpiochip_reqres_irq(chip, d->hwirq); |
---|
| 582 | +} |
---|
| 583 | + |
---|
| 584 | +static void zynq_gpio_irq_relres(struct irq_data *d) |
---|
| 585 | +{ |
---|
| 586 | + struct gpio_chip *chip = irq_data_get_irq_chip_data(d); |
---|
| 587 | + |
---|
| 588 | + gpiochip_relres_irq(chip, d->hwirq); |
---|
| 589 | + pm_runtime_put(chip->parent); |
---|
| 590 | +} |
---|
| 591 | + |
---|
558 | 592 | /* irq chip descriptor */ |
---|
559 | 593 | static struct irq_chip zynq_gpio_level_irqchip = { |
---|
560 | 594 | .name = DRIVER_NAME, |
---|
.. | .. |
---|
564 | 598 | .irq_unmask = zynq_gpio_irq_unmask, |
---|
565 | 599 | .irq_set_type = zynq_gpio_set_irq_type, |
---|
566 | 600 | .irq_set_wake = zynq_gpio_set_wake, |
---|
| 601 | + .irq_request_resources = zynq_gpio_irq_reqres, |
---|
| 602 | + .irq_release_resources = zynq_gpio_irq_relres, |
---|
567 | 603 | .flags = IRQCHIP_EOI_THREADED | IRQCHIP_EOI_IF_HANDLED | |
---|
568 | 604 | IRQCHIP_MASK_ON_SUSPEND, |
---|
569 | 605 | }; |
---|
.. | .. |
---|
576 | 612 | .irq_unmask = zynq_gpio_irq_unmask, |
---|
577 | 613 | .irq_set_type = zynq_gpio_set_irq_type, |
---|
578 | 614 | .irq_set_wake = zynq_gpio_set_wake, |
---|
| 615 | + .irq_request_resources = zynq_gpio_irq_reqres, |
---|
| 616 | + .irq_release_resources = zynq_gpio_irq_relres, |
---|
579 | 617 | .flags = IRQCHIP_MASK_ON_SUSPEND, |
---|
580 | 618 | }; |
---|
581 | 619 | |
---|
.. | .. |
---|
624 | 662 | int_enb = readl_relaxed(gpio->base_addr + |
---|
625 | 663 | ZYNQ_GPIO_INTMASK_OFFSET(bank_num)); |
---|
626 | 664 | zynq_gpio_handle_bank_irq(gpio, bank_num, int_sts & ~int_enb); |
---|
| 665 | + if (gpio->p_data->quirks & GPIO_QUIRK_VERSAL) |
---|
| 666 | + bank_num = bank_num + VERSAL_UNUSED_BANKS; |
---|
627 | 667 | } |
---|
628 | 668 | |
---|
629 | 669 | chained_irq_exit(irqchip, desc); |
---|
.. | .. |
---|
653 | 693 | gpio->context.int_any[bank_num] = |
---|
654 | 694 | readl_relaxed(gpio->base_addr + |
---|
655 | 695 | ZYNQ_GPIO_INTANY_OFFSET(bank_num)); |
---|
| 696 | + if (gpio->p_data->quirks & GPIO_QUIRK_VERSAL) |
---|
| 697 | + bank_num = bank_num + VERSAL_UNUSED_BANKS; |
---|
656 | 698 | } |
---|
657 | 699 | } |
---|
658 | 700 | |
---|
.. | .. |
---|
684 | 726 | writel_relaxed(~(gpio->context.int_en[bank_num]), |
---|
685 | 727 | gpio->base_addr + |
---|
686 | 728 | ZYNQ_GPIO_INTEN_OFFSET(bank_num)); |
---|
| 729 | + if (gpio->p_data->quirks & GPIO_QUIRK_VERSAL) |
---|
| 730 | + bank_num = bank_num + VERSAL_UNUSED_BANKS; |
---|
687 | 731 | } |
---|
688 | 732 | } |
---|
689 | 733 | |
---|
.. | .. |
---|
691 | 735 | { |
---|
692 | 736 | struct zynq_gpio *gpio = dev_get_drvdata(dev); |
---|
693 | 737 | struct irq_data *data = irq_get_irq_data(gpio->irq); |
---|
| 738 | + |
---|
| 739 | + if (!data) { |
---|
| 740 | + dev_err(dev, "irq_get_irq_data() failed\n"); |
---|
| 741 | + return -EINVAL; |
---|
| 742 | + } |
---|
| 743 | + |
---|
| 744 | + if (!device_may_wakeup(dev)) |
---|
| 745 | + disable_irq(gpio->irq); |
---|
694 | 746 | |
---|
695 | 747 | if (!irqd_is_wakeup_set(data)) { |
---|
696 | 748 | zynq_gpio_save_context(gpio); |
---|
.. | .. |
---|
706 | 758 | struct irq_data *data = irq_get_irq_data(gpio->irq); |
---|
707 | 759 | int ret; |
---|
708 | 760 | |
---|
| 761 | + if (!data) { |
---|
| 762 | + dev_err(dev, "irq_get_irq_data() failed\n"); |
---|
| 763 | + return -EINVAL; |
---|
| 764 | + } |
---|
| 765 | + |
---|
| 766 | + if (!device_may_wakeup(dev)) |
---|
| 767 | + enable_irq(gpio->irq); |
---|
| 768 | + |
---|
709 | 769 | if (!irqd_is_wakeup_set(data)) { |
---|
710 | 770 | ret = pm_runtime_force_resume(dev); |
---|
711 | 771 | zynq_gpio_restore_context(gpio); |
---|
.. | .. |
---|
717 | 777 | |
---|
718 | 778 | static int __maybe_unused zynq_gpio_runtime_suspend(struct device *dev) |
---|
719 | 779 | { |
---|
720 | | - struct platform_device *pdev = to_platform_device(dev); |
---|
721 | | - struct zynq_gpio *gpio = platform_get_drvdata(pdev); |
---|
| 780 | + struct zynq_gpio *gpio = dev_get_drvdata(dev); |
---|
722 | 781 | |
---|
723 | 782 | clk_disable_unprepare(gpio->clk); |
---|
724 | 783 | |
---|
.. | .. |
---|
727 | 786 | |
---|
728 | 787 | static int __maybe_unused zynq_gpio_runtime_resume(struct device *dev) |
---|
729 | 788 | { |
---|
730 | | - struct platform_device *pdev = to_platform_device(dev); |
---|
731 | | - struct zynq_gpio *gpio = platform_get_drvdata(pdev); |
---|
| 789 | + struct zynq_gpio *gpio = dev_get_drvdata(dev); |
---|
732 | 790 | |
---|
733 | 791 | return clk_prepare_enable(gpio->clk); |
---|
734 | 792 | } |
---|
.. | .. |
---|
755 | 813 | SET_SYSTEM_SLEEP_PM_OPS(zynq_gpio_suspend, zynq_gpio_resume) |
---|
756 | 814 | SET_RUNTIME_PM_OPS(zynq_gpio_runtime_suspend, |
---|
757 | 815 | zynq_gpio_runtime_resume, NULL) |
---|
| 816 | +}; |
---|
| 817 | + |
---|
| 818 | +static const struct zynq_platform_data versal_gpio_def = { |
---|
| 819 | + .label = "versal_gpio", |
---|
| 820 | + .quirks = GPIO_QUIRK_VERSAL, |
---|
| 821 | + .ngpio = 58, |
---|
| 822 | + .max_bank = VERSAL_GPIO_MAX_BANK, |
---|
| 823 | + .bank_min[0] = 0, |
---|
| 824 | + .bank_max[0] = 25, /* 0 to 25 are connected to MIOs (26 pins) */ |
---|
| 825 | + .bank_min[3] = 26, |
---|
| 826 | + .bank_max[3] = 57, /* Bank 3 is connected to FMIOs (32 pins) */ |
---|
| 827 | +}; |
---|
| 828 | + |
---|
| 829 | +static const struct zynq_platform_data pmc_gpio_def = { |
---|
| 830 | + .label = "pmc_gpio", |
---|
| 831 | + .ngpio = 116, |
---|
| 832 | + .max_bank = PMC_GPIO_MAX_BANK, |
---|
| 833 | + .bank_min[0] = 0, |
---|
| 834 | + .bank_max[0] = 25, /* 0 to 25 are connected to MIOs (26 pins) */ |
---|
| 835 | + .bank_min[1] = 26, |
---|
| 836 | + .bank_max[1] = 51, /* Bank 1 are connected to MIOs (26 pins) */ |
---|
| 837 | + .bank_min[3] = 52, |
---|
| 838 | + .bank_max[3] = 83, /* Bank 3 is connected to EMIOs (32 pins) */ |
---|
| 839 | + .bank_min[4] = 84, |
---|
| 840 | + .bank_max[4] = 115, /* Bank 4 is connected to EMIOs (32 pins) */ |
---|
758 | 841 | }; |
---|
759 | 842 | |
---|
760 | 843 | static const struct zynq_platform_data zynqmp_gpio_def = { |
---|
.. | .. |
---|
794 | 877 | static const struct of_device_id zynq_gpio_of_match[] = { |
---|
795 | 878 | { .compatible = "xlnx,zynq-gpio-1.0", .data = &zynq_gpio_def }, |
---|
796 | 879 | { .compatible = "xlnx,zynqmp-gpio-1.0", .data = &zynqmp_gpio_def }, |
---|
| 880 | + { .compatible = "xlnx,versal-gpio-1.0", .data = &versal_gpio_def }, |
---|
| 881 | + { .compatible = "xlnx,pmc-gpio-1.0", .data = &pmc_gpio_def }, |
---|
797 | 882 | { /* end of table */ } |
---|
798 | 883 | }; |
---|
799 | 884 | MODULE_DEVICE_TABLE(of, zynq_gpio_of_match); |
---|
.. | .. |
---|
814 | 899 | int ret, bank_num; |
---|
815 | 900 | struct zynq_gpio *gpio; |
---|
816 | 901 | struct gpio_chip *chip; |
---|
817 | | - struct resource *res; |
---|
| 902 | + struct gpio_irq_chip *girq; |
---|
818 | 903 | const struct of_device_id *match; |
---|
819 | 904 | |
---|
820 | 905 | gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL); |
---|
.. | .. |
---|
829 | 914 | gpio->p_data = match->data; |
---|
830 | 915 | platform_set_drvdata(pdev, gpio); |
---|
831 | 916 | |
---|
832 | | - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
---|
833 | | - gpio->base_addr = devm_ioremap_resource(&pdev->dev, res); |
---|
| 917 | + gpio->base_addr = devm_platform_ioremap_resource(pdev, 0); |
---|
834 | 918 | if (IS_ERR(gpio->base_addr)) |
---|
835 | 919 | return PTR_ERR(gpio->base_addr); |
---|
836 | 920 | |
---|
837 | 921 | gpio->irq = platform_get_irq(pdev, 0); |
---|
838 | | - if (gpio->irq < 0) { |
---|
839 | | - dev_err(&pdev->dev, "invalid IRQ\n"); |
---|
| 922 | + if (gpio->irq < 0) |
---|
840 | 923 | return gpio->irq; |
---|
841 | | - } |
---|
842 | 924 | |
---|
843 | 925 | /* configure the gpio chip */ |
---|
844 | 926 | chip = &gpio->chip; |
---|
.. | .. |
---|
857 | 939 | |
---|
858 | 940 | /* Retrieve GPIO clock */ |
---|
859 | 941 | gpio->clk = devm_clk_get(&pdev->dev, NULL); |
---|
860 | | - if (IS_ERR(gpio->clk)) { |
---|
861 | | - dev_err(&pdev->dev, "input clock not found.\n"); |
---|
862 | | - return PTR_ERR(gpio->clk); |
---|
863 | | - } |
---|
| 942 | + if (IS_ERR(gpio->clk)) |
---|
| 943 | + return dev_err_probe(&pdev->dev, PTR_ERR(gpio->clk), "input clock not found.\n"); |
---|
| 944 | + |
---|
864 | 945 | ret = clk_prepare_enable(gpio->clk); |
---|
865 | 946 | if (ret) { |
---|
866 | 947 | dev_err(&pdev->dev, "Unable to enable clock.\n"); |
---|
867 | 948 | return ret; |
---|
868 | 949 | } |
---|
869 | 950 | |
---|
| 951 | + spin_lock_init(&gpio->dirlock); |
---|
| 952 | + |
---|
870 | 953 | pm_runtime_set_active(&pdev->dev); |
---|
871 | 954 | pm_runtime_enable(&pdev->dev); |
---|
872 | | - ret = pm_runtime_get_sync(&pdev->dev); |
---|
| 955 | + ret = pm_runtime_resume_and_get(&pdev->dev); |
---|
873 | 956 | if (ret < 0) |
---|
874 | 957 | goto err_pm_dis; |
---|
| 958 | + |
---|
| 959 | + /* disable interrupts for all banks */ |
---|
| 960 | + for (bank_num = 0; bank_num < gpio->p_data->max_bank; bank_num++) { |
---|
| 961 | + writel_relaxed(ZYNQ_GPIO_IXR_DISABLE_ALL, gpio->base_addr + |
---|
| 962 | + ZYNQ_GPIO_INTDIS_OFFSET(bank_num)); |
---|
| 963 | + if (gpio->p_data->quirks & GPIO_QUIRK_VERSAL) |
---|
| 964 | + bank_num = bank_num + VERSAL_UNUSED_BANKS; |
---|
| 965 | + } |
---|
| 966 | + |
---|
| 967 | + /* Set up the GPIO irqchip */ |
---|
| 968 | + girq = &chip->irq; |
---|
| 969 | + girq->chip = &zynq_gpio_edge_irqchip; |
---|
| 970 | + girq->parent_handler = zynq_gpio_irqhandler; |
---|
| 971 | + girq->num_parents = 1; |
---|
| 972 | + girq->parents = devm_kcalloc(&pdev->dev, 1, |
---|
| 973 | + sizeof(*girq->parents), |
---|
| 974 | + GFP_KERNEL); |
---|
| 975 | + if (!girq->parents) { |
---|
| 976 | + ret = -ENOMEM; |
---|
| 977 | + goto err_pm_put; |
---|
| 978 | + } |
---|
| 979 | + girq->parents[0] = gpio->irq; |
---|
| 980 | + girq->default_type = IRQ_TYPE_NONE; |
---|
| 981 | + girq->handler = handle_level_irq; |
---|
875 | 982 | |
---|
876 | 983 | /* report a bug if gpio chip registration fails */ |
---|
877 | 984 | ret = gpiochip_add_data(chip, gpio); |
---|
.. | .. |
---|
880 | 987 | goto err_pm_put; |
---|
881 | 988 | } |
---|
882 | 989 | |
---|
883 | | - /* disable interrupts for all banks */ |
---|
884 | | - for (bank_num = 0; bank_num < gpio->p_data->max_bank; bank_num++) |
---|
885 | | - writel_relaxed(ZYNQ_GPIO_IXR_DISABLE_ALL, gpio->base_addr + |
---|
886 | | - ZYNQ_GPIO_INTDIS_OFFSET(bank_num)); |
---|
887 | | - |
---|
888 | | - ret = gpiochip_irqchip_add(chip, &zynq_gpio_edge_irqchip, 0, |
---|
889 | | - handle_level_irq, IRQ_TYPE_NONE); |
---|
890 | | - if (ret) { |
---|
891 | | - dev_err(&pdev->dev, "Failed to add irq chip\n"); |
---|
892 | | - goto err_rm_gpiochip; |
---|
893 | | - } |
---|
894 | | - |
---|
895 | | - gpiochip_set_chained_irqchip(chip, &zynq_gpio_edge_irqchip, gpio->irq, |
---|
896 | | - zynq_gpio_irqhandler); |
---|
897 | | - |
---|
| 990 | + irq_set_status_flags(gpio->irq, IRQ_DISABLE_UNLAZY); |
---|
| 991 | + device_init_wakeup(&pdev->dev, 1); |
---|
898 | 992 | pm_runtime_put(&pdev->dev); |
---|
899 | 993 | |
---|
900 | 994 | return 0; |
---|
901 | 995 | |
---|
902 | | -err_rm_gpiochip: |
---|
903 | | - gpiochip_remove(chip); |
---|
904 | 996 | err_pm_put: |
---|
905 | 997 | pm_runtime_put(&pdev->dev); |
---|
906 | 998 | err_pm_dis: |
---|