| .. | .. |
|---|
| 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) |
|---|
| .. | .. |
|---|
| 418 | 417 | { |
|---|
| 419 | 418 | int ret = 0; |
|---|
| 420 | 419 | u32 pin_reg, pin_reg_irq_en, mask; |
|---|
| 421 | | - unsigned long flags, irq_flags; |
|---|
| 420 | + unsigned long flags; |
|---|
| 422 | 421 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); |
|---|
| 423 | 422 | struct amd_gpio *gpio_dev = gpiochip_get_data(gc); |
|---|
| 424 | 423 | |
|---|
| 425 | 424 | raw_spin_lock_irqsave(&gpio_dev->lock, flags); |
|---|
| 426 | 425 | 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 | 426 | |
|---|
| 437 | 427 | switch (type & IRQ_TYPE_SENSE_MASK) { |
|---|
| 438 | 428 | case IRQ_TYPE_EDGE_RISING: |
|---|
| .. | .. |
|---|
| 482 | 472 | /* |
|---|
| 483 | 473 | * If WAKE_INT_MASTER_REG.MaskStsEn is set, a software write to the |
|---|
| 484 | 474 | * debounce registers of any GPIO will block wake/interrupt status |
|---|
| 485 | | - * generation for *all* GPIOs for a lenght of time that depends on |
|---|
| 475 | + * generation for *all* GPIOs for a length of time that depends on |
|---|
| 486 | 476 | * WAKE_INT_MASTER_REG.MaskStsLength[11:0]. During this period the |
|---|
| 487 | 477 | * INTERRUPT_ENABLE bit will read as 0. |
|---|
| 488 | 478 | * |
|---|
| .. | .. |
|---|
| 774 | 764 | .pin_config_group_set = amd_pinconf_group_set, |
|---|
| 775 | 765 | }; |
|---|
| 776 | 766 | |
|---|
| 767 | +static void amd_gpio_irq_init(struct amd_gpio *gpio_dev) |
|---|
| 768 | +{ |
|---|
| 769 | + struct pinctrl_desc *desc = gpio_dev->pctrl->desc; |
|---|
| 770 | + unsigned long flags; |
|---|
| 771 | + u32 pin_reg, mask; |
|---|
| 772 | + int i; |
|---|
| 773 | + |
|---|
| 774 | + mask = BIT(WAKE_CNTRL_OFF_S0I3) | BIT(WAKE_CNTRL_OFF_S3) | |
|---|
| 775 | + BIT(INTERRUPT_MASK_OFF) | BIT(INTERRUPT_ENABLE_OFF) | |
|---|
| 776 | + BIT(WAKE_CNTRL_OFF_S4); |
|---|
| 777 | + |
|---|
| 778 | + for (i = 0; i < desc->npins; i++) { |
|---|
| 779 | + int pin = desc->pins[i].number; |
|---|
| 780 | + const struct pin_desc *pd = pin_desc_get(gpio_dev->pctrl, pin); |
|---|
| 781 | + |
|---|
| 782 | + if (!pd) |
|---|
| 783 | + continue; |
|---|
| 784 | + |
|---|
| 785 | + raw_spin_lock_irqsave(&gpio_dev->lock, flags); |
|---|
| 786 | + |
|---|
| 787 | + pin_reg = readl(gpio_dev->base + i * 4); |
|---|
| 788 | + pin_reg &= ~mask; |
|---|
| 789 | + writel(pin_reg, gpio_dev->base + i * 4); |
|---|
| 790 | + |
|---|
| 791 | + raw_spin_unlock_irqrestore(&gpio_dev->lock, flags); |
|---|
| 792 | + } |
|---|
| 793 | +} |
|---|
| 794 | + |
|---|
| 777 | 795 | #ifdef CONFIG_PM_SLEEP |
|---|
| 778 | 796 | static bool amd_gpio_should_save(struct amd_gpio *gpio_dev, unsigned int pin) |
|---|
| 779 | 797 | { |
|---|
| .. | .. |
|---|
| 795 | 813 | |
|---|
| 796 | 814 | static int amd_gpio_suspend(struct device *dev) |
|---|
| 797 | 815 | { |
|---|
| 798 | | - struct platform_device *pdev = to_platform_device(dev); |
|---|
| 799 | | - struct amd_gpio *gpio_dev = platform_get_drvdata(pdev); |
|---|
| 816 | + struct amd_gpio *gpio_dev = dev_get_drvdata(dev); |
|---|
| 800 | 817 | struct pinctrl_desc *desc = gpio_dev->pctrl->desc; |
|---|
| 818 | + unsigned long flags; |
|---|
| 801 | 819 | int i; |
|---|
| 802 | 820 | |
|---|
| 803 | 821 | for (i = 0; i < desc->npins; i++) { |
|---|
| .. | .. |
|---|
| 806 | 824 | if (!amd_gpio_should_save(gpio_dev, pin)) |
|---|
| 807 | 825 | continue; |
|---|
| 808 | 826 | |
|---|
| 809 | | - gpio_dev->saved_regs[i] = readl(gpio_dev->base + pin*4); |
|---|
| 827 | + raw_spin_lock_irqsave(&gpio_dev->lock, flags); |
|---|
| 828 | + gpio_dev->saved_regs[i] = readl(gpio_dev->base + pin * 4) & ~PIN_IRQ_PENDING; |
|---|
| 829 | + raw_spin_unlock_irqrestore(&gpio_dev->lock, flags); |
|---|
| 810 | 830 | } |
|---|
| 811 | 831 | |
|---|
| 812 | 832 | return 0; |
|---|
| .. | .. |
|---|
| 814 | 834 | |
|---|
| 815 | 835 | static int amd_gpio_resume(struct device *dev) |
|---|
| 816 | 836 | { |
|---|
| 817 | | - struct platform_device *pdev = to_platform_device(dev); |
|---|
| 818 | | - struct amd_gpio *gpio_dev = platform_get_drvdata(pdev); |
|---|
| 837 | + struct amd_gpio *gpio_dev = dev_get_drvdata(dev); |
|---|
| 819 | 838 | struct pinctrl_desc *desc = gpio_dev->pctrl->desc; |
|---|
| 839 | + unsigned long flags; |
|---|
| 820 | 840 | int i; |
|---|
| 821 | 841 | |
|---|
| 822 | 842 | for (i = 0; i < desc->npins; i++) { |
|---|
| .. | .. |
|---|
| 825 | 845 | if (!amd_gpio_should_save(gpio_dev, pin)) |
|---|
| 826 | 846 | continue; |
|---|
| 827 | 847 | |
|---|
| 828 | | - writel(gpio_dev->saved_regs[i], gpio_dev->base + pin*4); |
|---|
| 848 | + raw_spin_lock_irqsave(&gpio_dev->lock, flags); |
|---|
| 849 | + gpio_dev->saved_regs[i] |= readl(gpio_dev->base + pin * 4) & PIN_IRQ_PENDING; |
|---|
| 850 | + writel(gpio_dev->saved_regs[i], gpio_dev->base + pin * 4); |
|---|
| 851 | + raw_spin_unlock_irqrestore(&gpio_dev->lock, flags); |
|---|
| 829 | 852 | } |
|---|
| 830 | 853 | |
|---|
| 831 | 854 | return 0; |
|---|
| .. | .. |
|---|
| 851 | 874 | int irq_base; |
|---|
| 852 | 875 | struct resource *res; |
|---|
| 853 | 876 | struct amd_gpio *gpio_dev; |
|---|
| 877 | + struct gpio_irq_chip *girq; |
|---|
| 854 | 878 | |
|---|
| 855 | 879 | gpio_dev = devm_kzalloc(&pdev->dev, |
|---|
| 856 | 880 | sizeof(struct amd_gpio), GFP_KERNEL); |
|---|
| .. | .. |
|---|
| 865 | 889 | return -EINVAL; |
|---|
| 866 | 890 | } |
|---|
| 867 | 891 | |
|---|
| 868 | | - gpio_dev->base = devm_ioremap_nocache(&pdev->dev, res->start, |
|---|
| 892 | + gpio_dev->base = devm_ioremap(&pdev->dev, res->start, |
|---|
| 869 | 893 | resource_size(res)); |
|---|
| 870 | 894 | if (!gpio_dev->base) |
|---|
| 871 | 895 | return -ENOMEM; |
|---|
| 872 | 896 | |
|---|
| 873 | 897 | 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); |
|---|
| 898 | + if (irq_base < 0) |
|---|
| 876 | 899 | return irq_base; |
|---|
| 877 | | - } |
|---|
| 878 | 900 | |
|---|
| 879 | 901 | #ifdef CONFIG_PM_SLEEP |
|---|
| 880 | 902 | gpio_dev->saved_regs = devm_kcalloc(&pdev->dev, amd_pinctrl_desc.npins, |
|---|
| .. | .. |
|---|
| 914 | 936 | return PTR_ERR(gpio_dev->pctrl); |
|---|
| 915 | 937 | } |
|---|
| 916 | 938 | |
|---|
| 939 | + /* Disable and mask interrupts */ |
|---|
| 940 | + amd_gpio_irq_init(gpio_dev); |
|---|
| 941 | + |
|---|
| 942 | + girq = &gpio_dev->gc.irq; |
|---|
| 943 | + girq->chip = &amd_gpio_irqchip; |
|---|
| 944 | + /* This will let us handle the parent IRQ in the driver */ |
|---|
| 945 | + girq->parent_handler = NULL; |
|---|
| 946 | + girq->num_parents = 0; |
|---|
| 947 | + girq->parents = NULL; |
|---|
| 948 | + girq->default_type = IRQ_TYPE_NONE; |
|---|
| 949 | + girq->handler = handle_simple_irq; |
|---|
| 950 | + |
|---|
| 917 | 951 | ret = gpiochip_add_data(&gpio_dev->gc, gpio_dev); |
|---|
| 918 | 952 | if (ret) |
|---|
| 919 | 953 | return ret; |
|---|
| .. | .. |
|---|
| 925 | 959 | goto out2; |
|---|
| 926 | 960 | } |
|---|
| 927 | 961 | |
|---|
| 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); |
|---|
| 962 | + ret = devm_request_irq(&pdev->dev, irq_base, amd_gpio_irq_handler, |
|---|
| 963 | + IRQF_SHARED, KBUILD_MODNAME, gpio_dev); |
|---|
| 941 | 964 | if (ret) |
|---|
| 942 | 965 | goto out2; |
|---|
| 943 | 966 | |
|---|
| .. | .. |
|---|
| 963 | 986 | return 0; |
|---|
| 964 | 987 | } |
|---|
| 965 | 988 | |
|---|
| 989 | +#ifdef CONFIG_ACPI |
|---|
| 966 | 990 | static const struct acpi_device_id amd_gpio_acpi_match[] = { |
|---|
| 967 | 991 | { "AMD0030", 0 }, |
|---|
| 968 | 992 | { "AMDI0030", 0}, |
|---|
| .. | .. |
|---|
| 970 | 994 | { }, |
|---|
| 971 | 995 | }; |
|---|
| 972 | 996 | MODULE_DEVICE_TABLE(acpi, amd_gpio_acpi_match); |
|---|
| 997 | +#endif |
|---|
| 973 | 998 | |
|---|
| 974 | 999 | static struct platform_driver amd_gpio_driver = { |
|---|
| 975 | 1000 | .driver = { |
|---|