.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * GPIO driver for AMD |
---|
3 | 4 | * |
---|
.. | .. |
---|
5 | 6 | * Authors: Ken Xue <Ken.Xue@amd.com> |
---|
6 | 7 | * Wu, Jeff <Jeff.Wu@amd.com> |
---|
7 | 8 | * |
---|
8 | | - * This program is free software; you can redistribute it and/or modify it |
---|
9 | | - * under the terms and conditions of the GNU General Public License, |
---|
10 | | - * version 2, as published by the Free Software Foundation. |
---|
11 | | - * |
---|
12 | 9 | * Contact Information: Nehal Shah <Nehal-bakulchandra.Shah@amd.com> |
---|
13 | 10 | * Shyam Sundar S K <Shyam-sundar.S-k@amd.com> |
---|
14 | | - * |
---|
15 | 11 | */ |
---|
16 | 12 | |
---|
17 | 13 | #include <linux/err.h> |
---|
.. | .. |
---|
24 | 20 | #include <linux/errno.h> |
---|
25 | 21 | #include <linux/log2.h> |
---|
26 | 22 | #include <linux/io.h> |
---|
27 | | -#include <linux/gpio.h> |
---|
| 23 | +#include <linux/gpio/driver.h> |
---|
28 | 24 | #include <linux/slab.h> |
---|
29 | 25 | #include <linux/platform_device.h> |
---|
30 | 26 | #include <linux/mutex.h> |
---|
.. | .. |
---|
50 | 46 | pin_reg = readl(gpio_dev->base + offset * 4); |
---|
51 | 47 | raw_spin_unlock_irqrestore(&gpio_dev->lock, flags); |
---|
52 | 48 | |
---|
53 | | - return !(pin_reg & BIT(OUTPUT_ENABLE_OFF)); |
---|
| 49 | + if (pin_reg & BIT(OUTPUT_ENABLE_OFF)) |
---|
| 50 | + return GPIO_LINE_DIRECTION_OUT; |
---|
| 51 | + |
---|
| 52 | + return GPIO_LINE_DIRECTION_IN; |
---|
54 | 53 | } |
---|
55 | 54 | |
---|
56 | 55 | static int amd_gpio_direction_input(struct gpio_chip *gc, unsigned offset) |
---|
.. | .. |
---|
127 | 126 | struct amd_gpio *gpio_dev = gpiochip_get_data(gc); |
---|
128 | 127 | |
---|
129 | 128 | raw_spin_lock_irqsave(&gpio_dev->lock, flags); |
---|
| 129 | + |
---|
| 130 | + /* Use special handling for Pin0 debounce */ |
---|
| 131 | + if (offset == 0) { |
---|
| 132 | + pin_reg = readl(gpio_dev->base + WAKE_INT_MASTER_REG); |
---|
| 133 | + if (pin_reg & INTERNAL_GPIO0_DEBOUNCE) |
---|
| 134 | + debounce = 0; |
---|
| 135 | + } |
---|
| 136 | + |
---|
130 | 137 | pin_reg = readl(gpio_dev->base + offset * 4); |
---|
131 | 138 | |
---|
132 | 139 | if (debounce) { |
---|
.. | .. |
---|
182 | 189 | return ret; |
---|
183 | 190 | } |
---|
184 | 191 | |
---|
185 | | -static int amd_gpio_set_config(struct gpio_chip *gc, unsigned offset, |
---|
186 | | - unsigned long config) |
---|
187 | | -{ |
---|
188 | | - u32 debounce; |
---|
189 | | - |
---|
190 | | - if (pinconf_to_config_param(config) != PIN_CONFIG_INPUT_DEBOUNCE) |
---|
191 | | - return -ENOTSUPP; |
---|
192 | | - |
---|
193 | | - debounce = pinconf_to_config_argument(config); |
---|
194 | | - return amd_gpio_set_debounce(gc, offset, debounce); |
---|
195 | | -} |
---|
196 | | - |
---|
197 | 192 | #ifdef CONFIG_DEBUG_FS |
---|
198 | 193 | static void amd_gpio_dbg_show(struct seq_file *s, struct gpio_chip *gc) |
---|
199 | 194 | { |
---|
.. | .. |
---|
216 | 211 | char *output_value; |
---|
217 | 212 | char *output_enable; |
---|
218 | 213 | |
---|
| 214 | + seq_printf(s, "WAKE_INT_MASTER_REG: 0x%08x\n", readl(gpio_dev->base + WAKE_INT_MASTER_REG)); |
---|
219 | 215 | for (bank = 0; bank < gpio_dev->hwbank_num; bank++) { |
---|
220 | 216 | seq_printf(s, "GPIO bank%d\t", bank); |
---|
221 | 217 | |
---|
.. | .. |
---|
418 | 414 | { |
---|
419 | 415 | int ret = 0; |
---|
420 | 416 | u32 pin_reg, pin_reg_irq_en, mask; |
---|
421 | | - unsigned long flags, irq_flags; |
---|
| 417 | + unsigned long flags; |
---|
422 | 418 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); |
---|
423 | 419 | struct amd_gpio *gpio_dev = gpiochip_get_data(gc); |
---|
424 | 420 | |
---|
425 | 421 | raw_spin_lock_irqsave(&gpio_dev->lock, flags); |
---|
426 | 422 | pin_reg = readl(gpio_dev->base + (d->hwirq)*4); |
---|
427 | | - |
---|
428 | | - /* Ignore the settings coming from the client and |
---|
429 | | - * read the values from the ACPI tables |
---|
430 | | - * while setting the trigger type |
---|
431 | | - */ |
---|
432 | | - |
---|
433 | | - irq_flags = irq_get_trigger_type(d->irq); |
---|
434 | | - if (irq_flags != IRQ_TYPE_NONE) |
---|
435 | | - type = irq_flags; |
---|
436 | 423 | |
---|
437 | 424 | switch (type & IRQ_TYPE_SENSE_MASK) { |
---|
438 | 425 | case IRQ_TYPE_EDGE_RISING: |
---|
.. | .. |
---|
482 | 469 | /* |
---|
483 | 470 | * If WAKE_INT_MASTER_REG.MaskStsEn is set, a software write to the |
---|
484 | 471 | * debounce registers of any GPIO will block wake/interrupt status |
---|
485 | | - * generation for *all* GPIOs for a lenght of time that depends on |
---|
| 472 | + * generation for *all* GPIOs for a length of time that depends on |
---|
486 | 473 | * WAKE_INT_MASTER_REG.MaskStsLength[11:0]. During this period the |
---|
487 | 474 | * INTERRUPT_ENABLE bit will read as 0. |
---|
488 | 475 | * |
---|
.. | .. |
---|
666 | 653 | break; |
---|
667 | 654 | |
---|
668 | 655 | default: |
---|
669 | | - dev_err(&gpio_dev->pdev->dev, "Invalid config param %04x\n", |
---|
| 656 | + dev_dbg(&gpio_dev->pdev->dev, "Invalid config param %04x\n", |
---|
670 | 657 | param); |
---|
671 | 658 | return -ENOTSUPP; |
---|
672 | 659 | } |
---|
.. | .. |
---|
677 | 664 | } |
---|
678 | 665 | |
---|
679 | 666 | static int amd_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin, |
---|
680 | | - unsigned long *configs, unsigned num_configs) |
---|
| 667 | + unsigned long *configs, unsigned int num_configs) |
---|
681 | 668 | { |
---|
682 | 669 | int i; |
---|
683 | 670 | u32 arg; |
---|
.. | .. |
---|
719 | 706 | break; |
---|
720 | 707 | |
---|
721 | 708 | default: |
---|
722 | | - dev_err(&gpio_dev->pdev->dev, |
---|
| 709 | + dev_dbg(&gpio_dev->pdev->dev, |
---|
723 | 710 | "Invalid config param %04x\n", param); |
---|
724 | 711 | ret = -ENOTSUPP; |
---|
725 | 712 | } |
---|
.. | .. |
---|
767 | 754 | return 0; |
---|
768 | 755 | } |
---|
769 | 756 | |
---|
| 757 | +static int amd_gpio_set_config(struct gpio_chip *gc, unsigned int pin, |
---|
| 758 | + unsigned long config) |
---|
| 759 | +{ |
---|
| 760 | + struct amd_gpio *gpio_dev = gpiochip_get_data(gc); |
---|
| 761 | + |
---|
| 762 | + if (pinconf_to_config_param(config) == PIN_CONFIG_INPUT_DEBOUNCE) { |
---|
| 763 | + u32 debounce = pinconf_to_config_argument(config); |
---|
| 764 | + |
---|
| 765 | + return amd_gpio_set_debounce(gc, pin, debounce); |
---|
| 766 | + } |
---|
| 767 | + |
---|
| 768 | + return amd_pinconf_set(gpio_dev->pctrl, pin, &config, 1); |
---|
| 769 | +} |
---|
| 770 | + |
---|
770 | 771 | static const struct pinconf_ops amd_pinconf_ops = { |
---|
771 | 772 | .pin_config_get = amd_pinconf_get, |
---|
772 | 773 | .pin_config_set = amd_pinconf_set, |
---|
773 | 774 | .pin_config_group_get = amd_pinconf_group_get, |
---|
774 | 775 | .pin_config_group_set = amd_pinconf_group_set, |
---|
775 | 776 | }; |
---|
| 777 | + |
---|
| 778 | +static void amd_gpio_irq_init(struct amd_gpio *gpio_dev) |
---|
| 779 | +{ |
---|
| 780 | + struct pinctrl_desc *desc = gpio_dev->pctrl->desc; |
---|
| 781 | + unsigned long flags; |
---|
| 782 | + u32 pin_reg, mask; |
---|
| 783 | + int i; |
---|
| 784 | + |
---|
| 785 | + mask = BIT(WAKE_CNTRL_OFF_S0I3) | BIT(WAKE_CNTRL_OFF_S3) | |
---|
| 786 | + BIT(INTERRUPT_MASK_OFF) | BIT(INTERRUPT_ENABLE_OFF) | |
---|
| 787 | + BIT(WAKE_CNTRL_OFF_S4); |
---|
| 788 | + |
---|
| 789 | + for (i = 0; i < desc->npins; i++) { |
---|
| 790 | + int pin = desc->pins[i].number; |
---|
| 791 | + const struct pin_desc *pd = pin_desc_get(gpio_dev->pctrl, pin); |
---|
| 792 | + |
---|
| 793 | + if (!pd) |
---|
| 794 | + continue; |
---|
| 795 | + |
---|
| 796 | + raw_spin_lock_irqsave(&gpio_dev->lock, flags); |
---|
| 797 | + |
---|
| 798 | + pin_reg = readl(gpio_dev->base + pin * 4); |
---|
| 799 | + pin_reg &= ~mask; |
---|
| 800 | + writel(pin_reg, gpio_dev->base + pin * 4); |
---|
| 801 | + |
---|
| 802 | + raw_spin_unlock_irqrestore(&gpio_dev->lock, flags); |
---|
| 803 | + } |
---|
| 804 | +} |
---|
776 | 805 | |
---|
777 | 806 | #ifdef CONFIG_PM_SLEEP |
---|
778 | 807 | static bool amd_gpio_should_save(struct amd_gpio *gpio_dev, unsigned int pin) |
---|
.. | .. |
---|
795 | 824 | |
---|
796 | 825 | static int amd_gpio_suspend(struct device *dev) |
---|
797 | 826 | { |
---|
798 | | - struct platform_device *pdev = to_platform_device(dev); |
---|
799 | | - struct amd_gpio *gpio_dev = platform_get_drvdata(pdev); |
---|
| 827 | + struct amd_gpio *gpio_dev = dev_get_drvdata(dev); |
---|
800 | 828 | struct pinctrl_desc *desc = gpio_dev->pctrl->desc; |
---|
| 829 | + unsigned long flags; |
---|
801 | 830 | int i; |
---|
802 | 831 | |
---|
803 | 832 | for (i = 0; i < desc->npins; i++) { |
---|
.. | .. |
---|
806 | 835 | if (!amd_gpio_should_save(gpio_dev, pin)) |
---|
807 | 836 | continue; |
---|
808 | 837 | |
---|
809 | | - gpio_dev->saved_regs[i] = readl(gpio_dev->base + pin*4); |
---|
| 838 | + raw_spin_lock_irqsave(&gpio_dev->lock, flags); |
---|
| 839 | + gpio_dev->saved_regs[i] = readl(gpio_dev->base + pin * 4) & ~PIN_IRQ_PENDING; |
---|
| 840 | + raw_spin_unlock_irqrestore(&gpio_dev->lock, flags); |
---|
810 | 841 | } |
---|
811 | 842 | |
---|
812 | 843 | return 0; |
---|
.. | .. |
---|
814 | 845 | |
---|
815 | 846 | static int amd_gpio_resume(struct device *dev) |
---|
816 | 847 | { |
---|
817 | | - struct platform_device *pdev = to_platform_device(dev); |
---|
818 | | - struct amd_gpio *gpio_dev = platform_get_drvdata(pdev); |
---|
| 848 | + struct amd_gpio *gpio_dev = dev_get_drvdata(dev); |
---|
819 | 849 | struct pinctrl_desc *desc = gpio_dev->pctrl->desc; |
---|
| 850 | + unsigned long flags; |
---|
820 | 851 | int i; |
---|
821 | 852 | |
---|
822 | 853 | for (i = 0; i < desc->npins; i++) { |
---|
.. | .. |
---|
825 | 856 | if (!amd_gpio_should_save(gpio_dev, pin)) |
---|
826 | 857 | continue; |
---|
827 | 858 | |
---|
828 | | - writel(gpio_dev->saved_regs[i], gpio_dev->base + pin*4); |
---|
| 859 | + raw_spin_lock_irqsave(&gpio_dev->lock, flags); |
---|
| 860 | + gpio_dev->saved_regs[i] |= readl(gpio_dev->base + pin * 4) & PIN_IRQ_PENDING; |
---|
| 861 | + writel(gpio_dev->saved_regs[i], gpio_dev->base + pin * 4); |
---|
| 862 | + raw_spin_unlock_irqrestore(&gpio_dev->lock, flags); |
---|
829 | 863 | } |
---|
830 | 864 | |
---|
831 | 865 | return 0; |
---|
.. | .. |
---|
851 | 885 | int irq_base; |
---|
852 | 886 | struct resource *res; |
---|
853 | 887 | struct amd_gpio *gpio_dev; |
---|
| 888 | + struct gpio_irq_chip *girq; |
---|
854 | 889 | |
---|
855 | 890 | gpio_dev = devm_kzalloc(&pdev->dev, |
---|
856 | 891 | sizeof(struct amd_gpio), GFP_KERNEL); |
---|
.. | .. |
---|
865 | 900 | return -EINVAL; |
---|
866 | 901 | } |
---|
867 | 902 | |
---|
868 | | - gpio_dev->base = devm_ioremap_nocache(&pdev->dev, res->start, |
---|
| 903 | + gpio_dev->base = devm_ioremap(&pdev->dev, res->start, |
---|
869 | 904 | resource_size(res)); |
---|
870 | 905 | if (!gpio_dev->base) |
---|
871 | 906 | return -ENOMEM; |
---|
872 | 907 | |
---|
873 | 908 | irq_base = platform_get_irq(pdev, 0); |
---|
874 | | - if (irq_base < 0) { |
---|
875 | | - dev_err(&pdev->dev, "Failed to get gpio IRQ: %d\n", irq_base); |
---|
| 909 | + if (irq_base < 0) |
---|
876 | 910 | return irq_base; |
---|
877 | | - } |
---|
878 | 911 | |
---|
879 | 912 | #ifdef CONFIG_PM_SLEEP |
---|
880 | 913 | gpio_dev->saved_regs = devm_kcalloc(&pdev->dev, amd_pinctrl_desc.npins, |
---|
.. | .. |
---|
914 | 947 | return PTR_ERR(gpio_dev->pctrl); |
---|
915 | 948 | } |
---|
916 | 949 | |
---|
| 950 | + /* Disable and mask interrupts */ |
---|
| 951 | + amd_gpio_irq_init(gpio_dev); |
---|
| 952 | + |
---|
| 953 | + girq = &gpio_dev->gc.irq; |
---|
| 954 | + girq->chip = &amd_gpio_irqchip; |
---|
| 955 | + /* This will let us handle the parent IRQ in the driver */ |
---|
| 956 | + girq->parent_handler = NULL; |
---|
| 957 | + girq->num_parents = 0; |
---|
| 958 | + girq->parents = NULL; |
---|
| 959 | + girq->default_type = IRQ_TYPE_NONE; |
---|
| 960 | + girq->handler = handle_simple_irq; |
---|
| 961 | + |
---|
917 | 962 | ret = gpiochip_add_data(&gpio_dev->gc, gpio_dev); |
---|
918 | 963 | if (ret) |
---|
919 | 964 | return ret; |
---|
.. | .. |
---|
925 | 970 | goto out2; |
---|
926 | 971 | } |
---|
927 | 972 | |
---|
928 | | - ret = gpiochip_irqchip_add(&gpio_dev->gc, |
---|
929 | | - &amd_gpio_irqchip, |
---|
930 | | - 0, |
---|
931 | | - handle_simple_irq, |
---|
932 | | - IRQ_TYPE_NONE); |
---|
933 | | - if (ret) { |
---|
934 | | - dev_err(&pdev->dev, "could not add irqchip\n"); |
---|
935 | | - ret = -ENODEV; |
---|
936 | | - goto out2; |
---|
937 | | - } |
---|
938 | | - |
---|
939 | | - ret = devm_request_irq(&pdev->dev, irq_base, amd_gpio_irq_handler, 0, |
---|
940 | | - KBUILD_MODNAME, gpio_dev); |
---|
| 973 | + ret = devm_request_irq(&pdev->dev, irq_base, amd_gpio_irq_handler, |
---|
| 974 | + IRQF_SHARED, KBUILD_MODNAME, gpio_dev); |
---|
941 | 975 | if (ret) |
---|
942 | 976 | goto out2; |
---|
943 | 977 | |
---|
.. | .. |
---|
963 | 997 | return 0; |
---|
964 | 998 | } |
---|
965 | 999 | |
---|
| 1000 | +#ifdef CONFIG_ACPI |
---|
966 | 1001 | static const struct acpi_device_id amd_gpio_acpi_match[] = { |
---|
967 | 1002 | { "AMD0030", 0 }, |
---|
968 | 1003 | { "AMDI0030", 0}, |
---|
.. | .. |
---|
970 | 1005 | { }, |
---|
971 | 1006 | }; |
---|
972 | 1007 | MODULE_DEVICE_TABLE(acpi, amd_gpio_acpi_match); |
---|
| 1008 | +#endif |
---|
973 | 1009 | |
---|
974 | 1010 | static struct platform_driver amd_gpio_driver = { |
---|
975 | 1011 | .driver = { |
---|