diff options
77 files changed, 2438 insertions, 755 deletions
diff --git a/Documentation/devicetree/bindings/gpio/gateworks,pld-gpio.txt b/Documentation/devicetree/bindings/gpio/gateworks,pld-gpio.txt new file mode 100644 index 000000000000..6e81f8b755c5 --- /dev/null +++ b/Documentation/devicetree/bindings/gpio/gateworks,pld-gpio.txt | |||
| @@ -0,0 +1,20 @@ | |||
| 1 | Gateworks PLD GPIO controller bindings | ||
| 2 | |||
| 3 | The GPIO controller should be a child node on an I2C bus, | ||
| 4 | see: i2c/i2c.txt for details. | ||
| 5 | |||
| 6 | Required properties: | ||
| 7 | - compatible: Should be "gateworks,pld-gpio" | ||
| 8 | - reg: I2C slave address | ||
| 9 | - gpio-controller: Marks the device node as a GPIO controller. | ||
| 10 | - #gpio-cells: Should be <2>. The first cell is the gpio number and | ||
| 11 | the second cell is used to specify optional parameters. | ||
| 12 | |||
| 13 | Example: | ||
| 14 | |||
| 15 | pld@56 { | ||
| 16 | compatible = "gateworks,pld-gpio"; | ||
| 17 | reg = <0x56>; | ||
| 18 | gpio-controller; | ||
| 19 | #gpio-cells = <2>; | ||
| 20 | }; | ||
diff --git a/Documentation/devicetree/bindings/gpio/gpio-eic-sprd.txt b/Documentation/devicetree/bindings/gpio/gpio-eic-sprd.txt index 93d98d09d92b..54040a2bfe3a 100644 --- a/Documentation/devicetree/bindings/gpio/gpio-eic-sprd.txt +++ b/Documentation/devicetree/bindings/gpio/gpio-eic-sprd.txt | |||
| @@ -33,7 +33,7 @@ Required properties: | |||
| 33 | "sprd,sc9860-eic-latch", | 33 | "sprd,sc9860-eic-latch", |
| 34 | "sprd,sc9860-eic-async", | 34 | "sprd,sc9860-eic-async", |
| 35 | "sprd,sc9860-eic-sync", | 35 | "sprd,sc9860-eic-sync", |
| 36 | "sprd,sc27xx-eic". | 36 | "sprd,sc2731-eic". |
| 37 | - reg: Define the base and range of the I/O address space containing | 37 | - reg: Define the base and range of the I/O address space containing |
| 38 | the GPIO controller registers. | 38 | the GPIO controller registers. |
| 39 | - gpio-controller: Marks the device node as a GPIO controller. | 39 | - gpio-controller: Marks the device node as a GPIO controller. |
| @@ -86,7 +86,7 @@ Example: | |||
| 86 | }; | 86 | }; |
| 87 | 87 | ||
| 88 | pmic_eic: gpio@300 { | 88 | pmic_eic: gpio@300 { |
| 89 | compatible = "sprd,sc27xx-eic"; | 89 | compatible = "sprd,sc2731-eic"; |
| 90 | reg = <0x300>; | 90 | reg = <0x300>; |
| 91 | interrupt-parent = <&sc2731_pmic>; | 91 | interrupt-parent = <&sc2731_pmic>; |
| 92 | interrupts = <5 IRQ_TYPE_LEVEL_HIGH>; | 92 | interrupts = <5 IRQ_TYPE_LEVEL_HIGH>; |
diff --git a/Documentation/devicetree/bindings/gpio/gpio-pca953x.txt b/Documentation/devicetree/bindings/gpio/gpio-pca953x.txt index 4e3c550e319a..fb144e2b6522 100644 --- a/Documentation/devicetree/bindings/gpio/gpio-pca953x.txt +++ b/Documentation/devicetree/bindings/gpio/gpio-pca953x.txt | |||
| @@ -16,6 +16,7 @@ Required properties: | |||
| 16 | nxp,pca9574 | 16 | nxp,pca9574 |
| 17 | nxp,pca9575 | 17 | nxp,pca9575 |
| 18 | nxp,pca9698 | 18 | nxp,pca9698 |
| 19 | nxp,pcal6416 | ||
| 19 | nxp,pcal6524 | 20 | nxp,pcal6524 |
| 20 | nxp,pcal9555a | 21 | nxp,pcal9555a |
| 21 | maxim,max7310 | 22 | maxim,max7310 |
diff --git a/Documentation/devicetree/bindings/gpio/gpio.txt b/Documentation/devicetree/bindings/gpio/gpio.txt index f0ba154b5723..a8895d339bfe 100644 --- a/Documentation/devicetree/bindings/gpio/gpio.txt +++ b/Documentation/devicetree/bindings/gpio/gpio.txt | |||
| @@ -67,6 +67,18 @@ Optional standard bitfield specifiers for the last cell: | |||
| 67 | https://en.wikipedia.org/wiki/Open_collector | 67 | https://en.wikipedia.org/wiki/Open_collector |
| 68 | - Bit 3: 0 means the output should be maintained during sleep/low-power mode | 68 | - Bit 3: 0 means the output should be maintained during sleep/low-power mode |
| 69 | 1 means the output state can be lost during sleep/low-power mode | 69 | 1 means the output state can be lost during sleep/low-power mode |
| 70 | - Bit 4: 0 means no pull-up resistor should be enabled | ||
| 71 | 1 means a pull-up resistor should be enabled | ||
| 72 | This setting only applies to hardware with a simple on/off | ||
| 73 | control for pull-up configuration. If the hardware has more | ||
| 74 | elaborate pull-up configuration, it should be represented | ||
| 75 | using a pin control binding. | ||
| 76 | - Bit 5: 0 means no pull-down resistor should be enabled | ||
| 77 | 1 means a pull-down resistor should be enabled | ||
| 78 | This setting only applies to hardware with a simple on/off | ||
| 79 | control for pull-down configuration. If the hardware has more | ||
| 80 | elaborate pull-down configuration, it should be represented | ||
| 81 | using a pin control binding. | ||
| 70 | 82 | ||
| 71 | 1.1) GPIO specifier best practices | 83 | 1.1) GPIO specifier best practices |
| 72 | ---------------------------------- | 84 | ---------------------------------- |
diff --git a/Documentation/devicetree/bindings/gpio/intel,ixp4xx-gpio.txt b/Documentation/devicetree/bindings/gpio/intel,ixp4xx-gpio.txt new file mode 100644 index 000000000000..8dc41ed99685 --- /dev/null +++ b/Documentation/devicetree/bindings/gpio/intel,ixp4xx-gpio.txt | |||
| @@ -0,0 +1,38 @@ | |||
| 1 | Intel IXP4xx XScale Networking Processors GPIO | ||
| 2 | |||
| 3 | This GPIO controller is found in the Intel IXP4xx processors. | ||
| 4 | It supports 16 GPIO lines. | ||
| 5 | |||
| 6 | The interrupt portions of the GPIO controller is hierarchical: | ||
| 7 | the synchronous edge detector is part of the GPIO block, but the | ||
| 8 | actual enabling/disabling of the interrupt line is done in the | ||
| 9 | main IXP4xx interrupt controller which has a 1:1 mapping for | ||
| 10 | the first 12 GPIO lines to 12 system interrupts. | ||
| 11 | |||
| 12 | The remaining 4 GPIO lines can not be used for receiving | ||
| 13 | interrupts. | ||
| 14 | |||
| 15 | The interrupt parent of this GPIO controller must be the | ||
| 16 | IXP4xx interrupt controller. | ||
| 17 | |||
| 18 | Required properties: | ||
| 19 | |||
| 20 | - compatible : Should be | ||
| 21 | "intel,ixp4xx-gpio" | ||
| 22 | - reg : Should contain registers location and length | ||
| 23 | - gpio-controller : marks this as a GPIO controller | ||
| 24 | - #gpio-cells : Should be 2, see gpio/gpio.txt | ||
| 25 | - interrupt-controller : marks this as an interrupt controller | ||
| 26 | - #interrupt-cells : a standard two-cell interrupt, see | ||
| 27 | interrupt-controller/interrupts.txt | ||
| 28 | |||
| 29 | Example: | ||
| 30 | |||
| 31 | gpio0: gpio@c8004000 { | ||
| 32 | compatible = "intel,ixp4xx-gpio"; | ||
| 33 | reg = <0xc8004000 0x1000>; | ||
| 34 | gpio-controller; | ||
| 35 | #gpio-cells = <2>; | ||
| 36 | interrupt-controller; | ||
| 37 | #interrupt-cells = <2>; | ||
| 38 | }; | ||
diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,pmic-gpio.txt b/Documentation/devicetree/bindings/pinctrl/qcom,pmic-gpio.txt index 759aa1732e48..7f64a7e92c28 100644 --- a/Documentation/devicetree/bindings/pinctrl/qcom,pmic-gpio.txt +++ b/Documentation/devicetree/bindings/pinctrl/qcom,pmic-gpio.txt | |||
| @@ -19,6 +19,7 @@ PMIC's from Qualcomm. | |||
| 19 | "qcom,pm8998-gpio" | 19 | "qcom,pm8998-gpio" |
| 20 | "qcom,pma8084-gpio" | 20 | "qcom,pma8084-gpio" |
| 21 | "qcom,pmi8994-gpio" | 21 | "qcom,pmi8994-gpio" |
| 22 | "qcom,pmi8998-gpio" | ||
| 22 | "qcom,pms405-gpio" | 23 | "qcom,pms405-gpio" |
| 23 | 24 | ||
| 24 | And must contain either "qcom,spmi-gpio" or "qcom,ssbi-gpio" | 25 | And must contain either "qcom,spmi-gpio" or "qcom,ssbi-gpio" |
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt index aaa18bb1a9f4..385d22460b1d 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.txt +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt | |||
| @@ -145,6 +145,7 @@ focaltech FocalTech Systems Co.,Ltd | |||
| 145 | friendlyarm Guangzhou FriendlyARM Computer Tech Co., Ltd | 145 | friendlyarm Guangzhou FriendlyARM Computer Tech Co., Ltd |
| 146 | fsl Freescale Semiconductor | 146 | fsl Freescale Semiconductor |
| 147 | fujitsu Fujitsu Ltd. | 147 | fujitsu Fujitsu Ltd. |
| 148 | gateworks Gateworks Corporation | ||
| 148 | gcw Game Consoles Worldwide | 149 | gcw Game Consoles Worldwide |
| 149 | ge General Electric Company | 150 | ge General Electric Company |
| 150 | geekbuying GeekBuying | 151 | geekbuying GeekBuying |
diff --git a/Documentation/driver-api/gpio/board.rst b/Documentation/driver-api/gpio/board.rst index a0f294e2e250..b37f3f7b8926 100644 --- a/Documentation/driver-api/gpio/board.rst +++ b/Documentation/driver-api/gpio/board.rst | |||
| @@ -204,6 +204,7 @@ between a caller and a respective .get/set_multiple() callback of a GPIO chip. | |||
| 204 | 204 | ||
| 205 | In order to qualify for fast bitmap processing, the array must meet the | 205 | In order to qualify for fast bitmap processing, the array must meet the |
| 206 | following requirements: | 206 | following requirements: |
| 207 | |||
| 207 | - pin hardware number of array member 0 must also be 0, | 208 | - pin hardware number of array member 0 must also be 0, |
| 208 | - pin hardware numbers of consecutive array members which belong to the same | 209 | - pin hardware numbers of consecutive array members which belong to the same |
| 209 | chip as member 0 does must also match their array indexes. | 210 | chip as member 0 does must also match their array indexes. |
diff --git a/Documentation/driver-api/gpio/driver.rst b/Documentation/driver-api/gpio/driver.rst index a92d8837b62b..3043167fc557 100644 --- a/Documentation/driver-api/gpio/driver.rst +++ b/Documentation/driver-api/gpio/driver.rst | |||
| @@ -135,7 +135,7 @@ This configuration is normally used as a way to achieve one of two things: | |||
| 135 | - inverse wire-OR on an I/O line, for example a GPIO line, making it possible | 135 | - inverse wire-OR on an I/O line, for example a GPIO line, making it possible |
| 136 | for any driving stage on the line to drive it low even if any other output | 136 | for any driving stage on the line to drive it low even if any other output |
| 137 | to the same line is simultaneously driving it high. A special case of this | 137 | to the same line is simultaneously driving it high. A special case of this |
| 138 | is driving the SCL and SCA lines of an I2C bus, which is by definition a | 138 | is driving the SCL and SDA lines of an I2C bus, which is by definition a |
| 139 | wire-OR bus. | 139 | wire-OR bus. |
| 140 | 140 | ||
| 141 | Both usecases require that the line be equipped with a pull-up resistor. This | 141 | Both usecases require that the line be equipped with a pull-up resistor. This |
diff --git a/Documentation/driver-api/gpio/legacy.rst b/Documentation/driver-api/gpio/legacy.rst index 5e9421e05f1d..9bc34ba697d9 100644 --- a/Documentation/driver-api/gpio/legacy.rst +++ b/Documentation/driver-api/gpio/legacy.rst | |||
| @@ -690,11 +690,10 @@ and have the following read/write attributes: | |||
| 690 | and if it has been configured to generate interrupts (see the | 690 | and if it has been configured to generate interrupts (see the |
| 691 | description of "edge"), you can poll(2) on that file and | 691 | description of "edge"), you can poll(2) on that file and |
| 692 | poll(2) will return whenever the interrupt was triggered. If | 692 | poll(2) will return whenever the interrupt was triggered. If |
| 693 | you use poll(2), set the events POLLPRI and POLLERR. If you | 693 | you use poll(2), set the events POLLPRI. If you use select(2), |
| 694 | use select(2), set the file descriptor in exceptfds. After | 694 | set the file descriptor in exceptfds. After poll(2) returns, |
| 695 | poll(2) returns, either lseek(2) to the beginning of the sysfs | 695 | either lseek(2) to the beginning of the sysfs file and read the |
| 696 | file and read the new value or close the file and re-open it | 696 | new value or close the file and re-open it to read the value. |
| 697 | to read the value. | ||
| 698 | 697 | ||
| 699 | "edge" ... reads as either "none", "rising", "falling", or | 698 | "edge" ... reads as either "none", "rising", "falling", or |
| 700 | "both". Write these strings to select the signal edge(s) | 699 | "both". Write these strings to select the signal edge(s) |
diff --git a/MAINTAINERS b/MAINTAINERS index e261ca14ebd0..21ab06488be8 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
| @@ -766,6 +766,13 @@ S: Supported | |||
| 766 | F: Documentation/hwmon/fam15h_power | 766 | F: Documentation/hwmon/fam15h_power |
| 767 | F: drivers/hwmon/fam15h_power.c | 767 | F: drivers/hwmon/fam15h_power.c |
| 768 | 768 | ||
| 769 | AMD FCH GPIO DRIVER | ||
| 770 | M: Enrico Weigelt, metux IT consult <info@metux.net> | ||
| 771 | L: linux-gpio@vger.kernel.org | ||
| 772 | S: Maintained | ||
| 773 | F: drivers/gpio/gpio-amd-fch.c | ||
| 774 | F: include/linux/platform_data/gpio/gpio-amd-fch.h | ||
| 775 | |||
| 769 | AMD GEODE CS5536 USB DEVICE CONTROLLER DRIVER | 776 | AMD GEODE CS5536 USB DEVICE CONTROLLER DRIVER |
| 770 | L: linux-geode@lists.infradead.org (moderated for non-subscribers) | 777 | L: linux-geode@lists.infradead.org (moderated for non-subscribers) |
| 771 | S: Orphan | 778 | S: Orphan |
| @@ -11716,6 +11723,11 @@ F: lib/parman.c | |||
| 11716 | F: lib/test_parman.c | 11723 | F: lib/test_parman.c |
| 11717 | F: include/linux/parman.h | 11724 | F: include/linux/parman.h |
| 11718 | 11725 | ||
| 11726 | PC ENGINES APU BOARD DRIVER | ||
| 11727 | M: Enrico Weigelt, metux IT consult <info@metux.net> | ||
| 11728 | S: Maintained | ||
| 11729 | F: drivers/platform/x86/pcengines-apuv2.c | ||
| 11730 | |||
| 11719 | PC87360 HARDWARE MONITORING DRIVER | 11731 | PC87360 HARDWARE MONITORING DRIVER |
| 11720 | M: Jim Cromie <jim.cromie@gmail.com> | 11732 | M: Jim Cromie <jim.cromie@gmail.com> |
| 11721 | L: linux-hwmon@vger.kernel.org | 11733 | L: linux-hwmon@vger.kernel.org |
diff --git a/arch/arm/boot/dts/qcom-apq8060-dragonboard.dts b/arch/arm/boot/dts/qcom-apq8060-dragonboard.dts index 497bb065eb9d..4e6c50d45cb2 100644 --- a/arch/arm/boot/dts/qcom-apq8060-dragonboard.dts +++ b/arch/arm/boot/dts/qcom-apq8060-dragonboard.dts | |||
| @@ -93,9 +93,8 @@ | |||
| 93 | vdd-supply = <&pm8058_l14>; // 2.85V | 93 | vdd-supply = <&pm8058_l14>; // 2.85V |
| 94 | aset-gpios = <&pm8058_gpio 35 GPIO_ACTIVE_LOW>; | 94 | aset-gpios = <&pm8058_gpio 35 GPIO_ACTIVE_LOW>; |
| 95 | capella,aset-resistance-ohms = <100000>; | 95 | capella,aset-resistance-ohms = <100000>; |
| 96 | /* GPIO34 has interrupt 225 on the PM8058 */ | ||
| 97 | /* Trig on both edges - getting close or far away */ | 96 | /* Trig on both edges - getting close or far away */ |
| 98 | interrupts-extended = <&pm8058 225 IRQ_TYPE_EDGE_BOTH>; | 97 | interrupts-extended = <&pm8058_gpio 34 IRQ_TYPE_EDGE_BOTH>; |
| 99 | /* MPP05 analog input to the XOADC */ | 98 | /* MPP05 analog input to the XOADC */ |
| 100 | io-channels = <&xoadc 0x00 0x05>; | 99 | io-channels = <&xoadc 0x00 0x05>; |
| 101 | io-channel-names = "aout"; | 100 | io-channel-names = "aout"; |
| @@ -515,9 +514,8 @@ | |||
| 515 | ak8975@c { | 514 | ak8975@c { |
| 516 | compatible = "asahi-kasei,ak8975"; | 515 | compatible = "asahi-kasei,ak8975"; |
| 517 | reg = <0x0c>; | 516 | reg = <0x0c>; |
| 518 | /* FIXME: GPIO33 has interrupt 224 on the PM8058 */ | 517 | interrupt-parent = <&pm8058_gpio>; |
| 519 | interrupt-parent = <&pm8058>; | 518 | interrupts = <33 IRQ_TYPE_EDGE_RISING>; |
| 520 | interrupts = <224 IRQ_TYPE_EDGE_RISING>; | ||
| 521 | pinctrl-names = "default"; | 519 | pinctrl-names = "default"; |
| 522 | pinctrl-0 = <&dragon_ak8975_gpios>; | 520 | pinctrl-0 = <&dragon_ak8975_gpios>; |
| 523 | vid-supply = <&pm8058_lvs0>; // 1.8V | 521 | vid-supply = <&pm8058_lvs0>; // 1.8V |
| @@ -526,9 +524,8 @@ | |||
| 526 | bmp085@77 { | 524 | bmp085@77 { |
| 527 | compatible = "bosch,bmp085"; | 525 | compatible = "bosch,bmp085"; |
| 528 | reg = <0x77>; | 526 | reg = <0x77>; |
| 529 | /* FIXME: GPIO16 has interrupt 207 on the PM8058 */ | 527 | interrupt-parent = <&pm8058_gpio>; |
| 530 | interrupt-parent = <&pm8058>; | 528 | interrupts = <16 IRQ_TYPE_EDGE_RISING>; |
| 531 | interrupts = <207 IRQ_TYPE_EDGE_RISING>; | ||
| 532 | reset-gpios = <&tlmm 86 GPIO_ACTIVE_LOW>; | 529 | reset-gpios = <&tlmm 86 GPIO_ACTIVE_LOW>; |
| 533 | pinctrl-names = "default"; | 530 | pinctrl-names = "default"; |
| 534 | pinctrl-0 = <&dragon_bmp085_gpios>; | 531 | pinctrl-0 = <&dragon_bmp085_gpios>; |
| @@ -539,12 +536,11 @@ | |||
| 539 | compatible = "invensense,mpu3050"; | 536 | compatible = "invensense,mpu3050"; |
| 540 | reg = <0x68>; | 537 | reg = <0x68>; |
| 541 | /* | 538 | /* |
| 542 | * GPIO17 has interrupt 208 on the | 539 | * GPIO17 is pulled high by a 10k |
| 543 | * PM8058, it is pulled high by a 10k | ||
| 544 | * resistor to VLOGIC so needs to be | 540 | * resistor to VLOGIC so needs to be |
| 545 | * active low/falling edge. | 541 | * active low/falling edge. |
| 546 | */ | 542 | */ |
| 547 | interrupts-extended = <&pm8058 208 IRQ_TYPE_EDGE_FALLING>; | 543 | interrupts-extended = <&pm8058_gpio 17 IRQ_TYPE_EDGE_FALLING>; |
| 548 | pinctrl-names = "default"; | 544 | pinctrl-names = "default"; |
| 549 | pinctrl-0 = <&dragon_mpu3050_gpios>; | 545 | pinctrl-0 = <&dragon_mpu3050_gpios>; |
| 550 | vlogic-supply = <&pm8058_lvs0>; // 1.8V | 546 | vlogic-supply = <&pm8058_lvs0>; // 1.8V |
| @@ -589,11 +585,10 @@ | |||
| 589 | compatible = "smsc,lan9221", "smsc,lan9115"; | 585 | compatible = "smsc,lan9221", "smsc,lan9115"; |
| 590 | reg = <2 0x0 0x100>; | 586 | reg = <2 0x0 0x100>; |
| 591 | /* | 587 | /* |
| 592 | * GPIO7 has interrupt 198 on the PM8058 | ||
| 593 | * The second interrupt is the PME interrupt | 588 | * The second interrupt is the PME interrupt |
| 594 | * for network wakeup, connected to the TLMM. | 589 | * for network wakeup, connected to the TLMM. |
| 595 | */ | 590 | */ |
| 596 | interrupts-extended = <&pm8058 198 IRQ_TYPE_EDGE_FALLING>, | 591 | interrupts-extended = <&pm8058_gpio 7 IRQ_TYPE_EDGE_FALLING>, |
| 597 | <&tlmm 29 IRQ_TYPE_EDGE_RISING>; | 592 | <&tlmm 29 IRQ_TYPE_EDGE_RISING>; |
| 598 | reset-gpios = <&tlmm 30 GPIO_ACTIVE_LOW>; | 593 | reset-gpios = <&tlmm 30 GPIO_ACTIVE_LOW>; |
| 599 | vdd33a-supply = <&dragon_veth>; | 594 | vdd33a-supply = <&dragon_veth>; |
diff --git a/arch/arm/boot/dts/qcom-apq8064.dtsi b/arch/arm/boot/dts/qcom-apq8064.dtsi index 1374c2e52c20..bd6907db615b 100644 --- a/arch/arm/boot/dts/qcom-apq8064.dtsi +++ b/arch/arm/boot/dts/qcom-apq8064.dtsi | |||
| @@ -711,50 +711,8 @@ | |||
| 711 | compatible = "qcom,pm8921-gpio", | 711 | compatible = "qcom,pm8921-gpio", |
| 712 | "qcom,ssbi-gpio"; | 712 | "qcom,ssbi-gpio"; |
| 713 | reg = <0x150>; | 713 | reg = <0x150>; |
| 714 | interrupts = <192 IRQ_TYPE_NONE>, | 714 | interrupt-controller; |
| 715 | <193 IRQ_TYPE_NONE>, | 715 | #interrupt-cells = <2>; |
| 716 | <194 IRQ_TYPE_NONE>, | ||
| 717 | <195 IRQ_TYPE_NONE>, | ||
| 718 | <196 IRQ_TYPE_NONE>, | ||
| 719 | <197 IRQ_TYPE_NONE>, | ||
| 720 | <198 IRQ_TYPE_NONE>, | ||
| 721 | <199 IRQ_TYPE_NONE>, | ||
| 722 | <200 IRQ_TYPE_NONE>, | ||
| 723 | <201 IRQ_TYPE_NONE>, | ||
| 724 | <202 IRQ_TYPE_NONE>, | ||
| 725 | <203 IRQ_TYPE_NONE>, | ||
| 726 | <204 IRQ_TYPE_NONE>, | ||
| 727 | <205 IRQ_TYPE_NONE>, | ||
| 728 | <206 IRQ_TYPE_NONE>, | ||
| 729 | <207 IRQ_TYPE_NONE>, | ||
| 730 | <208 IRQ_TYPE_NONE>, | ||
| 731 | <209 IRQ_TYPE_NONE>, | ||
| 732 | <210 IRQ_TYPE_NONE>, | ||
| 733 | <211 IRQ_TYPE_NONE>, | ||
| 734 | <212 IRQ_TYPE_NONE>, | ||
| 735 | <213 IRQ_TYPE_NONE>, | ||
| 736 | <214 IRQ_TYPE_NONE>, | ||
| 737 | <215 IRQ_TYPE_NONE>, | ||
| 738 | <216 IRQ_TYPE_NONE>, | ||
| 739 | <217 IRQ_TYPE_NONE>, | ||
| 740 | <218 IRQ_TYPE_NONE>, | ||
| 741 | <219 IRQ_TYPE_NONE>, | ||
| 742 | <220 IRQ_TYPE_NONE>, | ||
| 743 | <221 IRQ_TYPE_NONE>, | ||
| 744 | <222 IRQ_TYPE_NONE>, | ||
| 745 | <223 IRQ_TYPE_NONE>, | ||
| 746 | <224 IRQ_TYPE_NONE>, | ||
| 747 | <225 IRQ_TYPE_NONE>, | ||
| 748 | <226 IRQ_TYPE_NONE>, | ||
| 749 | <227 IRQ_TYPE_NONE>, | ||
| 750 | <228 IRQ_TYPE_NONE>, | ||
| 751 | <229 IRQ_TYPE_NONE>, | ||
| 752 | <230 IRQ_TYPE_NONE>, | ||
| 753 | <231 IRQ_TYPE_NONE>, | ||
| 754 | <232 IRQ_TYPE_NONE>, | ||
| 755 | <233 IRQ_TYPE_NONE>, | ||
| 756 | <234 IRQ_TYPE_NONE>, | ||
| 757 | <235 IRQ_TYPE_NONE>; | ||
| 758 | gpio-controller; | 716 | gpio-controller; |
| 759 | #gpio-cells = <2>; | 717 | #gpio-cells = <2>; |
| 760 | 718 | ||
diff --git a/arch/arm/boot/dts/qcom-mdm9615.dtsi b/arch/arm/boot/dts/qcom-mdm9615.dtsi index e49f67ad5dbc..02afc6a42005 100644 --- a/arch/arm/boot/dts/qcom-mdm9615.dtsi +++ b/arch/arm/boot/dts/qcom-mdm9615.dtsi | |||
| @@ -323,13 +323,8 @@ | |||
| 323 | 323 | ||
| 324 | pmicgpio: gpio@150 { | 324 | pmicgpio: gpio@150 { |
| 325 | compatible = "qcom,pm8018-gpio", "qcom,ssbi-gpio"; | 325 | compatible = "qcom,pm8018-gpio", "qcom,ssbi-gpio"; |
| 326 | interrupt-parent = <&pmicintc>; | 326 | interrupt-controller; |
| 327 | interrupts = <24 IRQ_TYPE_NONE>, | 327 | #interrupt-cells = <2>; |
| 328 | <25 IRQ_TYPE_NONE>, | ||
| 329 | <26 IRQ_TYPE_NONE>, | ||
| 330 | <27 IRQ_TYPE_NONE>, | ||
| 331 | <28 IRQ_TYPE_NONE>, | ||
| 332 | <29 IRQ_TYPE_NONE>; | ||
| 333 | gpio-controller; | 328 | gpio-controller; |
| 334 | #gpio-cells = <2>; | 329 | #gpio-cells = <2>; |
| 335 | }; | 330 | }; |
diff --git a/arch/arm/boot/dts/qcom-msm8660.dtsi b/arch/arm/boot/dts/qcom-msm8660.dtsi index 993107ed1476..65a994f0e09b 100644 --- a/arch/arm/boot/dts/qcom-msm8660.dtsi +++ b/arch/arm/boot/dts/qcom-msm8660.dtsi | |||
| @@ -292,51 +292,8 @@ | |||
| 292 | compatible = "qcom,pm8058-gpio", | 292 | compatible = "qcom,pm8058-gpio", |
| 293 | "qcom,ssbi-gpio"; | 293 | "qcom,ssbi-gpio"; |
| 294 | reg = <0x150>; | 294 | reg = <0x150>; |
| 295 | interrupt-parent = <&pm8058>; | 295 | interrupt-controller; |
| 296 | interrupts = <192 IRQ_TYPE_NONE>, | 296 | #interrupt-cells = <2>; |
| 297 | <193 IRQ_TYPE_NONE>, | ||
| 298 | <194 IRQ_TYPE_NONE>, | ||
| 299 | <195 IRQ_TYPE_NONE>, | ||
| 300 | <196 IRQ_TYPE_NONE>, | ||
| 301 | <197 IRQ_TYPE_NONE>, | ||
| 302 | <198 IRQ_TYPE_NONE>, | ||
| 303 | <199 IRQ_TYPE_NONE>, | ||
| 304 | <200 IRQ_TYPE_NONE>, | ||
| 305 | <201 IRQ_TYPE_NONE>, | ||
| 306 | <202 IRQ_TYPE_NONE>, | ||
| 307 | <203 IRQ_TYPE_NONE>, | ||
| 308 | <204 IRQ_TYPE_NONE>, | ||
| 309 | <205 IRQ_TYPE_NONE>, | ||
| 310 | <206 IRQ_TYPE_NONE>, | ||
| 311 | <207 IRQ_TYPE_NONE>, | ||
| 312 | <208 IRQ_TYPE_NONE>, | ||
| 313 | <209 IRQ_TYPE_NONE>, | ||
| 314 | <210 IRQ_TYPE_NONE>, | ||
| 315 | <211 IRQ_TYPE_NONE>, | ||
| 316 | <212 IRQ_TYPE_NONE>, | ||
| 317 | <213 IRQ_TYPE_NONE>, | ||
| 318 | <214 IRQ_TYPE_NONE>, | ||
| 319 | <215 IRQ_TYPE_NONE>, | ||
| 320 | <216 IRQ_TYPE_NONE>, | ||
| 321 | <217 IRQ_TYPE_NONE>, | ||
| 322 | <218 IRQ_TYPE_NONE>, | ||
| 323 | <219 IRQ_TYPE_NONE>, | ||
| 324 | <220 IRQ_TYPE_NONE>, | ||
| 325 | <221 IRQ_TYPE_NONE>, | ||
| 326 | <222 IRQ_TYPE_NONE>, | ||
| 327 | <223 IRQ_TYPE_NONE>, | ||
| 328 | <224 IRQ_TYPE_NONE>, | ||
| 329 | <225 IRQ_TYPE_NONE>, | ||
| 330 | <226 IRQ_TYPE_NONE>, | ||
| 331 | <227 IRQ_TYPE_NONE>, | ||
| 332 | <228 IRQ_TYPE_NONE>, | ||
| 333 | <229 IRQ_TYPE_NONE>, | ||
| 334 | <230 IRQ_TYPE_NONE>, | ||
| 335 | <231 IRQ_TYPE_NONE>, | ||
| 336 | <232 IRQ_TYPE_NONE>, | ||
| 337 | <233 IRQ_TYPE_NONE>, | ||
| 338 | <234 IRQ_TYPE_NONE>, | ||
| 339 | <235 IRQ_TYPE_NONE>; | ||
| 340 | gpio-controller; | 297 | gpio-controller; |
| 341 | #gpio-cells = <2>; | 298 | #gpio-cells = <2>; |
| 342 | 299 | ||
diff --git a/arch/arm/boot/dts/qcom-pm8941.dtsi b/arch/arm/boot/dts/qcom-pm8941.dtsi index 9a91b758f7aa..f198480c8ef4 100644 --- a/arch/arm/boot/dts/qcom-pm8941.dtsi +++ b/arch/arm/boot/dts/qcom-pm8941.dtsi | |||
| @@ -65,42 +65,8 @@ | |||
| 65 | gpio-controller; | 65 | gpio-controller; |
| 66 | gpio-ranges = <&pm8941_gpios 0 0 36>; | 66 | gpio-ranges = <&pm8941_gpios 0 0 36>; |
| 67 | #gpio-cells = <2>; | 67 | #gpio-cells = <2>; |
| 68 | interrupts = <0 0xc0 0 IRQ_TYPE_NONE>, | 68 | interrupt-controller; |
| 69 | <0 0xc1 0 IRQ_TYPE_NONE>, | 69 | #interrupt-cells = <2>; |
| 70 | <0 0xc2 0 IRQ_TYPE_NONE>, | ||
| 71 | <0 0xc3 0 IRQ_TYPE_NONE>, | ||
| 72 | <0 0xc4 0 IRQ_TYPE_NONE>, | ||
| 73 | <0 0xc5 0 IRQ_TYPE_NONE>, | ||
| 74 | <0 0xc6 0 IRQ_TYPE_NONE>, | ||
| 75 | <0 0xc7 0 IRQ_TYPE_NONE>, | ||
| 76 | <0 0xc8 0 IRQ_TYPE_NONE>, | ||
| 77 | <0 0xc9 0 IRQ_TYPE_NONE>, | ||
| 78 | <0 0xca 0 IRQ_TYPE_NONE>, | ||
| 79 | <0 0xcb 0 IRQ_TYPE_NONE>, | ||
| 80 | <0 0xcc 0 IRQ_TYPE_NONE>, | ||
| 81 | <0 0xcd 0 IRQ_TYPE_NONE>, | ||
| 82 | <0 0xce 0 IRQ_TYPE_NONE>, | ||
| 83 | <0 0xcf 0 IRQ_TYPE_NONE>, | ||
| 84 | <0 0xd0 0 IRQ_TYPE_NONE>, | ||
| 85 | <0 0xd1 0 IRQ_TYPE_NONE>, | ||
| 86 | <0 0xd2 0 IRQ_TYPE_NONE>, | ||
| 87 | <0 0xd3 0 IRQ_TYPE_NONE>, | ||
| 88 | <0 0xd4 0 IRQ_TYPE_NONE>, | ||
| 89 | <0 0xd5 0 IRQ_TYPE_NONE>, | ||
| 90 | <0 0xd6 0 IRQ_TYPE_NONE>, | ||
| 91 | <0 0xd7 0 IRQ_TYPE_NONE>, | ||
| 92 | <0 0xd8 0 IRQ_TYPE_NONE>, | ||
| 93 | <0 0xd9 0 IRQ_TYPE_NONE>, | ||
| 94 | <0 0xda 0 IRQ_TYPE_NONE>, | ||
| 95 | <0 0xdb 0 IRQ_TYPE_NONE>, | ||
| 96 | <0 0xdc 0 IRQ_TYPE_NONE>, | ||
| 97 | <0 0xdd 0 IRQ_TYPE_NONE>, | ||
| 98 | <0 0xde 0 IRQ_TYPE_NONE>, | ||
| 99 | <0 0xdf 0 IRQ_TYPE_NONE>, | ||
| 100 | <0 0xe0 0 IRQ_TYPE_NONE>, | ||
| 101 | <0 0xe1 0 IRQ_TYPE_NONE>, | ||
| 102 | <0 0xe2 0 IRQ_TYPE_NONE>, | ||
| 103 | <0 0xe3 0 IRQ_TYPE_NONE>; | ||
| 104 | 70 | ||
| 105 | boost_bypass_n_pin: boost-bypass { | 71 | boost_bypass_n_pin: boost-bypass { |
| 106 | pins = "gpio21"; | 72 | pins = "gpio21"; |
diff --git a/arch/arm/boot/dts/qcom-pma8084.dtsi b/arch/arm/boot/dts/qcom-pma8084.dtsi index aac7e73b6872..8f5ea7add20f 100644 --- a/arch/arm/boot/dts/qcom-pma8084.dtsi +++ b/arch/arm/boot/dts/qcom-pma8084.dtsi | |||
| @@ -32,28 +32,8 @@ | |||
| 32 | reg = <0xc000>; | 32 | reg = <0xc000>; |
| 33 | gpio-controller; | 33 | gpio-controller; |
| 34 | #gpio-cells = <2>; | 34 | #gpio-cells = <2>; |
| 35 | interrupts = <0 0xc0 0 IRQ_TYPE_NONE>, | 35 | interrupt-controller; |
| 36 | <0 0xc1 0 IRQ_TYPE_NONE>, | 36 | #interrupt-cells = <2>; |
| 37 | <0 0xc2 0 IRQ_TYPE_NONE>, | ||
| 38 | <0 0xc3 0 IRQ_TYPE_NONE>, | ||
| 39 | <0 0xc4 0 IRQ_TYPE_NONE>, | ||
| 40 | <0 0xc5 0 IRQ_TYPE_NONE>, | ||
| 41 | <0 0xc6 0 IRQ_TYPE_NONE>, | ||
| 42 | <0 0xc7 0 IRQ_TYPE_NONE>, | ||
| 43 | <0 0xc8 0 IRQ_TYPE_NONE>, | ||
| 44 | <0 0xc9 0 IRQ_TYPE_NONE>, | ||
| 45 | <0 0xca 0 IRQ_TYPE_NONE>, | ||
| 46 | <0 0xcb 0 IRQ_TYPE_NONE>, | ||
| 47 | <0 0xcc 0 IRQ_TYPE_NONE>, | ||
| 48 | <0 0xcd 0 IRQ_TYPE_NONE>, | ||
| 49 | <0 0xce 0 IRQ_TYPE_NONE>, | ||
| 50 | <0 0xcf 0 IRQ_TYPE_NONE>, | ||
| 51 | <0 0xd0 0 IRQ_TYPE_NONE>, | ||
| 52 | <0 0xd1 0 IRQ_TYPE_NONE>, | ||
| 53 | <0 0xd2 0 IRQ_TYPE_NONE>, | ||
| 54 | <0 0xd3 0 IRQ_TYPE_NONE>, | ||
| 55 | <0 0xd4 0 IRQ_TYPE_NONE>, | ||
| 56 | <0 0xd5 0 IRQ_TYPE_NONE>; | ||
| 57 | }; | 37 | }; |
| 58 | 38 | ||
| 59 | pma8084_mpps: mpps@a000 { | 39 | pma8084_mpps: mpps@a000 { |
diff --git a/arch/arm/mach-sa1100/simpad.c b/arch/arm/mach-sa1100/simpad.c index 406487e76a5c..c7fb9a73e4c5 100644 --- a/arch/arm/mach-sa1100/simpad.c +++ b/arch/arm/mach-sa1100/simpad.c | |||
| @@ -18,7 +18,6 @@ | |||
| 18 | #include <linux/mtd/partitions.h> | 18 | #include <linux/mtd/partitions.h> |
| 19 | #include <linux/io.h> | 19 | #include <linux/io.h> |
| 20 | #include <linux/gpio/driver.h> | 20 | #include <linux/gpio/driver.h> |
| 21 | #include <linux/gpio/machine.h> | ||
| 22 | 21 | ||
| 23 | #include <mach/hardware.h> | 22 | #include <mach/hardware.h> |
| 24 | #include <asm/setup.h> | 23 | #include <asm/setup.h> |
diff --git a/arch/arm64/boot/dts/qcom/pm8005.dtsi b/arch/arm64/boot/dts/qcom/pm8005.dtsi index 4d5aca3eeb69..c0ddf128136c 100644 --- a/arch/arm64/boot/dts/qcom/pm8005.dtsi +++ b/arch/arm64/boot/dts/qcom/pm8005.dtsi | |||
| @@ -16,10 +16,8 @@ | |||
| 16 | reg = <0xc000>; | 16 | reg = <0xc000>; |
| 17 | gpio-controller; | 17 | gpio-controller; |
| 18 | #gpio-cells = <2>; | 18 | #gpio-cells = <2>; |
| 19 | interrupts = <0 0xc0 0 IRQ_TYPE_NONE>, | 19 | interrupt-controller; |
| 20 | <0 0xc1 0 IRQ_TYPE_NONE>, | 20 | #interrupt-cells = <2>; |
| 21 | <0 0xc2 0 IRQ_TYPE_NONE>, | ||
| 22 | <0 0xc3 0 IRQ_TYPE_NONE>; | ||
| 23 | }; | 21 | }; |
| 24 | 22 | ||
| 25 | }; | 23 | }; |
diff --git a/arch/arm64/boot/dts/qcom/pm8998.dtsi b/arch/arm64/boot/dts/qcom/pm8998.dtsi index f1025a50c227..43cb5ea14089 100644 --- a/arch/arm64/boot/dts/qcom/pm8998.dtsi +++ b/arch/arm64/boot/dts/qcom/pm8998.dtsi | |||
| @@ -94,32 +94,8 @@ | |||
| 94 | reg = <0xc000>; | 94 | reg = <0xc000>; |
| 95 | gpio-controller; | 95 | gpio-controller; |
| 96 | #gpio-cells = <2>; | 96 | #gpio-cells = <2>; |
| 97 | interrupts = <0 0xc0 0 IRQ_TYPE_NONE>, | 97 | interrupt-controller; |
| 98 | <0 0xc1 0 IRQ_TYPE_NONE>, | 98 | #interrupt-cells = <2>; |
| 99 | <0 0xc2 0 IRQ_TYPE_NONE>, | ||
| 100 | <0 0xc3 0 IRQ_TYPE_NONE>, | ||
| 101 | <0 0xc4 0 IRQ_TYPE_NONE>, | ||
| 102 | <0 0xc5 0 IRQ_TYPE_NONE>, | ||
| 103 | <0 0xc6 0 IRQ_TYPE_NONE>, | ||
| 104 | <0 0xc7 0 IRQ_TYPE_NONE>, | ||
| 105 | <0 0xc8 0 IRQ_TYPE_NONE>, | ||
| 106 | <0 0xc9 0 IRQ_TYPE_NONE>, | ||
| 107 | <0 0xca 0 IRQ_TYPE_NONE>, | ||
| 108 | <0 0xcb 0 IRQ_TYPE_NONE>, | ||
| 109 | <0 0xcc 0 IRQ_TYPE_NONE>, | ||
| 110 | <0 0xcd 0 IRQ_TYPE_NONE>, | ||
| 111 | <0 0xce 0 IRQ_TYPE_NONE>, | ||
| 112 | <0 0xcf 0 IRQ_TYPE_NONE>, | ||
| 113 | <0 0xd0 0 IRQ_TYPE_NONE>, | ||
| 114 | <0 0xd1 0 IRQ_TYPE_NONE>, | ||
| 115 | <0 0xd2 0 IRQ_TYPE_NONE>, | ||
| 116 | <0 0xd3 0 IRQ_TYPE_NONE>, | ||
| 117 | <0 0xd4 0 IRQ_TYPE_NONE>, | ||
| 118 | <0 0xd5 0 IRQ_TYPE_NONE>, | ||
| 119 | <0 0xd6 0 IRQ_TYPE_NONE>, | ||
| 120 | <0 0xd7 0 IRQ_TYPE_NONE>, | ||
| 121 | <0 0xd8 0 IRQ_TYPE_NONE>, | ||
| 122 | <0 0xd9 0 IRQ_TYPE_NONE>; | ||
| 123 | }; | 99 | }; |
| 124 | 100 | ||
| 125 | }; | 101 | }; |
diff --git a/arch/arm64/boot/dts/qcom/pmi8994.dtsi b/arch/arm64/boot/dts/qcom/pmi8994.dtsi index dae1cdc23f54..3aee10e3f921 100644 --- a/arch/arm64/boot/dts/qcom/pmi8994.dtsi +++ b/arch/arm64/boot/dts/qcom/pmi8994.dtsi | |||
| @@ -15,16 +15,8 @@ | |||
| 15 | reg = <0xc000>; | 15 | reg = <0xc000>; |
| 16 | gpio-controller; | 16 | gpio-controller; |
| 17 | #gpio-cells = <2>; | 17 | #gpio-cells = <2>; |
| 18 | interrupts = <2 0xc0 0 IRQ_TYPE_NONE>, | 18 | interrupt-controller; |
| 19 | <2 0xc1 0 IRQ_TYPE_NONE>, | 19 | #interrupt-cells = <2>; |
| 20 | <2 0xc2 0 IRQ_TYPE_NONE>, | ||
| 21 | <2 0xc3 0 IRQ_TYPE_NONE>, | ||
| 22 | <2 0xc4 0 IRQ_TYPE_NONE>, | ||
| 23 | <2 0xc5 0 IRQ_TYPE_NONE>, | ||
| 24 | <2 0xc6 0 IRQ_TYPE_NONE>, | ||
| 25 | <2 0xc7 0 IRQ_TYPE_NONE>, | ||
| 26 | <2 0xc8 0 IRQ_TYPE_NONE>, | ||
| 27 | <2 0xc9 0 IRQ_TYPE_NONE>; | ||
| 28 | }; | 20 | }; |
| 29 | }; | 21 | }; |
| 30 | 22 | ||
diff --git a/arch/arm64/boot/dts/qcom/pmi8998.dtsi b/arch/arm64/boot/dts/qcom/pmi8998.dtsi index da3285e216e2..051f57e7d6ac 100644 --- a/arch/arm64/boot/dts/qcom/pmi8998.dtsi +++ b/arch/arm64/boot/dts/qcom/pmi8998.dtsi | |||
| @@ -14,20 +14,8 @@ | |||
| 14 | reg = <0xc000>; | 14 | reg = <0xc000>; |
| 15 | gpio-controller; | 15 | gpio-controller; |
| 16 | #gpio-cells = <2>; | 16 | #gpio-cells = <2>; |
| 17 | interrupts = <0 0xc0 0 IRQ_TYPE_NONE>, | 17 | interrupt-controller; |
| 18 | <0 0xc1 0 IRQ_TYPE_NONE>, | 18 | #interrupt-cells = <2>; |
| 19 | <0 0xc2 0 IRQ_TYPE_NONE>, | ||
| 20 | <0 0xc3 0 IRQ_TYPE_NONE>, | ||
| 21 | <0 0xc4 0 IRQ_TYPE_NONE>, | ||
| 22 | <0 0xc5 0 IRQ_TYPE_NONE>, | ||
| 23 | <0 0xc6 0 IRQ_TYPE_NONE>, | ||
| 24 | <0 0xc7 0 IRQ_TYPE_NONE>, | ||
| 25 | <0 0xc8 0 IRQ_TYPE_NONE>, | ||
| 26 | <0 0xc9 0 IRQ_TYPE_NONE>, | ||
| 27 | <0 0xca 0 IRQ_TYPE_NONE>, | ||
| 28 | <0 0xcb 0 IRQ_TYPE_NONE>, | ||
| 29 | <0 0xcc 0 IRQ_TYPE_NONE>, | ||
| 30 | <0 0xcd 0 IRQ_TYPE_NONE>; | ||
| 31 | }; | 19 | }; |
| 32 | }; | 20 | }; |
| 33 | 21 | ||
diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 4e45ac21d672..dab0a5abc391 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c | |||
| @@ -80,6 +80,26 @@ struct resource *platform_get_resource(struct platform_device *dev, | |||
| 80 | EXPORT_SYMBOL_GPL(platform_get_resource); | 80 | EXPORT_SYMBOL_GPL(platform_get_resource); |
| 81 | 81 | ||
| 82 | /** | 82 | /** |
| 83 | * devm_platform_ioremap_resource - call devm_ioremap_resource() for a platform | ||
| 84 | * device | ||
| 85 | * | ||
| 86 | * @pdev: platform device to use both for memory resource lookup as well as | ||
| 87 | * resource managemend | ||
| 88 | * @index: resource index | ||
| 89 | */ | ||
| 90 | #ifdef CONFIG_HAS_IOMEM | ||
| 91 | void __iomem *devm_platform_ioremap_resource(struct platform_device *pdev, | ||
| 92 | unsigned int index) | ||
| 93 | { | ||
| 94 | struct resource *res; | ||
| 95 | |||
| 96 | res = platform_get_resource(pdev, IORESOURCE_MEM, index); | ||
| 97 | return devm_ioremap_resource(&pdev->dev, res); | ||
| 98 | } | ||
| 99 | EXPORT_SYMBOL_GPL(devm_platform_ioremap_resource); | ||
| 100 | #endif /* CONFIG_HAS_IOMEM */ | ||
| 101 | |||
| 102 | /** | ||
| 83 | * platform_get_irq - get an IRQ for a device | 103 | * platform_get_irq - get an IRQ for a device |
| 84 | * @dev: platform device | 104 | * @dev: platform device |
| 85 | * @num: IRQ number index | 105 | * @num: IRQ number index |
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index b5a2845347ec..3f50526a771f 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig | |||
| @@ -258,6 +258,7 @@ config GPIO_HLWD | |||
| 258 | tristate "Nintendo Wii (Hollywood) GPIO" | 258 | tristate "Nintendo Wii (Hollywood) GPIO" |
| 259 | depends on OF_GPIO | 259 | depends on OF_GPIO |
| 260 | select GPIO_GENERIC | 260 | select GPIO_GENERIC |
| 261 | select GPIOLIB_IRQCHIP | ||
| 261 | help | 262 | help |
| 262 | Select this to support the GPIO controller of the Nintendo Wii. | 263 | Select this to support the GPIO controller of the Nintendo Wii. |
| 263 | 264 | ||
| @@ -654,6 +655,15 @@ config GPIO_LOONGSON1 | |||
| 654 | help | 655 | help |
| 655 | Say Y or M here to support GPIO on Loongson1 SoCs. | 656 | Say Y or M here to support GPIO on Loongson1 SoCs. |
| 656 | 657 | ||
| 658 | config GPIO_AMD_FCH | ||
| 659 | tristate "GPIO support for AMD Fusion Controller Hub (G-series SOCs)" | ||
| 660 | help | ||
| 661 | This option enables driver for GPIO on AMDs Fusion Controller Hub, | ||
| 662 | as found on G-series SOCs (eg. GX-412TC) | ||
| 663 | |||
| 664 | Note: This driver doesn't registers itself automatically, as it | ||
| 665 | needs to be provided with platform specific configuration. | ||
| 666 | (See eg. CONFIG_PCENGINES_APU2.) | ||
| 657 | endmenu | 667 | endmenu |
| 658 | 668 | ||
| 659 | menu "Port-mapped I/O GPIO drivers" | 669 | menu "Port-mapped I/O GPIO drivers" |
| @@ -830,6 +840,13 @@ config GPIO_ADNP | |||
| 830 | enough to represent all pins, but the driver will assume a | 840 | enough to represent all pins, but the driver will assume a |
| 831 | register layout for 64 pins (8 registers). | 841 | register layout for 64 pins (8 registers). |
| 832 | 842 | ||
| 843 | config GPIO_GW_PLD | ||
| 844 | tristate "Gateworks PLD GPIO Expander" | ||
| 845 | depends on OF_GPIO | ||
| 846 | help | ||
| 847 | Say yes here to provide access to the Gateworks I2C PLD GPIO | ||
| 848 | Expander. This is used at least on the Cambria GW2358-4. | ||
| 849 | |||
| 833 | config GPIO_MAX7300 | 850 | config GPIO_MAX7300 |
| 834 | tristate "Maxim MAX7300 GPIO expander" | 851 | tristate "Maxim MAX7300 GPIO expander" |
| 835 | select GPIO_MAX730X | 852 | select GPIO_MAX730X |
| @@ -1190,6 +1207,13 @@ config GPIO_TPS68470 | |||
| 1190 | of the TPS68470 must be available before dependent | 1207 | of the TPS68470 must be available before dependent |
| 1191 | drivers are loaded. | 1208 | drivers are loaded. |
| 1192 | 1209 | ||
| 1210 | config GPIO_TQMX86 | ||
| 1211 | tristate "TQ-Systems QTMX86 GPIO" | ||
| 1212 | depends on MFD_TQMX86 || COMPILE_TEST | ||
| 1213 | select GPIOLIB_IRQCHIP | ||
| 1214 | help | ||
| 1215 | This driver supports GPIO on the TQMX86 IO controller. | ||
| 1216 | |||
| 1193 | config GPIO_TWL4030 | 1217 | config GPIO_TWL4030 |
| 1194 | tristate "TWL4030, TWL5030, and TPS659x0 GPIOs" | 1218 | tristate "TWL4030, TWL5030, and TPS659x0 GPIOs" |
| 1195 | depends on TWL4030_CORE | 1219 | depends on TWL4030_CORE |
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 37628f8dbf70..54d55274b93a 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile | |||
| @@ -27,6 +27,7 @@ obj-$(CONFIG_GPIO_ADP5520) += gpio-adp5520.o | |||
| 27 | obj-$(CONFIG_GPIO_ADP5588) += gpio-adp5588.o | 27 | obj-$(CONFIG_GPIO_ADP5588) += gpio-adp5588.o |
| 28 | obj-$(CONFIG_GPIO_ALTERA) += gpio-altera.o | 28 | obj-$(CONFIG_GPIO_ALTERA) += gpio-altera.o |
| 29 | obj-$(CONFIG_GPIO_ALTERA_A10SR) += gpio-altera-a10sr.o | 29 | obj-$(CONFIG_GPIO_ALTERA_A10SR) += gpio-altera-a10sr.o |
| 30 | obj-$(CONFIG_GPIO_AMD_FCH) += gpio-amd-fch.o | ||
| 30 | obj-$(CONFIG_GPIO_AMD8111) += gpio-amd8111.o | 31 | obj-$(CONFIG_GPIO_AMD8111) += gpio-amd8111.o |
| 31 | obj-$(CONFIG_GPIO_AMDPT) += gpio-amdpt.o | 32 | obj-$(CONFIG_GPIO_AMDPT) += gpio-amdpt.o |
| 32 | obj-$(CONFIG_GPIO_ARIZONA) += gpio-arizona.o | 33 | obj-$(CONFIG_GPIO_ARIZONA) += gpio-arizona.o |
| @@ -55,6 +56,7 @@ obj-$(CONFIG_GPIO_FTGPIO010) += gpio-ftgpio010.o | |||
| 55 | obj-$(CONFIG_GPIO_GE_FPGA) += gpio-ge.o | 56 | obj-$(CONFIG_GPIO_GE_FPGA) += gpio-ge.o |
| 56 | obj-$(CONFIG_GPIO_GPIO_MM) += gpio-gpio-mm.o | 57 | obj-$(CONFIG_GPIO_GPIO_MM) += gpio-gpio-mm.o |
| 57 | obj-$(CONFIG_GPIO_GRGPIO) += gpio-grgpio.o | 58 | obj-$(CONFIG_GPIO_GRGPIO) += gpio-grgpio.o |
| 59 | obj-$(CONFIG_GPIO_GW_PLD) += gpio-gw-pld.o | ||
| 58 | obj-$(CONFIG_GPIO_HLWD) += gpio-hlwd.o | 60 | obj-$(CONFIG_GPIO_HLWD) += gpio-hlwd.o |
| 59 | obj-$(CONFIG_HTC_EGPIO) += gpio-htc-egpio.o | 61 | obj-$(CONFIG_HTC_EGPIO) += gpio-htc-egpio.o |
| 60 | obj-$(CONFIG_GPIO_ICH) += gpio-ich.o | 62 | obj-$(CONFIG_GPIO_ICH) += gpio-ich.o |
| @@ -135,6 +137,7 @@ obj-$(CONFIG_GPIO_TPS6586X) += gpio-tps6586x.o | |||
| 135 | obj-$(CONFIG_GPIO_TPS65910) += gpio-tps65910.o | 137 | obj-$(CONFIG_GPIO_TPS65910) += gpio-tps65910.o |
| 136 | obj-$(CONFIG_GPIO_TPS65912) += gpio-tps65912.o | 138 | obj-$(CONFIG_GPIO_TPS65912) += gpio-tps65912.o |
| 137 | obj-$(CONFIG_GPIO_TPS68470) += gpio-tps68470.o | 139 | obj-$(CONFIG_GPIO_TPS68470) += gpio-tps68470.o |
| 140 | obj-$(CONFIG_GPIO_TQMX86) += gpio-tqmx86.o | ||
| 138 | obj-$(CONFIG_GPIO_TS4800) += gpio-ts4800.o | 141 | obj-$(CONFIG_GPIO_TS4800) += gpio-ts4800.o |
| 139 | obj-$(CONFIG_GPIO_TS4900) += gpio-ts4900.o | 142 | obj-$(CONFIG_GPIO_TS4900) += gpio-ts4900.o |
| 140 | obj-$(CONFIG_GPIO_TS5500) += gpio-ts5500.o | 143 | obj-$(CONFIG_GPIO_TS5500) += gpio-ts5500.o |
diff --git a/drivers/gpio/gpio-adp5588.c b/drivers/gpio/gpio-adp5588.c index cc33d8986ad3..c4a5b499f53e 100644 --- a/drivers/gpio/gpio-adp5588.c +++ b/drivers/gpio/gpio-adp5588.c | |||
| @@ -15,6 +15,7 @@ | |||
| 15 | #include <linux/gpio/driver.h> | 15 | #include <linux/gpio/driver.h> |
| 16 | #include <linux/interrupt.h> | 16 | #include <linux/interrupt.h> |
| 17 | #include <linux/irq.h> | 17 | #include <linux/irq.h> |
| 18 | #include <linux/of_device.h> | ||
| 18 | 19 | ||
| 19 | #include <linux/platform_data/adp5588.h> | 20 | #include <linux/platform_data/adp5588.h> |
| 20 | 21 | ||
| @@ -33,16 +34,13 @@ struct adp5588_gpio { | |||
| 33 | struct mutex lock; /* protect cached dir, dat_out */ | 34 | struct mutex lock; /* protect cached dir, dat_out */ |
| 34 | /* protect serialized access to the interrupt controller bus */ | 35 | /* protect serialized access to the interrupt controller bus */ |
| 35 | struct mutex irq_lock; | 36 | struct mutex irq_lock; |
| 36 | unsigned gpio_start; | ||
| 37 | unsigned irq_base; | ||
| 38 | uint8_t dat_out[3]; | 37 | uint8_t dat_out[3]; |
| 39 | uint8_t dir[3]; | 38 | uint8_t dir[3]; |
| 40 | uint8_t int_lvl[3]; | 39 | uint8_t int_lvl_low[3]; |
| 40 | uint8_t int_lvl_high[3]; | ||
| 41 | uint8_t int_en[3]; | 41 | uint8_t int_en[3]; |
| 42 | uint8_t irq_mask[3]; | 42 | uint8_t irq_mask[3]; |
| 43 | uint8_t irq_stat[3]; | ||
| 44 | uint8_t int_input_en[3]; | 43 | uint8_t int_input_en[3]; |
| 45 | uint8_t int_lvl_cached[3]; | ||
| 46 | }; | 44 | }; |
| 47 | 45 | ||
| 48 | static int adp5588_gpio_read(struct i2c_client *client, u8 reg) | 46 | static int adp5588_gpio_read(struct i2c_client *client, u8 reg) |
| @@ -148,16 +146,11 @@ static int adp5588_gpio_direction_output(struct gpio_chip *chip, | |||
| 148 | } | 146 | } |
| 149 | 147 | ||
| 150 | #ifdef CONFIG_GPIO_ADP5588_IRQ | 148 | #ifdef CONFIG_GPIO_ADP5588_IRQ |
| 151 | static int adp5588_gpio_to_irq(struct gpio_chip *chip, unsigned off) | ||
| 152 | { | ||
| 153 | struct adp5588_gpio *dev = gpiochip_get_data(chip); | ||
| 154 | |||
| 155 | return dev->irq_base + off; | ||
| 156 | } | ||
| 157 | 149 | ||
| 158 | static void adp5588_irq_bus_lock(struct irq_data *d) | 150 | static void adp5588_irq_bus_lock(struct irq_data *d) |
| 159 | { | 151 | { |
| 160 | struct adp5588_gpio *dev = irq_data_get_irq_chip_data(d); | 152 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); |
| 153 | struct adp5588_gpio *dev = gpiochip_get_data(gc); | ||
| 161 | 154 | ||
| 162 | mutex_lock(&dev->irq_lock); | 155 | mutex_lock(&dev->irq_lock); |
| 163 | } | 156 | } |
| @@ -172,7 +165,8 @@ static void adp5588_irq_bus_lock(struct irq_data *d) | |||
| 172 | 165 | ||
| 173 | static void adp5588_irq_bus_sync_unlock(struct irq_data *d) | 166 | static void adp5588_irq_bus_sync_unlock(struct irq_data *d) |
| 174 | { | 167 | { |
| 175 | struct adp5588_gpio *dev = irq_data_get_irq_chip_data(d); | 168 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); |
| 169 | struct adp5588_gpio *dev = gpiochip_get_data(gc); | ||
| 176 | int i; | 170 | int i; |
| 177 | 171 | ||
| 178 | for (i = 0; i <= ADP5588_BANK(ADP5588_MAXGPIO); i++) { | 172 | for (i = 0; i <= ADP5588_BANK(ADP5588_MAXGPIO); i++) { |
| @@ -185,15 +179,9 @@ static void adp5588_irq_bus_sync_unlock(struct irq_data *d) | |||
| 185 | mutex_unlock(&dev->lock); | 179 | mutex_unlock(&dev->lock); |
| 186 | } | 180 | } |
| 187 | 181 | ||
| 188 | if (dev->int_lvl_cached[i] != dev->int_lvl[i]) { | ||
| 189 | dev->int_lvl_cached[i] = dev->int_lvl[i]; | ||
| 190 | adp5588_gpio_write(dev->client, GPIO_INT_LVL1 + i, | ||
| 191 | dev->int_lvl[i]); | ||
| 192 | } | ||
| 193 | |||
| 194 | if (dev->int_en[i] ^ dev->irq_mask[i]) { | 182 | if (dev->int_en[i] ^ dev->irq_mask[i]) { |
| 195 | dev->int_en[i] = dev->irq_mask[i]; | 183 | dev->int_en[i] = dev->irq_mask[i]; |
| 196 | adp5588_gpio_write(dev->client, GPIO_INT_EN1 + i, | 184 | adp5588_gpio_write(dev->client, GPI_EM1 + i, |
| 197 | dev->int_en[i]); | 185 | dev->int_en[i]); |
| 198 | } | 186 | } |
| 199 | } | 187 | } |
| @@ -203,41 +191,38 @@ static void adp5588_irq_bus_sync_unlock(struct irq_data *d) | |||
| 203 | 191 | ||
| 204 | static void adp5588_irq_mask(struct irq_data *d) | 192 | static void adp5588_irq_mask(struct irq_data *d) |
| 205 | { | 193 | { |
| 206 | struct adp5588_gpio *dev = irq_data_get_irq_chip_data(d); | 194 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); |
| 207 | unsigned gpio = d->irq - dev->irq_base; | 195 | struct adp5588_gpio *dev = gpiochip_get_data(gc); |
| 208 | 196 | ||
| 209 | dev->irq_mask[ADP5588_BANK(gpio)] &= ~ADP5588_BIT(gpio); | 197 | dev->irq_mask[ADP5588_BANK(d->hwirq)] &= ~ADP5588_BIT(d->hwirq); |
| 210 | } | 198 | } |
| 211 | 199 | ||
| 212 | static void adp5588_irq_unmask(struct irq_data *d) | 200 | static void adp5588_irq_unmask(struct irq_data *d) |
| 213 | { | 201 | { |
| 214 | struct adp5588_gpio *dev = irq_data_get_irq_chip_data(d); | 202 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); |
| 215 | unsigned gpio = d->irq - dev->irq_base; | 203 | struct adp5588_gpio *dev = gpiochip_get_data(gc); |
| 216 | 204 | ||
| 217 | dev->irq_mask[ADP5588_BANK(gpio)] |= ADP5588_BIT(gpio); | 205 | dev->irq_mask[ADP5588_BANK(d->hwirq)] |= ADP5588_BIT(d->hwirq); |
| 218 | } | 206 | } |
| 219 | 207 | ||
| 220 | static int adp5588_irq_set_type(struct irq_data *d, unsigned int type) | 208 | static int adp5588_irq_set_type(struct irq_data *d, unsigned int type) |
| 221 | { | 209 | { |
| 222 | struct adp5588_gpio *dev = irq_data_get_irq_chip_data(d); | 210 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); |
| 223 | uint16_t gpio = d->irq - dev->irq_base; | 211 | struct adp5588_gpio *dev = gpiochip_get_data(gc); |
| 212 | uint16_t gpio = d->hwirq; | ||
| 224 | unsigned bank, bit; | 213 | unsigned bank, bit; |
| 225 | 214 | ||
| 226 | if ((type & IRQ_TYPE_EDGE_BOTH)) { | ||
| 227 | dev_err(&dev->client->dev, "irq %d: unsupported type %d\n", | ||
| 228 | d->irq, type); | ||
| 229 | return -EINVAL; | ||
| 230 | } | ||
| 231 | |||
| 232 | bank = ADP5588_BANK(gpio); | 215 | bank = ADP5588_BANK(gpio); |
| 233 | bit = ADP5588_BIT(gpio); | 216 | bit = ADP5588_BIT(gpio); |
| 234 | 217 | ||
| 235 | if (type & IRQ_TYPE_LEVEL_HIGH) | 218 | dev->int_lvl_low[bank] &= ~bit; |
| 236 | dev->int_lvl[bank] |= bit; | 219 | dev->int_lvl_high[bank] &= ~bit; |
| 237 | else if (type & IRQ_TYPE_LEVEL_LOW) | 220 | |
| 238 | dev->int_lvl[bank] &= ~bit; | 221 | if (type & IRQ_TYPE_EDGE_BOTH || type & IRQ_TYPE_LEVEL_HIGH) |
| 239 | else | 222 | dev->int_lvl_high[bank] |= bit; |
| 240 | return -EINVAL; | 223 | |
| 224 | if (type & IRQ_TYPE_EDGE_BOTH || type & IRQ_TYPE_LEVEL_LOW) | ||
| 225 | dev->int_lvl_low[bank] |= bit; | ||
| 241 | 226 | ||
| 242 | dev->int_input_en[bank] |= bit; | 227 | dev->int_input_en[bank] |= bit; |
| 243 | 228 | ||
| @@ -253,40 +238,32 @@ static struct irq_chip adp5588_irq_chip = { | |||
| 253 | .irq_set_type = adp5588_irq_set_type, | 238 | .irq_set_type = adp5588_irq_set_type, |
| 254 | }; | 239 | }; |
| 255 | 240 | ||
| 256 | static int adp5588_gpio_read_intstat(struct i2c_client *client, u8 *buf) | ||
| 257 | { | ||
| 258 | int ret = i2c_smbus_read_i2c_block_data(client, GPIO_INT_STAT1, 3, buf); | ||
| 259 | |||
| 260 | if (ret < 0) | ||
| 261 | dev_err(&client->dev, "Read INT_STAT Error\n"); | ||
| 262 | |||
| 263 | return ret; | ||
| 264 | } | ||
| 265 | |||
| 266 | static irqreturn_t adp5588_irq_handler(int irq, void *devid) | 241 | static irqreturn_t adp5588_irq_handler(int irq, void *devid) |
| 267 | { | 242 | { |
| 268 | struct adp5588_gpio *dev = devid; | 243 | struct adp5588_gpio *dev = devid; |
| 269 | unsigned status, bank, bit, pending; | 244 | int status = adp5588_gpio_read(dev->client, INT_STAT); |
| 270 | int ret; | 245 | |
| 271 | status = adp5588_gpio_read(dev->client, INT_STAT); | 246 | if (status & ADP5588_KE_INT) { |
| 272 | 247 | int ev_cnt = adp5588_gpio_read(dev->client, KEY_LCK_EC_STAT); | |
| 273 | if (status & ADP5588_GPI_INT) { | 248 | |
| 274 | ret = adp5588_gpio_read_intstat(dev->client, dev->irq_stat); | 249 | if (ev_cnt > 0) { |
| 275 | if (ret < 0) | 250 | int i; |
| 276 | memset(dev->irq_stat, 0, ARRAY_SIZE(dev->irq_stat)); | 251 | |
| 277 | 252 | for (i = 0; i < (ev_cnt & ADP5588_KEC); i++) { | |
| 278 | for (bank = 0, bit = 0; bank <= ADP5588_BANK(ADP5588_MAXGPIO); | 253 | int key = adp5588_gpio_read(dev->client, |
| 279 | bank++, bit = 0) { | 254 | Key_EVENTA + i); |
| 280 | pending = dev->irq_stat[bank] & dev->irq_mask[bank]; | 255 | /* GPIN events begin at 97, |
| 281 | 256 | * bit 7 indicates logic level | |
| 282 | while (pending) { | 257 | */ |
| 283 | if (pending & (1 << bit)) { | 258 | int gpio = (key & 0x7f) - 97; |
| 284 | handle_nested_irq(dev->irq_base + | 259 | int lvl = key & (1 << 7); |
| 285 | (bank << 3) + bit); | 260 | int bank = ADP5588_BANK(gpio); |
| 286 | pending &= ~(1 << bit); | 261 | int bit = ADP5588_BIT(gpio); |
| 287 | 262 | ||
| 288 | } | 263 | if ((lvl && dev->int_lvl_high[bank] & bit) || |
| 289 | bit++; | 264 | (!lvl && dev->int_lvl_low[bank] & bit)) |
| 265 | handle_nested_irq(irq_find_mapping( | ||
| 266 | dev->gpio_chip.irq.domain, gpio)); | ||
| 290 | } | 267 | } |
| 291 | } | 268 | } |
| 292 | } | 269 | } |
| @@ -299,53 +276,42 @@ static irqreturn_t adp5588_irq_handler(int irq, void *devid) | |||
| 299 | static int adp5588_irq_setup(struct adp5588_gpio *dev) | 276 | static int adp5588_irq_setup(struct adp5588_gpio *dev) |
| 300 | { | 277 | { |
| 301 | struct i2c_client *client = dev->client; | 278 | struct i2c_client *client = dev->client; |
| 279 | int ret; | ||
| 302 | struct adp5588_gpio_platform_data *pdata = | 280 | struct adp5588_gpio_platform_data *pdata = |
| 303 | dev_get_platdata(&client->dev); | 281 | dev_get_platdata(&client->dev); |
| 304 | unsigned gpio; | 282 | int irq_base = pdata ? pdata->irq_base : 0; |
| 305 | int ret; | ||
| 306 | 283 | ||
| 307 | adp5588_gpio_write(client, CFG, ADP5588_AUTO_INC); | 284 | adp5588_gpio_write(client, CFG, ADP5588_AUTO_INC); |
| 308 | adp5588_gpio_write(client, INT_STAT, -1); /* status is W1C */ | 285 | adp5588_gpio_write(client, INT_STAT, -1); /* status is W1C */ |
| 309 | adp5588_gpio_read_intstat(client, dev->irq_stat); /* read to clear */ | ||
| 310 | 286 | ||
| 311 | dev->irq_base = pdata->irq_base; | ||
| 312 | mutex_init(&dev->irq_lock); | 287 | mutex_init(&dev->irq_lock); |
| 313 | 288 | ||
| 314 | for (gpio = 0; gpio < dev->gpio_chip.ngpio; gpio++) { | 289 | ret = devm_request_threaded_irq(&client->dev, client->irq, |
| 315 | int irq = gpio + dev->irq_base; | 290 | NULL, adp5588_irq_handler, IRQF_ONESHOT |
| 316 | irq_set_chip_data(irq, dev); | 291 | | IRQF_TRIGGER_FALLING | IRQF_SHARED, |
| 317 | irq_set_chip_and_handler(irq, &adp5588_irq_chip, | 292 | dev_name(&client->dev), dev); |
| 318 | handle_level_irq); | ||
| 319 | irq_set_nested_thread(irq, 1); | ||
| 320 | irq_modify_status(irq, IRQ_NOREQUEST, IRQ_NOPROBE); | ||
| 321 | } | ||
| 322 | |||
| 323 | ret = request_threaded_irq(client->irq, | ||
| 324 | NULL, | ||
| 325 | adp5588_irq_handler, | ||
| 326 | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, | ||
| 327 | dev_name(&client->dev), dev); | ||
| 328 | if (ret) { | 293 | if (ret) { |
| 329 | dev_err(&client->dev, "failed to request irq %d\n", | 294 | dev_err(&client->dev, "failed to request irq %d\n", |
| 330 | client->irq); | 295 | client->irq); |
| 331 | goto out; | 296 | return ret; |
| 332 | } | 297 | } |
| 298 | ret = gpiochip_irqchip_add_nested(&dev->gpio_chip, | ||
| 299 | &adp5588_irq_chip, irq_base, | ||
| 300 | handle_simple_irq, | ||
| 301 | IRQ_TYPE_NONE); | ||
| 302 | if (ret) { | ||
| 303 | dev_err(&client->dev, | ||
| 304 | "could not connect irqchip to gpiochip\n"); | ||
| 305 | return ret; | ||
| 306 | } | ||
| 307 | gpiochip_set_nested_irqchip(&dev->gpio_chip, | ||
| 308 | &adp5588_irq_chip, | ||
| 309 | client->irq); | ||
| 333 | 310 | ||
| 334 | dev->gpio_chip.to_irq = adp5588_gpio_to_irq; | ||
| 335 | adp5588_gpio_write(client, CFG, | 311 | adp5588_gpio_write(client, CFG, |
| 336 | ADP5588_AUTO_INC | ADP5588_INT_CFG | ADP5588_GPI_INT); | 312 | ADP5588_AUTO_INC | ADP5588_INT_CFG | ADP5588_KE_IEN); |
| 337 | 313 | ||
| 338 | return 0; | 314 | return 0; |
| 339 | |||
| 340 | out: | ||
| 341 | dev->irq_base = 0; | ||
| 342 | return ret; | ||
| 343 | } | ||
| 344 | |||
| 345 | static void adp5588_irq_teardown(struct adp5588_gpio *dev) | ||
| 346 | { | ||
| 347 | if (dev->irq_base) | ||
| 348 | free_irq(dev->client->irq, dev); | ||
| 349 | } | 315 | } |
| 350 | 316 | ||
| 351 | #else | 317 | #else |
| @@ -357,24 +323,16 @@ static int adp5588_irq_setup(struct adp5588_gpio *dev) | |||
| 357 | return 0; | 323 | return 0; |
| 358 | } | 324 | } |
| 359 | 325 | ||
| 360 | static void adp5588_irq_teardown(struct adp5588_gpio *dev) | ||
| 361 | { | ||
| 362 | } | ||
| 363 | #endif /* CONFIG_GPIO_ADP5588_IRQ */ | 326 | #endif /* CONFIG_GPIO_ADP5588_IRQ */ |
| 364 | 327 | ||
| 365 | static int adp5588_gpio_probe(struct i2c_client *client, | 328 | static int adp5588_gpio_probe(struct i2c_client *client) |
| 366 | const struct i2c_device_id *id) | ||
| 367 | { | 329 | { |
| 368 | struct adp5588_gpio_platform_data *pdata = | 330 | struct adp5588_gpio_platform_data *pdata = |
| 369 | dev_get_platdata(&client->dev); | 331 | dev_get_platdata(&client->dev); |
| 370 | struct adp5588_gpio *dev; | 332 | struct adp5588_gpio *dev; |
| 371 | struct gpio_chip *gc; | 333 | struct gpio_chip *gc; |
| 372 | int ret, i, revid; | 334 | int ret, i, revid; |
| 373 | 335 | unsigned int pullup_dis_mask = 0; | |
| 374 | if (!pdata) { | ||
| 375 | dev_err(&client->dev, "missing platform data\n"); | ||
| 376 | return -ENODEV; | ||
| 377 | } | ||
| 378 | 336 | ||
| 379 | if (!i2c_check_functionality(client->adapter, | 337 | if (!i2c_check_functionality(client->adapter, |
| 380 | I2C_FUNC_SMBUS_BYTE_DATA)) { | 338 | I2C_FUNC_SMBUS_BYTE_DATA)) { |
| @@ -394,18 +352,24 @@ static int adp5588_gpio_probe(struct i2c_client *client, | |||
| 394 | gc->get = adp5588_gpio_get_value; | 352 | gc->get = adp5588_gpio_get_value; |
| 395 | gc->set = adp5588_gpio_set_value; | 353 | gc->set = adp5588_gpio_set_value; |
| 396 | gc->can_sleep = true; | 354 | gc->can_sleep = true; |
| 355 | gc->base = -1; | ||
| 356 | gc->parent = &client->dev; | ||
| 357 | |||
| 358 | if (pdata) { | ||
| 359 | gc->base = pdata->gpio_start; | ||
| 360 | gc->names = pdata->names; | ||
| 361 | pullup_dis_mask = pdata->pullup_dis_mask; | ||
| 362 | } | ||
| 397 | 363 | ||
| 398 | gc->base = pdata->gpio_start; | ||
| 399 | gc->ngpio = ADP5588_MAXGPIO; | 364 | gc->ngpio = ADP5588_MAXGPIO; |
| 400 | gc->label = client->name; | 365 | gc->label = client->name; |
| 401 | gc->owner = THIS_MODULE; | 366 | gc->owner = THIS_MODULE; |
| 402 | gc->names = pdata->names; | ||
| 403 | 367 | ||
| 404 | mutex_init(&dev->lock); | 368 | mutex_init(&dev->lock); |
| 405 | 369 | ||
| 406 | ret = adp5588_gpio_read(dev->client, DEV_ID); | 370 | ret = adp5588_gpio_read(dev->client, DEV_ID); |
| 407 | if (ret < 0) | 371 | if (ret < 0) |
| 408 | goto err; | 372 | return ret; |
| 409 | 373 | ||
| 410 | revid = ret & ADP5588_DEVICE_ID_MASK; | 374 | revid = ret & ADP5588_DEVICE_ID_MASK; |
| 411 | 375 | ||
| @@ -414,30 +378,27 @@ static int adp5588_gpio_probe(struct i2c_client *client, | |||
| 414 | dev->dir[i] = adp5588_gpio_read(client, GPIO_DIR1 + i); | 378 | dev->dir[i] = adp5588_gpio_read(client, GPIO_DIR1 + i); |
| 415 | ret |= adp5588_gpio_write(client, KP_GPIO1 + i, 0); | 379 | ret |= adp5588_gpio_write(client, KP_GPIO1 + i, 0); |
| 416 | ret |= adp5588_gpio_write(client, GPIO_PULL1 + i, | 380 | ret |= adp5588_gpio_write(client, GPIO_PULL1 + i, |
| 417 | (pdata->pullup_dis_mask >> (8 * i)) & 0xFF); | 381 | (pullup_dis_mask >> (8 * i)) & 0xFF); |
| 418 | ret |= adp5588_gpio_write(client, GPIO_INT_EN1 + i, 0); | 382 | ret |= adp5588_gpio_write(client, GPIO_INT_EN1 + i, 0); |
| 419 | if (ret) | 383 | if (ret) |
| 420 | goto err; | 384 | return ret; |
| 421 | } | 385 | } |
| 422 | 386 | ||
| 423 | if (pdata->irq_base) { | 387 | if (client->irq) { |
| 424 | if (WA_DELAYED_READOUT_REVID(revid)) { | 388 | if (WA_DELAYED_READOUT_REVID(revid)) { |
| 425 | dev_warn(&client->dev, "GPIO int not supported\n"); | 389 | dev_warn(&client->dev, "GPIO int not supported\n"); |
| 426 | } else { | 390 | } else { |
| 427 | ret = adp5588_irq_setup(dev); | 391 | ret = adp5588_irq_setup(dev); |
| 428 | if (ret) | 392 | if (ret) |
| 429 | goto err; | 393 | return ret; |
| 430 | } | 394 | } |
| 431 | } | 395 | } |
| 432 | 396 | ||
| 433 | ret = devm_gpiochip_add_data(&client->dev, &dev->gpio_chip, dev); | 397 | ret = devm_gpiochip_add_data(&client->dev, &dev->gpio_chip, dev); |
| 434 | if (ret) | 398 | if (ret) |
| 435 | goto err_irq; | 399 | return ret; |
| 436 | 400 | ||
| 437 | dev_info(&client->dev, "IRQ Base: %d Rev.: %d\n", | 401 | if (pdata && pdata->setup) { |
| 438 | pdata->irq_base, revid); | ||
| 439 | |||
| 440 | if (pdata->setup) { | ||
| 441 | ret = pdata->setup(client, gc->base, gc->ngpio, pdata->context); | 402 | ret = pdata->setup(client, gc->base, gc->ngpio, pdata->context); |
| 442 | if (ret < 0) | 403 | if (ret < 0) |
| 443 | dev_warn(&client->dev, "setup failed, %d\n", ret); | 404 | dev_warn(&client->dev, "setup failed, %d\n", ret); |
| @@ -446,11 +407,6 @@ static int adp5588_gpio_probe(struct i2c_client *client, | |||
| 446 | i2c_set_clientdata(client, dev); | 407 | i2c_set_clientdata(client, dev); |
| 447 | 408 | ||
| 448 | return 0; | 409 | return 0; |
| 449 | |||
| 450 | err_irq: | ||
| 451 | adp5588_irq_teardown(dev); | ||
| 452 | err: | ||
| 453 | return ret; | ||
| 454 | } | 410 | } |
| 455 | 411 | ||
| 456 | static int adp5588_gpio_remove(struct i2c_client *client) | 412 | static int adp5588_gpio_remove(struct i2c_client *client) |
| @@ -460,7 +416,7 @@ static int adp5588_gpio_remove(struct i2c_client *client) | |||
| 460 | struct adp5588_gpio *dev = i2c_get_clientdata(client); | 416 | struct adp5588_gpio *dev = i2c_get_clientdata(client); |
| 461 | int ret; | 417 | int ret; |
| 462 | 418 | ||
| 463 | if (pdata->teardown) { | 419 | if (pdata && pdata->teardown) { |
| 464 | ret = pdata->teardown(client, | 420 | ret = pdata->teardown(client, |
| 465 | dev->gpio_chip.base, dev->gpio_chip.ngpio, | 421 | dev->gpio_chip.base, dev->gpio_chip.ngpio, |
| 466 | pdata->context); | 422 | pdata->context); |
| @@ -470,7 +426,7 @@ static int adp5588_gpio_remove(struct i2c_client *client) | |||
| 470 | } | 426 | } |
| 471 | } | 427 | } |
| 472 | 428 | ||
| 473 | if (dev->irq_base) | 429 | if (dev->client->irq) |
| 474 | free_irq(dev->client->irq, dev); | 430 | free_irq(dev->client->irq, dev); |
| 475 | 431 | ||
| 476 | return 0; | 432 | return 0; |
| @@ -480,14 +436,22 @@ static const struct i2c_device_id adp5588_gpio_id[] = { | |||
| 480 | {DRV_NAME, 0}, | 436 | {DRV_NAME, 0}, |
| 481 | {} | 437 | {} |
| 482 | }; | 438 | }; |
| 483 | |||
| 484 | MODULE_DEVICE_TABLE(i2c, adp5588_gpio_id); | 439 | MODULE_DEVICE_TABLE(i2c, adp5588_gpio_id); |
| 485 | 440 | ||
| 441 | #ifdef CONFIG_OF | ||
| 442 | static const struct of_device_id adp5588_gpio_of_id[] = { | ||
| 443 | { .compatible = "adi," DRV_NAME, }, | ||
| 444 | {}, | ||
| 445 | }; | ||
| 446 | MODULE_DEVICE_TABLE(of, adp5588_gpio_of_id); | ||
| 447 | #endif | ||
| 448 | |||
| 486 | static struct i2c_driver adp5588_gpio_driver = { | 449 | static struct i2c_driver adp5588_gpio_driver = { |
| 487 | .driver = { | 450 | .driver = { |
| 488 | .name = DRV_NAME, | 451 | .name = DRV_NAME, |
| 489 | }, | 452 | .of_match_table = of_match_ptr(adp5588_gpio_of_id), |
| 490 | .probe = adp5588_gpio_probe, | 453 | }, |
| 454 | .probe_new = adp5588_gpio_probe, | ||
| 491 | .remove = adp5588_gpio_remove, | 455 | .remove = adp5588_gpio_remove, |
| 492 | .id_table = adp5588_gpio_id, | 456 | .id_table = adp5588_gpio_id, |
| 493 | }; | 457 | }; |
diff --git a/drivers/gpio/gpio-altera-a10sr.c b/drivers/gpio/gpio-altera-a10sr.c index 7f9e0304b510..1cea4efccf7c 100644 --- a/drivers/gpio/gpio-altera-a10sr.c +++ b/drivers/gpio/gpio-altera-a10sr.c | |||
| @@ -58,19 +58,20 @@ static void altr_a10sr_gpio_set(struct gpio_chip *chip, unsigned int offset, | |||
| 58 | static int altr_a10sr_gpio_direction_input(struct gpio_chip *gc, | 58 | static int altr_a10sr_gpio_direction_input(struct gpio_chip *gc, |
| 59 | unsigned int nr) | 59 | unsigned int nr) |
| 60 | { | 60 | { |
| 61 | if (nr >= (ALTR_A10SR_IN_VALID_RANGE_LO - ALTR_A10SR_LED_VALID_SHIFT)) | 61 | if (nr < (ALTR_A10SR_IN_VALID_RANGE_LO - ALTR_A10SR_LED_VALID_SHIFT)) |
| 62 | return 0; | 62 | return -EINVAL; |
| 63 | return -EINVAL; | 63 | |
| 64 | return 0; | ||
| 64 | } | 65 | } |
| 65 | 66 | ||
| 66 | static int altr_a10sr_gpio_direction_output(struct gpio_chip *gc, | 67 | static int altr_a10sr_gpio_direction_output(struct gpio_chip *gc, |
| 67 | unsigned int nr, int value) | 68 | unsigned int nr, int value) |
| 68 | { | 69 | { |
| 69 | if (nr <= (ALTR_A10SR_OUT_VALID_RANGE_HI - ALTR_A10SR_LED_VALID_SHIFT)) { | 70 | if (nr > (ALTR_A10SR_OUT_VALID_RANGE_HI - ALTR_A10SR_LED_VALID_SHIFT)) |
| 70 | altr_a10sr_gpio_set(gc, nr, value); | 71 | return -EINVAL; |
| 71 | return 0; | 72 | |
| 72 | } | 73 | altr_a10sr_gpio_set(gc, nr, value); |
| 73 | return -EINVAL; | 74 | return 0; |
| 74 | } | 75 | } |
| 75 | 76 | ||
| 76 | static const struct gpio_chip altr_a10sr_gc = { | 77 | static const struct gpio_chip altr_a10sr_gc = { |
diff --git a/drivers/gpio/gpio-altera.c b/drivers/gpio/gpio-altera.c index 8c3ff6e2366f..748fdd4e9a53 100644 --- a/drivers/gpio/gpio-altera.c +++ b/drivers/gpio/gpio-altera.c | |||
| @@ -32,9 +32,9 @@ | |||
| 32 | * struct altera_gpio_chip | 32 | * struct altera_gpio_chip |
| 33 | * @mmchip : memory mapped chip structure. | 33 | * @mmchip : memory mapped chip structure. |
| 34 | * @gpio_lock : synchronization lock so that new irq/set/get requests | 34 | * @gpio_lock : synchronization lock so that new irq/set/get requests |
| 35 | will be blocked until the current one completes. | 35 | * will be blocked until the current one completes. |
| 36 | * @interrupt_trigger : specifies the hardware configured IRQ trigger type | 36 | * @interrupt_trigger : specifies the hardware configured IRQ trigger type |
| 37 | (rising, falling, both, high) | 37 | * (rising, falling, both, high) |
| 38 | * @mapped_irq : kernel mapped irq number. | 38 | * @mapped_irq : kernel mapped irq number. |
| 39 | */ | 39 | */ |
| 40 | struct altera_gpio_chip { | 40 | struct altera_gpio_chip { |
diff --git a/drivers/gpio/gpio-amd-fch.c b/drivers/gpio/gpio-amd-fch.c new file mode 100644 index 000000000000..38c3f4a3d4aa --- /dev/null +++ b/drivers/gpio/gpio-amd-fch.c | |||
| @@ -0,0 +1,194 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0+ | ||
| 2 | |||
| 3 | /* | ||
| 4 | * GPIO driver for the AMD G series FCH (eg. GX-412TC) | ||
| 5 | * | ||
| 6 | * Copyright (C) 2018 metux IT consult | ||
| 7 | * Author: Enrico Weigelt, metux IT consult <info@metux.net> | ||
| 8 | * | ||
| 9 | */ | ||
| 10 | |||
| 11 | #include <linux/err.h> | ||
| 12 | #include <linux/io.h> | ||
| 13 | #include <linux/kernel.h> | ||
| 14 | #include <linux/module.h> | ||
| 15 | #include <linux/platform_device.h> | ||
| 16 | #include <linux/gpio/driver.h> | ||
| 17 | #include <linux/platform_data/gpio/gpio-amd-fch.h> | ||
| 18 | #include <linux/spinlock.h> | ||
| 19 | |||
| 20 | #define AMD_FCH_MMIO_BASE 0xFED80000 | ||
| 21 | #define AMD_FCH_GPIO_BANK0_BASE 0x1500 | ||
| 22 | #define AMD_FCH_GPIO_SIZE 0x0300 | ||
| 23 | |||
| 24 | #define AMD_FCH_GPIO_FLAG_DIRECTION BIT(23) | ||
| 25 | #define AMD_FCH_GPIO_FLAG_WRITE BIT(22) | ||
| 26 | #define AMD_FCH_GPIO_FLAG_READ BIT(16) | ||
| 27 | |||
| 28 | static struct resource amd_fch_gpio_iores = | ||
| 29 | DEFINE_RES_MEM_NAMED( | ||
| 30 | AMD_FCH_MMIO_BASE + AMD_FCH_GPIO_BANK0_BASE, | ||
| 31 | AMD_FCH_GPIO_SIZE, | ||
| 32 | "amd-fch-gpio-iomem"); | ||
| 33 | |||
| 34 | struct amd_fch_gpio_priv { | ||
| 35 | struct platform_device *pdev; | ||
| 36 | struct gpio_chip gc; | ||
| 37 | void __iomem *base; | ||
| 38 | struct amd_fch_gpio_pdata *pdata; | ||
| 39 | spinlock_t lock; | ||
| 40 | }; | ||
| 41 | |||
| 42 | static void __iomem *amd_fch_gpio_addr(struct amd_fch_gpio_priv *priv, | ||
| 43 | unsigned int gpio) | ||
| 44 | { | ||
| 45 | return priv->base + priv->pdata->gpio_reg[gpio]*sizeof(u32); | ||
| 46 | } | ||
| 47 | |||
| 48 | static int amd_fch_gpio_direction_input(struct gpio_chip *gc, | ||
| 49 | unsigned int offset) | ||
| 50 | { | ||
| 51 | unsigned long flags; | ||
| 52 | struct amd_fch_gpio_priv *priv = gpiochip_get_data(gc); | ||
| 53 | void __iomem *ptr = amd_fch_gpio_addr(priv, offset); | ||
| 54 | |||
| 55 | spin_lock_irqsave(&priv->lock, flags); | ||
| 56 | writel_relaxed(readl_relaxed(ptr) & ~AMD_FCH_GPIO_FLAG_DIRECTION, ptr); | ||
| 57 | spin_unlock_irqrestore(&priv->lock, flags); | ||
| 58 | |||
| 59 | return 0; | ||
| 60 | } | ||
| 61 | |||
| 62 | static int amd_fch_gpio_direction_output(struct gpio_chip *gc, | ||
| 63 | unsigned int gpio, int value) | ||
| 64 | { | ||
| 65 | unsigned long flags; | ||
| 66 | struct amd_fch_gpio_priv *priv = gpiochip_get_data(gc); | ||
| 67 | void __iomem *ptr = amd_fch_gpio_addr(priv, gpio); | ||
| 68 | u32 val; | ||
| 69 | |||
| 70 | spin_lock_irqsave(&priv->lock, flags); | ||
| 71 | |||
| 72 | val = readl_relaxed(ptr); | ||
| 73 | if (value) | ||
| 74 | val |= AMD_FCH_GPIO_FLAG_WRITE; | ||
| 75 | else | ||
| 76 | val &= ~AMD_FCH_GPIO_FLAG_WRITE; | ||
| 77 | |||
| 78 | writel_relaxed(val | AMD_FCH_GPIO_FLAG_DIRECTION, ptr); | ||
| 79 | |||
| 80 | spin_unlock_irqrestore(&priv->lock, flags); | ||
| 81 | |||
| 82 | return 0; | ||
| 83 | } | ||
| 84 | |||
| 85 | static int amd_fch_gpio_get_direction(struct gpio_chip *gc, unsigned int gpio) | ||
| 86 | { | ||
| 87 | int ret; | ||
| 88 | unsigned long flags; | ||
| 89 | struct amd_fch_gpio_priv *priv = gpiochip_get_data(gc); | ||
| 90 | void __iomem *ptr = amd_fch_gpio_addr(priv, gpio); | ||
| 91 | |||
| 92 | spin_lock_irqsave(&priv->lock, flags); | ||
| 93 | ret = (readl_relaxed(ptr) & AMD_FCH_GPIO_FLAG_DIRECTION); | ||
| 94 | spin_unlock_irqrestore(&priv->lock, flags); | ||
| 95 | |||
| 96 | return ret; | ||
| 97 | } | ||
| 98 | |||
| 99 | static void amd_fch_gpio_set(struct gpio_chip *gc, | ||
| 100 | unsigned int gpio, int value) | ||
| 101 | { | ||
| 102 | unsigned long flags; | ||
| 103 | struct amd_fch_gpio_priv *priv = gpiochip_get_data(gc); | ||
| 104 | void __iomem *ptr = amd_fch_gpio_addr(priv, gpio); | ||
| 105 | u32 mask; | ||
| 106 | |||
| 107 | spin_lock_irqsave(&priv->lock, flags); | ||
| 108 | |||
| 109 | mask = readl_relaxed(ptr); | ||
| 110 | if (value) | ||
| 111 | mask |= AMD_FCH_GPIO_FLAG_WRITE; | ||
| 112 | else | ||
| 113 | mask &= ~AMD_FCH_GPIO_FLAG_WRITE; | ||
| 114 | writel_relaxed(mask, ptr); | ||
| 115 | |||
| 116 | spin_unlock_irqrestore(&priv->lock, flags); | ||
| 117 | } | ||
| 118 | |||
| 119 | static int amd_fch_gpio_get(struct gpio_chip *gc, | ||
| 120 | unsigned int offset) | ||
| 121 | { | ||
| 122 | unsigned long flags; | ||
| 123 | int ret; | ||
| 124 | struct amd_fch_gpio_priv *priv = gpiochip_get_data(gc); | ||
| 125 | void __iomem *ptr = amd_fch_gpio_addr(priv, offset); | ||
| 126 | |||
| 127 | spin_lock_irqsave(&priv->lock, flags); | ||
| 128 | ret = (readl_relaxed(ptr) & AMD_FCH_GPIO_FLAG_READ); | ||
| 129 | spin_unlock_irqrestore(&priv->lock, flags); | ||
| 130 | |||
| 131 | return ret; | ||
| 132 | } | ||
| 133 | |||
| 134 | static int amd_fch_gpio_request(struct gpio_chip *chip, | ||
| 135 | unsigned int gpio_pin) | ||
| 136 | { | ||
| 137 | return 0; | ||
| 138 | } | ||
| 139 | |||
| 140 | static int amd_fch_gpio_probe(struct platform_device *pdev) | ||
| 141 | { | ||
| 142 | struct amd_fch_gpio_priv *priv; | ||
| 143 | struct amd_fch_gpio_pdata *pdata; | ||
| 144 | |||
| 145 | pdata = dev_get_platdata(&pdev->dev); | ||
| 146 | if (!pdata) { | ||
| 147 | dev_err(&pdev->dev, "no platform_data\n"); | ||
| 148 | return -ENOENT; | ||
| 149 | } | ||
| 150 | |||
| 151 | priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); | ||
| 152 | if (!priv) | ||
| 153 | return -ENOMEM; | ||
| 154 | |||
| 155 | priv->pdata = pdata; | ||
| 156 | priv->pdev = pdev; | ||
| 157 | |||
| 158 | priv->gc.owner = THIS_MODULE; | ||
| 159 | priv->gc.parent = &pdev->dev; | ||
| 160 | priv->gc.label = dev_name(&pdev->dev); | ||
| 161 | priv->gc.ngpio = priv->pdata->gpio_num; | ||
| 162 | priv->gc.names = priv->pdata->gpio_names; | ||
| 163 | priv->gc.base = -1; | ||
| 164 | priv->gc.request = amd_fch_gpio_request; | ||
| 165 | priv->gc.direction_input = amd_fch_gpio_direction_input; | ||
| 166 | priv->gc.direction_output = amd_fch_gpio_direction_output; | ||
| 167 | priv->gc.get_direction = amd_fch_gpio_get_direction; | ||
| 168 | priv->gc.get = amd_fch_gpio_get; | ||
| 169 | priv->gc.set = amd_fch_gpio_set; | ||
| 170 | |||
| 171 | spin_lock_init(&priv->lock); | ||
| 172 | |||
| 173 | priv->base = devm_ioremap_resource(&pdev->dev, &amd_fch_gpio_iores); | ||
| 174 | if (IS_ERR(priv->base)) | ||
| 175 | return PTR_ERR(priv->base); | ||
| 176 | |||
| 177 | platform_set_drvdata(pdev, priv); | ||
| 178 | |||
| 179 | return devm_gpiochip_add_data(&pdev->dev, &priv->gc, priv); | ||
| 180 | } | ||
| 181 | |||
| 182 | static struct platform_driver amd_fch_gpio_driver = { | ||
| 183 | .driver = { | ||
| 184 | .name = AMD_FCH_GPIO_DRIVER_NAME, | ||
| 185 | }, | ||
| 186 | .probe = amd_fch_gpio_probe, | ||
| 187 | }; | ||
| 188 | |||
| 189 | module_platform_driver(amd_fch_gpio_driver); | ||
| 190 | |||
| 191 | MODULE_AUTHOR("Enrico Weigelt, metux IT consult <info@metux.net>"); | ||
| 192 | MODULE_DESCRIPTION("AMD G-series FCH GPIO driver"); | ||
| 193 | MODULE_LICENSE("GPL"); | ||
| 194 | MODULE_ALIAS("platform:" AMD_FCH_GPIO_DRIVER_NAME); | ||
diff --git a/drivers/gpio/gpio-crystalcove.c b/drivers/gpio/gpio-crystalcove.c index 58531d8b8c6e..14d1f4c933b6 100644 --- a/drivers/gpio/gpio-crystalcove.c +++ b/drivers/gpio/gpio-crystalcove.c | |||
| @@ -1,28 +1,20 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 1 | /* | 2 | /* |
| 2 | * gpio-crystalcove.c - Intel Crystal Cove GPIO Driver | 3 | * Intel Crystal Cove GPIO Driver |
| 3 | * | 4 | * |
| 4 | * Copyright (C) 2012, 2014 Intel Corporation. All rights reserved. | 5 | * Copyright (C) 2012, 2014 Intel Corporation. All rights reserved. |
| 5 | * | 6 | * |
| 6 | * This program is free software; you can redistribute it and/or | ||
| 7 | * modify it under the terms of the GNU General Public License version | ||
| 8 | * 2 as published by the Free Software Foundation. | ||
| 9 | * | ||
| 10 | * This program is distributed in the hope that it will be useful, | ||
| 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 13 | * GNU General Public License for more details. | ||
| 14 | * | ||
| 15 | * Author: Yang, Bin <bin.yang@intel.com> | 7 | * Author: Yang, Bin <bin.yang@intel.com> |
| 16 | */ | 8 | */ |
| 17 | 9 | ||
| 10 | #include <linux/bitops.h> | ||
| 11 | #include <linux/gpio/driver.h> | ||
| 18 | #include <linux/interrupt.h> | 12 | #include <linux/interrupt.h> |
| 13 | #include <linux/mfd/intel_soc_pmic.h> | ||
| 19 | #include <linux/module.h> | 14 | #include <linux/module.h> |
| 20 | #include <linux/platform_device.h> | 15 | #include <linux/platform_device.h> |
| 21 | #include <linux/gpio/driver.h> | ||
| 22 | #include <linux/seq_file.h> | ||
| 23 | #include <linux/bitops.h> | ||
| 24 | #include <linux/regmap.h> | 16 | #include <linux/regmap.h> |
| 25 | #include <linux/mfd/intel_soc_pmic.h> | 17 | #include <linux/seq_file.h> |
| 26 | 18 | ||
| 27 | #define CRYSTALCOVE_GPIO_NUM 16 | 19 | #define CRYSTALCOVE_GPIO_NUM 16 |
| 28 | #define CRYSTALCOVE_VGPIO_NUM 95 | 20 | #define CRYSTALCOVE_VGPIO_NUM 95 |
| @@ -279,8 +271,8 @@ static struct irq_chip crystalcove_irqchip = { | |||
| 279 | static irqreturn_t crystalcove_gpio_irq_handler(int irq, void *data) | 271 | static irqreturn_t crystalcove_gpio_irq_handler(int irq, void *data) |
| 280 | { | 272 | { |
| 281 | struct crystalcove_gpio *cg = data; | 273 | struct crystalcove_gpio *cg = data; |
| 274 | unsigned long pending; | ||
| 282 | unsigned int p0, p1; | 275 | unsigned int p0, p1; |
| 283 | int pending; | ||
| 284 | int gpio; | 276 | int gpio; |
| 285 | unsigned int virq; | 277 | unsigned int virq; |
| 286 | 278 | ||
| @@ -293,11 +285,9 @@ static irqreturn_t crystalcove_gpio_irq_handler(int irq, void *data) | |||
| 293 | 285 | ||
| 294 | pending = p0 | p1 << 8; | 286 | pending = p0 | p1 << 8; |
| 295 | 287 | ||
| 296 | for (gpio = 0; gpio < CRYSTALCOVE_GPIO_NUM; gpio++) { | 288 | for_each_set_bit(gpio, &pending, CRYSTALCOVE_GPIO_NUM) { |
| 297 | if (pending & BIT(gpio)) { | 289 | virq = irq_find_mapping(cg->chip.irq.domain, gpio); |
| 298 | virq = irq_find_mapping(cg->chip.irq.domain, gpio); | 290 | handle_nested_irq(virq); |
| 299 | handle_nested_irq(virq); | ||
| 300 | } | ||
| 301 | } | 291 | } |
| 302 | 292 | ||
| 303 | return IRQ_HANDLED; | 293 | return IRQ_HANDLED; |
diff --git a/drivers/gpio/gpio-davinci.c b/drivers/gpio/gpio-davinci.c index bdb29e51b417..188b8e5c8e67 100644 --- a/drivers/gpio/gpio-davinci.c +++ b/drivers/gpio/gpio-davinci.c | |||
| @@ -198,7 +198,6 @@ static int davinci_gpio_probe(struct platform_device *pdev) | |||
| 198 | struct davinci_gpio_controller *chips; | 198 | struct davinci_gpio_controller *chips; |
| 199 | struct davinci_gpio_platform_data *pdata; | 199 | struct davinci_gpio_platform_data *pdata; |
| 200 | struct device *dev = &pdev->dev; | 200 | struct device *dev = &pdev->dev; |
| 201 | struct resource *res; | ||
| 202 | 201 | ||
| 203 | pdata = davinci_gpio_get_pdata(pdev); | 202 | pdata = davinci_gpio_get_pdata(pdev); |
| 204 | if (!pdata) { | 203 | if (!pdata) { |
| @@ -236,8 +235,7 @@ static int davinci_gpio_probe(struct platform_device *pdev) | |||
| 236 | if (!chips) | 235 | if (!chips) |
| 237 | return -ENOMEM; | 236 | return -ENOMEM; |
| 238 | 237 | ||
| 239 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 238 | gpio_base = devm_platform_ioremap_resource(pdev, 0); |
| 240 | gpio_base = devm_ioremap_resource(dev, res); | ||
| 241 | if (IS_ERR(gpio_base)) | 239 | if (IS_ERR(gpio_base)) |
| 242 | return PTR_ERR(gpio_base); | 240 | return PTR_ERR(gpio_base); |
| 243 | 241 | ||
diff --git a/drivers/gpio/gpio-eic-sprd.c b/drivers/gpio/gpio-eic-sprd.c index e41223c05f6e..f0223cee9774 100644 --- a/drivers/gpio/gpio-eic-sprd.c +++ b/drivers/gpio/gpio-eic-sprd.c | |||
| @@ -432,6 +432,7 @@ static int sprd_eic_irq_set_type(struct irq_data *data, unsigned int flow_type) | |||
| 432 | default: | 432 | default: |
| 433 | return -ENOTSUPP; | 433 | return -ENOTSUPP; |
| 434 | } | 434 | } |
| 435 | break; | ||
| 435 | default: | 436 | default: |
| 436 | dev_err(chip->parent, "Unsupported EIC type.\n"); | 437 | dev_err(chip->parent, "Unsupported EIC type.\n"); |
| 437 | return -ENOTSUPP; | 438 | return -ENOTSUPP; |
diff --git a/drivers/gpio/gpio-f7188x.c b/drivers/gpio/gpio-f7188x.c index 13350c9d7f5e..0896c825b312 100644 --- a/drivers/gpio/gpio-f7188x.c +++ b/drivers/gpio/gpio-f7188x.c | |||
| @@ -39,8 +39,10 @@ | |||
| 39 | #define SIO_F71889_ID 0x0909 /* F71889 chipset ID */ | 39 | #define SIO_F71889_ID 0x0909 /* F71889 chipset ID */ |
| 40 | #define SIO_F71889A_ID 0x1005 /* F71889A chipset ID */ | 40 | #define SIO_F71889A_ID 0x1005 /* F71889A chipset ID */ |
| 41 | #define SIO_F81866_ID 0x1010 /* F81866 chipset ID */ | 41 | #define SIO_F81866_ID 0x1010 /* F81866 chipset ID */ |
| 42 | #define SIO_F81804_ID 0x1502 /* F81804 chipset ID, same for f81966 */ | ||
| 42 | 43 | ||
| 43 | enum chips { f71869, f71869a, f71882fg, f71889a, f71889f, f81866 }; | 44 | |
| 45 | enum chips { f71869, f71869a, f71882fg, f71889a, f71889f, f81866, f81804 }; | ||
| 44 | 46 | ||
| 45 | static const char * const f7188x_names[] = { | 47 | static const char * const f7188x_names[] = { |
| 46 | "f71869", | 48 | "f71869", |
| @@ -49,6 +51,7 @@ static const char * const f7188x_names[] = { | |||
| 49 | "f71889a", | 51 | "f71889a", |
| 50 | "f71889f", | 52 | "f71889f", |
| 51 | "f81866", | 53 | "f81866", |
| 54 | "f81804", | ||
| 52 | }; | 55 | }; |
| 53 | 56 | ||
| 54 | struct f7188x_sio { | 57 | struct f7188x_sio { |
| @@ -223,6 +226,18 @@ static struct f7188x_gpio_bank f81866_gpio_bank[] = { | |||
| 223 | F7188X_GPIO_BANK(80, 8, 0x88), | 226 | F7188X_GPIO_BANK(80, 8, 0x88), |
| 224 | }; | 227 | }; |
| 225 | 228 | ||
| 229 | |||
| 230 | static struct f7188x_gpio_bank f81804_gpio_bank[] = { | ||
| 231 | F7188X_GPIO_BANK(0, 8, 0xF0), | ||
| 232 | F7188X_GPIO_BANK(10, 8, 0xE0), | ||
| 233 | F7188X_GPIO_BANK(20, 8, 0xD0), | ||
| 234 | F7188X_GPIO_BANK(50, 8, 0xA0), | ||
| 235 | F7188X_GPIO_BANK(60, 8, 0x90), | ||
| 236 | F7188X_GPIO_BANK(70, 8, 0x80), | ||
| 237 | F7188X_GPIO_BANK(90, 8, 0x98), | ||
| 238 | }; | ||
| 239 | |||
| 240 | |||
| 226 | static int f7188x_gpio_get_direction(struct gpio_chip *chip, unsigned offset) | 241 | static int f7188x_gpio_get_direction(struct gpio_chip *chip, unsigned offset) |
| 227 | { | 242 | { |
| 228 | int err; | 243 | int err; |
| @@ -407,6 +422,10 @@ static int f7188x_gpio_probe(struct platform_device *pdev) | |||
| 407 | data->nr_bank = ARRAY_SIZE(f81866_gpio_bank); | 422 | data->nr_bank = ARRAY_SIZE(f81866_gpio_bank); |
| 408 | data->bank = f81866_gpio_bank; | 423 | data->bank = f81866_gpio_bank; |
| 409 | break; | 424 | break; |
| 425 | case f81804: | ||
| 426 | data->nr_bank = ARRAY_SIZE(f81804_gpio_bank); | ||
| 427 | data->bank = f81804_gpio_bank; | ||
| 428 | break; | ||
| 410 | default: | 429 | default: |
| 411 | return -ENODEV; | 430 | return -ENODEV; |
| 412 | } | 431 | } |
| @@ -469,6 +488,9 @@ static int __init f7188x_find(int addr, struct f7188x_sio *sio) | |||
| 469 | case SIO_F81866_ID: | 488 | case SIO_F81866_ID: |
| 470 | sio->type = f81866; | 489 | sio->type = f81866; |
| 471 | break; | 490 | break; |
| 491 | case SIO_F81804_ID: | ||
| 492 | sio->type = f81804; | ||
| 493 | break; | ||
| 472 | default: | 494 | default: |
| 473 | pr_info(DRVNAME ": Unsupported Fintek device 0x%04x\n", devid); | 495 | pr_info(DRVNAME ": Unsupported Fintek device 0x%04x\n", devid); |
| 474 | goto err; | 496 | goto err; |
diff --git a/drivers/gpio/gpio-ftgpio010.c b/drivers/gpio/gpio-ftgpio010.c index 95f578804b0e..45fe125823a8 100644 --- a/drivers/gpio/gpio-ftgpio010.c +++ b/drivers/gpio/gpio-ftgpio010.c | |||
| @@ -41,12 +41,14 @@ | |||
| 41 | * struct ftgpio_gpio - Gemini GPIO state container | 41 | * struct ftgpio_gpio - Gemini GPIO state container |
| 42 | * @dev: containing device for this instance | 42 | * @dev: containing device for this instance |
| 43 | * @gc: gpiochip for this instance | 43 | * @gc: gpiochip for this instance |
| 44 | * @irq: irqchip for this instance | ||
| 44 | * @base: remapped I/O-memory base | 45 | * @base: remapped I/O-memory base |
| 45 | * @clk: silicon clock | 46 | * @clk: silicon clock |
| 46 | */ | 47 | */ |
| 47 | struct ftgpio_gpio { | 48 | struct ftgpio_gpio { |
| 48 | struct device *dev; | 49 | struct device *dev; |
| 49 | struct gpio_chip gc; | 50 | struct gpio_chip gc; |
| 51 | struct irq_chip irq; | ||
| 50 | void __iomem *base; | 52 | void __iomem *base; |
| 51 | struct clk *clk; | 53 | struct clk *clk; |
| 52 | }; | 54 | }; |
| @@ -134,14 +136,6 @@ static int ftgpio_gpio_set_irq_type(struct irq_data *d, unsigned int type) | |||
| 134 | return 0; | 136 | return 0; |
| 135 | } | 137 | } |
| 136 | 138 | ||
| 137 | static struct irq_chip ftgpio_gpio_irqchip = { | ||
| 138 | .name = "FTGPIO010", | ||
| 139 | .irq_ack = ftgpio_gpio_ack_irq, | ||
| 140 | .irq_mask = ftgpio_gpio_mask_irq, | ||
| 141 | .irq_unmask = ftgpio_gpio_unmask_irq, | ||
| 142 | .irq_set_type = ftgpio_gpio_set_irq_type, | ||
| 143 | }; | ||
| 144 | |||
| 145 | static void ftgpio_gpio_irq_handler(struct irq_desc *desc) | 139 | static void ftgpio_gpio_irq_handler(struct irq_desc *desc) |
| 146 | { | 140 | { |
| 147 | struct gpio_chip *gc = irq_desc_get_handler_data(desc); | 141 | struct gpio_chip *gc = irq_desc_get_handler_data(desc); |
| @@ -297,14 +291,20 @@ static int ftgpio_gpio_probe(struct platform_device *pdev) | |||
| 297 | /* Clear any use of debounce */ | 291 | /* Clear any use of debounce */ |
| 298 | writel(0x0, g->base + GPIO_DEBOUNCE_EN); | 292 | writel(0x0, g->base + GPIO_DEBOUNCE_EN); |
| 299 | 293 | ||
| 300 | ret = gpiochip_irqchip_add(&g->gc, &ftgpio_gpio_irqchip, | 294 | g->irq.name = "FTGPIO010"; |
| 295 | g->irq.irq_ack = ftgpio_gpio_ack_irq; | ||
| 296 | g->irq.irq_mask = ftgpio_gpio_mask_irq; | ||
| 297 | g->irq.irq_unmask = ftgpio_gpio_unmask_irq; | ||
| 298 | g->irq.irq_set_type = ftgpio_gpio_set_irq_type; | ||
| 299 | |||
| 300 | ret = gpiochip_irqchip_add(&g->gc, &g->irq, | ||
| 301 | 0, handle_bad_irq, | 301 | 0, handle_bad_irq, |
| 302 | IRQ_TYPE_NONE); | 302 | IRQ_TYPE_NONE); |
| 303 | if (ret) { | 303 | if (ret) { |
| 304 | dev_info(dev, "could not add irqchip\n"); | 304 | dev_info(dev, "could not add irqchip\n"); |
| 305 | goto dis_clk; | 305 | goto dis_clk; |
| 306 | } | 306 | } |
| 307 | gpiochip_set_chained_irqchip(&g->gc, &ftgpio_gpio_irqchip, | 307 | gpiochip_set_chained_irqchip(&g->gc, &g->irq, |
| 308 | irq, ftgpio_gpio_irq_handler); | 308 | irq, ftgpio_gpio_irq_handler); |
| 309 | 309 | ||
| 310 | platform_set_drvdata(pdev, g); | 310 | platform_set_drvdata(pdev, g); |
diff --git a/drivers/gpio/gpio-gw-pld.c b/drivers/gpio/gpio-gw-pld.c new file mode 100644 index 000000000000..242112ff60ee --- /dev/null +++ b/drivers/gpio/gpio-gw-pld.c | |||
| @@ -0,0 +1,137 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0+ | ||
| 2 | // | ||
| 3 | // Gateworks I2C PLD GPIO expander | ||
| 4 | // | ||
| 5 | // Copyright (C) 2019 Linus Walleij <linus.walleij@linaro.org> | ||
| 6 | // | ||
| 7 | // Based on code and know-how from the OpenWrt driver: | ||
| 8 | // Copyright (C) 2009 Gateworks Corporation | ||
| 9 | // Authors: Chris Lang, Imre Kaloz | ||
| 10 | |||
| 11 | #include <linux/bits.h> | ||
| 12 | #include <linux/kernel.h> | ||
| 13 | #include <linux/slab.h> | ||
| 14 | #include <linux/gpio/driver.h> | ||
| 15 | #include <linux/i2c.h> | ||
| 16 | #include <linux/module.h> | ||
| 17 | |||
| 18 | /** | ||
| 19 | * struct gw_pld - State container for Gateworks PLD | ||
| 20 | * @chip: GPIO chip instance | ||
| 21 | * @client: I2C client | ||
| 22 | * @out: shadow register for the output bute | ||
| 23 | */ | ||
| 24 | struct gw_pld { | ||
| 25 | struct gpio_chip chip; | ||
| 26 | struct i2c_client *client; | ||
| 27 | u8 out; | ||
| 28 | }; | ||
| 29 | |||
| 30 | /* | ||
| 31 | * The Gateworks I2C PLD chip only expose one read and one write register. | ||
| 32 | * Writing a "one" bit (to match the reset state) lets that pin be used as an | ||
| 33 | * input. It is an open-drain model. | ||
| 34 | */ | ||
| 35 | static int gw_pld_input8(struct gpio_chip *gc, unsigned offset) | ||
| 36 | { | ||
| 37 | struct gw_pld *gw = gpiochip_get_data(gc); | ||
| 38 | |||
| 39 | gw->out |= BIT(offset); | ||
| 40 | return i2c_smbus_write_byte(gw->client, gw->out); | ||
| 41 | } | ||
| 42 | |||
| 43 | static int gw_pld_get8(struct gpio_chip *gc, unsigned offset) | ||
| 44 | { | ||
| 45 | struct gw_pld *gw = gpiochip_get_data(gc); | ||
| 46 | s32 val; | ||
| 47 | |||
| 48 | val = i2c_smbus_read_byte(gw->client); | ||
| 49 | |||
| 50 | return (val < 0) ? 0 : !!(val & BIT(offset)); | ||
| 51 | } | ||
| 52 | |||
| 53 | static int gw_pld_output8(struct gpio_chip *gc, unsigned offset, int value) | ||
| 54 | { | ||
| 55 | struct gw_pld *gw = gpiochip_get_data(gc); | ||
| 56 | |||
| 57 | if (value) | ||
| 58 | gw->out |= BIT(offset); | ||
| 59 | else | ||
| 60 | gw->out &= ~BIT(offset); | ||
| 61 | |||
| 62 | return i2c_smbus_write_byte(gw->client, gw->out); | ||
| 63 | } | ||
| 64 | |||
| 65 | static void gw_pld_set8(struct gpio_chip *gc, unsigned offset, int value) | ||
| 66 | { | ||
| 67 | gw_pld_output8(gc, offset, value); | ||
| 68 | } | ||
| 69 | |||
| 70 | static int gw_pld_probe(struct i2c_client *client, | ||
| 71 | const struct i2c_device_id *id) | ||
| 72 | { | ||
| 73 | struct device *dev = &client->dev; | ||
| 74 | struct device_node *np = dev->of_node; | ||
| 75 | struct gw_pld *gw; | ||
| 76 | int ret; | ||
| 77 | |||
| 78 | gw = devm_kzalloc(dev, sizeof(*gw), GFP_KERNEL); | ||
| 79 | if (!gw) | ||
| 80 | return -ENOMEM; | ||
| 81 | |||
| 82 | gw->chip.base = -1; | ||
| 83 | gw->chip.can_sleep = true; | ||
| 84 | gw->chip.parent = dev; | ||
| 85 | gw->chip.of_node = np; | ||
| 86 | gw->chip.owner = THIS_MODULE; | ||
| 87 | gw->chip.label = dev_name(dev); | ||
| 88 | gw->chip.ngpio = 8; | ||
| 89 | gw->chip.direction_input = gw_pld_input8; | ||
| 90 | gw->chip.get = gw_pld_get8; | ||
| 91 | gw->chip.direction_output = gw_pld_output8; | ||
| 92 | gw->chip.set = gw_pld_set8; | ||
| 93 | gw->client = client; | ||
| 94 | |||
| 95 | /* | ||
| 96 | * The Gateworks I2C PLD chip does not properly send the acknowledge | ||
| 97 | * bit at all times, but we can still use the standard i2c_smbus | ||
| 98 | * functions by simply ignoring this bit. | ||
| 99 | */ | ||
| 100 | client->flags |= I2C_M_IGNORE_NAK; | ||
| 101 | gw->out = 0xFF; | ||
| 102 | |||
| 103 | i2c_set_clientdata(client, gw); | ||
| 104 | |||
| 105 | ret = devm_gpiochip_add_data(dev, &gw->chip, gw); | ||
| 106 | if (ret) | ||
| 107 | return ret; | ||
| 108 | |||
| 109 | dev_info(dev, "registered Gateworks PLD GPIO device\n"); | ||
| 110 | |||
| 111 | return 0; | ||
| 112 | } | ||
| 113 | |||
| 114 | static const struct i2c_device_id gw_pld_id[] = { | ||
| 115 | { "gw-pld", }, | ||
| 116 | { } | ||
| 117 | }; | ||
| 118 | MODULE_DEVICE_TABLE(i2c, gw_pld_id); | ||
| 119 | |||
| 120 | static const struct of_device_id gw_pld_dt_ids[] = { | ||
| 121 | { .compatible = "gateworks,pld-gpio", }, | ||
| 122 | { }, | ||
| 123 | }; | ||
| 124 | MODULE_DEVICE_TABLE(of, gw_pld_dt_ids); | ||
| 125 | |||
| 126 | static struct i2c_driver gw_pld_driver = { | ||
| 127 | .driver = { | ||
| 128 | .name = "gw_pld", | ||
| 129 | .of_match_table = gw_pld_dt_ids, | ||
| 130 | }, | ||
| 131 | .probe = gw_pld_probe, | ||
| 132 | .id_table = gw_pld_id, | ||
| 133 | }; | ||
| 134 | module_i2c_driver(gw_pld_driver); | ||
| 135 | |||
| 136 | MODULE_LICENSE("GPL"); | ||
| 137 | MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>"); | ||
diff --git a/drivers/gpio/gpio-hlwd.c b/drivers/gpio/gpio-hlwd.c index a63136a68ba3..a7b17897356e 100644 --- a/drivers/gpio/gpio-hlwd.c +++ b/drivers/gpio/gpio-hlwd.c | |||
| @@ -48,9 +48,163 @@ | |||
| 48 | 48 | ||
| 49 | struct hlwd_gpio { | 49 | struct hlwd_gpio { |
| 50 | struct gpio_chip gpioc; | 50 | struct gpio_chip gpioc; |
| 51 | struct irq_chip irqc; | ||
| 51 | void __iomem *regs; | 52 | void __iomem *regs; |
| 53 | int irq; | ||
| 54 | u32 edge_emulation; | ||
| 55 | u32 rising_edge, falling_edge; | ||
| 52 | }; | 56 | }; |
| 53 | 57 | ||
| 58 | static void hlwd_gpio_irqhandler(struct irq_desc *desc) | ||
| 59 | { | ||
| 60 | struct hlwd_gpio *hlwd = | ||
| 61 | gpiochip_get_data(irq_desc_get_handler_data(desc)); | ||
| 62 | struct irq_chip *chip = irq_desc_get_chip(desc); | ||
| 63 | unsigned long flags; | ||
| 64 | unsigned long pending; | ||
| 65 | int hwirq; | ||
| 66 | u32 emulated_pending; | ||
| 67 | |||
| 68 | spin_lock_irqsave(&hlwd->gpioc.bgpio_lock, flags); | ||
| 69 | pending = ioread32be(hlwd->regs + HW_GPIOB_INTFLAG); | ||
| 70 | pending &= ioread32be(hlwd->regs + HW_GPIOB_INTMASK); | ||
| 71 | |||
| 72 | /* Treat interrupts due to edge trigger emulation separately */ | ||
| 73 | emulated_pending = hlwd->edge_emulation & pending; | ||
| 74 | pending &= ~emulated_pending; | ||
| 75 | if (emulated_pending) { | ||
| 76 | u32 level, rising, falling; | ||
| 77 | |||
| 78 | level = ioread32be(hlwd->regs + HW_GPIOB_INTLVL); | ||
| 79 | rising = level & emulated_pending; | ||
| 80 | falling = ~level & emulated_pending; | ||
| 81 | |||
| 82 | /* Invert the levels */ | ||
| 83 | iowrite32be(level ^ emulated_pending, | ||
| 84 | hlwd->regs + HW_GPIOB_INTLVL); | ||
| 85 | |||
| 86 | /* Ack all emulated-edge interrupts */ | ||
| 87 | iowrite32be(emulated_pending, hlwd->regs + HW_GPIOB_INTFLAG); | ||
| 88 | |||
| 89 | /* Signal interrupts only on the correct edge */ | ||
| 90 | rising &= hlwd->rising_edge; | ||
| 91 | falling &= hlwd->falling_edge; | ||
| 92 | |||
| 93 | /* Mark emulated interrupts as pending */ | ||
| 94 | pending |= rising | falling; | ||
| 95 | } | ||
| 96 | spin_unlock_irqrestore(&hlwd->gpioc.bgpio_lock, flags); | ||
| 97 | |||
| 98 | chained_irq_enter(chip, desc); | ||
| 99 | |||
| 100 | for_each_set_bit(hwirq, &pending, 32) { | ||
| 101 | int irq = irq_find_mapping(hlwd->gpioc.irq.domain, hwirq); | ||
| 102 | |||
| 103 | generic_handle_irq(irq); | ||
| 104 | } | ||
| 105 | |||
| 106 | chained_irq_exit(chip, desc); | ||
| 107 | } | ||
| 108 | |||
| 109 | static void hlwd_gpio_irq_ack(struct irq_data *data) | ||
| 110 | { | ||
| 111 | struct hlwd_gpio *hlwd = | ||
| 112 | gpiochip_get_data(irq_data_get_irq_chip_data(data)); | ||
| 113 | |||
| 114 | iowrite32be(BIT(data->hwirq), hlwd->regs + HW_GPIOB_INTFLAG); | ||
| 115 | } | ||
| 116 | |||
| 117 | static void hlwd_gpio_irq_mask(struct irq_data *data) | ||
| 118 | { | ||
| 119 | struct hlwd_gpio *hlwd = | ||
| 120 | gpiochip_get_data(irq_data_get_irq_chip_data(data)); | ||
| 121 | unsigned long flags; | ||
| 122 | u32 mask; | ||
| 123 | |||
| 124 | spin_lock_irqsave(&hlwd->gpioc.bgpio_lock, flags); | ||
| 125 | mask = ioread32be(hlwd->regs + HW_GPIOB_INTMASK); | ||
| 126 | mask &= ~BIT(data->hwirq); | ||
| 127 | iowrite32be(mask, hlwd->regs + HW_GPIOB_INTMASK); | ||
| 128 | spin_unlock_irqrestore(&hlwd->gpioc.bgpio_lock, flags); | ||
| 129 | } | ||
| 130 | |||
| 131 | static void hlwd_gpio_irq_unmask(struct irq_data *data) | ||
| 132 | { | ||
| 133 | struct hlwd_gpio *hlwd = | ||
| 134 | gpiochip_get_data(irq_data_get_irq_chip_data(data)); | ||
| 135 | unsigned long flags; | ||
| 136 | u32 mask; | ||
| 137 | |||
| 138 | spin_lock_irqsave(&hlwd->gpioc.bgpio_lock, flags); | ||
| 139 | mask = ioread32be(hlwd->regs + HW_GPIOB_INTMASK); | ||
| 140 | mask |= BIT(data->hwirq); | ||
| 141 | iowrite32be(mask, hlwd->regs + HW_GPIOB_INTMASK); | ||
| 142 | spin_unlock_irqrestore(&hlwd->gpioc.bgpio_lock, flags); | ||
| 143 | } | ||
| 144 | |||
| 145 | static void hlwd_gpio_irq_enable(struct irq_data *data) | ||
| 146 | { | ||
| 147 | hlwd_gpio_irq_ack(data); | ||
| 148 | hlwd_gpio_irq_unmask(data); | ||
| 149 | } | ||
| 150 | |||
| 151 | static void hlwd_gpio_irq_setup_emulation(struct hlwd_gpio *hlwd, int hwirq, | ||
| 152 | unsigned int flow_type) | ||
| 153 | { | ||
| 154 | u32 level, state; | ||
| 155 | |||
| 156 | /* Set the trigger level to the inactive level */ | ||
| 157 | level = ioread32be(hlwd->regs + HW_GPIOB_INTLVL); | ||
| 158 | state = ioread32be(hlwd->regs + HW_GPIOB_IN) & BIT(hwirq); | ||
| 159 | level &= ~BIT(hwirq); | ||
| 160 | level |= state ^ BIT(hwirq); | ||
| 161 | iowrite32be(level, hlwd->regs + HW_GPIOB_INTLVL); | ||
| 162 | |||
| 163 | hlwd->edge_emulation |= BIT(hwirq); | ||
| 164 | hlwd->rising_edge &= ~BIT(hwirq); | ||
| 165 | hlwd->falling_edge &= ~BIT(hwirq); | ||
| 166 | if (flow_type & IRQ_TYPE_EDGE_RISING) | ||
| 167 | hlwd->rising_edge |= BIT(hwirq); | ||
| 168 | if (flow_type & IRQ_TYPE_EDGE_FALLING) | ||
| 169 | hlwd->falling_edge |= BIT(hwirq); | ||
| 170 | } | ||
| 171 | |||
| 172 | static int hlwd_gpio_irq_set_type(struct irq_data *data, unsigned int flow_type) | ||
| 173 | { | ||
| 174 | struct hlwd_gpio *hlwd = | ||
| 175 | gpiochip_get_data(irq_data_get_irq_chip_data(data)); | ||
| 176 | unsigned long flags; | ||
| 177 | u32 level; | ||
| 178 | |||
| 179 | spin_lock_irqsave(&hlwd->gpioc.bgpio_lock, flags); | ||
| 180 | |||
| 181 | hlwd->edge_emulation &= ~BIT(data->hwirq); | ||
| 182 | |||
| 183 | switch (flow_type) { | ||
| 184 | case IRQ_TYPE_LEVEL_HIGH: | ||
| 185 | level = ioread32be(hlwd->regs + HW_GPIOB_INTLVL); | ||
| 186 | level |= BIT(data->hwirq); | ||
| 187 | iowrite32be(level, hlwd->regs + HW_GPIOB_INTLVL); | ||
| 188 | break; | ||
| 189 | case IRQ_TYPE_LEVEL_LOW: | ||
| 190 | level = ioread32be(hlwd->regs + HW_GPIOB_INTLVL); | ||
| 191 | level &= ~BIT(data->hwirq); | ||
| 192 | iowrite32be(level, hlwd->regs + HW_GPIOB_INTLVL); | ||
| 193 | break; | ||
| 194 | case IRQ_TYPE_EDGE_RISING: | ||
| 195 | case IRQ_TYPE_EDGE_FALLING: | ||
| 196 | case IRQ_TYPE_EDGE_BOTH: | ||
| 197 | hlwd_gpio_irq_setup_emulation(hlwd, data->hwirq, flow_type); | ||
| 198 | break; | ||
| 199 | default: | ||
| 200 | spin_unlock_irqrestore(&hlwd->gpioc.bgpio_lock, flags); | ||
| 201 | return -EINVAL; | ||
| 202 | } | ||
| 203 | |||
| 204 | spin_unlock_irqrestore(&hlwd->gpioc.bgpio_lock, flags); | ||
| 205 | return 0; | ||
| 206 | } | ||
| 207 | |||
| 54 | static int hlwd_gpio_probe(struct platform_device *pdev) | 208 | static int hlwd_gpio_probe(struct platform_device *pdev) |
| 55 | { | 209 | { |
| 56 | struct hlwd_gpio *hlwd; | 210 | struct hlwd_gpio *hlwd; |
| @@ -92,7 +246,43 @@ static int hlwd_gpio_probe(struct platform_device *pdev) | |||
| 92 | ngpios = 32; | 246 | ngpios = 32; |
| 93 | hlwd->gpioc.ngpio = ngpios; | 247 | hlwd->gpioc.ngpio = ngpios; |
| 94 | 248 | ||
| 95 | return devm_gpiochip_add_data(&pdev->dev, &hlwd->gpioc, hlwd); | 249 | res = devm_gpiochip_add_data(&pdev->dev, &hlwd->gpioc, hlwd); |
| 250 | if (res) | ||
| 251 | return res; | ||
| 252 | |||
| 253 | /* Mask and ack all interrupts */ | ||
| 254 | iowrite32be(0, hlwd->regs + HW_GPIOB_INTMASK); | ||
| 255 | iowrite32be(0xffffffff, hlwd->regs + HW_GPIOB_INTFLAG); | ||
| 256 | |||
| 257 | /* | ||
| 258 | * If this GPIO controller is not marked as an interrupt controller in | ||
| 259 | * the DT, return. | ||
| 260 | */ | ||
| 261 | if (!of_property_read_bool(pdev->dev.of_node, "interrupt-controller")) | ||
| 262 | return 0; | ||
| 263 | |||
| 264 | hlwd->irq = platform_get_irq(pdev, 0); | ||
| 265 | if (hlwd->irq < 0) { | ||
| 266 | dev_info(&pdev->dev, "platform_get_irq returned %d\n", | ||
| 267 | hlwd->irq); | ||
| 268 | return hlwd->irq; | ||
| 269 | } | ||
| 270 | |||
| 271 | hlwd->irqc.name = dev_name(&pdev->dev); | ||
| 272 | hlwd->irqc.irq_mask = hlwd_gpio_irq_mask; | ||
| 273 | hlwd->irqc.irq_unmask = hlwd_gpio_irq_unmask; | ||
| 274 | hlwd->irqc.irq_enable = hlwd_gpio_irq_enable; | ||
| 275 | hlwd->irqc.irq_set_type = hlwd_gpio_irq_set_type; | ||
| 276 | |||
| 277 | res = gpiochip_irqchip_add(&hlwd->gpioc, &hlwd->irqc, 0, | ||
| 278 | handle_level_irq, IRQ_TYPE_NONE); | ||
| 279 | if (res) | ||
| 280 | return res; | ||
| 281 | |||
| 282 | gpiochip_set_chained_irqchip(&hlwd->gpioc, &hlwd->irqc, | ||
| 283 | hlwd->irq, hlwd_gpio_irqhandler); | ||
| 284 | |||
| 285 | return 0; | ||
| 96 | } | 286 | } |
| 97 | 287 | ||
| 98 | static const struct of_device_id hlwd_gpio_match[] = { | 288 | static const struct of_device_id hlwd_gpio_match[] = { |
diff --git a/drivers/gpio/gpio-madera.c b/drivers/gpio/gpio-madera.c index 7ba68d1a0932..c9dad0543672 100644 --- a/drivers/gpio/gpio-madera.c +++ b/drivers/gpio/gpio-madera.c | |||
| @@ -107,7 +107,7 @@ static void madera_gpio_set(struct gpio_chip *chip, unsigned int offset, | |||
| 107 | MADERA_GPIO1_CTRL_1 + reg_offset, ret); | 107 | MADERA_GPIO1_CTRL_1 + reg_offset, ret); |
| 108 | } | 108 | } |
| 109 | 109 | ||
| 110 | static struct gpio_chip madera_gpio_chip = { | 110 | static const struct gpio_chip madera_gpio_chip = { |
| 111 | .label = "madera", | 111 | .label = "madera", |
| 112 | .owner = THIS_MODULE, | 112 | .owner = THIS_MODULE, |
| 113 | .request = gpiochip_generic_request, | 113 | .request = gpiochip_generic_request, |
diff --git a/drivers/gpio/gpio-mockup.c b/drivers/gpio/gpio-mockup.c index 6a50f9f59c90..154d959e8993 100644 --- a/drivers/gpio/gpio-mockup.c +++ b/drivers/gpio/gpio-mockup.c | |||
| @@ -47,6 +47,7 @@ enum { | |||
| 47 | struct gpio_mockup_line_status { | 47 | struct gpio_mockup_line_status { |
| 48 | int dir; | 48 | int dir; |
| 49 | int value; | 49 | int value; |
| 50 | int pull; | ||
| 50 | }; | 51 | }; |
| 51 | 52 | ||
| 52 | struct gpio_mockup_chip { | 53 | struct gpio_mockup_chip { |
| @@ -54,12 +55,13 @@ struct gpio_mockup_chip { | |||
| 54 | struct gpio_mockup_line_status *lines; | 55 | struct gpio_mockup_line_status *lines; |
| 55 | struct irq_sim irqsim; | 56 | struct irq_sim irqsim; |
| 56 | struct dentry *dbg_dir; | 57 | struct dentry *dbg_dir; |
| 58 | struct mutex lock; | ||
| 57 | }; | 59 | }; |
| 58 | 60 | ||
| 59 | struct gpio_mockup_dbgfs_private { | 61 | struct gpio_mockup_dbgfs_private { |
| 60 | struct gpio_mockup_chip *chip; | 62 | struct gpio_mockup_chip *chip; |
| 61 | struct gpio_desc *desc; | 63 | struct gpio_desc *desc; |
| 62 | int offset; | 64 | unsigned int offset; |
| 63 | }; | 65 | }; |
| 64 | 66 | ||
| 65 | static int gpio_mockup_ranges[GPIO_MOCKUP_MAX_RANGES]; | 67 | static int gpio_mockup_ranges[GPIO_MOCKUP_MAX_RANGES]; |
| @@ -82,29 +84,66 @@ static int gpio_mockup_range_ngpio(unsigned int index) | |||
| 82 | return gpio_mockup_ranges[index * 2 + 1]; | 84 | return gpio_mockup_ranges[index * 2 + 1]; |
| 83 | } | 85 | } |
| 84 | 86 | ||
| 87 | static int __gpio_mockup_get(struct gpio_mockup_chip *chip, | ||
| 88 | unsigned int offset) | ||
| 89 | { | ||
| 90 | return chip->lines[offset].value; | ||
| 91 | } | ||
| 92 | |||
| 85 | static int gpio_mockup_get(struct gpio_chip *gc, unsigned int offset) | 93 | static int gpio_mockup_get(struct gpio_chip *gc, unsigned int offset) |
| 86 | { | 94 | { |
| 87 | struct gpio_mockup_chip *chip = gpiochip_get_data(gc); | 95 | struct gpio_mockup_chip *chip = gpiochip_get_data(gc); |
| 96 | int val; | ||
| 88 | 97 | ||
| 89 | return chip->lines[offset].value; | 98 | mutex_lock(&chip->lock); |
| 99 | val = __gpio_mockup_get(chip, offset); | ||
| 100 | mutex_unlock(&chip->lock); | ||
| 101 | |||
| 102 | return val; | ||
| 90 | } | 103 | } |
| 91 | 104 | ||
| 92 | static void gpio_mockup_set(struct gpio_chip *gc, | 105 | static int gpio_mockup_get_multiple(struct gpio_chip *gc, |
| 93 | unsigned int offset, int value) | 106 | unsigned long *mask, unsigned long *bits) |
| 94 | { | 107 | { |
| 95 | struct gpio_mockup_chip *chip = gpiochip_get_data(gc); | 108 | struct gpio_mockup_chip *chip = gpiochip_get_data(gc); |
| 109 | unsigned int bit, val; | ||
| 110 | |||
| 111 | mutex_lock(&chip->lock); | ||
| 112 | for_each_set_bit(bit, mask, gc->ngpio) { | ||
| 113 | val = __gpio_mockup_get(chip, bit); | ||
| 114 | __assign_bit(bit, bits, val); | ||
| 115 | } | ||
| 116 | mutex_unlock(&chip->lock); | ||
| 117 | |||
| 118 | return 0; | ||
| 119 | } | ||
| 96 | 120 | ||
| 121 | static void __gpio_mockup_set(struct gpio_mockup_chip *chip, | ||
| 122 | unsigned int offset, int value) | ||
| 123 | { | ||
| 97 | chip->lines[offset].value = !!value; | 124 | chip->lines[offset].value = !!value; |
| 98 | } | 125 | } |
| 99 | 126 | ||
| 127 | static void gpio_mockup_set(struct gpio_chip *gc, | ||
| 128 | unsigned int offset, int value) | ||
| 129 | { | ||
| 130 | struct gpio_mockup_chip *chip = gpiochip_get_data(gc); | ||
| 131 | |||
| 132 | mutex_lock(&chip->lock); | ||
| 133 | __gpio_mockup_set(chip, offset, value); | ||
| 134 | mutex_unlock(&chip->lock); | ||
| 135 | } | ||
| 136 | |||
| 100 | static void gpio_mockup_set_multiple(struct gpio_chip *gc, | 137 | static void gpio_mockup_set_multiple(struct gpio_chip *gc, |
| 101 | unsigned long *mask, unsigned long *bits) | 138 | unsigned long *mask, unsigned long *bits) |
| 102 | { | 139 | { |
| 140 | struct gpio_mockup_chip *chip = gpiochip_get_data(gc); | ||
| 103 | unsigned int bit; | 141 | unsigned int bit; |
| 104 | 142 | ||
| 143 | mutex_lock(&chip->lock); | ||
| 105 | for_each_set_bit(bit, mask, gc->ngpio) | 144 | for_each_set_bit(bit, mask, gc->ngpio) |
| 106 | gpio_mockup_set(gc, bit, test_bit(bit, bits)); | 145 | __gpio_mockup_set(chip, bit, test_bit(bit, bits)); |
| 107 | 146 | mutex_unlock(&chip->lock); | |
| 108 | } | 147 | } |
| 109 | 148 | ||
| 110 | static int gpio_mockup_dirout(struct gpio_chip *gc, | 149 | static int gpio_mockup_dirout(struct gpio_chip *gc, |
| @@ -112,8 +151,10 @@ static int gpio_mockup_dirout(struct gpio_chip *gc, | |||
| 112 | { | 151 | { |
| 113 | struct gpio_mockup_chip *chip = gpiochip_get_data(gc); | 152 | struct gpio_mockup_chip *chip = gpiochip_get_data(gc); |
| 114 | 153 | ||
| 115 | gpio_mockup_set(gc, offset, value); | 154 | mutex_lock(&chip->lock); |
| 116 | chip->lines[offset].dir = GPIO_MOCKUP_DIR_OUT; | 155 | chip->lines[offset].dir = GPIO_MOCKUP_DIR_OUT; |
| 156 | __gpio_mockup_set(chip, offset, value); | ||
| 157 | mutex_unlock(&chip->lock); | ||
| 117 | 158 | ||
| 118 | return 0; | 159 | return 0; |
| 119 | } | 160 | } |
| @@ -122,7 +163,9 @@ static int gpio_mockup_dirin(struct gpio_chip *gc, unsigned int offset) | |||
| 122 | { | 163 | { |
| 123 | struct gpio_mockup_chip *chip = gpiochip_get_data(gc); | 164 | struct gpio_mockup_chip *chip = gpiochip_get_data(gc); |
| 124 | 165 | ||
| 166 | mutex_lock(&chip->lock); | ||
| 125 | chip->lines[offset].dir = GPIO_MOCKUP_DIR_IN; | 167 | chip->lines[offset].dir = GPIO_MOCKUP_DIR_IN; |
| 168 | mutex_unlock(&chip->lock); | ||
| 126 | 169 | ||
| 127 | return 0; | 170 | return 0; |
| 128 | } | 171 | } |
| @@ -130,8 +173,13 @@ static int gpio_mockup_dirin(struct gpio_chip *gc, unsigned int offset) | |||
| 130 | static int gpio_mockup_get_direction(struct gpio_chip *gc, unsigned int offset) | 173 | static int gpio_mockup_get_direction(struct gpio_chip *gc, unsigned int offset) |
| 131 | { | 174 | { |
| 132 | struct gpio_mockup_chip *chip = gpiochip_get_data(gc); | 175 | struct gpio_mockup_chip *chip = gpiochip_get_data(gc); |
| 176 | int direction; | ||
| 133 | 177 | ||
| 134 | return !chip->lines[offset].dir; | 178 | mutex_lock(&chip->lock); |
| 179 | direction = !chip->lines[offset].dir; | ||
| 180 | mutex_unlock(&chip->lock); | ||
| 181 | |||
| 182 | return direction; | ||
| 135 | } | 183 | } |
| 136 | 184 | ||
| 137 | static int gpio_mockup_to_irq(struct gpio_chip *gc, unsigned int offset) | 185 | static int gpio_mockup_to_irq(struct gpio_chip *gc, unsigned int offset) |
| @@ -141,15 +189,56 @@ static int gpio_mockup_to_irq(struct gpio_chip *gc, unsigned int offset) | |||
| 141 | return irq_sim_irqnum(&chip->irqsim, offset); | 189 | return irq_sim_irqnum(&chip->irqsim, offset); |
| 142 | } | 190 | } |
| 143 | 191 | ||
| 144 | static ssize_t gpio_mockup_event_write(struct file *file, | 192 | static void gpio_mockup_free(struct gpio_chip *gc, unsigned int offset) |
| 145 | const char __user *usr_buf, | 193 | { |
| 146 | size_t size, loff_t *ppos) | 194 | struct gpio_mockup_chip *chip = gpiochip_get_data(gc); |
| 195 | |||
| 196 | __gpio_mockup_set(chip, offset, chip->lines[offset].pull); | ||
| 197 | } | ||
| 198 | |||
| 199 | static ssize_t gpio_mockup_debugfs_read(struct file *file, | ||
| 200 | char __user *usr_buf, | ||
| 201 | size_t size, loff_t *ppos) | ||
| 147 | { | 202 | { |
| 148 | struct gpio_mockup_dbgfs_private *priv; | 203 | struct gpio_mockup_dbgfs_private *priv; |
| 149 | struct gpio_mockup_chip *chip; | 204 | struct gpio_mockup_chip *chip; |
| 150 | struct seq_file *sfile; | 205 | struct seq_file *sfile; |
| 206 | struct gpio_chip *gc; | ||
| 207 | char buf[3]; | ||
| 208 | int val, rv; | ||
| 209 | |||
| 210 | if (*ppos != 0) | ||
| 211 | return 0; | ||
| 212 | |||
| 213 | sfile = file->private_data; | ||
| 214 | priv = sfile->private; | ||
| 215 | chip = priv->chip; | ||
| 216 | gc = &chip->gc; | ||
| 217 | |||
| 218 | val = gpio_mockup_get(gc, priv->offset); | ||
| 219 | snprintf(buf, sizeof(buf), "%d\n", val); | ||
| 220 | |||
| 221 | rv = copy_to_user(usr_buf, buf, sizeof(buf)); | ||
| 222 | if (rv) | ||
| 223 | return rv; | ||
| 224 | |||
| 225 | return sizeof(buf) - 1; | ||
| 226 | } | ||
| 227 | |||
| 228 | static ssize_t gpio_mockup_debugfs_write(struct file *file, | ||
| 229 | const char __user *usr_buf, | ||
| 230 | size_t size, loff_t *ppos) | ||
| 231 | { | ||
| 232 | struct gpio_mockup_dbgfs_private *priv; | ||
| 233 | int rv, val, curr, irq, irq_type; | ||
| 234 | struct gpio_mockup_chip *chip; | ||
| 235 | struct seq_file *sfile; | ||
| 151 | struct gpio_desc *desc; | 236 | struct gpio_desc *desc; |
| 152 | int rv, val; | 237 | struct gpio_chip *gc; |
| 238 | struct irq_sim *sim; | ||
| 239 | |||
| 240 | if (*ppos != 0) | ||
| 241 | return -EINVAL; | ||
| 153 | 242 | ||
| 154 | rv = kstrtoint_from_user(usr_buf, size, 0, &val); | 243 | rv = kstrtoint_from_user(usr_buf, size, 0, &val); |
| 155 | if (rv) | 244 | if (rv) |
| @@ -159,24 +248,70 @@ static ssize_t gpio_mockup_event_write(struct file *file, | |||
| 159 | 248 | ||
| 160 | sfile = file->private_data; | 249 | sfile = file->private_data; |
| 161 | priv = sfile->private; | 250 | priv = sfile->private; |
| 162 | desc = priv->desc; | ||
| 163 | chip = priv->chip; | 251 | chip = priv->chip; |
| 252 | gc = &chip->gc; | ||
| 253 | desc = &gc->gpiodev->descs[priv->offset]; | ||
| 254 | sim = &chip->irqsim; | ||
| 255 | |||
| 256 | mutex_lock(&chip->lock); | ||
| 257 | |||
| 258 | if (test_bit(FLAG_REQUESTED, &desc->flags) && | ||
| 259 | !test_bit(FLAG_IS_OUT, &desc->flags)) { | ||
| 260 | curr = __gpio_mockup_get(chip, priv->offset); | ||
| 261 | if (curr == val) | ||
| 262 | goto out; | ||
| 263 | |||
| 264 | irq = irq_sim_irqnum(sim, priv->offset); | ||
| 265 | irq_type = irq_get_trigger_type(irq); | ||
| 266 | |||
| 267 | if ((val == 1 && (irq_type & IRQ_TYPE_EDGE_RISING)) || | ||
| 268 | (val == 0 && (irq_type & IRQ_TYPE_EDGE_FALLING))) | ||
| 269 | irq_sim_fire(sim, priv->offset); | ||
| 270 | } | ||
| 271 | |||
| 272 | /* Change the value unless we're actively driving the line. */ | ||
| 273 | if (!test_bit(FLAG_REQUESTED, &desc->flags) || | ||
| 274 | !test_bit(FLAG_IS_OUT, &desc->flags)) | ||
| 275 | __gpio_mockup_set(chip, priv->offset, val); | ||
| 164 | 276 | ||
| 165 | gpiod_set_value_cansleep(desc, val); | 277 | out: |
| 166 | irq_sim_fire(&chip->irqsim, priv->offset); | 278 | chip->lines[priv->offset].pull = val; |
| 279 | mutex_unlock(&chip->lock); | ||
| 167 | 280 | ||
| 168 | return size; | 281 | return size; |
| 169 | } | 282 | } |
| 170 | 283 | ||
| 171 | static int gpio_mockup_event_open(struct inode *inode, struct file *file) | 284 | static int gpio_mockup_debugfs_open(struct inode *inode, struct file *file) |
| 172 | { | 285 | { |
| 173 | return single_open(file, NULL, inode->i_private); | 286 | return single_open(file, NULL, inode->i_private); |
| 174 | } | 287 | } |
| 175 | 288 | ||
| 176 | static const struct file_operations gpio_mockup_event_ops = { | 289 | /* |
| 290 | * Each mockup chip is represented by a directory named after the chip's device | ||
| 291 | * name under /sys/kernel/debug/gpio-mockup/. Each line is represented by | ||
| 292 | * a file using the line's offset as the name under the chip's directory. | ||
| 293 | * | ||
| 294 | * Reading from the line's file yields the current *value*, writing to the | ||
| 295 | * line's file changes the current *pull*. Default pull for mockup lines is | ||
| 296 | * down. | ||
| 297 | * | ||
| 298 | * Examples: | ||
| 299 | * - when a line pulled down is requested in output mode and driven high, its | ||
| 300 | * value will return to 0 once it's released | ||
| 301 | * - when the line is requested in output mode and driven high, writing 0 to | ||
| 302 | * the corresponding debugfs file will change the pull to down but the | ||
| 303 | * reported value will still be 1 until the line is released | ||
| 304 | * - line requested in input mode always reports the same value as its pull | ||
| 305 | * configuration | ||
| 306 | * - when the line is requested in input mode and monitored for events, writing | ||
| 307 | * the same value to the debugfs file will be a noop, while writing the | ||
| 308 | * opposite value will generate a dummy interrupt with an appropriate edge | ||
| 309 | */ | ||
| 310 | static const struct file_operations gpio_mockup_debugfs_ops = { | ||
| 177 | .owner = THIS_MODULE, | 311 | .owner = THIS_MODULE, |
| 178 | .open = gpio_mockup_event_open, | 312 | .open = gpio_mockup_debugfs_open, |
| 179 | .write = gpio_mockup_event_write, | 313 | .read = gpio_mockup_debugfs_read, |
| 314 | .write = gpio_mockup_debugfs_write, | ||
| 180 | .llseek = no_llseek, | 315 | .llseek = no_llseek, |
| 181 | }; | 316 | }; |
| 182 | 317 | ||
| @@ -184,7 +319,7 @@ static void gpio_mockup_debugfs_setup(struct device *dev, | |||
| 184 | struct gpio_mockup_chip *chip) | 319 | struct gpio_mockup_chip *chip) |
| 185 | { | 320 | { |
| 186 | struct gpio_mockup_dbgfs_private *priv; | 321 | struct gpio_mockup_dbgfs_private *priv; |
| 187 | struct dentry *evfile, *link; | 322 | struct dentry *evfile; |
| 188 | struct gpio_chip *gc; | 323 | struct gpio_chip *gc; |
| 189 | const char *devname; | 324 | const char *devname; |
| 190 | char *name; | 325 | char *name; |
| @@ -197,10 +332,6 @@ static void gpio_mockup_debugfs_setup(struct device *dev, | |||
| 197 | if (IS_ERR_OR_NULL(chip->dbg_dir)) | 332 | if (IS_ERR_OR_NULL(chip->dbg_dir)) |
| 198 | goto err; | 333 | goto err; |
| 199 | 334 | ||
| 200 | link = debugfs_create_symlink(gc->label, gpio_mockup_dbg_dir, devname); | ||
| 201 | if (IS_ERR_OR_NULL(link)) | ||
| 202 | goto err; | ||
| 203 | |||
| 204 | for (i = 0; i < gc->ngpio; i++) { | 335 | for (i = 0; i < gc->ngpio; i++) { |
| 205 | name = devm_kasprintf(dev, GFP_KERNEL, "%d", i); | 336 | name = devm_kasprintf(dev, GFP_KERNEL, "%d", i); |
| 206 | if (!name) | 337 | if (!name) |
| @@ -215,7 +346,7 @@ static void gpio_mockup_debugfs_setup(struct device *dev, | |||
| 215 | priv->desc = &gc->gpiodev->descs[i]; | 346 | priv->desc = &gc->gpiodev->descs[i]; |
| 216 | 347 | ||
| 217 | evfile = debugfs_create_file(name, 0200, chip->dbg_dir, priv, | 348 | evfile = debugfs_create_file(name, 0200, chip->dbg_dir, priv, |
| 218 | &gpio_mockup_event_ops); | 349 | &gpio_mockup_debugfs_ops); |
| 219 | if (IS_ERR_OR_NULL(evfile)) | 350 | if (IS_ERR_OR_NULL(evfile)) |
| 220 | goto err; | 351 | goto err; |
| 221 | } | 352 | } |
| @@ -223,7 +354,7 @@ static void gpio_mockup_debugfs_setup(struct device *dev, | |||
| 223 | return; | 354 | return; |
| 224 | 355 | ||
| 225 | err: | 356 | err: |
| 226 | dev_err(dev, "error creating debugfs event files\n"); | 357 | dev_err(dev, "error creating debugfs files\n"); |
| 227 | } | 358 | } |
| 228 | 359 | ||
| 229 | static int gpio_mockup_name_lines(struct device *dev, | 360 | static int gpio_mockup_name_lines(struct device *dev, |
| @@ -283,6 +414,8 @@ static int gpio_mockup_probe(struct platform_device *pdev) | |||
| 283 | return -ENOMEM; | 414 | return -ENOMEM; |
| 284 | } | 415 | } |
| 285 | 416 | ||
| 417 | mutex_init(&chip->lock); | ||
| 418 | |||
| 286 | gc = &chip->gc; | 419 | gc = &chip->gc; |
| 287 | gc->base = base; | 420 | gc->base = base; |
| 288 | gc->ngpio = ngpio; | 421 | gc->ngpio = ngpio; |
| @@ -291,11 +424,13 @@ static int gpio_mockup_probe(struct platform_device *pdev) | |||
| 291 | gc->parent = dev; | 424 | gc->parent = dev; |
| 292 | gc->get = gpio_mockup_get; | 425 | gc->get = gpio_mockup_get; |
| 293 | gc->set = gpio_mockup_set; | 426 | gc->set = gpio_mockup_set; |
| 427 | gc->get_multiple = gpio_mockup_get_multiple; | ||
| 294 | gc->set_multiple = gpio_mockup_set_multiple; | 428 | gc->set_multiple = gpio_mockup_set_multiple; |
| 295 | gc->direction_output = gpio_mockup_dirout; | 429 | gc->direction_output = gpio_mockup_dirout; |
| 296 | gc->direction_input = gpio_mockup_dirin; | 430 | gc->direction_input = gpio_mockup_dirin; |
| 297 | gc->get_direction = gpio_mockup_get_direction; | 431 | gc->get_direction = gpio_mockup_get_direction; |
| 298 | gc->to_irq = gpio_mockup_to_irq; | 432 | gc->to_irq = gpio_mockup_to_irq; |
| 433 | gc->free = gpio_mockup_free; | ||
| 299 | 434 | ||
| 300 | chip->lines = devm_kcalloc(dev, gc->ngpio, | 435 | chip->lines = devm_kcalloc(dev, gc->ngpio, |
| 301 | sizeof(*chip->lines), GFP_KERNEL); | 436 | sizeof(*chip->lines), GFP_KERNEL); |
| @@ -369,7 +504,7 @@ static int __init gpio_mockup_init(void) | |||
| 369 | return -EINVAL; | 504 | return -EINVAL; |
| 370 | } | 505 | } |
| 371 | 506 | ||
| 372 | gpio_mockup_dbg_dir = debugfs_create_dir("gpio-mockup-event", NULL); | 507 | gpio_mockup_dbg_dir = debugfs_create_dir("gpio-mockup", NULL); |
| 373 | if (IS_ERR_OR_NULL(gpio_mockup_dbg_dir)) | 508 | if (IS_ERR_OR_NULL(gpio_mockup_dbg_dir)) |
| 374 | gpio_mockup_err("error creating debugfs directory\n"); | 509 | gpio_mockup_err("error creating debugfs directory\n"); |
| 375 | 510 | ||
diff --git a/drivers/gpio/gpio-msic.c b/drivers/gpio/gpio-msic.c index 3b34dbecef99..7e3c96e4ab2c 100644 --- a/drivers/gpio/gpio-msic.c +++ b/drivers/gpio/gpio-msic.c | |||
| @@ -1,32 +1,19 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 1 | /* | 2 | /* |
| 2 | * Intel Medfield MSIC GPIO driver> | 3 | * Intel Medfield MSIC GPIO driver> |
| 3 | * Copyright (c) 2011, Intel Corporation. | 4 | * Copyright (c) 2011, Intel Corporation. |
| 4 | * | 5 | * |
| 5 | * Author: Mathias Nyman <mathias.nyman@linux.intel.com> | 6 | * Author: Mathias Nyman <mathias.nyman@linux.intel.com> |
| 6 | * Based on intel_pmic_gpio.c | 7 | * Based on intel_pmic_gpio.c |
| 7 | * | ||
| 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 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
| 13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
| 14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
| 15 | * more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License along with | ||
| 18 | * this program; if not, write to the Free Software Foundation, Inc., | ||
| 19 | * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
| 20 | * | ||
| 21 | */ | 8 | */ |
| 22 | 9 | ||
| 23 | #include <linux/kernel.h> | ||
| 24 | #include <linux/slab.h> | ||
| 25 | #include <linux/interrupt.h> | ||
| 26 | #include <linux/init.h> | ||
| 27 | #include <linux/gpio/driver.h> | 10 | #include <linux/gpio/driver.h> |
| 28 | #include <linux/platform_device.h> | 11 | #include <linux/init.h> |
| 12 | #include <linux/interrupt.h> | ||
| 13 | #include <linux/kernel.h> | ||
| 29 | #include <linux/mfd/intel_msic.h> | 14 | #include <linux/mfd/intel_msic.h> |
| 15 | #include <linux/platform_device.h> | ||
| 16 | #include <linux/slab.h> | ||
| 30 | 17 | ||
| 31 | /* the offset for the mapping of global gpio pin to irq */ | 18 | /* the offset for the mapping of global gpio pin to irq */ |
| 32 | #define MSIC_GPIO_IRQ_OFFSET 0x100 | 19 | #define MSIC_GPIO_IRQ_OFFSET 0x100 |
| @@ -237,20 +224,17 @@ static void msic_gpio_irq_handler(struct irq_desc *desc) | |||
| 237 | struct msic_gpio *mg = irq_data_get_irq_handler_data(data); | 224 | struct msic_gpio *mg = irq_data_get_irq_handler_data(data); |
| 238 | struct irq_chip *chip = irq_data_get_irq_chip(data); | 225 | struct irq_chip *chip = irq_data_get_irq_chip(data); |
| 239 | struct intel_msic *msic = pdev_to_intel_msic(mg->pdev); | 226 | struct intel_msic *msic = pdev_to_intel_msic(mg->pdev); |
| 227 | unsigned long pending; | ||
| 240 | int i; | 228 | int i; |
| 241 | int bitnr; | 229 | int bitnr; |
| 242 | u8 pin; | 230 | u8 pin; |
| 243 | unsigned long pending = 0; | ||
| 244 | 231 | ||
| 245 | for (i = 0; i < (mg->chip.ngpio / BITS_PER_BYTE); i++) { | 232 | for (i = 0; i < (mg->chip.ngpio / BITS_PER_BYTE); i++) { |
| 246 | intel_msic_irq_read(msic, INTEL_MSIC_GPIO0LVIRQ + i, &pin); | 233 | intel_msic_irq_read(msic, INTEL_MSIC_GPIO0LVIRQ + i, &pin); |
| 247 | pending = pin; | 234 | pending = pin; |
| 248 | 235 | ||
| 249 | if (pending) { | 236 | for_each_set_bit(bitnr, &pending, BITS_PER_BYTE) |
| 250 | for_each_set_bit(bitnr, &pending, BITS_PER_BYTE) | 237 | generic_handle_irq(mg->irq_base + i * BITS_PER_BYTE + bitnr); |
| 251 | generic_handle_irq(mg->irq_base + | ||
| 252 | (i * BITS_PER_BYTE) + bitnr); | ||
| 253 | } | ||
| 254 | } | 238 | } |
| 255 | chip->irq_eoi(data); | 239 | chip->irq_eoi(data); |
| 256 | } | 240 | } |
diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c index 7d5c55494ccd..f97ed32b8beb 100644 --- a/drivers/gpio/gpio-mvebu.c +++ b/drivers/gpio/gpio-mvebu.c | |||
| @@ -376,6 +376,16 @@ static int mvebu_gpio_direction_output(struct gpio_chip *chip, unsigned int pin, | |||
| 376 | return 0; | 376 | return 0; |
| 377 | } | 377 | } |
| 378 | 378 | ||
| 379 | static int mvebu_gpio_get_direction(struct gpio_chip *chip, unsigned int pin) | ||
| 380 | { | ||
| 381 | struct mvebu_gpio_chip *mvchip = gpiochip_get_data(chip); | ||
| 382 | u32 u; | ||
| 383 | |||
| 384 | regmap_read(mvchip->regs, GPIO_IO_CONF_OFF + mvchip->offset, &u); | ||
| 385 | |||
| 386 | return !!(u & BIT(pin)); | ||
| 387 | } | ||
| 388 | |||
| 379 | static int mvebu_gpio_to_irq(struct gpio_chip *chip, unsigned int pin) | 389 | static int mvebu_gpio_to_irq(struct gpio_chip *chip, unsigned int pin) |
| 380 | { | 390 | { |
| 381 | struct mvebu_gpio_chip *mvchip = gpiochip_get_data(chip); | 391 | struct mvebu_gpio_chip *mvchip = gpiochip_get_data(chip); |
| @@ -1130,6 +1140,7 @@ static int mvebu_gpio_probe(struct platform_device *pdev) | |||
| 1130 | mvchip->chip.parent = &pdev->dev; | 1140 | mvchip->chip.parent = &pdev->dev; |
| 1131 | mvchip->chip.request = gpiochip_generic_request; | 1141 | mvchip->chip.request = gpiochip_generic_request; |
| 1132 | mvchip->chip.free = gpiochip_generic_free; | 1142 | mvchip->chip.free = gpiochip_generic_free; |
| 1143 | mvchip->chip.get_direction = mvebu_gpio_get_direction; | ||
| 1133 | mvchip->chip.direction_input = mvebu_gpio_direction_input; | 1144 | mvchip->chip.direction_input = mvebu_gpio_direction_input; |
| 1134 | mvchip->chip.get = mvebu_gpio_get; | 1145 | mvchip->chip.get = mvebu_gpio_get; |
| 1135 | mvchip->chip.direction_output = mvebu_gpio_direction_output; | 1146 | mvchip->chip.direction_output = mvebu_gpio_direction_output; |
diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c index 2d1dfa1e0745..e86e61dda4b7 100644 --- a/drivers/gpio/gpio-mxc.c +++ b/drivers/gpio/gpio-mxc.c | |||
| @@ -438,8 +438,11 @@ static int mxc_gpio_probe(struct platform_device *pdev) | |||
| 438 | 438 | ||
| 439 | /* the controller clock is optional */ | 439 | /* the controller clock is optional */ |
| 440 | port->clk = devm_clk_get(&pdev->dev, NULL); | 440 | port->clk = devm_clk_get(&pdev->dev, NULL); |
| 441 | if (IS_ERR(port->clk)) | 441 | if (IS_ERR(port->clk)) { |
| 442 | if (PTR_ERR(port->clk) == -EPROBE_DEFER) | ||
| 443 | return -EPROBE_DEFER; | ||
| 442 | port->clk = NULL; | 444 | port->clk = NULL; |
| 445 | } | ||
| 443 | 446 | ||
| 444 | err = clk_prepare_enable(port->clk); | 447 | err = clk_prepare_enable(port->clk); |
| 445 | if (err) { | 448 | if (err) { |
diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index f4e9921fa966..7f33024b6d83 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c | |||
| @@ -883,14 +883,16 @@ static void omap_gpio_unmask_irq(struct irq_data *d) | |||
| 883 | if (trigger) | 883 | if (trigger) |
| 884 | omap_set_gpio_triggering(bank, offset, trigger); | 884 | omap_set_gpio_triggering(bank, offset, trigger); |
| 885 | 885 | ||
| 886 | /* For level-triggered GPIOs, the clearing must be done after | 886 | omap_set_gpio_irqenable(bank, offset, 1); |
| 887 | * the HW source is cleared, thus after the handler has run */ | 887 | |
| 888 | if (bank->level_mask & BIT(offset)) { | 888 | /* |
| 889 | omap_set_gpio_irqenable(bank, offset, 0); | 889 | * For level-triggered GPIOs, clearing must be done after the source |
| 890 | * is cleared, thus after the handler has run. OMAP4 needs this done | ||
| 891 | * after enabing the interrupt to clear the wakeup status. | ||
| 892 | */ | ||
| 893 | if (bank->level_mask & BIT(offset)) | ||
| 890 | omap_clear_gpio_irqstatus(bank, offset); | 894 | omap_clear_gpio_irqstatus(bank, offset); |
| 891 | } | ||
| 892 | 895 | ||
| 893 | omap_set_gpio_irqenable(bank, offset, 1); | ||
| 894 | raw_spin_unlock_irqrestore(&bank->lock, flags); | 896 | raw_spin_unlock_irqrestore(&bank->lock, flags); |
| 895 | } | 897 | } |
| 896 | 898 | ||
diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index 0dc96419efe3..7e76830b3368 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c | |||
| @@ -65,7 +65,7 @@ | |||
| 65 | 65 | ||
| 66 | #define PCA_INT 0x0100 | 66 | #define PCA_INT 0x0100 |
| 67 | #define PCA_PCAL 0x0200 | 67 | #define PCA_PCAL 0x0200 |
| 68 | #define PCA_LATCH_INT (PCA_PCAL | PCA_INT) | 68 | #define PCA_LATCH_INT (PCA_PCAL | PCA_INT) |
| 69 | #define PCA953X_TYPE 0x1000 | 69 | #define PCA953X_TYPE 0x1000 |
| 70 | #define PCA957X_TYPE 0x2000 | 70 | #define PCA957X_TYPE 0x2000 |
| 71 | #define PCA_TYPE_MASK 0xF000 | 71 | #define PCA_TYPE_MASK 0xF000 |
| @@ -88,8 +88,9 @@ static const struct i2c_device_id pca953x_id[] = { | |||
| 88 | { "pca9575", 16 | PCA957X_TYPE | PCA_INT, }, | 88 | { "pca9575", 16 | PCA957X_TYPE | PCA_INT, }, |
| 89 | { "pca9698", 40 | PCA953X_TYPE, }, | 89 | { "pca9698", 40 | PCA953X_TYPE, }, |
| 90 | 90 | ||
| 91 | { "pcal6524", 24 | PCA953X_TYPE | PCA_INT | PCA_PCAL, }, | 91 | { "pcal6416", 16 | PCA953X_TYPE | PCA_LATCH_INT, }, |
| 92 | { "pcal9555a", 16 | PCA953X_TYPE | PCA_INT | PCA_PCAL, }, | 92 | { "pcal6524", 24 | PCA953X_TYPE | PCA_LATCH_INT, }, |
| 93 | { "pcal9555a", 16 | PCA953X_TYPE | PCA_LATCH_INT, }, | ||
| 93 | 94 | ||
| 94 | { "max7310", 8 | PCA953X_TYPE, }, | 95 | { "max7310", 8 | PCA953X_TYPE, }, |
| 95 | { "max7312", 16 | PCA953X_TYPE | PCA_INT, }, | 96 | { "max7312", 16 | PCA953X_TYPE | PCA_INT, }, |
| @@ -108,7 +109,7 @@ static const struct i2c_device_id pca953x_id[] = { | |||
| 108 | MODULE_DEVICE_TABLE(i2c, pca953x_id); | 109 | MODULE_DEVICE_TABLE(i2c, pca953x_id); |
| 109 | 110 | ||
| 110 | static const struct acpi_device_id pca953x_acpi_ids[] = { | 111 | static const struct acpi_device_id pca953x_acpi_ids[] = { |
| 111 | { "INT3491", 16 | PCA953X_TYPE | PCA_INT | PCA_PCAL, }, | 112 | { "INT3491", 16 | PCA953X_TYPE | PCA_LATCH_INT, }, |
| 112 | { } | 113 | { } |
| 113 | }; | 114 | }; |
| 114 | MODULE_DEVICE_TABLE(acpi, pca953x_acpi_ids); | 115 | MODULE_DEVICE_TABLE(acpi, pca953x_acpi_ids); |
| @@ -150,6 +151,7 @@ struct pca953x_chip { | |||
| 150 | u8 irq_stat[MAX_BANK]; | 151 | u8 irq_stat[MAX_BANK]; |
| 151 | u8 irq_trig_raise[MAX_BANK]; | 152 | u8 irq_trig_raise[MAX_BANK]; |
| 152 | u8 irq_trig_fall[MAX_BANK]; | 153 | u8 irq_trig_fall[MAX_BANK]; |
| 154 | struct irq_chip irq_chip; | ||
| 153 | #endif | 155 | #endif |
| 154 | 156 | ||
| 155 | struct i2c_client *client; | 157 | struct i2c_client *client; |
| @@ -178,6 +180,8 @@ static int pca953x_bank_shift(struct pca953x_chip *chip) | |||
| 178 | #define PCA957x_BANK_OUTPUT BIT(5) | 180 | #define PCA957x_BANK_OUTPUT BIT(5) |
| 179 | 181 | ||
| 180 | #define PCAL9xxx_BANK_IN_LATCH BIT(8 + 2) | 182 | #define PCAL9xxx_BANK_IN_LATCH BIT(8 + 2) |
| 183 | #define PCAL9xxx_BANK_PULL_EN BIT(8 + 3) | ||
| 184 | #define PCAL9xxx_BANK_PULL_SEL BIT(8 + 4) | ||
| 181 | #define PCAL9xxx_BANK_IRQ_MASK BIT(8 + 5) | 185 | #define PCAL9xxx_BANK_IRQ_MASK BIT(8 + 5) |
| 182 | #define PCAL9xxx_BANK_IRQ_STAT BIT(8 + 6) | 186 | #define PCAL9xxx_BANK_IRQ_STAT BIT(8 + 6) |
| 183 | 187 | ||
| @@ -199,6 +203,8 @@ static int pca953x_bank_shift(struct pca953x_chip *chip) | |||
| 199 | * - Extended set, above 0x40, often chip specific. | 203 | * - Extended set, above 0x40, often chip specific. |
| 200 | * - PCAL6524/PCAL9555A with custom PCAL IRQ handling: | 204 | * - PCAL6524/PCAL9555A with custom PCAL IRQ handling: |
| 201 | * Input latch register 0x40 + 2 * bank_size RW | 205 | * Input latch register 0x40 + 2 * bank_size RW |
| 206 | * Pull-up/pull-down enable reg 0x40 + 3 * bank_size RW | ||
| 207 | * Pull-up/pull-down select reg 0x40 + 4 * bank_size RW | ||
| 202 | * Interrupt mask register 0x40 + 5 * bank_size RW | 208 | * Interrupt mask register 0x40 + 5 * bank_size RW |
| 203 | * Interrupt status register 0x40 + 6 * bank_size R | 209 | * Interrupt status register 0x40 + 6 * bank_size R |
| 204 | * | 210 | * |
| @@ -247,7 +253,8 @@ static bool pca953x_readable_register(struct device *dev, unsigned int reg) | |||
| 247 | } | 253 | } |
| 248 | 254 | ||
| 249 | if (chip->driver_data & PCA_PCAL) { | 255 | if (chip->driver_data & PCA_PCAL) { |
| 250 | bank |= PCAL9xxx_BANK_IN_LATCH | PCAL9xxx_BANK_IRQ_MASK | | 256 | bank |= PCAL9xxx_BANK_IN_LATCH | PCAL9xxx_BANK_PULL_EN | |
| 257 | PCAL9xxx_BANK_PULL_SEL | PCAL9xxx_BANK_IRQ_MASK | | ||
| 251 | PCAL9xxx_BANK_IRQ_STAT; | 258 | PCAL9xxx_BANK_IRQ_STAT; |
| 252 | } | 259 | } |
| 253 | 260 | ||
| @@ -268,7 +275,8 @@ static bool pca953x_writeable_register(struct device *dev, unsigned int reg) | |||
| 268 | } | 275 | } |
| 269 | 276 | ||
| 270 | if (chip->driver_data & PCA_PCAL) | 277 | if (chip->driver_data & PCA_PCAL) |
| 271 | bank |= PCAL9xxx_BANK_IN_LATCH | PCAL9xxx_BANK_IRQ_MASK; | 278 | bank |= PCAL9xxx_BANK_IN_LATCH | PCAL9xxx_BANK_PULL_EN | |
| 279 | PCAL9xxx_BANK_PULL_SEL | PCAL9xxx_BANK_IRQ_MASK; | ||
| 272 | 280 | ||
| 273 | return pca953x_check_register(chip, reg, bank); | 281 | return pca953x_check_register(chip, reg, bank); |
| 274 | } | 282 | } |
| @@ -473,6 +481,61 @@ exit: | |||
| 473 | mutex_unlock(&chip->i2c_lock); | 481 | mutex_unlock(&chip->i2c_lock); |
| 474 | } | 482 | } |
| 475 | 483 | ||
| 484 | static int pca953x_gpio_set_pull_up_down(struct pca953x_chip *chip, | ||
| 485 | unsigned int offset, | ||
| 486 | unsigned long config) | ||
| 487 | { | ||
| 488 | u8 pull_en_reg = pca953x_recalc_addr(chip, PCAL953X_PULL_EN, offset, | ||
| 489 | true, false); | ||
| 490 | u8 pull_sel_reg = pca953x_recalc_addr(chip, PCAL953X_PULL_SEL, offset, | ||
| 491 | true, false); | ||
| 492 | u8 bit = BIT(offset % BANK_SZ); | ||
| 493 | int ret; | ||
| 494 | |||
| 495 | /* | ||
| 496 | * pull-up/pull-down configuration requires PCAL extended | ||
| 497 | * registers | ||
| 498 | */ | ||
| 499 | if (!(chip->driver_data & PCA_PCAL)) | ||
| 500 | return -ENOTSUPP; | ||
| 501 | |||
| 502 | mutex_lock(&chip->i2c_lock); | ||
| 503 | |||
| 504 | /* Disable pull-up/pull-down */ | ||
| 505 | ret = regmap_write_bits(chip->regmap, pull_en_reg, bit, 0); | ||
| 506 | if (ret) | ||
| 507 | goto exit; | ||
| 508 | |||
| 509 | /* Configure pull-up/pull-down */ | ||
| 510 | if (config == PIN_CONFIG_BIAS_PULL_UP) | ||
| 511 | ret = regmap_write_bits(chip->regmap, pull_sel_reg, bit, bit); | ||
| 512 | else if (config == PIN_CONFIG_BIAS_PULL_DOWN) | ||
| 513 | ret = regmap_write_bits(chip->regmap, pull_sel_reg, bit, 0); | ||
| 514 | if (ret) | ||
| 515 | goto exit; | ||
| 516 | |||
| 517 | /* Enable pull-up/pull-down */ | ||
| 518 | ret = regmap_write_bits(chip->regmap, pull_en_reg, bit, bit); | ||
| 519 | |||
| 520 | exit: | ||
| 521 | mutex_unlock(&chip->i2c_lock); | ||
| 522 | return ret; | ||
| 523 | } | ||
| 524 | |||
| 525 | static int pca953x_gpio_set_config(struct gpio_chip *gc, unsigned int offset, | ||
| 526 | unsigned long config) | ||
| 527 | { | ||
| 528 | struct pca953x_chip *chip = gpiochip_get_data(gc); | ||
| 529 | |||
| 530 | switch (config) { | ||
| 531 | case PIN_CONFIG_BIAS_PULL_UP: | ||
| 532 | case PIN_CONFIG_BIAS_PULL_DOWN: | ||
| 533 | return pca953x_gpio_set_pull_up_down(chip, offset, config); | ||
| 534 | default: | ||
| 535 | return -ENOTSUPP; | ||
| 536 | } | ||
| 537 | } | ||
| 538 | |||
| 476 | static void pca953x_setup_gpio(struct pca953x_chip *chip, int gpios) | 539 | static void pca953x_setup_gpio(struct pca953x_chip *chip, int gpios) |
| 477 | { | 540 | { |
| 478 | struct gpio_chip *gc; | 541 | struct gpio_chip *gc; |
| @@ -485,6 +548,7 @@ static void pca953x_setup_gpio(struct pca953x_chip *chip, int gpios) | |||
| 485 | gc->set = pca953x_gpio_set_value; | 548 | gc->set = pca953x_gpio_set_value; |
| 486 | gc->get_direction = pca953x_gpio_get_direction; | 549 | gc->get_direction = pca953x_gpio_get_direction; |
| 487 | gc->set_multiple = pca953x_gpio_set_multiple; | 550 | gc->set_multiple = pca953x_gpio_set_multiple; |
| 551 | gc->set_config = pca953x_gpio_set_config; | ||
| 488 | gc->can_sleep = true; | 552 | gc->can_sleep = true; |
| 489 | 553 | ||
| 490 | gc->base = chip->gpio_start; | 554 | gc->base = chip->gpio_start; |
| @@ -512,6 +576,14 @@ static void pca953x_irq_unmask(struct irq_data *d) | |||
| 512 | chip->irq_mask[d->hwirq / BANK_SZ] |= 1 << (d->hwirq % BANK_SZ); | 576 | chip->irq_mask[d->hwirq / BANK_SZ] |= 1 << (d->hwirq % BANK_SZ); |
| 513 | } | 577 | } |
| 514 | 578 | ||
| 579 | static int pca953x_irq_set_wake(struct irq_data *d, unsigned int on) | ||
| 580 | { | ||
| 581 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); | ||
| 582 | struct pca953x_chip *chip = gpiochip_get_data(gc); | ||
| 583 | |||
| 584 | return irq_set_irq_wake(chip->client->irq, on); | ||
| 585 | } | ||
| 586 | |||
| 515 | static void pca953x_irq_bus_lock(struct irq_data *d) | 587 | static void pca953x_irq_bus_lock(struct irq_data *d) |
| 516 | { | 588 | { |
| 517 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); | 589 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); |
| @@ -587,23 +659,14 @@ static int pca953x_irq_set_type(struct irq_data *d, unsigned int type) | |||
| 587 | 659 | ||
| 588 | static void pca953x_irq_shutdown(struct irq_data *d) | 660 | static void pca953x_irq_shutdown(struct irq_data *d) |
| 589 | { | 661 | { |
| 590 | struct pca953x_chip *chip = irq_data_get_irq_chip_data(d); | 662 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); |
| 663 | struct pca953x_chip *chip = gpiochip_get_data(gc); | ||
| 591 | u8 mask = 1 << (d->hwirq % BANK_SZ); | 664 | u8 mask = 1 << (d->hwirq % BANK_SZ); |
| 592 | 665 | ||
| 593 | chip->irq_trig_raise[d->hwirq / BANK_SZ] &= ~mask; | 666 | chip->irq_trig_raise[d->hwirq / BANK_SZ] &= ~mask; |
| 594 | chip->irq_trig_fall[d->hwirq / BANK_SZ] &= ~mask; | 667 | chip->irq_trig_fall[d->hwirq / BANK_SZ] &= ~mask; |
| 595 | } | 668 | } |
| 596 | 669 | ||
| 597 | static struct irq_chip pca953x_irq_chip = { | ||
| 598 | .name = "pca953x", | ||
| 599 | .irq_mask = pca953x_irq_mask, | ||
| 600 | .irq_unmask = pca953x_irq_unmask, | ||
| 601 | .irq_bus_lock = pca953x_irq_bus_lock, | ||
| 602 | .irq_bus_sync_unlock = pca953x_irq_bus_sync_unlock, | ||
| 603 | .irq_set_type = pca953x_irq_set_type, | ||
| 604 | .irq_shutdown = pca953x_irq_shutdown, | ||
| 605 | }; | ||
| 606 | |||
| 607 | static bool pca953x_irq_pending(struct pca953x_chip *chip, u8 *pending) | 670 | static bool pca953x_irq_pending(struct pca953x_chip *chip, u8 *pending) |
| 608 | { | 671 | { |
| 609 | u8 cur_stat[MAX_BANK]; | 672 | u8 cur_stat[MAX_BANK]; |
| @@ -699,56 +762,65 @@ static int pca953x_irq_setup(struct pca953x_chip *chip, | |||
| 699 | int irq_base) | 762 | int irq_base) |
| 700 | { | 763 | { |
| 701 | struct i2c_client *client = chip->client; | 764 | struct i2c_client *client = chip->client; |
| 765 | struct irq_chip *irq_chip = &chip->irq_chip; | ||
| 702 | int reg_direction[MAX_BANK]; | 766 | int reg_direction[MAX_BANK]; |
| 703 | int ret, i; | 767 | int ret, i; |
| 704 | 768 | ||
| 705 | if (client->irq && irq_base != -1 | 769 | if (!client->irq) |
| 706 | && (chip->driver_data & PCA_INT)) { | 770 | return 0; |
| 707 | ret = pca953x_read_regs(chip, | ||
| 708 | chip->regs->input, chip->irq_stat); | ||
| 709 | if (ret) | ||
| 710 | return ret; | ||
| 711 | 771 | ||
| 712 | /* | 772 | if (irq_base == -1) |
| 713 | * There is no way to know which GPIO line generated the | 773 | return 0; |
| 714 | * interrupt. We have to rely on the previous read for | ||
| 715 | * this purpose. | ||
| 716 | */ | ||
| 717 | regmap_bulk_read(chip->regmap, chip->regs->direction, | ||
| 718 | reg_direction, NBANK(chip)); | ||
| 719 | for (i = 0; i < NBANK(chip); i++) | ||
| 720 | chip->irq_stat[i] &= reg_direction[i]; | ||
| 721 | mutex_init(&chip->irq_lock); | ||
| 722 | |||
| 723 | ret = devm_request_threaded_irq(&client->dev, | ||
| 724 | client->irq, | ||
| 725 | NULL, | ||
| 726 | pca953x_irq_handler, | ||
| 727 | IRQF_TRIGGER_LOW | IRQF_ONESHOT | | ||
| 728 | IRQF_SHARED, | ||
| 729 | dev_name(&client->dev), chip); | ||
| 730 | if (ret) { | ||
| 731 | dev_err(&client->dev, "failed to request irq %d\n", | ||
| 732 | client->irq); | ||
| 733 | return ret; | ||
| 734 | } | ||
| 735 | 774 | ||
| 736 | ret = gpiochip_irqchip_add_nested(&chip->gpio_chip, | 775 | if (!(chip->driver_data & PCA_INT)) |
| 737 | &pca953x_irq_chip, | 776 | return 0; |
| 738 | irq_base, | ||
| 739 | handle_simple_irq, | ||
| 740 | IRQ_TYPE_NONE); | ||
| 741 | if (ret) { | ||
| 742 | dev_err(&client->dev, | ||
| 743 | "could not connect irqchip to gpiochip\n"); | ||
| 744 | return ret; | ||
| 745 | } | ||
| 746 | 777 | ||
| 747 | gpiochip_set_nested_irqchip(&chip->gpio_chip, | 778 | ret = pca953x_read_regs(chip, chip->regs->input, chip->irq_stat); |
| 748 | &pca953x_irq_chip, | 779 | if (ret) |
| 749 | client->irq); | 780 | return ret; |
| 781 | |||
| 782 | /* | ||
| 783 | * There is no way to know which GPIO line generated the | ||
| 784 | * interrupt. We have to rely on the previous read for | ||
| 785 | * this purpose. | ||
| 786 | */ | ||
| 787 | regmap_bulk_read(chip->regmap, chip->regs->direction, reg_direction, | ||
| 788 | NBANK(chip)); | ||
| 789 | for (i = 0; i < NBANK(chip); i++) | ||
| 790 | chip->irq_stat[i] &= reg_direction[i]; | ||
| 791 | mutex_init(&chip->irq_lock); | ||
| 792 | |||
| 793 | ret = devm_request_threaded_irq(&client->dev, client->irq, | ||
| 794 | NULL, pca953x_irq_handler, | ||
| 795 | IRQF_TRIGGER_LOW | IRQF_ONESHOT | | ||
| 796 | IRQF_SHARED, | ||
| 797 | dev_name(&client->dev), chip); | ||
| 798 | if (ret) { | ||
| 799 | dev_err(&client->dev, "failed to request irq %d\n", | ||
| 800 | client->irq); | ||
| 801 | return ret; | ||
| 750 | } | 802 | } |
| 751 | 803 | ||
| 804 | irq_chip->name = dev_name(&chip->client->dev); | ||
| 805 | irq_chip->irq_mask = pca953x_irq_mask; | ||
| 806 | irq_chip->irq_unmask = pca953x_irq_unmask; | ||
| 807 | irq_chip->irq_set_wake = pca953x_irq_set_wake; | ||
| 808 | irq_chip->irq_bus_lock = pca953x_irq_bus_lock; | ||
| 809 | irq_chip->irq_bus_sync_unlock = pca953x_irq_bus_sync_unlock; | ||
| 810 | irq_chip->irq_set_type = pca953x_irq_set_type; | ||
| 811 | irq_chip->irq_shutdown = pca953x_irq_shutdown; | ||
| 812 | |||
| 813 | ret = gpiochip_irqchip_add_nested(&chip->gpio_chip, irq_chip, | ||
| 814 | irq_base, handle_simple_irq, | ||
| 815 | IRQ_TYPE_NONE); | ||
| 816 | if (ret) { | ||
| 817 | dev_err(&client->dev, | ||
| 818 | "could not connect irqchip to gpiochip\n"); | ||
| 819 | return ret; | ||
| 820 | } | ||
| 821 | |||
| 822 | gpiochip_set_nested_irqchip(&chip->gpio_chip, irq_chip, client->irq); | ||
| 823 | |||
| 752 | return 0; | 824 | return 0; |
| 753 | } | 825 | } |
| 754 | 826 | ||
diff --git a/drivers/gpio/gpio-pcf857x.c b/drivers/gpio/gpio-pcf857x.c index 68a35b65925a..c9b650f617fa 100644 --- a/drivers/gpio/gpio-pcf857x.c +++ b/drivers/gpio/gpio-pcf857x.c | |||
| @@ -89,7 +89,6 @@ struct pcf857x { | |||
| 89 | struct mutex lock; /* protect 'out' */ | 89 | struct mutex lock; /* protect 'out' */ |
| 90 | unsigned out; /* software latch */ | 90 | unsigned out; /* software latch */ |
| 91 | unsigned status; /* current status */ | 91 | unsigned status; /* current status */ |
| 92 | unsigned int irq_parent; | ||
| 93 | unsigned irq_enabled; /* enabled irqs */ | 92 | unsigned irq_enabled; /* enabled irqs */ |
| 94 | 93 | ||
| 95 | int (*write)(struct i2c_client *client, unsigned data); | 94 | int (*write)(struct i2c_client *client, unsigned data); |
| @@ -211,18 +210,7 @@ static int pcf857x_irq_set_wake(struct irq_data *data, unsigned int on) | |||
| 211 | { | 210 | { |
| 212 | struct pcf857x *gpio = irq_data_get_irq_chip_data(data); | 211 | struct pcf857x *gpio = irq_data_get_irq_chip_data(data); |
| 213 | 212 | ||
| 214 | int error = 0; | 213 | return irq_set_irq_wake(gpio->client->irq, on); |
| 215 | |||
| 216 | if (gpio->irq_parent) { | ||
| 217 | error = irq_set_irq_wake(gpio->irq_parent, on); | ||
| 218 | if (error) { | ||
| 219 | dev_dbg(&gpio->client->dev, | ||
| 220 | "irq %u doesn't support irq_set_wake\n", | ||
| 221 | gpio->irq_parent); | ||
| 222 | gpio->irq_parent = 0; | ||
| 223 | } | ||
| 224 | } | ||
| 225 | return error; | ||
| 226 | } | 214 | } |
| 227 | 215 | ||
| 228 | static void pcf857x_irq_enable(struct irq_data *data) | 216 | static void pcf857x_irq_enable(struct irq_data *data) |
| @@ -392,7 +380,6 @@ static int pcf857x_probe(struct i2c_client *client, | |||
| 392 | 380 | ||
| 393 | gpiochip_set_nested_irqchip(&gpio->chip, &gpio->irqchip, | 381 | gpiochip_set_nested_irqchip(&gpio->chip, &gpio->irqchip, |
| 394 | client->irq); | 382 | client->irq); |
| 395 | gpio->irq_parent = client->irq; | ||
| 396 | } | 383 | } |
| 397 | 384 | ||
| 398 | /* Let platform code set up the GPIOs and their users. | 385 | /* Let platform code set up the GPIOs and their users. |
diff --git a/drivers/gpio/gpio-pmic-eic-sprd.c b/drivers/gpio/gpio-pmic-eic-sprd.c index 29e044ff4b17..24228cf79afc 100644 --- a/drivers/gpio/gpio-pmic-eic-sprd.c +++ b/drivers/gpio/gpio-pmic-eic-sprd.c | |||
| @@ -322,7 +322,6 @@ static int sprd_pmic_eic_probe(struct platform_device *pdev) | |||
| 322 | 322 | ||
| 323 | ret = devm_request_threaded_irq(&pdev->dev, pmic_eic->irq, NULL, | 323 | ret = devm_request_threaded_irq(&pdev->dev, pmic_eic->irq, NULL, |
| 324 | sprd_pmic_eic_irq_handler, | 324 | sprd_pmic_eic_irq_handler, |
| 325 | IRQF_TRIGGER_LOW | | ||
| 326 | IRQF_ONESHOT | IRQF_NO_SUSPEND, | 325 | IRQF_ONESHOT | IRQF_NO_SUSPEND, |
| 327 | dev_name(&pdev->dev), pmic_eic); | 326 | dev_name(&pdev->dev), pmic_eic); |
| 328 | if (ret) { | 327 | if (ret) { |
| @@ -365,7 +364,7 @@ static int sprd_pmic_eic_probe(struct platform_device *pdev) | |||
| 365 | } | 364 | } |
| 366 | 365 | ||
| 367 | static const struct of_device_id sprd_pmic_eic_of_match[] = { | 366 | static const struct of_device_id sprd_pmic_eic_of_match[] = { |
| 368 | { .compatible = "sprd,sc27xx-eic", }, | 367 | { .compatible = "sprd,sc2731-eic", }, |
| 369 | { /* end of list */ } | 368 | { /* end of list */ } |
| 370 | }; | 369 | }; |
| 371 | MODULE_DEVICE_TABLE(of, sprd_pmic_eic_of_match); | 370 | MODULE_DEVICE_TABLE(of, sprd_pmic_eic_of_match); |
diff --git a/drivers/gpio/gpio-rcar.c b/drivers/gpio/gpio-rcar.c index 068ce25ffd28..500a3596aaf4 100644 --- a/drivers/gpio/gpio-rcar.c +++ b/drivers/gpio/gpio-rcar.c | |||
| @@ -40,6 +40,7 @@ struct gpio_rcar_priv { | |||
| 40 | struct irq_chip irq_chip; | 40 | struct irq_chip irq_chip; |
| 41 | unsigned int irq_parent; | 41 | unsigned int irq_parent; |
| 42 | atomic_t wakeup_path; | 42 | atomic_t wakeup_path; |
| 43 | bool has_outdtsel; | ||
| 43 | bool has_both_edge_trigger; | 44 | bool has_both_edge_trigger; |
| 44 | struct gpio_rcar_bank_info bank_info; | 45 | struct gpio_rcar_bank_info bank_info; |
| 45 | }; | 46 | }; |
| @@ -55,6 +56,7 @@ struct gpio_rcar_priv { | |||
| 55 | #define POSNEG 0x20 /* Positive/Negative Logic Select Register */ | 56 | #define POSNEG 0x20 /* Positive/Negative Logic Select Register */ |
| 56 | #define EDGLEVEL 0x24 /* Edge/level Select Register */ | 57 | #define EDGLEVEL 0x24 /* Edge/level Select Register */ |
| 57 | #define FILONOFF 0x28 /* Chattering Prevention On/Off Register */ | 58 | #define FILONOFF 0x28 /* Chattering Prevention On/Off Register */ |
| 59 | #define OUTDTSEL 0x40 /* Output Data Select Register */ | ||
| 58 | #define BOTHEDGE 0x4c /* One Edge/Both Edge Select Register */ | 60 | #define BOTHEDGE 0x4c /* One Edge/Both Edge Select Register */ |
| 59 | 61 | ||
| 60 | #define RCAR_MAX_GPIO_PER_BANK 32 | 62 | #define RCAR_MAX_GPIO_PER_BANK 32 |
| @@ -235,6 +237,10 @@ static void gpio_rcar_config_general_input_output_mode(struct gpio_chip *chip, | |||
| 235 | /* Select Input Mode or Output Mode in INOUTSEL */ | 237 | /* Select Input Mode or Output Mode in INOUTSEL */ |
| 236 | gpio_rcar_modify_bit(p, INOUTSEL, gpio, output); | 238 | gpio_rcar_modify_bit(p, INOUTSEL, gpio, output); |
| 237 | 239 | ||
| 240 | /* Select General Output Register to output data in OUTDTSEL */ | ||
| 241 | if (p->has_outdtsel && output) | ||
| 242 | gpio_rcar_modify_bit(p, OUTDTSEL, gpio, false); | ||
| 243 | |||
| 238 | spin_unlock_irqrestore(&p->lock, flags); | 244 | spin_unlock_irqrestore(&p->lock, flags); |
| 239 | } | 245 | } |
| 240 | 246 | ||
| @@ -336,14 +342,17 @@ static int gpio_rcar_direction_output(struct gpio_chip *chip, unsigned offset, | |||
| 336 | } | 342 | } |
| 337 | 343 | ||
| 338 | struct gpio_rcar_info { | 344 | struct gpio_rcar_info { |
| 345 | bool has_outdtsel; | ||
| 339 | bool has_both_edge_trigger; | 346 | bool has_both_edge_trigger; |
| 340 | }; | 347 | }; |
| 341 | 348 | ||
| 342 | static const struct gpio_rcar_info gpio_rcar_info_gen1 = { | 349 | static const struct gpio_rcar_info gpio_rcar_info_gen1 = { |
| 350 | .has_outdtsel = false, | ||
| 343 | .has_both_edge_trigger = false, | 351 | .has_both_edge_trigger = false, |
| 344 | }; | 352 | }; |
| 345 | 353 | ||
| 346 | static const struct gpio_rcar_info gpio_rcar_info_gen2 = { | 354 | static const struct gpio_rcar_info gpio_rcar_info_gen2 = { |
| 355 | .has_outdtsel = true, | ||
| 347 | .has_both_edge_trigger = true, | 356 | .has_both_edge_trigger = true, |
| 348 | }; | 357 | }; |
| 349 | 358 | ||
| @@ -403,10 +412,11 @@ static int gpio_rcar_parse_dt(struct gpio_rcar_priv *p, unsigned int *npins) | |||
| 403 | int ret; | 412 | int ret; |
| 404 | 413 | ||
| 405 | info = of_device_get_match_data(p->dev); | 414 | info = of_device_get_match_data(p->dev); |
| 415 | p->has_outdtsel = info->has_outdtsel; | ||
| 416 | p->has_both_edge_trigger = info->has_both_edge_trigger; | ||
| 406 | 417 | ||
| 407 | ret = of_parse_phandle_with_fixed_args(np, "gpio-ranges", 3, 0, &args); | 418 | ret = of_parse_phandle_with_fixed_args(np, "gpio-ranges", 3, 0, &args); |
| 408 | *npins = ret == 0 ? args.args[2] : RCAR_MAX_GPIO_PER_BANK; | 419 | *npins = ret == 0 ? args.args[2] : RCAR_MAX_GPIO_PER_BANK; |
| 409 | p->has_both_edge_trigger = info->has_both_edge_trigger; | ||
| 410 | 420 | ||
| 411 | if (*npins == 0 || *npins > RCAR_MAX_GPIO_PER_BANK) { | 421 | if (*npins == 0 || *npins > RCAR_MAX_GPIO_PER_BANK) { |
| 412 | dev_warn(p->dev, "Invalid number of gpio lines %u, using %u\n", | 422 | dev_warn(p->dev, "Invalid number of gpio lines %u, using %u\n", |
diff --git a/drivers/gpio/gpio-sama5d2-piobu.c b/drivers/gpio/gpio-sama5d2-piobu.c index 03a000659fa1..7d718557092e 100644 --- a/drivers/gpio/gpio-sama5d2-piobu.c +++ b/drivers/gpio/gpio-sama5d2-piobu.c | |||
| @@ -109,16 +109,6 @@ static int sama5d2_piobu_read_value(struct gpio_chip *chip, unsigned int pin, | |||
| 109 | } | 109 | } |
| 110 | 110 | ||
| 111 | /** | 111 | /** |
| 112 | * sama5d2_piobu_set_direction() - mark pin as input or output | ||
| 113 | */ | ||
| 114 | static int sama5d2_piobu_set_direction(struct gpio_chip *chip, | ||
| 115 | unsigned int direction, | ||
| 116 | unsigned int pin) | ||
| 117 | { | ||
| 118 | return sama5d2_piobu_write_value(chip, pin, PIOBU_DIRECTION, direction); | ||
| 119 | } | ||
| 120 | |||
| 121 | /** | ||
| 122 | * sama5d2_piobu_get_direction() - gpiochip get_direction | 112 | * sama5d2_piobu_get_direction() - gpiochip get_direction |
| 123 | */ | 113 | */ |
| 124 | static int sama5d2_piobu_get_direction(struct gpio_chip *chip, | 114 | static int sama5d2_piobu_get_direction(struct gpio_chip *chip, |
| @@ -138,7 +128,7 @@ static int sama5d2_piobu_get_direction(struct gpio_chip *chip, | |||
| 138 | static int sama5d2_piobu_direction_input(struct gpio_chip *chip, | 128 | static int sama5d2_piobu_direction_input(struct gpio_chip *chip, |
| 139 | unsigned int pin) | 129 | unsigned int pin) |
| 140 | { | 130 | { |
| 141 | return sama5d2_piobu_set_direction(chip, PIOBU_IN, pin); | 131 | return sama5d2_piobu_write_value(chip, pin, PIOBU_DIRECTION, PIOBU_IN); |
| 142 | } | 132 | } |
| 143 | 133 | ||
| 144 | /** | 134 | /** |
| @@ -147,7 +137,13 @@ static int sama5d2_piobu_direction_input(struct gpio_chip *chip, | |||
| 147 | static int sama5d2_piobu_direction_output(struct gpio_chip *chip, | 137 | static int sama5d2_piobu_direction_output(struct gpio_chip *chip, |
| 148 | unsigned int pin, int value) | 138 | unsigned int pin, int value) |
| 149 | { | 139 | { |
| 150 | return sama5d2_piobu_set_direction(chip, PIOBU_OUT, pin); | 140 | unsigned int val = PIOBU_OUT; |
| 141 | |||
| 142 | if (value) | ||
| 143 | val |= PIOBU_HIGH; | ||
| 144 | |||
| 145 | return sama5d2_piobu_write_value(chip, pin, PIOBU_DIRECTION | PIOBU_SOD, | ||
| 146 | val); | ||
| 151 | } | 147 | } |
| 152 | 148 | ||
| 153 | /** | 149 | /** |
diff --git a/drivers/gpio/gpio-tegra.c b/drivers/gpio/gpio-tegra.c index 02f6db925fd5..1ececf2c3282 100644 --- a/drivers/gpio/gpio-tegra.c +++ b/drivers/gpio/gpio-tegra.c | |||
| @@ -2,6 +2,7 @@ | |||
| 2 | * arch/arm/mach-tegra/gpio.c | 2 | * arch/arm/mach-tegra/gpio.c |
| 3 | * | 3 | * |
| 4 | * Copyright (c) 2010 Google, Inc | 4 | * Copyright (c) 2010 Google, Inc |
| 5 | * Copyright (c) 2011-2016, NVIDIA CORPORATION. All rights reserved. | ||
| 5 | * | 6 | * |
| 6 | * Author: | 7 | * Author: |
| 7 | * Erik Gilling <konkers@google.com> | 8 | * Erik Gilling <konkers@google.com> |
| @@ -141,14 +142,14 @@ static void tegra_gpio_disable(struct tegra_gpio_info *tgi, unsigned int gpio) | |||
| 141 | 142 | ||
| 142 | static int tegra_gpio_request(struct gpio_chip *chip, unsigned int offset) | 143 | static int tegra_gpio_request(struct gpio_chip *chip, unsigned int offset) |
| 143 | { | 144 | { |
| 144 | return pinctrl_gpio_request(offset); | 145 | return pinctrl_gpio_request(chip->base + offset); |
| 145 | } | 146 | } |
| 146 | 147 | ||
| 147 | static void tegra_gpio_free(struct gpio_chip *chip, unsigned int offset) | 148 | static void tegra_gpio_free(struct gpio_chip *chip, unsigned int offset) |
| 148 | { | 149 | { |
| 149 | struct tegra_gpio_info *tgi = gpiochip_get_data(chip); | 150 | struct tegra_gpio_info *tgi = gpiochip_get_data(chip); |
| 150 | 151 | ||
| 151 | pinctrl_gpio_free(offset); | 152 | pinctrl_gpio_free(chip->base + offset); |
| 152 | tegra_gpio_disable(tgi, offset); | 153 | tegra_gpio_disable(tgi, offset); |
| 153 | } | 154 | } |
| 154 | 155 | ||
| @@ -176,10 +177,18 @@ static int tegra_gpio_direction_input(struct gpio_chip *chip, | |||
| 176 | unsigned int offset) | 177 | unsigned int offset) |
| 177 | { | 178 | { |
| 178 | struct tegra_gpio_info *tgi = gpiochip_get_data(chip); | 179 | struct tegra_gpio_info *tgi = gpiochip_get_data(chip); |
| 180 | int ret; | ||
| 179 | 181 | ||
| 180 | tegra_gpio_mask_write(tgi, GPIO_MSK_OE(tgi, offset), offset, 0); | 182 | tegra_gpio_mask_write(tgi, GPIO_MSK_OE(tgi, offset), offset, 0); |
| 181 | tegra_gpio_enable(tgi, offset); | 183 | tegra_gpio_enable(tgi, offset); |
| 182 | return 0; | 184 | |
| 185 | ret = pinctrl_gpio_direction_input(chip->base + offset); | ||
| 186 | if (ret < 0) | ||
| 187 | dev_err(tgi->dev, | ||
| 188 | "Failed to set pinctrl input direction of GPIO %d: %d", | ||
| 189 | chip->base + offset, ret); | ||
| 190 | |||
| 191 | return ret; | ||
| 183 | } | 192 | } |
| 184 | 193 | ||
| 185 | static int tegra_gpio_direction_output(struct gpio_chip *chip, | 194 | static int tegra_gpio_direction_output(struct gpio_chip *chip, |
| @@ -187,11 +196,19 @@ static int tegra_gpio_direction_output(struct gpio_chip *chip, | |||
| 187 | int value) | 196 | int value) |
| 188 | { | 197 | { |
| 189 | struct tegra_gpio_info *tgi = gpiochip_get_data(chip); | 198 | struct tegra_gpio_info *tgi = gpiochip_get_data(chip); |
| 199 | int ret; | ||
| 190 | 200 | ||
| 191 | tegra_gpio_set(chip, offset, value); | 201 | tegra_gpio_set(chip, offset, value); |
| 192 | tegra_gpio_mask_write(tgi, GPIO_MSK_OE(tgi, offset), offset, 1); | 202 | tegra_gpio_mask_write(tgi, GPIO_MSK_OE(tgi, offset), offset, 1); |
| 193 | tegra_gpio_enable(tgi, offset); | 203 | tegra_gpio_enable(tgi, offset); |
| 194 | return 0; | 204 | |
| 205 | ret = pinctrl_gpio_direction_output(chip->base + offset); | ||
| 206 | if (ret < 0) | ||
| 207 | dev_err(tgi->dev, | ||
| 208 | "Failed to set pinctrl output direction of GPIO %d: %d", | ||
| 209 | chip->base + offset, ret); | ||
| 210 | |||
| 211 | return ret; | ||
| 195 | } | 212 | } |
| 196 | 213 | ||
| 197 | static int tegra_gpio_get_direction(struct gpio_chip *chip, | 214 | static int tegra_gpio_get_direction(struct gpio_chip *chip, |
diff --git a/drivers/gpio/gpio-tegra186.c b/drivers/gpio/gpio-tegra186.c index 66ec38bb7954..7d42e3d7572c 100644 --- a/drivers/gpio/gpio-tegra186.c +++ b/drivers/gpio/gpio-tegra186.c | |||
| @@ -529,8 +529,8 @@ static int tegra186_gpio_remove(struct platform_device *pdev) | |||
| 529 | return 0; | 529 | return 0; |
| 530 | } | 530 | } |
| 531 | 531 | ||
| 532 | #define TEGRA_MAIN_GPIO_PORT(port, base, count, controller) \ | 532 | #define TEGRA186_MAIN_GPIO_PORT(port, base, count, controller) \ |
| 533 | [TEGRA_MAIN_GPIO_PORT_##port] = { \ | 533 | [TEGRA186_MAIN_GPIO_PORT_##port] = { \ |
| 534 | .name = #port, \ | 534 | .name = #port, \ |
| 535 | .offset = base, \ | 535 | .offset = base, \ |
| 536 | .pins = count, \ | 536 | .pins = count, \ |
| @@ -538,29 +538,29 @@ static int tegra186_gpio_remove(struct platform_device *pdev) | |||
| 538 | } | 538 | } |
| 539 | 539 | ||
| 540 | static const struct tegra_gpio_port tegra186_main_ports[] = { | 540 | static const struct tegra_gpio_port tegra186_main_ports[] = { |
| 541 | TEGRA_MAIN_GPIO_PORT( A, 0x2000, 7, 2), | 541 | TEGRA186_MAIN_GPIO_PORT( A, 0x2000, 7, 2), |
| 542 | TEGRA_MAIN_GPIO_PORT( B, 0x3000, 7, 3), | 542 | TEGRA186_MAIN_GPIO_PORT( B, 0x3000, 7, 3), |
| 543 | TEGRA_MAIN_GPIO_PORT( C, 0x3200, 7, 3), | 543 | TEGRA186_MAIN_GPIO_PORT( C, 0x3200, 7, 3), |
| 544 | TEGRA_MAIN_GPIO_PORT( D, 0x3400, 6, 3), | 544 | TEGRA186_MAIN_GPIO_PORT( D, 0x3400, 6, 3), |
| 545 | TEGRA_MAIN_GPIO_PORT( E, 0x2200, 8, 2), | 545 | TEGRA186_MAIN_GPIO_PORT( E, 0x2200, 8, 2), |
| 546 | TEGRA_MAIN_GPIO_PORT( F, 0x2400, 6, 2), | 546 | TEGRA186_MAIN_GPIO_PORT( F, 0x2400, 6, 2), |
| 547 | TEGRA_MAIN_GPIO_PORT( G, 0x4200, 6, 4), | 547 | TEGRA186_MAIN_GPIO_PORT( G, 0x4200, 6, 4), |
| 548 | TEGRA_MAIN_GPIO_PORT( H, 0x1000, 7, 1), | 548 | TEGRA186_MAIN_GPIO_PORT( H, 0x1000, 7, 1), |
| 549 | TEGRA_MAIN_GPIO_PORT( I, 0x0800, 8, 0), | 549 | TEGRA186_MAIN_GPIO_PORT( I, 0x0800, 8, 0), |
| 550 | TEGRA_MAIN_GPIO_PORT( J, 0x5000, 8, 5), | 550 | TEGRA186_MAIN_GPIO_PORT( J, 0x5000, 8, 5), |
| 551 | TEGRA_MAIN_GPIO_PORT( K, 0x5200, 1, 5), | 551 | TEGRA186_MAIN_GPIO_PORT( K, 0x5200, 1, 5), |
| 552 | TEGRA_MAIN_GPIO_PORT( L, 0x1200, 8, 1), | 552 | TEGRA186_MAIN_GPIO_PORT( L, 0x1200, 8, 1), |
| 553 | TEGRA_MAIN_GPIO_PORT( M, 0x5600, 6, 5), | 553 | TEGRA186_MAIN_GPIO_PORT( M, 0x5600, 6, 5), |
| 554 | TEGRA_MAIN_GPIO_PORT( N, 0x0000, 7, 0), | 554 | TEGRA186_MAIN_GPIO_PORT( N, 0x0000, 7, 0), |
| 555 | TEGRA_MAIN_GPIO_PORT( O, 0x0200, 4, 0), | 555 | TEGRA186_MAIN_GPIO_PORT( O, 0x0200, 4, 0), |
| 556 | TEGRA_MAIN_GPIO_PORT( P, 0x4000, 7, 4), | 556 | TEGRA186_MAIN_GPIO_PORT( P, 0x4000, 7, 4), |
| 557 | TEGRA_MAIN_GPIO_PORT( Q, 0x0400, 6, 0), | 557 | TEGRA186_MAIN_GPIO_PORT( Q, 0x0400, 6, 0), |
| 558 | TEGRA_MAIN_GPIO_PORT( R, 0x0a00, 6, 0), | 558 | TEGRA186_MAIN_GPIO_PORT( R, 0x0a00, 6, 0), |
| 559 | TEGRA_MAIN_GPIO_PORT( T, 0x0600, 4, 0), | 559 | TEGRA186_MAIN_GPIO_PORT( T, 0x0600, 4, 0), |
| 560 | TEGRA_MAIN_GPIO_PORT( X, 0x1400, 8, 1), | 560 | TEGRA186_MAIN_GPIO_PORT( X, 0x1400, 8, 1), |
| 561 | TEGRA_MAIN_GPIO_PORT( Y, 0x1600, 7, 1), | 561 | TEGRA186_MAIN_GPIO_PORT( Y, 0x1600, 7, 1), |
| 562 | TEGRA_MAIN_GPIO_PORT(BB, 0x2600, 2, 2), | 562 | TEGRA186_MAIN_GPIO_PORT(BB, 0x2600, 2, 2), |
| 563 | TEGRA_MAIN_GPIO_PORT(CC, 0x5400, 4, 5), | 563 | TEGRA186_MAIN_GPIO_PORT(CC, 0x5400, 4, 5), |
| 564 | }; | 564 | }; |
| 565 | 565 | ||
| 566 | static const struct tegra_gpio_soc tegra186_main_soc = { | 566 | static const struct tegra_gpio_soc tegra186_main_soc = { |
| @@ -569,8 +569,8 @@ static const struct tegra_gpio_soc tegra186_main_soc = { | |||
| 569 | .name = "tegra186-gpio", | 569 | .name = "tegra186-gpio", |
| 570 | }; | 570 | }; |
| 571 | 571 | ||
| 572 | #define TEGRA_AON_GPIO_PORT(port, base, count, controller) \ | 572 | #define TEGRA186_AON_GPIO_PORT(port, base, count, controller) \ |
| 573 | [TEGRA_AON_GPIO_PORT_##port] = { \ | 573 | [TEGRA186_AON_GPIO_PORT_##port] = { \ |
| 574 | .name = #port, \ | 574 | .name = #port, \ |
| 575 | .offset = base, \ | 575 | .offset = base, \ |
| 576 | .pins = count, \ | 576 | .pins = count, \ |
| @@ -578,14 +578,14 @@ static const struct tegra_gpio_soc tegra186_main_soc = { | |||
| 578 | } | 578 | } |
| 579 | 579 | ||
| 580 | static const struct tegra_gpio_port tegra186_aon_ports[] = { | 580 | static const struct tegra_gpio_port tegra186_aon_ports[] = { |
| 581 | TEGRA_AON_GPIO_PORT( S, 0x0200, 5, 0), | 581 | TEGRA186_AON_GPIO_PORT( S, 0x0200, 5, 0), |
| 582 | TEGRA_AON_GPIO_PORT( U, 0x0400, 6, 0), | 582 | TEGRA186_AON_GPIO_PORT( U, 0x0400, 6, 0), |
| 583 | TEGRA_AON_GPIO_PORT( V, 0x0800, 8, 0), | 583 | TEGRA186_AON_GPIO_PORT( V, 0x0800, 8, 0), |
| 584 | TEGRA_AON_GPIO_PORT( W, 0x0a00, 8, 0), | 584 | TEGRA186_AON_GPIO_PORT( W, 0x0a00, 8, 0), |
| 585 | TEGRA_AON_GPIO_PORT( Z, 0x0e00, 4, 0), | 585 | TEGRA186_AON_GPIO_PORT( Z, 0x0e00, 4, 0), |
| 586 | TEGRA_AON_GPIO_PORT(AA, 0x0c00, 8, 0), | 586 | TEGRA186_AON_GPIO_PORT(AA, 0x0c00, 8, 0), |
| 587 | TEGRA_AON_GPIO_PORT(EE, 0x0600, 3, 0), | 587 | TEGRA186_AON_GPIO_PORT(EE, 0x0600, 3, 0), |
| 588 | TEGRA_AON_GPIO_PORT(FF, 0x0000, 5, 0), | 588 | TEGRA186_AON_GPIO_PORT(FF, 0x0000, 5, 0), |
| 589 | }; | 589 | }; |
| 590 | 590 | ||
| 591 | static const struct tegra_gpio_soc tegra186_aon_soc = { | 591 | static const struct tegra_gpio_soc tegra186_aon_soc = { |
diff --git a/drivers/gpio/gpio-tqmx86.c b/drivers/gpio/gpio-tqmx86.c new file mode 100644 index 000000000000..d5880db7f9d4 --- /dev/null +++ b/drivers/gpio/gpio-tqmx86.c | |||
| @@ -0,0 +1,332 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 2 | /* | ||
| 3 | * TQ-Systems TQMx86 PLD GPIO driver | ||
| 4 | * | ||
| 5 | * Based on vendor driver by: | ||
| 6 | * Vadim V.Vlasov <vvlasov@dev.rtsoft.ru> | ||
| 7 | */ | ||
| 8 | |||
| 9 | #include <linux/bitops.h> | ||
| 10 | #include <linux/errno.h> | ||
| 11 | #include <linux/gpio/driver.h> | ||
| 12 | #include <linux/init.h> | ||
| 13 | #include <linux/interrupt.h> | ||
| 14 | #include <linux/kernel.h> | ||
| 15 | #include <linux/module.h> | ||
| 16 | #include <linux/platform_device.h> | ||
| 17 | #include <linux/pm_runtime.h> | ||
| 18 | #include <linux/slab.h> | ||
| 19 | |||
| 20 | #define TQMX86_NGPIO 8 | ||
| 21 | #define TQMX86_NGPO 4 /* 0-3 - output */ | ||
| 22 | #define TQMX86_NGPI 4 /* 4-7 - input */ | ||
| 23 | #define TQMX86_DIR_INPUT_MASK 0xf0 /* 0-3 - output, 4-7 - input */ | ||
| 24 | |||
| 25 | #define TQMX86_GPIODD 0 /* GPIO Data Direction Register */ | ||
| 26 | #define TQMX86_GPIOD 1 /* GPIO Data Register */ | ||
| 27 | #define TQMX86_GPIIC 3 /* GPI Interrupt Configuration Register */ | ||
| 28 | #define TQMX86_GPIIS 4 /* GPI Interrupt Status Register */ | ||
| 29 | |||
| 30 | #define TQMX86_GPII_FALLING BIT(0) | ||
| 31 | #define TQMX86_GPII_RISING BIT(1) | ||
| 32 | #define TQMX86_GPII_MASK (BIT(0) | BIT(1)) | ||
| 33 | #define TQMX86_GPII_BITS 2 | ||
| 34 | |||
| 35 | struct tqmx86_gpio_data { | ||
| 36 | struct gpio_chip chip; | ||
| 37 | struct irq_chip irq_chip; | ||
| 38 | void __iomem *io_base; | ||
| 39 | int irq; | ||
| 40 | raw_spinlock_t spinlock; | ||
| 41 | u8 irq_type[TQMX86_NGPI]; | ||
| 42 | }; | ||
| 43 | |||
| 44 | static u8 tqmx86_gpio_read(struct tqmx86_gpio_data *gd, unsigned int reg) | ||
| 45 | { | ||
| 46 | return ioread8(gd->io_base + reg); | ||
| 47 | } | ||
| 48 | |||
| 49 | static void tqmx86_gpio_write(struct tqmx86_gpio_data *gd, u8 val, | ||
| 50 | unsigned int reg) | ||
| 51 | { | ||
| 52 | iowrite8(val, gd->io_base + reg); | ||
| 53 | } | ||
| 54 | |||
| 55 | static int tqmx86_gpio_get(struct gpio_chip *chip, unsigned int offset) | ||
| 56 | { | ||
| 57 | struct tqmx86_gpio_data *gpio = gpiochip_get_data(chip); | ||
| 58 | |||
| 59 | return !!(tqmx86_gpio_read(gpio, TQMX86_GPIOD) & BIT(offset)); | ||
| 60 | } | ||
| 61 | |||
| 62 | static void tqmx86_gpio_set(struct gpio_chip *chip, unsigned int offset, | ||
| 63 | int value) | ||
| 64 | { | ||
| 65 | struct tqmx86_gpio_data *gpio = gpiochip_get_data(chip); | ||
| 66 | unsigned long flags; | ||
| 67 | u8 val; | ||
| 68 | |||
| 69 | raw_spin_lock_irqsave(&gpio->spinlock, flags); | ||
| 70 | val = tqmx86_gpio_read(gpio, TQMX86_GPIOD); | ||
| 71 | if (value) | ||
| 72 | val |= BIT(offset); | ||
| 73 | else | ||
| 74 | val &= ~BIT(offset); | ||
| 75 | tqmx86_gpio_write(gpio, val, TQMX86_GPIOD); | ||
| 76 | raw_spin_unlock_irqrestore(&gpio->spinlock, flags); | ||
| 77 | } | ||
| 78 | |||
| 79 | static int tqmx86_gpio_direction_input(struct gpio_chip *chip, | ||
| 80 | unsigned int offset) | ||
| 81 | { | ||
| 82 | /* Direction cannot be changed. Validate is an input. */ | ||
| 83 | if (BIT(offset) & TQMX86_DIR_INPUT_MASK) | ||
| 84 | return 0; | ||
| 85 | else | ||
| 86 | return -EINVAL; | ||
| 87 | } | ||
| 88 | |||
| 89 | static int tqmx86_gpio_direction_output(struct gpio_chip *chip, | ||
| 90 | unsigned int offset, | ||
| 91 | int value) | ||
| 92 | { | ||
| 93 | /* Direction cannot be changed, validate is an output */ | ||
| 94 | if (BIT(offset) & TQMX86_DIR_INPUT_MASK) | ||
| 95 | return -EINVAL; | ||
| 96 | |||
| 97 | tqmx86_gpio_set(chip, offset, value); | ||
| 98 | return 0; | ||
| 99 | } | ||
| 100 | |||
| 101 | static int tqmx86_gpio_get_direction(struct gpio_chip *chip, | ||
| 102 | unsigned int offset) | ||
| 103 | { | ||
| 104 | return !!(TQMX86_DIR_INPUT_MASK & BIT(offset)); | ||
| 105 | } | ||
| 106 | |||
| 107 | static void tqmx86_gpio_irq_mask(struct irq_data *data) | ||
| 108 | { | ||
| 109 | unsigned int offset = (data->hwirq - TQMX86_NGPO); | ||
| 110 | struct tqmx86_gpio_data *gpio = gpiochip_get_data( | ||
| 111 | irq_data_get_irq_chip_data(data)); | ||
| 112 | unsigned long flags; | ||
| 113 | u8 gpiic, mask; | ||
| 114 | |||
| 115 | mask = TQMX86_GPII_MASK << (offset * TQMX86_GPII_BITS); | ||
| 116 | |||
| 117 | raw_spin_lock_irqsave(&gpio->spinlock, flags); | ||
| 118 | gpiic = tqmx86_gpio_read(gpio, TQMX86_GPIIC); | ||
| 119 | gpiic &= ~mask; | ||
| 120 | tqmx86_gpio_write(gpio, gpiic, TQMX86_GPIIC); | ||
| 121 | raw_spin_unlock_irqrestore(&gpio->spinlock, flags); | ||
| 122 | } | ||
| 123 | |||
| 124 | static void tqmx86_gpio_irq_unmask(struct irq_data *data) | ||
| 125 | { | ||
| 126 | unsigned int offset = (data->hwirq - TQMX86_NGPO); | ||
| 127 | struct tqmx86_gpio_data *gpio = gpiochip_get_data( | ||
| 128 | irq_data_get_irq_chip_data(data)); | ||
| 129 | unsigned long flags; | ||
| 130 | u8 gpiic, mask; | ||
| 131 | |||
| 132 | mask = TQMX86_GPII_MASK << (offset * TQMX86_GPII_BITS); | ||
| 133 | |||
| 134 | raw_spin_lock_irqsave(&gpio->spinlock, flags); | ||
| 135 | gpiic = tqmx86_gpio_read(gpio, TQMX86_GPIIC); | ||
| 136 | gpiic &= ~mask; | ||
| 137 | gpiic |= gpio->irq_type[offset] << (offset * TQMX86_GPII_BITS); | ||
| 138 | tqmx86_gpio_write(gpio, gpiic, TQMX86_GPIIC); | ||
| 139 | raw_spin_unlock_irqrestore(&gpio->spinlock, flags); | ||
| 140 | } | ||
| 141 | |||
| 142 | static int tqmx86_gpio_irq_set_type(struct irq_data *data, unsigned int type) | ||
| 143 | { | ||
| 144 | struct tqmx86_gpio_data *gpio = gpiochip_get_data( | ||
| 145 | irq_data_get_irq_chip_data(data)); | ||
| 146 | unsigned int offset = (data->hwirq - TQMX86_NGPO); | ||
| 147 | unsigned int edge_type = type & IRQF_TRIGGER_MASK; | ||
| 148 | unsigned long flags; | ||
| 149 | u8 new_type, gpiic; | ||
| 150 | |||
| 151 | switch (edge_type) { | ||
| 152 | case IRQ_TYPE_EDGE_RISING: | ||
| 153 | new_type = TQMX86_GPII_RISING; | ||
| 154 | break; | ||
| 155 | case IRQ_TYPE_EDGE_FALLING: | ||
| 156 | new_type = TQMX86_GPII_FALLING; | ||
| 157 | break; | ||
| 158 | case IRQ_TYPE_EDGE_BOTH: | ||
| 159 | new_type = TQMX86_GPII_FALLING | TQMX86_GPII_RISING; | ||
| 160 | break; | ||
| 161 | default: | ||
| 162 | return -EINVAL; /* not supported */ | ||
| 163 | } | ||
| 164 | |||
| 165 | gpio->irq_type[offset] = new_type; | ||
| 166 | |||
| 167 | raw_spin_lock_irqsave(&gpio->spinlock, flags); | ||
| 168 | gpiic = tqmx86_gpio_read(gpio, TQMX86_GPIIC); | ||
| 169 | gpiic &= ~((TQMX86_GPII_MASK) << (offset * TQMX86_GPII_BITS)); | ||
| 170 | gpiic |= new_type << (offset * TQMX86_GPII_BITS); | ||
| 171 | tqmx86_gpio_write(gpio, gpiic, TQMX86_GPIIC); | ||
| 172 | raw_spin_unlock_irqrestore(&gpio->spinlock, flags); | ||
| 173 | |||
| 174 | return 0; | ||
| 175 | } | ||
| 176 | |||
| 177 | static void tqmx86_gpio_irq_handler(struct irq_desc *desc) | ||
| 178 | { | ||
| 179 | struct gpio_chip *chip = irq_desc_get_handler_data(desc); | ||
| 180 | struct tqmx86_gpio_data *gpio = gpiochip_get_data(chip); | ||
| 181 | struct irq_chip *irq_chip = irq_desc_get_chip(desc); | ||
| 182 | unsigned long irq_bits; | ||
| 183 | int i = 0, child_irq; | ||
| 184 | u8 irq_status; | ||
| 185 | |||
| 186 | chained_irq_enter(irq_chip, desc); | ||
| 187 | |||
| 188 | irq_status = tqmx86_gpio_read(gpio, TQMX86_GPIIS); | ||
| 189 | tqmx86_gpio_write(gpio, irq_status, TQMX86_GPIIS); | ||
| 190 | |||
| 191 | irq_bits = irq_status; | ||
| 192 | for_each_set_bit(i, &irq_bits, TQMX86_NGPI) { | ||
| 193 | child_irq = irq_find_mapping(gpio->chip.irq.domain, | ||
| 194 | i + TQMX86_NGPO); | ||
| 195 | generic_handle_irq(child_irq); | ||
| 196 | } | ||
| 197 | |||
| 198 | chained_irq_exit(irq_chip, desc); | ||
| 199 | } | ||
| 200 | |||
| 201 | /* Minimal runtime PM is needed by the IRQ subsystem */ | ||
| 202 | static int __maybe_unused tqmx86_gpio_runtime_suspend(struct device *dev) | ||
| 203 | { | ||
| 204 | return 0; | ||
| 205 | } | ||
| 206 | |||
| 207 | static int __maybe_unused tqmx86_gpio_runtime_resume(struct device *dev) | ||
| 208 | { | ||
| 209 | return 0; | ||
| 210 | } | ||
| 211 | |||
| 212 | static const struct dev_pm_ops tqmx86_gpio_dev_pm_ops = { | ||
| 213 | SET_RUNTIME_PM_OPS(tqmx86_gpio_runtime_suspend, | ||
| 214 | tqmx86_gpio_runtime_resume, NULL) | ||
| 215 | }; | ||
| 216 | |||
| 217 | static int tqmx86_gpio_probe(struct platform_device *pdev) | ||
| 218 | { | ||
| 219 | struct device *dev = &pdev->dev; | ||
| 220 | struct tqmx86_gpio_data *gpio; | ||
| 221 | struct gpio_chip *chip; | ||
| 222 | void __iomem *io_base; | ||
| 223 | struct resource *res; | ||
| 224 | int ret, irq; | ||
| 225 | |||
| 226 | irq = platform_get_irq(pdev, 0); | ||
| 227 | if (irq < 0) | ||
| 228 | return irq; | ||
| 229 | |||
| 230 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); | ||
| 231 | if (!res) { | ||
| 232 | dev_err(&pdev->dev, "Cannot get I/O\n"); | ||
| 233 | return -ENODEV; | ||
| 234 | } | ||
| 235 | |||
| 236 | io_base = devm_ioport_map(&pdev->dev, res->start, resource_size(res)); | ||
| 237 | if (!io_base) | ||
| 238 | return -ENOMEM; | ||
| 239 | |||
| 240 | gpio = devm_kzalloc(dev, sizeof(*gpio), GFP_KERNEL); | ||
| 241 | if (!gpio) | ||
| 242 | return -ENOMEM; | ||
| 243 | |||
| 244 | raw_spin_lock_init(&gpio->spinlock); | ||
| 245 | gpio->io_base = io_base; | ||
| 246 | |||
| 247 | tqmx86_gpio_write(gpio, (u8)~TQMX86_DIR_INPUT_MASK, TQMX86_GPIODD); | ||
| 248 | |||
| 249 | platform_set_drvdata(pdev, gpio); | ||
| 250 | |||
| 251 | chip = &gpio->chip; | ||
| 252 | chip->label = "gpio-tqmx86"; | ||
| 253 | chip->owner = THIS_MODULE; | ||
| 254 | chip->can_sleep = false; | ||
| 255 | chip->base = -1; | ||
| 256 | chip->direction_input = tqmx86_gpio_direction_input; | ||
| 257 | chip->direction_output = tqmx86_gpio_direction_output; | ||
| 258 | chip->get_direction = tqmx86_gpio_get_direction; | ||
| 259 | chip->get = tqmx86_gpio_get; | ||
| 260 | chip->set = tqmx86_gpio_set; | ||
| 261 | chip->ngpio = TQMX86_NGPIO; | ||
| 262 | chip->irq.need_valid_mask = true; | ||
| 263 | chip->parent = pdev->dev.parent; | ||
| 264 | |||
| 265 | pm_runtime_enable(&pdev->dev); | ||
| 266 | |||
| 267 | ret = devm_gpiochip_add_data(dev, chip, gpio); | ||
| 268 | if (ret) { | ||
| 269 | dev_err(dev, "Could not register GPIO chip\n"); | ||
| 270 | goto out_pm_dis; | ||
| 271 | } | ||
| 272 | |||
| 273 | if (irq) { | ||
| 274 | struct irq_chip *irq_chip = &gpio->irq_chip; | ||
| 275 | u8 irq_status; | ||
| 276 | |||
| 277 | irq_chip->name = chip->label; | ||
| 278 | irq_chip->parent_device = &pdev->dev; | ||
| 279 | irq_chip->irq_mask = tqmx86_gpio_irq_mask; | ||
| 280 | irq_chip->irq_unmask = tqmx86_gpio_irq_unmask; | ||
| 281 | irq_chip->irq_set_type = tqmx86_gpio_irq_set_type; | ||
| 282 | |||
| 283 | /* Mask all interrupts */ | ||
| 284 | tqmx86_gpio_write(gpio, 0, TQMX86_GPIIC); | ||
| 285 | |||
| 286 | /* Clear all pending interrupts */ | ||
| 287 | irq_status = tqmx86_gpio_read(gpio, TQMX86_GPIIS); | ||
| 288 | tqmx86_gpio_write(gpio, irq_status, TQMX86_GPIIS); | ||
| 289 | |||
| 290 | ret = gpiochip_irqchip_add(chip, irq_chip, | ||
| 291 | 0, handle_simple_irq, | ||
| 292 | IRQ_TYPE_EDGE_BOTH); | ||
| 293 | if (ret) { | ||
| 294 | dev_err(dev, "Could not add irq chip\n"); | ||
| 295 | goto out_pm_dis; | ||
| 296 | } | ||
| 297 | |||
| 298 | gpiochip_set_chained_irqchip(chip, irq_chip, | ||
| 299 | irq, tqmx86_gpio_irq_handler); | ||
| 300 | } | ||
| 301 | |||
| 302 | /* Only GPIOs 4-7 are valid for interrupts. Clear the others */ | ||
| 303 | clear_bit(0, chip->irq.valid_mask); | ||
| 304 | clear_bit(1, chip->irq.valid_mask); | ||
| 305 | clear_bit(2, chip->irq.valid_mask); | ||
| 306 | clear_bit(3, chip->irq.valid_mask); | ||
| 307 | |||
| 308 | dev_info(dev, "GPIO functionality initialized with %d pins\n", | ||
| 309 | chip->ngpio); | ||
| 310 | |||
| 311 | return 0; | ||
| 312 | |||
| 313 | out_pm_dis: | ||
| 314 | pm_runtime_disable(&pdev->dev); | ||
| 315 | |||
| 316 | return ret; | ||
| 317 | } | ||
| 318 | |||
| 319 | static struct platform_driver tqmx86_gpio_driver = { | ||
| 320 | .driver = { | ||
| 321 | .name = "tqmx86-gpio", | ||
| 322 | .pm = &tqmx86_gpio_dev_pm_ops, | ||
| 323 | }, | ||
| 324 | .probe = tqmx86_gpio_probe, | ||
| 325 | }; | ||
| 326 | |||
| 327 | module_platform_driver(tqmx86_gpio_driver); | ||
| 328 | |||
| 329 | MODULE_DESCRIPTION("TQMx86 PLD GPIO Driver"); | ||
| 330 | MODULE_AUTHOR("Andrew Lunn <andrew@lunn.ch>"); | ||
| 331 | MODULE_LICENSE("GPL"); | ||
| 332 | MODULE_ALIAS("platform:tqmx86-gpio"); | ||
diff --git a/drivers/gpio/gpio-wcove.c b/drivers/gpio/gpio-wcove.c index dde7c6aecbb5..444fe9e7f04a 100644 --- a/drivers/gpio/gpio-wcove.c +++ b/drivers/gpio/gpio-wcove.c | |||
| @@ -1,34 +1,26 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 1 | /* | 2 | /* |
| 2 | * Intel Whiskey Cove PMIC GPIO Driver | 3 | * Intel Whiskey Cove PMIC GPIO Driver |
| 3 | * | 4 | * |
| 4 | * This driver is written based on gpio-crystalcove.c | 5 | * This driver is written based on gpio-crystalcove.c |
| 5 | * | 6 | * |
| 6 | * Copyright (C) 2016 Intel Corporation. All rights reserved. | 7 | * Copyright (C) 2016 Intel Corporation. All rights reserved. |
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or | ||
| 9 | * modify it under the terms of the GNU General Public License version | ||
| 10 | * 2 as published by the Free Software Foundation. | ||
| 11 | * | ||
| 12 | * This program is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | * GNU General Public License for more details. | ||
| 16 | */ | 8 | */ |
| 17 | 9 | ||
| 18 | #include <linux/bitops.h> | 10 | #include <linux/bitops.h> |
| 19 | #include <linux/module.h> | ||
| 20 | #include <linux/interrupt.h> | ||
| 21 | #include <linux/gpio/driver.h> | 11 | #include <linux/gpio/driver.h> |
| 12 | #include <linux/interrupt.h> | ||
| 22 | #include <linux/mfd/intel_soc_pmic.h> | 13 | #include <linux/mfd/intel_soc_pmic.h> |
| 14 | #include <linux/module.h> | ||
| 23 | #include <linux/platform_device.h> | 15 | #include <linux/platform_device.h> |
| 24 | #include <linux/regmap.h> | 16 | #include <linux/regmap.h> |
| 25 | #include <linux/seq_file.h> | 17 | #include <linux/seq_file.h> |
| 26 | 18 | ||
| 27 | /* | 19 | /* |
| 28 | * Whiskey Cove PMIC has 13 physical GPIO pins divided into 3 banks: | 20 | * Whiskey Cove PMIC has 13 physical GPIO pins divided into 3 banks: |
| 29 | * Bank 0: Pin 0 - 6 | 21 | * Bank 0: Pin 0 - 6 |
| 30 | * Bank 1: Pin 7 - 10 | 22 | * Bank 1: Pin 7 - 10 |
| 31 | * Bank 2: Pin 11 -12 | 23 | * Bank 2: Pin 11 - 12 |
| 32 | * Each pin has one output control register and one input control register. | 24 | * Each pin has one output control register and one input control register. |
| 33 | */ | 25 | */ |
| 34 | #define BANK0_NR_PINS 7 | 26 | #define BANK0_NR_PINS 7 |
| @@ -75,8 +67,8 @@ | |||
| 75 | #define CTLO_RVAL_50KDOWN (2 << 1) | 67 | #define CTLO_RVAL_50KDOWN (2 << 1) |
| 76 | #define CTLO_RVAL_50KUP (3 << 1) | 68 | #define CTLO_RVAL_50KUP (3 << 1) |
| 77 | 69 | ||
| 78 | #define CTLO_INPUT_SET (CTLO_DRV_CMOS | CTLO_DRV_REN | CTLO_RVAL_2KUP) | 70 | #define CTLO_INPUT_SET (CTLO_DRV_CMOS | CTLO_DRV_REN | CTLO_RVAL_2KUP) |
| 79 | #define CTLO_OUTPUT_SET (CTLO_DIR_OUT | CTLO_INPUT_SET) | 71 | #define CTLO_OUTPUT_SET (CTLO_DIR_OUT | CTLO_INPUT_SET) |
| 80 | 72 | ||
| 81 | enum ctrl_register { | 73 | enum ctrl_register { |
| 82 | CTRL_IN, | 74 | CTRL_IN, |
| @@ -105,7 +97,7 @@ struct wcove_gpio { | |||
| 105 | bool set_irq_mask; | 97 | bool set_irq_mask; |
| 106 | }; | 98 | }; |
| 107 | 99 | ||
| 108 | static inline unsigned int to_reg(int gpio, enum ctrl_register reg_type) | 100 | static inline int to_reg(int gpio, enum ctrl_register reg_type) |
| 109 | { | 101 | { |
| 110 | unsigned int reg; | 102 | unsigned int reg; |
| 111 | 103 | ||
| @@ -203,8 +195,7 @@ static int wcove_gpio_get(struct gpio_chip *chip, unsigned int gpio) | |||
| 203 | return val & 0x1; | 195 | return val & 0x1; |
| 204 | } | 196 | } |
| 205 | 197 | ||
| 206 | static void wcove_gpio_set(struct gpio_chip *chip, | 198 | static void wcove_gpio_set(struct gpio_chip *chip, unsigned int gpio, int value) |
| 207 | unsigned int gpio, int value) | ||
| 208 | { | 199 | { |
| 209 | struct wcove_gpio *wg = gpiochip_get_data(chip); | 200 | struct wcove_gpio *wg = gpiochip_get_data(chip); |
| 210 | int reg = to_reg(gpio, CTRL_OUT); | 201 | int reg = to_reg(gpio, CTRL_OUT); |
diff --git a/drivers/gpio/gpio-zynq.c b/drivers/gpio/gpio-zynq.c index b3b4edcdffe0..00ff7b1fa8a1 100644 --- a/drivers/gpio/gpio-zynq.c +++ b/drivers/gpio/gpio-zynq.c | |||
| @@ -555,6 +555,26 @@ static int zynq_gpio_set_wake(struct irq_data *data, unsigned int on) | |||
| 555 | return 0; | 555 | return 0; |
| 556 | } | 556 | } |
| 557 | 557 | ||
| 558 | static int zynq_gpio_irq_reqres(struct irq_data *d) | ||
| 559 | { | ||
| 560 | struct gpio_chip *chip = irq_data_get_irq_chip_data(d); | ||
| 561 | int ret; | ||
| 562 | |||
| 563 | ret = pm_runtime_get_sync(chip->parent); | ||
| 564 | if (ret < 0) | ||
| 565 | return ret; | ||
| 566 | |||
| 567 | return gpiochip_reqres_irq(chip, d->hwirq); | ||
| 568 | } | ||
| 569 | |||
| 570 | static void zynq_gpio_irq_relres(struct irq_data *d) | ||
| 571 | { | ||
| 572 | struct gpio_chip *chip = irq_data_get_irq_chip_data(d); | ||
| 573 | |||
| 574 | gpiochip_relres_irq(chip, d->hwirq); | ||
| 575 | pm_runtime_put(chip->parent); | ||
| 576 | } | ||
| 577 | |||
| 558 | /* irq chip descriptor */ | 578 | /* irq chip descriptor */ |
| 559 | static struct irq_chip zynq_gpio_level_irqchip = { | 579 | static struct irq_chip zynq_gpio_level_irqchip = { |
| 560 | .name = DRIVER_NAME, | 580 | .name = DRIVER_NAME, |
| @@ -564,6 +584,8 @@ static struct irq_chip zynq_gpio_level_irqchip = { | |||
| 564 | .irq_unmask = zynq_gpio_irq_unmask, | 584 | .irq_unmask = zynq_gpio_irq_unmask, |
| 565 | .irq_set_type = zynq_gpio_set_irq_type, | 585 | .irq_set_type = zynq_gpio_set_irq_type, |
| 566 | .irq_set_wake = zynq_gpio_set_wake, | 586 | .irq_set_wake = zynq_gpio_set_wake, |
| 587 | .irq_request_resources = zynq_gpio_irq_reqres, | ||
| 588 | .irq_release_resources = zynq_gpio_irq_relres, | ||
| 567 | .flags = IRQCHIP_EOI_THREADED | IRQCHIP_EOI_IF_HANDLED | | 589 | .flags = IRQCHIP_EOI_THREADED | IRQCHIP_EOI_IF_HANDLED | |
| 568 | IRQCHIP_MASK_ON_SUSPEND, | 590 | IRQCHIP_MASK_ON_SUSPEND, |
| 569 | }; | 591 | }; |
| @@ -576,6 +598,8 @@ static struct irq_chip zynq_gpio_edge_irqchip = { | |||
| 576 | .irq_unmask = zynq_gpio_irq_unmask, | 598 | .irq_unmask = zynq_gpio_irq_unmask, |
| 577 | .irq_set_type = zynq_gpio_set_irq_type, | 599 | .irq_set_type = zynq_gpio_set_irq_type, |
| 578 | .irq_set_wake = zynq_gpio_set_wake, | 600 | .irq_set_wake = zynq_gpio_set_wake, |
| 601 | .irq_request_resources = zynq_gpio_irq_reqres, | ||
| 602 | .irq_release_resources = zynq_gpio_irq_relres, | ||
| 579 | .flags = IRQCHIP_MASK_ON_SUSPEND, | 603 | .flags = IRQCHIP_MASK_ON_SUSPEND, |
| 580 | }; | 604 | }; |
| 581 | 605 | ||
diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c index 3e8e2d3ce7a8..30d0baf7ddae 100644 --- a/drivers/gpio/gpiolib-acpi.c +++ b/drivers/gpio/gpiolib-acpi.c | |||
| @@ -29,7 +29,7 @@ | |||
| 29 | * @irq: Linux IRQ number for the event, for request_ / free_irq | 29 | * @irq: Linux IRQ number for the event, for request_ / free_irq |
| 30 | * @irqflags: flags to pass to request_irq when requesting the IRQ | 30 | * @irqflags: flags to pass to request_irq when requesting the IRQ |
| 31 | * @irq_is_wake: If the ACPI flags indicate the IRQ is a wakeup source | 31 | * @irq_is_wake: If the ACPI flags indicate the IRQ is a wakeup source |
| 32 | * @is_requested: True if request_irq has been done | 32 | * @irq_requested:True if request_irq has been done |
| 33 | * @desc: gpio_desc for the GPIO pin for this event | 33 | * @desc: gpio_desc for the GPIO pin for this event |
| 34 | */ | 34 | */ |
| 35 | struct acpi_gpio_event { | 35 | struct acpi_gpio_event { |
| @@ -469,6 +469,9 @@ acpi_gpio_to_gpiod_flags(const struct acpi_resource_gpio *agpio) | |||
| 469 | static int | 469 | static int |
| 470 | __acpi_gpio_update_gpiod_flags(enum gpiod_flags *flags, enum gpiod_flags update) | 470 | __acpi_gpio_update_gpiod_flags(enum gpiod_flags *flags, enum gpiod_flags update) |
| 471 | { | 471 | { |
| 472 | const enum gpiod_flags mask = | ||
| 473 | GPIOD_FLAGS_BIT_DIR_SET | GPIOD_FLAGS_BIT_DIR_OUT | | ||
| 474 | GPIOD_FLAGS_BIT_DIR_VAL; | ||
| 472 | int ret = 0; | 475 | int ret = 0; |
| 473 | 476 | ||
| 474 | /* | 477 | /* |
| @@ -489,7 +492,7 @@ __acpi_gpio_update_gpiod_flags(enum gpiod_flags *flags, enum gpiod_flags update) | |||
| 489 | if (((*flags & GPIOD_FLAGS_BIT_DIR_SET) && (diff & GPIOD_FLAGS_BIT_DIR_OUT)) || | 492 | if (((*flags & GPIOD_FLAGS_BIT_DIR_SET) && (diff & GPIOD_FLAGS_BIT_DIR_OUT)) || |
| 490 | ((*flags & GPIOD_FLAGS_BIT_DIR_OUT) && (diff & GPIOD_FLAGS_BIT_DIR_VAL))) | 493 | ((*flags & GPIOD_FLAGS_BIT_DIR_OUT) && (diff & GPIOD_FLAGS_BIT_DIR_VAL))) |
| 491 | ret = -EINVAL; | 494 | ret = -EINVAL; |
| 492 | *flags = update; | 495 | *flags = (*flags & ~mask) | (update & mask); |
| 493 | } | 496 | } |
| 494 | return ret; | 497 | return ret; |
| 495 | } | 498 | } |
diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c index c34eb9d9c59a..8b9c3ab70f6e 100644 --- a/drivers/gpio/gpiolib-of.c +++ b/drivers/gpio/gpiolib-of.c | |||
| @@ -86,7 +86,9 @@ static void of_gpio_flags_quirks(struct device_node *np, | |||
| 86 | if (IS_ENABLED(CONFIG_REGULATOR) && | 86 | if (IS_ENABLED(CONFIG_REGULATOR) && |
| 87 | (of_device_is_compatible(np, "regulator-fixed") || | 87 | (of_device_is_compatible(np, "regulator-fixed") || |
| 88 | of_device_is_compatible(np, "reg-fixed-voltage") || | 88 | of_device_is_compatible(np, "reg-fixed-voltage") || |
| 89 | of_device_is_compatible(np, "regulator-gpio"))) { | 89 | (of_device_is_compatible(np, "regulator-gpio") && |
| 90 | !(strcmp(propname, "enable-gpio") && | ||
| 91 | strcmp(propname, "enable-gpios"))))) { | ||
| 90 | /* | 92 | /* |
| 91 | * The regulator GPIO handles are specified such that the | 93 | * The regulator GPIO handles are specified such that the |
| 92 | * presence or absence of "enable-active-high" solely controls | 94 | * presence or absence of "enable-active-high" solely controls |
| @@ -345,6 +347,11 @@ struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id, | |||
| 345 | if (of_flags & OF_GPIO_TRANSITORY) | 347 | if (of_flags & OF_GPIO_TRANSITORY) |
| 346 | *flags |= GPIO_TRANSITORY; | 348 | *flags |= GPIO_TRANSITORY; |
| 347 | 349 | ||
| 350 | if (of_flags & OF_GPIO_PULL_UP) | ||
| 351 | *flags |= GPIO_PULL_UP; | ||
| 352 | if (of_flags & OF_GPIO_PULL_DOWN) | ||
| 353 | *flags |= GPIO_PULL_DOWN; | ||
| 354 | |||
| 348 | return desc; | 355 | return desc; |
| 349 | } | 356 | } |
| 350 | 357 | ||
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index d1adfdf50fb3..144af0733581 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c | |||
| @@ -1782,6 +1782,43 @@ static const struct irq_domain_ops gpiochip_domain_ops = { | |||
| 1782 | .xlate = irq_domain_xlate_twocell, | 1782 | .xlate = irq_domain_xlate_twocell, |
| 1783 | }; | 1783 | }; |
| 1784 | 1784 | ||
| 1785 | /** | ||
| 1786 | * gpiochip_irq_domain_activate() - Lock a GPIO to be used as an IRQ | ||
| 1787 | * @domain: The IRQ domain used by this IRQ chip | ||
| 1788 | * @data: Outermost irq_data associated with the IRQ | ||
| 1789 | * @reserve: If set, only reserve an interrupt vector instead of assigning one | ||
| 1790 | * | ||
| 1791 | * This function is a wrapper that calls gpiochip_lock_as_irq() and is to be | ||
| 1792 | * used as the activate function for the &struct irq_domain_ops. The host_data | ||
| 1793 | * for the IRQ domain must be the &struct gpio_chip. | ||
| 1794 | */ | ||
| 1795 | int gpiochip_irq_domain_activate(struct irq_domain *domain, | ||
| 1796 | struct irq_data *data, bool reserve) | ||
| 1797 | { | ||
| 1798 | struct gpio_chip *chip = domain->host_data; | ||
| 1799 | |||
| 1800 | return gpiochip_lock_as_irq(chip, data->hwirq); | ||
| 1801 | } | ||
| 1802 | EXPORT_SYMBOL_GPL(gpiochip_irq_domain_activate); | ||
| 1803 | |||
| 1804 | /** | ||
| 1805 | * gpiochip_irq_domain_deactivate() - Unlock a GPIO used as an IRQ | ||
| 1806 | * @domain: The IRQ domain used by this IRQ chip | ||
| 1807 | * @data: Outermost irq_data associated with the IRQ | ||
| 1808 | * | ||
| 1809 | * This function is a wrapper that will call gpiochip_unlock_as_irq() and is to | ||
| 1810 | * be used as the deactivate function for the &struct irq_domain_ops. The | ||
| 1811 | * host_data for the IRQ domain must be the &struct gpio_chip. | ||
| 1812 | */ | ||
| 1813 | void gpiochip_irq_domain_deactivate(struct irq_domain *domain, | ||
| 1814 | struct irq_data *data) | ||
| 1815 | { | ||
| 1816 | struct gpio_chip *chip = domain->host_data; | ||
| 1817 | |||
| 1818 | return gpiochip_unlock_as_irq(chip, data->hwirq); | ||
| 1819 | } | ||
| 1820 | EXPORT_SYMBOL_GPL(gpiochip_irq_domain_deactivate); | ||
| 1821 | |||
| 1785 | static int gpiochip_to_irq(struct gpio_chip *chip, unsigned offset) | 1822 | static int gpiochip_to_irq(struct gpio_chip *chip, unsigned offset) |
| 1786 | { | 1823 | { |
| 1787 | if (!gpiochip_irqchip_irq_valid(chip, offset)) | 1824 | if (!gpiochip_irqchip_irq_valid(chip, offset)) |
| @@ -2525,6 +2562,14 @@ EXPORT_SYMBOL_GPL(gpiochip_free_own_desc); | |||
| 2525 | * rely on gpio_request() having been called beforehand. | 2562 | * rely on gpio_request() having been called beforehand. |
| 2526 | */ | 2563 | */ |
| 2527 | 2564 | ||
| 2565 | static int gpio_set_config(struct gpio_chip *gc, unsigned offset, | ||
| 2566 | enum pin_config_param mode) | ||
| 2567 | { | ||
| 2568 | unsigned long config = { PIN_CONF_PACKED(mode, 0) }; | ||
| 2569 | |||
| 2570 | return gc->set_config ? gc->set_config(gc, offset, config) : -ENOTSUPP; | ||
| 2571 | } | ||
| 2572 | |||
| 2528 | /** | 2573 | /** |
| 2529 | * gpiod_direction_input - set the GPIO direction to input | 2574 | * gpiod_direction_input - set the GPIO direction to input |
| 2530 | * @desc: GPIO to set to input | 2575 | * @desc: GPIO to set to input |
| @@ -2572,20 +2617,19 @@ int gpiod_direction_input(struct gpio_desc *desc) | |||
| 2572 | if (status == 0) | 2617 | if (status == 0) |
| 2573 | clear_bit(FLAG_IS_OUT, &desc->flags); | 2618 | clear_bit(FLAG_IS_OUT, &desc->flags); |
| 2574 | 2619 | ||
| 2620 | if (test_bit(FLAG_PULL_UP, &desc->flags)) | ||
| 2621 | gpio_set_config(chip, gpio_chip_hwgpio(desc), | ||
| 2622 | PIN_CONFIG_BIAS_PULL_UP); | ||
| 2623 | else if (test_bit(FLAG_PULL_DOWN, &desc->flags)) | ||
| 2624 | gpio_set_config(chip, gpio_chip_hwgpio(desc), | ||
| 2625 | PIN_CONFIG_BIAS_PULL_DOWN); | ||
| 2626 | |||
| 2575 | trace_gpio_direction(desc_to_gpio(desc), 1, status); | 2627 | trace_gpio_direction(desc_to_gpio(desc), 1, status); |
| 2576 | 2628 | ||
| 2577 | return status; | 2629 | return status; |
| 2578 | } | 2630 | } |
| 2579 | EXPORT_SYMBOL_GPL(gpiod_direction_input); | 2631 | EXPORT_SYMBOL_GPL(gpiod_direction_input); |
| 2580 | 2632 | ||
| 2581 | static int gpio_set_drive_single_ended(struct gpio_chip *gc, unsigned offset, | ||
| 2582 | enum pin_config_param mode) | ||
| 2583 | { | ||
| 2584 | unsigned long config = { PIN_CONF_PACKED(mode, 0) }; | ||
| 2585 | |||
| 2586 | return gc->set_config ? gc->set_config(gc, offset, config) : -ENOTSUPP; | ||
| 2587 | } | ||
| 2588 | |||
| 2589 | static int gpiod_direction_output_raw_commit(struct gpio_desc *desc, int value) | 2633 | static int gpiod_direction_output_raw_commit(struct gpio_desc *desc, int value) |
| 2590 | { | 2634 | { |
| 2591 | struct gpio_chip *gc = desc->gdev->chip; | 2635 | struct gpio_chip *gc = desc->gdev->chip; |
| @@ -2682,8 +2726,8 @@ int gpiod_direction_output(struct gpio_desc *desc, int value) | |||
| 2682 | gc = desc->gdev->chip; | 2726 | gc = desc->gdev->chip; |
| 2683 | if (test_bit(FLAG_OPEN_DRAIN, &desc->flags)) { | 2727 | if (test_bit(FLAG_OPEN_DRAIN, &desc->flags)) { |
| 2684 | /* First see if we can enable open drain in hardware */ | 2728 | /* First see if we can enable open drain in hardware */ |
| 2685 | ret = gpio_set_drive_single_ended(gc, gpio_chip_hwgpio(desc), | 2729 | ret = gpio_set_config(gc, gpio_chip_hwgpio(desc), |
| 2686 | PIN_CONFIG_DRIVE_OPEN_DRAIN); | 2730 | PIN_CONFIG_DRIVE_OPEN_DRAIN); |
| 2687 | if (!ret) | 2731 | if (!ret) |
| 2688 | goto set_output_value; | 2732 | goto set_output_value; |
| 2689 | /* Emulate open drain by not actively driving the line high */ | 2733 | /* Emulate open drain by not actively driving the line high */ |
| @@ -2691,16 +2735,16 @@ int gpiod_direction_output(struct gpio_desc *desc, int value) | |||
| 2691 | return gpiod_direction_input(desc); | 2735 | return gpiod_direction_input(desc); |
| 2692 | } | 2736 | } |
| 2693 | else if (test_bit(FLAG_OPEN_SOURCE, &desc->flags)) { | 2737 | else if (test_bit(FLAG_OPEN_SOURCE, &desc->flags)) { |
| 2694 | ret = gpio_set_drive_single_ended(gc, gpio_chip_hwgpio(desc), | 2738 | ret = gpio_set_config(gc, gpio_chip_hwgpio(desc), |
| 2695 | PIN_CONFIG_DRIVE_OPEN_SOURCE); | 2739 | PIN_CONFIG_DRIVE_OPEN_SOURCE); |
| 2696 | if (!ret) | 2740 | if (!ret) |
| 2697 | goto set_output_value; | 2741 | goto set_output_value; |
| 2698 | /* Emulate open source by not actively driving the line low */ | 2742 | /* Emulate open source by not actively driving the line low */ |
| 2699 | if (!value) | 2743 | if (!value) |
| 2700 | return gpiod_direction_input(desc); | 2744 | return gpiod_direction_input(desc); |
| 2701 | } else { | 2745 | } else { |
| 2702 | gpio_set_drive_single_ended(gc, gpio_chip_hwgpio(desc), | 2746 | gpio_set_config(gc, gpio_chip_hwgpio(desc), |
| 2703 | PIN_CONFIG_DRIVE_PUSH_PULL); | 2747 | PIN_CONFIG_DRIVE_PUSH_PULL); |
| 2704 | } | 2748 | } |
| 2705 | 2749 | ||
| 2706 | set_output_value: | 2750 | set_output_value: |
| @@ -2732,7 +2776,7 @@ int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce) | |||
| 2732 | } | 2776 | } |
| 2733 | 2777 | ||
| 2734 | config = pinconf_to_config_packed(PIN_CONFIG_INPUT_DEBOUNCE, debounce); | 2778 | config = pinconf_to_config_packed(PIN_CONFIG_INPUT_DEBOUNCE, debounce); |
| 2735 | return chip->set_config(chip, gpio_chip_hwgpio(desc), config); | 2779 | return gpio_set_config(chip, gpio_chip_hwgpio(desc), config); |
| 2736 | } | 2780 | } |
| 2737 | EXPORT_SYMBOL_GPL(gpiod_set_debounce); | 2781 | EXPORT_SYMBOL_GPL(gpiod_set_debounce); |
| 2738 | 2782 | ||
| @@ -2769,7 +2813,7 @@ int gpiod_set_transitory(struct gpio_desc *desc, bool transitory) | |||
| 2769 | packed = pinconf_to_config_packed(PIN_CONFIG_PERSIST_STATE, | 2813 | packed = pinconf_to_config_packed(PIN_CONFIG_PERSIST_STATE, |
| 2770 | !transitory); | 2814 | !transitory); |
| 2771 | gpio = gpio_chip_hwgpio(desc); | 2815 | gpio = gpio_chip_hwgpio(desc); |
| 2772 | rc = chip->set_config(chip, gpio, packed); | 2816 | rc = gpio_set_config(chip, gpio, packed); |
| 2773 | if (rc == -ENOTSUPP) { | 2817 | if (rc == -ENOTSUPP) { |
| 2774 | dev_dbg(&desc->gdev->dev, "Persistence not supported for GPIO %d\n", | 2818 | dev_dbg(&desc->gdev->dev, "Persistence not supported for GPIO %d\n", |
| 2775 | gpio); | 2819 | gpio); |
| @@ -4057,6 +4101,17 @@ int gpiod_configure_flags(struct gpio_desc *desc, const char *con_id, | |||
| 4057 | if (lflags & GPIO_OPEN_SOURCE) | 4101 | if (lflags & GPIO_OPEN_SOURCE) |
| 4058 | set_bit(FLAG_OPEN_SOURCE, &desc->flags); | 4102 | set_bit(FLAG_OPEN_SOURCE, &desc->flags); |
| 4059 | 4103 | ||
| 4104 | if ((lflags & GPIO_PULL_UP) && (lflags & GPIO_PULL_DOWN)) { | ||
| 4105 | gpiod_err(desc, | ||
| 4106 | "both pull-up and pull-down enabled, invalid configuration\n"); | ||
| 4107 | return -EINVAL; | ||
| 4108 | } | ||
| 4109 | |||
| 4110 | if (lflags & GPIO_PULL_UP) | ||
| 4111 | set_bit(FLAG_PULL_UP, &desc->flags); | ||
| 4112 | else if (lflags & GPIO_PULL_DOWN) | ||
| 4113 | set_bit(FLAG_PULL_DOWN, &desc->flags); | ||
| 4114 | |||
| 4060 | status = gpiod_set_transitory(desc, (lflags & GPIO_TRANSITORY)); | 4115 | status = gpiod_set_transitory(desc, (lflags & GPIO_TRANSITORY)); |
| 4061 | if (status < 0) | 4116 | if (status < 0) |
| 4062 | return status; | 4117 | return status; |
diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h index bc57f0dc5953..078ab17b96bf 100644 --- a/drivers/gpio/gpiolib.h +++ b/drivers/gpio/gpiolib.h | |||
| @@ -219,6 +219,8 @@ struct gpio_desc { | |||
| 219 | #define FLAG_IRQ_IS_ENABLED 10 /* GPIO is connected to an enabled IRQ */ | 219 | #define FLAG_IRQ_IS_ENABLED 10 /* GPIO is connected to an enabled IRQ */ |
| 220 | #define FLAG_IS_HOGGED 11 /* GPIO is hogged */ | 220 | #define FLAG_IS_HOGGED 11 /* GPIO is hogged */ |
| 221 | #define FLAG_TRANSITORY 12 /* GPIO may lose value in sleep or reset */ | 221 | #define FLAG_TRANSITORY 12 /* GPIO may lose value in sleep or reset */ |
| 222 | #define FLAG_PULL_UP 13 /* GPIO has pull up enabled */ | ||
| 223 | #define FLAG_PULL_DOWN 14 /* GPIO has pull down enabled */ | ||
| 222 | 224 | ||
| 223 | /* Connection label */ | 225 | /* Connection label */ |
| 224 | const char *label; | 226 | const char *label; |
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 1b50fa955992..ad8b1f400919 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig | |||
| @@ -927,7 +927,7 @@ config UCB1400_CORE | |||
| 927 | config MFD_PM8XXX | 927 | config MFD_PM8XXX |
| 928 | tristate "Qualcomm PM8xxx PMIC chips driver" | 928 | tristate "Qualcomm PM8xxx PMIC chips driver" |
| 929 | depends on (ARM || HEXAGON || COMPILE_TEST) | 929 | depends on (ARM || HEXAGON || COMPILE_TEST) |
| 930 | select IRQ_DOMAIN | 930 | select IRQ_DOMAIN_HIERARCHY |
| 931 | select MFD_CORE | 931 | select MFD_CORE |
| 932 | select REGMAP | 932 | select REGMAP |
| 933 | help | 933 | help |
diff --git a/drivers/mfd/qcom-pm8xxx.c b/drivers/mfd/qcom-pm8xxx.c index e6e8d81c15fd..8eb2528793f9 100644 --- a/drivers/mfd/qcom-pm8xxx.c +++ b/drivers/mfd/qcom-pm8xxx.c | |||
| @@ -70,22 +70,23 @@ | |||
| 70 | #define PM8XXX_NR_IRQS 256 | 70 | #define PM8XXX_NR_IRQS 256 |
| 71 | #define PM8821_NR_IRQS 112 | 71 | #define PM8821_NR_IRQS 112 |
| 72 | 72 | ||
| 73 | struct pm_irq_data { | ||
| 74 | int num_irqs; | ||
| 75 | struct irq_chip *irq_chip; | ||
| 76 | void (*irq_handler)(struct irq_desc *desc); | ||
| 77 | }; | ||
| 78 | |||
| 73 | struct pm_irq_chip { | 79 | struct pm_irq_chip { |
| 74 | struct regmap *regmap; | 80 | struct regmap *regmap; |
| 75 | spinlock_t pm_irq_lock; | 81 | spinlock_t pm_irq_lock; |
| 76 | struct irq_domain *irqdomain; | 82 | struct irq_domain *irqdomain; |
| 77 | unsigned int num_irqs; | ||
| 78 | unsigned int num_blocks; | 83 | unsigned int num_blocks; |
| 79 | unsigned int num_masters; | 84 | unsigned int num_masters; |
| 85 | const struct pm_irq_data *pm_irq_data; | ||
| 86 | /* MUST BE AT THE END OF THIS STRUCT */ | ||
| 80 | u8 config[0]; | 87 | u8 config[0]; |
| 81 | }; | 88 | }; |
| 82 | 89 | ||
| 83 | struct pm_irq_data { | ||
| 84 | int num_irqs; | ||
| 85 | const struct irq_domain_ops *irq_domain_ops; | ||
| 86 | void (*irq_handler)(struct irq_desc *desc); | ||
| 87 | }; | ||
| 88 | |||
| 89 | static int pm8xxx_read_block_irq(struct pm_irq_chip *chip, unsigned int bp, | 90 | static int pm8xxx_read_block_irq(struct pm_irq_chip *chip, unsigned int bp, |
| 90 | unsigned int *ip) | 91 | unsigned int *ip) |
| 91 | { | 92 | { |
| @@ -375,21 +376,38 @@ static struct irq_chip pm8xxx_irq_chip = { | |||
| 375 | .flags = IRQCHIP_MASK_ON_SUSPEND | IRQCHIP_SKIP_SET_WAKE, | 376 | .flags = IRQCHIP_MASK_ON_SUSPEND | IRQCHIP_SKIP_SET_WAKE, |
| 376 | }; | 377 | }; |
| 377 | 378 | ||
| 378 | static int pm8xxx_irq_domain_map(struct irq_domain *d, unsigned int irq, | 379 | static void pm8xxx_irq_domain_map(struct pm_irq_chip *chip, |
| 379 | irq_hw_number_t hwirq) | 380 | struct irq_domain *domain, unsigned int irq, |
| 381 | irq_hw_number_t hwirq, unsigned int type) | ||
| 380 | { | 382 | { |
| 381 | struct pm_irq_chip *chip = d->host_data; | 383 | irq_domain_set_info(domain, irq, hwirq, chip->pm_irq_data->irq_chip, |
| 382 | 384 | chip, handle_level_irq, NULL, NULL); | |
| 383 | irq_set_chip_and_handler(irq, &pm8xxx_irq_chip, handle_level_irq); | ||
| 384 | irq_set_chip_data(irq, chip); | ||
| 385 | irq_set_noprobe(irq); | 385 | irq_set_noprobe(irq); |
| 386 | } | ||
| 387 | |||
| 388 | static int pm8xxx_irq_domain_alloc(struct irq_domain *domain, unsigned int virq, | ||
| 389 | unsigned int nr_irqs, void *data) | ||
| 390 | { | ||
| 391 | struct pm_irq_chip *chip = domain->host_data; | ||
| 392 | struct irq_fwspec *fwspec = data; | ||
| 393 | irq_hw_number_t hwirq; | ||
| 394 | unsigned int type; | ||
| 395 | int ret, i; | ||
| 396 | |||
| 397 | ret = irq_domain_translate_twocell(domain, fwspec, &hwirq, &type); | ||
| 398 | if (ret) | ||
| 399 | return ret; | ||
| 400 | |||
| 401 | for (i = 0; i < nr_irqs; i++) | ||
| 402 | pm8xxx_irq_domain_map(chip, domain, virq + i, hwirq + i, type); | ||
| 386 | 403 | ||
| 387 | return 0; | 404 | return 0; |
| 388 | } | 405 | } |
| 389 | 406 | ||
| 390 | static const struct irq_domain_ops pm8xxx_irq_domain_ops = { | 407 | static const struct irq_domain_ops pm8xxx_irq_domain_ops = { |
| 391 | .xlate = irq_domain_xlate_twocell, | 408 | .alloc = pm8xxx_irq_domain_alloc, |
| 392 | .map = pm8xxx_irq_domain_map, | 409 | .free = irq_domain_free_irqs_common, |
| 410 | .translate = irq_domain_translate_twocell, | ||
| 393 | }; | 411 | }; |
| 394 | 412 | ||
| 395 | static void pm8821_irq_mask_ack(struct irq_data *d) | 413 | static void pm8821_irq_mask_ack(struct irq_data *d) |
| @@ -473,23 +491,6 @@ static struct irq_chip pm8821_irq_chip = { | |||
| 473 | .flags = IRQCHIP_MASK_ON_SUSPEND | IRQCHIP_SKIP_SET_WAKE, | 491 | .flags = IRQCHIP_MASK_ON_SUSPEND | IRQCHIP_SKIP_SET_WAKE, |
| 474 | }; | 492 | }; |
| 475 | 493 | ||
| 476 | static int pm8821_irq_domain_map(struct irq_domain *d, unsigned int irq, | ||
| 477 | irq_hw_number_t hwirq) | ||
| 478 | { | ||
| 479 | struct pm_irq_chip *chip = d->host_data; | ||
| 480 | |||
| 481 | irq_set_chip_and_handler(irq, &pm8821_irq_chip, handle_level_irq); | ||
| 482 | irq_set_chip_data(irq, chip); | ||
| 483 | irq_set_noprobe(irq); | ||
| 484 | |||
| 485 | return 0; | ||
| 486 | } | ||
| 487 | |||
| 488 | static const struct irq_domain_ops pm8821_irq_domain_ops = { | ||
| 489 | .xlate = irq_domain_xlate_twocell, | ||
| 490 | .map = pm8821_irq_domain_map, | ||
| 491 | }; | ||
| 492 | |||
| 493 | static const struct regmap_config ssbi_regmap_config = { | 494 | static const struct regmap_config ssbi_regmap_config = { |
| 494 | .reg_bits = 16, | 495 | .reg_bits = 16, |
| 495 | .val_bits = 8, | 496 | .val_bits = 8, |
| @@ -501,13 +502,13 @@ static const struct regmap_config ssbi_regmap_config = { | |||
| 501 | 502 | ||
| 502 | static const struct pm_irq_data pm8xxx_data = { | 503 | static const struct pm_irq_data pm8xxx_data = { |
| 503 | .num_irqs = PM8XXX_NR_IRQS, | 504 | .num_irqs = PM8XXX_NR_IRQS, |
| 504 | .irq_domain_ops = &pm8xxx_irq_domain_ops, | 505 | .irq_chip = &pm8xxx_irq_chip, |
| 505 | .irq_handler = pm8xxx_irq_handler, | 506 | .irq_handler = pm8xxx_irq_handler, |
| 506 | }; | 507 | }; |
| 507 | 508 | ||
| 508 | static const struct pm_irq_data pm8821_data = { | 509 | static const struct pm_irq_data pm8821_data = { |
| 509 | .num_irqs = PM8821_NR_IRQS, | 510 | .num_irqs = PM8821_NR_IRQS, |
| 510 | .irq_domain_ops = &pm8821_irq_domain_ops, | 511 | .irq_chip = &pm8821_irq_chip, |
| 511 | .irq_handler = pm8821_irq_handler, | 512 | .irq_handler = pm8821_irq_handler, |
| 512 | }; | 513 | }; |
| 513 | 514 | ||
| @@ -571,14 +572,14 @@ static int pm8xxx_probe(struct platform_device *pdev) | |||
| 571 | 572 | ||
| 572 | platform_set_drvdata(pdev, chip); | 573 | platform_set_drvdata(pdev, chip); |
| 573 | chip->regmap = regmap; | 574 | chip->regmap = regmap; |
| 574 | chip->num_irqs = data->num_irqs; | 575 | chip->num_blocks = DIV_ROUND_UP(data->num_irqs, 8); |
| 575 | chip->num_blocks = DIV_ROUND_UP(chip->num_irqs, 8); | ||
| 576 | chip->num_masters = DIV_ROUND_UP(chip->num_blocks, 8); | 576 | chip->num_masters = DIV_ROUND_UP(chip->num_blocks, 8); |
| 577 | chip->pm_irq_data = data; | ||
| 577 | spin_lock_init(&chip->pm_irq_lock); | 578 | spin_lock_init(&chip->pm_irq_lock); |
| 578 | 579 | ||
| 579 | chip->irqdomain = irq_domain_add_linear(pdev->dev.of_node, | 580 | chip->irqdomain = irq_domain_add_linear(pdev->dev.of_node, |
| 580 | data->num_irqs, | 581 | data->num_irqs, |
| 581 | data->irq_domain_ops, | 582 | &pm8xxx_irq_domain_ops, |
| 582 | chip); | 583 | chip); |
| 583 | if (!chip->irqdomain) | 584 | if (!chip->irqdomain) |
| 584 | return -ENODEV; | 585 | return -ENODEV; |
diff --git a/drivers/pinctrl/qcom/Kconfig b/drivers/pinctrl/qcom/Kconfig index 836e9f3eae4c..2e66ab72c10b 100644 --- a/drivers/pinctrl/qcom/Kconfig +++ b/drivers/pinctrl/qcom/Kconfig | |||
| @@ -137,6 +137,7 @@ config PINCTRL_QCOM_SPMI_PMIC | |||
| 137 | select PINMUX | 137 | select PINMUX |
| 138 | select PINCONF | 138 | select PINCONF |
| 139 | select GENERIC_PINCONF | 139 | select GENERIC_PINCONF |
| 140 | select IRQ_DOMAIN_HIERARCHY | ||
| 140 | help | 141 | help |
| 141 | This is the pinctrl, pinmux, pinconf and gpiolib driver for the | 142 | This is the pinctrl, pinmux, pinconf and gpiolib driver for the |
| 142 | Qualcomm GPIO and MPP blocks found in the Qualcomm PMIC's chips, | 143 | Qualcomm GPIO and MPP blocks found in the Qualcomm PMIC's chips, |
| @@ -149,6 +150,7 @@ config PINCTRL_QCOM_SSBI_PMIC | |||
| 149 | select PINMUX | 150 | select PINMUX |
| 150 | select PINCONF | 151 | select PINCONF |
| 151 | select GENERIC_PINCONF | 152 | select GENERIC_PINCONF |
| 153 | select IRQ_DOMAIN_HIERARCHY | ||
| 152 | help | 154 | help |
| 153 | This is the pinctrl, pinmux, pinconf and gpiolib driver for the | 155 | This is the pinctrl, pinmux, pinconf and gpiolib driver for the |
| 154 | Qualcomm GPIO and MPP blocks found in the Qualcomm PMIC's chips, | 156 | Qualcomm GPIO and MPP blocks found in the Qualcomm PMIC's chips, |
diff --git a/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c b/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c index 4458d44dfcf6..cb512c7a5251 100644 --- a/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c +++ b/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c | |||
| @@ -12,6 +12,7 @@ | |||
| 12 | */ | 12 | */ |
| 13 | 13 | ||
| 14 | #include <linux/gpio/driver.h> | 14 | #include <linux/gpio/driver.h> |
| 15 | #include <linux/interrupt.h> | ||
| 15 | #include <linux/module.h> | 16 | #include <linux/module.h> |
| 16 | #include <linux/of.h> | 17 | #include <linux/of.h> |
| 17 | #include <linux/of_irq.h> | 18 | #include <linux/of_irq.h> |
| @@ -136,7 +137,6 @@ enum pmic_gpio_func_index { | |||
| 136 | /** | 137 | /** |
| 137 | * struct pmic_gpio_pad - keep current GPIO settings | 138 | * struct pmic_gpio_pad - keep current GPIO settings |
| 138 | * @base: Address base in SPMI device. | 139 | * @base: Address base in SPMI device. |
| 139 | * @irq: IRQ number which this GPIO generate. | ||
| 140 | * @is_enabled: Set to false when GPIO should be put in high Z state. | 140 | * @is_enabled: Set to false when GPIO should be put in high Z state. |
| 141 | * @out_value: Cached pin output value | 141 | * @out_value: Cached pin output value |
| 142 | * @have_buffer: Set to true if GPIO output could be configured in push-pull, | 142 | * @have_buffer: Set to true if GPIO output could be configured in push-pull, |
| @@ -156,7 +156,6 @@ enum pmic_gpio_func_index { | |||
| 156 | */ | 156 | */ |
| 157 | struct pmic_gpio_pad { | 157 | struct pmic_gpio_pad { |
| 158 | u16 base; | 158 | u16 base; |
| 159 | int irq; | ||
| 160 | bool is_enabled; | 159 | bool is_enabled; |
| 161 | bool out_value; | 160 | bool out_value; |
| 162 | bool have_buffer; | 161 | bool have_buffer; |
| @@ -179,6 +178,8 @@ struct pmic_gpio_state { | |||
| 179 | struct regmap *map; | 178 | struct regmap *map; |
| 180 | struct pinctrl_dev *ctrl; | 179 | struct pinctrl_dev *ctrl; |
| 181 | struct gpio_chip chip; | 180 | struct gpio_chip chip; |
| 181 | struct fwnode_handle *fwnode; | ||
| 182 | struct irq_domain *domain; | ||
| 182 | }; | 183 | }; |
| 183 | 184 | ||
| 184 | static const struct pinconf_generic_params pmic_gpio_bindings[] = { | 185 | static const struct pinconf_generic_params pmic_gpio_bindings[] = { |
| @@ -761,11 +762,18 @@ static int pmic_gpio_of_xlate(struct gpio_chip *chip, | |||
| 761 | static int pmic_gpio_to_irq(struct gpio_chip *chip, unsigned pin) | 762 | static int pmic_gpio_to_irq(struct gpio_chip *chip, unsigned pin) |
| 762 | { | 763 | { |
| 763 | struct pmic_gpio_state *state = gpiochip_get_data(chip); | 764 | struct pmic_gpio_state *state = gpiochip_get_data(chip); |
| 764 | struct pmic_gpio_pad *pad; | 765 | struct irq_fwspec fwspec; |
| 765 | 766 | ||
| 766 | pad = state->ctrl->desc->pins[pin].drv_data; | 767 | fwspec.fwnode = state->fwnode; |
| 768 | fwspec.param_count = 2; | ||
| 769 | fwspec.param[0] = pin + PMIC_GPIO_PHYSICAL_OFFSET; | ||
| 770 | /* | ||
| 771 | * Set the type to a safe value temporarily. This will be overwritten | ||
| 772 | * later with the proper value by irq_set_type. | ||
| 773 | */ | ||
| 774 | fwspec.param[1] = IRQ_TYPE_EDGE_RISING; | ||
| 767 | 775 | ||
| 768 | return pad->irq; | 776 | return irq_create_fwspec_mapping(&fwspec); |
| 769 | } | 777 | } |
| 770 | 778 | ||
| 771 | static void pmic_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) | 779 | static void pmic_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) |
| @@ -935,8 +943,79 @@ static int pmic_gpio_populate(struct pmic_gpio_state *state, | |||
| 935 | return 0; | 943 | return 0; |
| 936 | } | 944 | } |
| 937 | 945 | ||
| 946 | static struct irq_chip pmic_gpio_irq_chip = { | ||
| 947 | .name = "spmi-gpio", | ||
| 948 | .irq_ack = irq_chip_ack_parent, | ||
| 949 | .irq_mask = irq_chip_mask_parent, | ||
| 950 | .irq_unmask = irq_chip_unmask_parent, | ||
| 951 | .irq_set_type = irq_chip_set_type_parent, | ||
| 952 | .irq_set_wake = irq_chip_set_wake_parent, | ||
| 953 | .flags = IRQCHIP_MASK_ON_SUSPEND, | ||
| 954 | }; | ||
| 955 | |||
| 956 | static int pmic_gpio_domain_translate(struct irq_domain *domain, | ||
| 957 | struct irq_fwspec *fwspec, | ||
| 958 | unsigned long *hwirq, | ||
| 959 | unsigned int *type) | ||
| 960 | { | ||
| 961 | struct pmic_gpio_state *state = container_of(domain->host_data, | ||
| 962 | struct pmic_gpio_state, | ||
| 963 | chip); | ||
| 964 | |||
| 965 | if (fwspec->param_count != 2 || | ||
| 966 | fwspec->param[0] < 1 || fwspec->param[0] > state->chip.ngpio) | ||
| 967 | return -EINVAL; | ||
| 968 | |||
| 969 | *hwirq = fwspec->param[0] - PMIC_GPIO_PHYSICAL_OFFSET; | ||
| 970 | *type = fwspec->param[1]; | ||
| 971 | |||
| 972 | return 0; | ||
| 973 | } | ||
| 974 | |||
| 975 | static int pmic_gpio_domain_alloc(struct irq_domain *domain, unsigned int virq, | ||
| 976 | unsigned int nr_irqs, void *data) | ||
| 977 | { | ||
| 978 | struct pmic_gpio_state *state = container_of(domain->host_data, | ||
| 979 | struct pmic_gpio_state, | ||
| 980 | chip); | ||
| 981 | struct irq_fwspec *fwspec = data; | ||
| 982 | struct irq_fwspec parent_fwspec; | ||
| 983 | irq_hw_number_t hwirq; | ||
| 984 | unsigned int type; | ||
| 985 | int ret, i; | ||
| 986 | |||
| 987 | ret = pmic_gpio_domain_translate(domain, fwspec, &hwirq, &type); | ||
| 988 | if (ret) | ||
| 989 | return ret; | ||
| 990 | |||
| 991 | for (i = 0; i < nr_irqs; i++) | ||
| 992 | irq_domain_set_info(domain, virq + i, hwirq + i, | ||
| 993 | &pmic_gpio_irq_chip, state, | ||
| 994 | handle_level_irq, NULL, NULL); | ||
| 995 | |||
| 996 | parent_fwspec.fwnode = domain->parent->fwnode; | ||
| 997 | parent_fwspec.param_count = 4; | ||
| 998 | parent_fwspec.param[0] = 0; | ||
| 999 | parent_fwspec.param[1] = hwirq + 0xc0; | ||
| 1000 | parent_fwspec.param[2] = 0; | ||
| 1001 | parent_fwspec.param[3] = fwspec->param[1]; | ||
| 1002 | |||
| 1003 | return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, | ||
| 1004 | &parent_fwspec); | ||
| 1005 | } | ||
| 1006 | |||
| 1007 | static const struct irq_domain_ops pmic_gpio_domain_ops = { | ||
| 1008 | .activate = gpiochip_irq_domain_activate, | ||
| 1009 | .alloc = pmic_gpio_domain_alloc, | ||
| 1010 | .deactivate = gpiochip_irq_domain_deactivate, | ||
| 1011 | .free = irq_domain_free_irqs_common, | ||
| 1012 | .translate = pmic_gpio_domain_translate, | ||
| 1013 | }; | ||
| 1014 | |||
| 938 | static int pmic_gpio_probe(struct platform_device *pdev) | 1015 | static int pmic_gpio_probe(struct platform_device *pdev) |
| 939 | { | 1016 | { |
| 1017 | struct irq_domain *parent_domain; | ||
| 1018 | struct device_node *parent_node; | ||
| 940 | struct device *dev = &pdev->dev; | 1019 | struct device *dev = &pdev->dev; |
| 941 | struct pinctrl_pin_desc *pindesc; | 1020 | struct pinctrl_pin_desc *pindesc; |
| 942 | struct pinctrl_desc *pctrldesc; | 1021 | struct pinctrl_desc *pctrldesc; |
| @@ -951,13 +1030,7 @@ static int pmic_gpio_probe(struct platform_device *pdev) | |||
| 951 | return ret; | 1030 | return ret; |
| 952 | } | 1031 | } |
| 953 | 1032 | ||
| 954 | npins = platform_irq_count(pdev); | 1033 | npins = (uintptr_t) device_get_match_data(&pdev->dev); |
| 955 | if (!npins) | ||
| 956 | return -EINVAL; | ||
| 957 | if (npins < 0) | ||
| 958 | return npins; | ||
| 959 | |||
| 960 | BUG_ON(npins > ARRAY_SIZE(pmic_gpio_groups)); | ||
| 961 | 1034 | ||
| 962 | state = devm_kzalloc(dev, sizeof(*state), GFP_KERNEL); | 1035 | state = devm_kzalloc(dev, sizeof(*state), GFP_KERNEL); |
| 963 | if (!state) | 1036 | if (!state) |
| @@ -999,10 +1072,6 @@ static int pmic_gpio_probe(struct platform_device *pdev) | |||
| 999 | pindesc->number = i; | 1072 | pindesc->number = i; |
| 1000 | pindesc->name = pmic_gpio_groups[i]; | 1073 | pindesc->name = pmic_gpio_groups[i]; |
| 1001 | 1074 | ||
| 1002 | pad->irq = platform_get_irq(pdev, i); | ||
| 1003 | if (pad->irq < 0) | ||
| 1004 | return pad->irq; | ||
| 1005 | |||
| 1006 | pad->base = reg + i * PMIC_GPIO_ADDRESS_RANGE; | 1075 | pad->base = reg + i * PMIC_GPIO_ADDRESS_RANGE; |
| 1007 | 1076 | ||
| 1008 | ret = pmic_gpio_populate(state, pad); | 1077 | ret = pmic_gpio_populate(state, pad); |
| @@ -1022,10 +1091,28 @@ static int pmic_gpio_probe(struct platform_device *pdev) | |||
| 1022 | if (IS_ERR(state->ctrl)) | 1091 | if (IS_ERR(state->ctrl)) |
| 1023 | return PTR_ERR(state->ctrl); | 1092 | return PTR_ERR(state->ctrl); |
| 1024 | 1093 | ||
| 1094 | parent_node = of_irq_find_parent(state->dev->of_node); | ||
| 1095 | if (!parent_node) | ||
| 1096 | return -ENXIO; | ||
| 1097 | |||
| 1098 | parent_domain = irq_find_host(parent_node); | ||
| 1099 | of_node_put(parent_node); | ||
| 1100 | if (!parent_domain) | ||
| 1101 | return -ENXIO; | ||
| 1102 | |||
| 1103 | state->fwnode = of_node_to_fwnode(state->dev->of_node); | ||
| 1104 | state->domain = irq_domain_create_hierarchy(parent_domain, 0, | ||
| 1105 | state->chip.ngpio, | ||
| 1106 | state->fwnode, | ||
| 1107 | &pmic_gpio_domain_ops, | ||
| 1108 | &state->chip); | ||
| 1109 | if (!state->domain) | ||
| 1110 | return -ENODEV; | ||
| 1111 | |||
| 1025 | ret = gpiochip_add_data(&state->chip, state); | 1112 | ret = gpiochip_add_data(&state->chip, state); |
| 1026 | if (ret) { | 1113 | if (ret) { |
| 1027 | dev_err(state->dev, "can't add gpio chip\n"); | 1114 | dev_err(state->dev, "can't add gpio chip\n"); |
| 1028 | return ret; | 1115 | goto err_chip_add_data; |
| 1029 | } | 1116 | } |
| 1030 | 1117 | ||
| 1031 | /* | 1118 | /* |
| @@ -1051,6 +1138,8 @@ static int pmic_gpio_probe(struct platform_device *pdev) | |||
| 1051 | 1138 | ||
| 1052 | err_range: | 1139 | err_range: |
| 1053 | gpiochip_remove(&state->chip); | 1140 | gpiochip_remove(&state->chip); |
| 1141 | err_chip_add_data: | ||
| 1142 | irq_domain_remove(state->domain); | ||
| 1054 | return ret; | 1143 | return ret; |
| 1055 | } | 1144 | } |
| 1056 | 1145 | ||
| @@ -1059,17 +1148,21 @@ static int pmic_gpio_remove(struct platform_device *pdev) | |||
| 1059 | struct pmic_gpio_state *state = platform_get_drvdata(pdev); | 1148 | struct pmic_gpio_state *state = platform_get_drvdata(pdev); |
| 1060 | 1149 | ||
| 1061 | gpiochip_remove(&state->chip); | 1150 | gpiochip_remove(&state->chip); |
| 1151 | irq_domain_remove(state->domain); | ||
| 1062 | return 0; | 1152 | return 0; |
| 1063 | } | 1153 | } |
| 1064 | 1154 | ||
| 1065 | static const struct of_device_id pmic_gpio_of_match[] = { | 1155 | static const struct of_device_id pmic_gpio_of_match[] = { |
| 1066 | { .compatible = "qcom,pm8916-gpio" }, /* 4 GPIO's */ | 1156 | { .compatible = "qcom,pm8005-gpio", .data = (void *) 4 }, |
| 1067 | { .compatible = "qcom,pm8941-gpio" }, /* 36 GPIO's */ | 1157 | { .compatible = "qcom,pm8916-gpio", .data = (void *) 4 }, |
| 1068 | { .compatible = "qcom,pm8994-gpio" }, /* 22 GPIO's */ | 1158 | { .compatible = "qcom,pm8941-gpio", .data = (void *) 36 }, |
| 1069 | { .compatible = "qcom,pmi8994-gpio" }, /* 10 GPIO's */ | 1159 | { .compatible = "qcom,pm8994-gpio", .data = (void *) 22 }, |
| 1070 | { .compatible = "qcom,pma8084-gpio" }, /* 22 GPIO's */ | 1160 | { .compatible = "qcom,pmi8994-gpio", .data = (void *) 10 }, |
| 1071 | { .compatible = "qcom,pms405-gpio" }, /* 12 GPIO's, holes on 1 9 10 */ | 1161 | { .compatible = "qcom,pm8998-gpio", .data = (void *) 26 }, |
| 1072 | { .compatible = "qcom,spmi-gpio" }, /* Generic */ | 1162 | { .compatible = "qcom,pmi8998-gpio", .data = (void *) 14 }, |
| 1163 | { .compatible = "qcom,pma8084-gpio", .data = (void *) 22 }, | ||
| 1164 | /* pms405 has 12 GPIOs with holes on 1, 9, and 10 */ | ||
| 1165 | { .compatible = "qcom,pms405-gpio", .data = (void *) 12 }, | ||
| 1073 | { }, | 1166 | { }, |
| 1074 | }; | 1167 | }; |
| 1075 | 1168 | ||
diff --git a/drivers/pinctrl/qcom/pinctrl-ssbi-gpio.c b/drivers/pinctrl/qcom/pinctrl-ssbi-gpio.c index ded7d765af2e..08dd62b5cebe 100644 --- a/drivers/pinctrl/qcom/pinctrl-ssbi-gpio.c +++ b/drivers/pinctrl/qcom/pinctrl-ssbi-gpio.c | |||
| @@ -55,6 +55,8 @@ | |||
| 55 | 55 | ||
| 56 | #define PM8XXX_MAX_GPIOS 44 | 56 | #define PM8XXX_MAX_GPIOS 44 |
| 57 | 57 | ||
| 58 | #define PM8XXX_GPIO_PHYSICAL_OFFSET 1 | ||
| 59 | |||
| 58 | /* custom pinconf parameters */ | 60 | /* custom pinconf parameters */ |
| 59 | #define PM8XXX_QCOM_DRIVE_STRENGH (PIN_CONFIG_END + 1) | 61 | #define PM8XXX_QCOM_DRIVE_STRENGH (PIN_CONFIG_END + 1) |
| 60 | #define PM8XXX_QCOM_PULL_UP_STRENGTH (PIN_CONFIG_END + 2) | 62 | #define PM8XXX_QCOM_PULL_UP_STRENGTH (PIN_CONFIG_END + 2) |
| @@ -99,6 +101,9 @@ struct pm8xxx_gpio { | |||
| 99 | 101 | ||
| 100 | struct pinctrl_desc desc; | 102 | struct pinctrl_desc desc; |
| 101 | unsigned npins; | 103 | unsigned npins; |
| 104 | |||
| 105 | struct fwnode_handle *fwnode; | ||
| 106 | struct irq_domain *domain; | ||
| 102 | }; | 107 | }; |
| 103 | 108 | ||
| 104 | static const struct pinconf_generic_params pm8xxx_gpio_bindings[] = { | 109 | static const struct pinconf_generic_params pm8xxx_gpio_bindings[] = { |
| @@ -499,11 +504,12 @@ static int pm8xxx_gpio_get(struct gpio_chip *chip, unsigned offset) | |||
| 499 | 504 | ||
| 500 | if (pin->mode == PM8XXX_GPIO_MODE_OUTPUT) { | 505 | if (pin->mode == PM8XXX_GPIO_MODE_OUTPUT) { |
| 501 | ret = pin->output_value; | 506 | ret = pin->output_value; |
| 502 | } else { | 507 | } else if (pin->irq >= 0) { |
| 503 | ret = irq_get_irqchip_state(pin->irq, IRQCHIP_STATE_LINE_LEVEL, &state); | 508 | ret = irq_get_irqchip_state(pin->irq, IRQCHIP_STATE_LINE_LEVEL, &state); |
| 504 | if (!ret) | 509 | if (!ret) |
| 505 | ret = !!state; | 510 | ret = !!state; |
| 506 | } | 511 | } else |
| 512 | ret = -EINVAL; | ||
| 507 | 513 | ||
| 508 | return ret; | 514 | return ret; |
| 509 | } | 515 | } |
| @@ -533,7 +539,7 @@ static int pm8xxx_gpio_of_xlate(struct gpio_chip *chip, | |||
| 533 | if (flags) | 539 | if (flags) |
| 534 | *flags = gpio_desc->args[1]; | 540 | *flags = gpio_desc->args[1]; |
| 535 | 541 | ||
| 536 | return gpio_desc->args[0] - 1; | 542 | return gpio_desc->args[0] - PM8XXX_GPIO_PHYSICAL_OFFSET; |
| 537 | } | 543 | } |
| 538 | 544 | ||
| 539 | 545 | ||
| @@ -541,8 +547,31 @@ static int pm8xxx_gpio_to_irq(struct gpio_chip *chip, unsigned offset) | |||
| 541 | { | 547 | { |
| 542 | struct pm8xxx_gpio *pctrl = gpiochip_get_data(chip); | 548 | struct pm8xxx_gpio *pctrl = gpiochip_get_data(chip); |
| 543 | struct pm8xxx_pin_data *pin = pctrl->desc.pins[offset].drv_data; | 549 | struct pm8xxx_pin_data *pin = pctrl->desc.pins[offset].drv_data; |
| 550 | struct irq_fwspec fwspec; | ||
| 551 | int ret; | ||
| 552 | |||
| 553 | fwspec.fwnode = pctrl->fwnode; | ||
| 554 | fwspec.param_count = 2; | ||
| 555 | fwspec.param[0] = offset + PM8XXX_GPIO_PHYSICAL_OFFSET; | ||
| 556 | fwspec.param[1] = IRQ_TYPE_EDGE_RISING; | ||
| 557 | |||
| 558 | ret = irq_create_fwspec_mapping(&fwspec); | ||
| 559 | |||
| 560 | /* | ||
| 561 | * Cache the IRQ since pm8xxx_gpio_get() needs this to get determine the | ||
| 562 | * line level. | ||
| 563 | */ | ||
| 564 | pin->irq = ret; | ||
| 565 | |||
| 566 | return ret; | ||
| 567 | } | ||
| 568 | |||
| 569 | static void pm8xxx_gpio_free(struct gpio_chip *chip, unsigned int offset) | ||
| 570 | { | ||
| 571 | struct pm8xxx_gpio *pctrl = gpiochip_get_data(chip); | ||
| 572 | struct pm8xxx_pin_data *pin = pctrl->desc.pins[offset].drv_data; | ||
| 544 | 573 | ||
| 545 | return pin->irq; | 574 | pin->irq = -1; |
| 546 | } | 575 | } |
| 547 | 576 | ||
| 548 | #ifdef CONFIG_DEBUG_FS | 577 | #ifdef CONFIG_DEBUG_FS |
| @@ -571,7 +600,7 @@ static void pm8xxx_gpio_dbg_show_one(struct seq_file *s, | |||
| 571 | "no", "high", "medium", "low" | 600 | "no", "high", "medium", "low" |
| 572 | }; | 601 | }; |
| 573 | 602 | ||
| 574 | seq_printf(s, " gpio%-2d:", offset + 1); | 603 | seq_printf(s, " gpio%-2d:", offset + PM8XXX_GPIO_PHYSICAL_OFFSET); |
| 575 | if (pin->disable) { | 604 | if (pin->disable) { |
| 576 | seq_puts(s, " ---"); | 605 | seq_puts(s, " ---"); |
| 577 | } else { | 606 | } else { |
| @@ -603,6 +632,7 @@ static void pm8xxx_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) | |||
| 603 | #endif | 632 | #endif |
| 604 | 633 | ||
| 605 | static const struct gpio_chip pm8xxx_gpio_template = { | 634 | static const struct gpio_chip pm8xxx_gpio_template = { |
| 635 | .free = pm8xxx_gpio_free, | ||
| 606 | .direction_input = pm8xxx_gpio_direction_input, | 636 | .direction_input = pm8xxx_gpio_direction_input, |
| 607 | .direction_output = pm8xxx_gpio_direction_output, | 637 | .direction_output = pm8xxx_gpio_direction_output, |
| 608 | .get = pm8xxx_gpio_get, | 638 | .get = pm8xxx_gpio_get, |
| @@ -664,13 +694,75 @@ static int pm8xxx_pin_populate(struct pm8xxx_gpio *pctrl, | |||
| 664 | return 0; | 694 | return 0; |
| 665 | } | 695 | } |
| 666 | 696 | ||
| 697 | static struct irq_chip pm8xxx_irq_chip = { | ||
| 698 | .name = "ssbi-gpio", | ||
| 699 | .irq_mask_ack = irq_chip_mask_ack_parent, | ||
| 700 | .irq_unmask = irq_chip_unmask_parent, | ||
| 701 | .irq_set_type = irq_chip_set_type_parent, | ||
| 702 | .flags = IRQCHIP_MASK_ON_SUSPEND | IRQCHIP_SKIP_SET_WAKE, | ||
| 703 | }; | ||
| 704 | |||
| 705 | static int pm8xxx_domain_translate(struct irq_domain *domain, | ||
| 706 | struct irq_fwspec *fwspec, | ||
| 707 | unsigned long *hwirq, | ||
| 708 | unsigned int *type) | ||
| 709 | { | ||
| 710 | struct pm8xxx_gpio *pctrl = container_of(domain->host_data, | ||
| 711 | struct pm8xxx_gpio, chip); | ||
| 712 | |||
| 713 | if (fwspec->param_count != 2 || fwspec->param[0] < 1 || | ||
| 714 | fwspec->param[0] > pctrl->chip.ngpio) | ||
| 715 | return -EINVAL; | ||
| 716 | |||
| 717 | *hwirq = fwspec->param[0] - PM8XXX_GPIO_PHYSICAL_OFFSET; | ||
| 718 | *type = fwspec->param[1]; | ||
| 719 | |||
| 720 | return 0; | ||
| 721 | } | ||
| 722 | |||
| 723 | static int pm8xxx_domain_alloc(struct irq_domain *domain, unsigned int virq, | ||
| 724 | unsigned int nr_irqs, void *data) | ||
| 725 | { | ||
| 726 | struct pm8xxx_gpio *pctrl = container_of(domain->host_data, | ||
| 727 | struct pm8xxx_gpio, chip); | ||
| 728 | struct irq_fwspec *fwspec = data; | ||
| 729 | struct irq_fwspec parent_fwspec; | ||
| 730 | irq_hw_number_t hwirq; | ||
| 731 | unsigned int type; | ||
| 732 | int ret, i; | ||
| 733 | |||
| 734 | ret = pm8xxx_domain_translate(domain, fwspec, &hwirq, &type); | ||
| 735 | if (ret) | ||
| 736 | return ret; | ||
| 737 | |||
| 738 | for (i = 0; i < nr_irqs; i++) | ||
| 739 | irq_domain_set_info(domain, virq + i, hwirq + i, | ||
| 740 | &pm8xxx_irq_chip, pctrl, handle_level_irq, | ||
| 741 | NULL, NULL); | ||
| 742 | |||
| 743 | parent_fwspec.fwnode = domain->parent->fwnode; | ||
| 744 | parent_fwspec.param_count = 2; | ||
| 745 | parent_fwspec.param[0] = hwirq + 0xc0; | ||
| 746 | parent_fwspec.param[1] = fwspec->param[1]; | ||
| 747 | |||
| 748 | return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, | ||
| 749 | &parent_fwspec); | ||
| 750 | } | ||
| 751 | |||
| 752 | static const struct irq_domain_ops pm8xxx_domain_ops = { | ||
| 753 | .activate = gpiochip_irq_domain_activate, | ||
| 754 | .alloc = pm8xxx_domain_alloc, | ||
| 755 | .deactivate = gpiochip_irq_domain_deactivate, | ||
| 756 | .free = irq_domain_free_irqs_common, | ||
| 757 | .translate = pm8xxx_domain_translate, | ||
| 758 | }; | ||
| 759 | |||
| 667 | static const struct of_device_id pm8xxx_gpio_of_match[] = { | 760 | static const struct of_device_id pm8xxx_gpio_of_match[] = { |
| 668 | { .compatible = "qcom,pm8018-gpio" }, | 761 | { .compatible = "qcom,pm8018-gpio", .data = (void *) 6 }, |
| 669 | { .compatible = "qcom,pm8038-gpio" }, | 762 | { .compatible = "qcom,pm8038-gpio", .data = (void *) 12 }, |
| 670 | { .compatible = "qcom,pm8058-gpio" }, | 763 | { .compatible = "qcom,pm8058-gpio", .data = (void *) 44 }, |
| 671 | { .compatible = "qcom,pm8917-gpio" }, | 764 | { .compatible = "qcom,pm8917-gpio", .data = (void *) 38 }, |
| 672 | { .compatible = "qcom,pm8921-gpio" }, | 765 | { .compatible = "qcom,pm8921-gpio", .data = (void *) 44 }, |
| 673 | { .compatible = "qcom,ssbi-gpio" }, | ||
| 674 | { }, | 766 | { }, |
| 675 | }; | 767 | }; |
| 676 | MODULE_DEVICE_TABLE(of, pm8xxx_gpio_of_match); | 768 | MODULE_DEVICE_TABLE(of, pm8xxx_gpio_of_match); |
| @@ -678,22 +770,18 @@ MODULE_DEVICE_TABLE(of, pm8xxx_gpio_of_match); | |||
| 678 | static int pm8xxx_gpio_probe(struct platform_device *pdev) | 770 | static int pm8xxx_gpio_probe(struct platform_device *pdev) |
| 679 | { | 771 | { |
| 680 | struct pm8xxx_pin_data *pin_data; | 772 | struct pm8xxx_pin_data *pin_data; |
| 773 | struct irq_domain *parent_domain; | ||
| 774 | struct device_node *parent_node; | ||
| 681 | struct pinctrl_pin_desc *pins; | 775 | struct pinctrl_pin_desc *pins; |
| 682 | struct pm8xxx_gpio *pctrl; | 776 | struct pm8xxx_gpio *pctrl; |
| 683 | int ret; | 777 | int ret, i; |
| 684 | int i, npins; | ||
| 685 | 778 | ||
| 686 | pctrl = devm_kzalloc(&pdev->dev, sizeof(*pctrl), GFP_KERNEL); | 779 | pctrl = devm_kzalloc(&pdev->dev, sizeof(*pctrl), GFP_KERNEL); |
| 687 | if (!pctrl) | 780 | if (!pctrl) |
| 688 | return -ENOMEM; | 781 | return -ENOMEM; |
| 689 | 782 | ||
| 690 | pctrl->dev = &pdev->dev; | 783 | pctrl->dev = &pdev->dev; |
| 691 | npins = platform_irq_count(pdev); | 784 | pctrl->npins = (uintptr_t) device_get_match_data(&pdev->dev); |
| 692 | if (!npins) | ||
| 693 | return -EINVAL; | ||
| 694 | if (npins < 0) | ||
| 695 | return npins; | ||
| 696 | pctrl->npins = npins; | ||
| 697 | 785 | ||
| 698 | pctrl->regmap = dev_get_regmap(pdev->dev.parent, NULL); | 786 | pctrl->regmap = dev_get_regmap(pdev->dev.parent, NULL); |
| 699 | if (!pctrl->regmap) { | 787 | if (!pctrl->regmap) { |
| @@ -720,12 +808,7 @@ static int pm8xxx_gpio_probe(struct platform_device *pdev) | |||
| 720 | 808 | ||
| 721 | for (i = 0; i < pctrl->desc.npins; i++) { | 809 | for (i = 0; i < pctrl->desc.npins; i++) { |
| 722 | pin_data[i].reg = SSBI_REG_ADDR_GPIO(i); | 810 | pin_data[i].reg = SSBI_REG_ADDR_GPIO(i); |
| 723 | pin_data[i].irq = platform_get_irq(pdev, i); | 811 | pin_data[i].irq = -1; |
| 724 | if (pin_data[i].irq < 0) { | ||
| 725 | dev_err(&pdev->dev, | ||
| 726 | "missing interrupts for pin %d\n", i); | ||
| 727 | return pin_data[i].irq; | ||
| 728 | } | ||
| 729 | 812 | ||
| 730 | ret = pm8xxx_pin_populate(pctrl, &pin_data[i]); | 813 | ret = pm8xxx_pin_populate(pctrl, &pin_data[i]); |
| 731 | if (ret) | 814 | if (ret) |
| @@ -756,10 +839,29 @@ static int pm8xxx_gpio_probe(struct platform_device *pdev) | |||
| 756 | pctrl->chip.of_gpio_n_cells = 2; | 839 | pctrl->chip.of_gpio_n_cells = 2; |
| 757 | pctrl->chip.label = dev_name(pctrl->dev); | 840 | pctrl->chip.label = dev_name(pctrl->dev); |
| 758 | pctrl->chip.ngpio = pctrl->npins; | 841 | pctrl->chip.ngpio = pctrl->npins; |
| 842 | |||
| 843 | parent_node = of_irq_find_parent(pctrl->dev->of_node); | ||
| 844 | if (!parent_node) | ||
| 845 | return -ENXIO; | ||
| 846 | |||
| 847 | parent_domain = irq_find_host(parent_node); | ||
| 848 | of_node_put(parent_node); | ||
| 849 | if (!parent_domain) | ||
| 850 | return -ENXIO; | ||
| 851 | |||
| 852 | pctrl->fwnode = of_node_to_fwnode(pctrl->dev->of_node); | ||
| 853 | pctrl->domain = irq_domain_create_hierarchy(parent_domain, 0, | ||
| 854 | pctrl->chip.ngpio, | ||
| 855 | pctrl->fwnode, | ||
| 856 | &pm8xxx_domain_ops, | ||
| 857 | &pctrl->chip); | ||
| 858 | if (!pctrl->domain) | ||
| 859 | return -ENODEV; | ||
| 860 | |||
| 759 | ret = gpiochip_add_data(&pctrl->chip, pctrl); | 861 | ret = gpiochip_add_data(&pctrl->chip, pctrl); |
| 760 | if (ret) { | 862 | if (ret) { |
| 761 | dev_err(&pdev->dev, "failed register gpiochip\n"); | 863 | dev_err(&pdev->dev, "failed register gpiochip\n"); |
| 762 | return ret; | 864 | goto err_chip_add_data; |
| 763 | } | 865 | } |
| 764 | 866 | ||
| 765 | /* | 867 | /* |
| @@ -789,6 +891,8 @@ static int pm8xxx_gpio_probe(struct platform_device *pdev) | |||
| 789 | 891 | ||
| 790 | unregister_gpiochip: | 892 | unregister_gpiochip: |
| 791 | gpiochip_remove(&pctrl->chip); | 893 | gpiochip_remove(&pctrl->chip); |
| 894 | err_chip_add_data: | ||
| 895 | irq_domain_remove(pctrl->domain); | ||
| 792 | 896 | ||
| 793 | return ret; | 897 | return ret; |
| 794 | } | 898 | } |
| @@ -798,6 +902,7 @@ static int pm8xxx_gpio_remove(struct platform_device *pdev) | |||
| 798 | struct pm8xxx_gpio *pctrl = platform_get_drvdata(pdev); | 902 | struct pm8xxx_gpio *pctrl = platform_get_drvdata(pdev); |
| 799 | 903 | ||
| 800 | gpiochip_remove(&pctrl->chip); | 904 | gpiochip_remove(&pctrl->chip); |
| 905 | irq_domain_remove(pctrl->domain); | ||
| 801 | 906 | ||
| 802 | return 0; | 907 | return 0; |
| 803 | } | 908 | } |
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index b5e9db85e881..a1ed13183559 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig | |||
| @@ -1303,6 +1303,20 @@ config HUAWEI_WMI | |||
| 1303 | To compile this driver as a module, choose M here: the module | 1303 | To compile this driver as a module, choose M here: the module |
| 1304 | will be called huawei-wmi. | 1304 | will be called huawei-wmi. |
| 1305 | 1305 | ||
| 1306 | config PCENGINES_APU2 | ||
| 1307 | tristate "PC Engines APUv2/3 front button and LEDs driver" | ||
| 1308 | depends on INPUT && INPUT_KEYBOARD | ||
| 1309 | depends on LEDS_CLASS | ||
| 1310 | select GPIO_AMD_FCH | ||
| 1311 | select KEYBOARD_GPIO_POLLED | ||
| 1312 | select LEDS_GPIO | ||
| 1313 | help | ||
| 1314 | This driver provides support for the front button and LEDs on | ||
| 1315 | PC Engines APUv2/APUv3 board. | ||
| 1316 | |||
| 1317 | To compile this driver as a module, choose M here: the module | ||
| 1318 | will be called pcengines-apuv2. | ||
| 1319 | |||
| 1306 | endif # X86_PLATFORM_DEVICES | 1320 | endif # X86_PLATFORM_DEVICES |
| 1307 | 1321 | ||
| 1308 | config PMC_ATOM | 1322 | config PMC_ATOM |
diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile index ce8da260c223..86cb76677bc8 100644 --- a/drivers/platform/x86/Makefile +++ b/drivers/platform/x86/Makefile | |||
| @@ -96,3 +96,4 @@ obj-$(CONFIG_INTEL_TURBO_MAX_3) += intel_turbo_max_3.o | |||
| 96 | obj-$(CONFIG_INTEL_CHTDC_TI_PWRBTN) += intel_chtdc_ti_pwrbtn.o | 96 | obj-$(CONFIG_INTEL_CHTDC_TI_PWRBTN) += intel_chtdc_ti_pwrbtn.o |
| 97 | obj-$(CONFIG_I2C_MULTI_INSTANTIATE) += i2c-multi-instantiate.o | 97 | obj-$(CONFIG_I2C_MULTI_INSTANTIATE) += i2c-multi-instantiate.o |
| 98 | obj-$(CONFIG_INTEL_ATOMISP2_PM) += intel_atomisp2_pm.o | 98 | obj-$(CONFIG_INTEL_ATOMISP2_PM) += intel_atomisp2_pm.o |
| 99 | obj-$(CONFIG_PCENGINES_APU2) += pcengines-apuv2.o | ||
diff --git a/drivers/platform/x86/pcengines-apuv2.c b/drivers/platform/x86/pcengines-apuv2.c new file mode 100644 index 000000000000..c1ca931e1fab --- /dev/null +++ b/drivers/platform/x86/pcengines-apuv2.c | |||
| @@ -0,0 +1,260 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0+ | ||
| 2 | |||
| 3 | /* | ||
| 4 | * PC-Engines APUv2/APUv3 board platform driver | ||
| 5 | * for gpio buttons and LEDs | ||
| 6 | * | ||
| 7 | * Copyright (C) 2018 metux IT consult | ||
| 8 | * Author: Enrico Weigelt <info@metux.net> | ||
| 9 | */ | ||
| 10 | |||
| 11 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
| 12 | |||
| 13 | #include <linux/dmi.h> | ||
| 14 | #include <linux/err.h> | ||
| 15 | #include <linux/kernel.h> | ||
| 16 | #include <linux/leds.h> | ||
| 17 | #include <linux/module.h> | ||
| 18 | #include <linux/platform_device.h> | ||
| 19 | #include <linux/gpio_keys.h> | ||
| 20 | #include <linux/gpio/machine.h> | ||
| 21 | #include <linux/input.h> | ||
| 22 | #include <linux/platform_data/gpio/gpio-amd-fch.h> | ||
| 23 | |||
| 24 | /* | ||
| 25 | * NOTE: this driver only supports APUv2/3 - not APUv1, as this one | ||
| 26 | * has completely different register layouts | ||
| 27 | */ | ||
| 28 | |||
| 29 | /* register mappings */ | ||
| 30 | #define APU2_GPIO_REG_LED1 AMD_FCH_GPIO_REG_GPIO57 | ||
| 31 | #define APU2_GPIO_REG_LED2 AMD_FCH_GPIO_REG_GPIO58 | ||
| 32 | #define APU2_GPIO_REG_LED3 AMD_FCH_GPIO_REG_GPIO59_DEVSLP1 | ||
| 33 | #define APU2_GPIO_REG_MODESW AMD_FCH_GPIO_REG_GPIO32_GE1 | ||
| 34 | #define APU2_GPIO_REG_SIMSWAP AMD_FCH_GPIO_REG_GPIO33_GE2 | ||
| 35 | |||
| 36 | /* order in which the gpio lines are defined in the register list */ | ||
| 37 | #define APU2_GPIO_LINE_LED1 0 | ||
| 38 | #define APU2_GPIO_LINE_LED2 1 | ||
| 39 | #define APU2_GPIO_LINE_LED3 2 | ||
| 40 | #define APU2_GPIO_LINE_MODESW 3 | ||
| 41 | #define APU2_GPIO_LINE_SIMSWAP 4 | ||
| 42 | |||
| 43 | /* gpio device */ | ||
| 44 | |||
| 45 | static int apu2_gpio_regs[] = { | ||
| 46 | [APU2_GPIO_LINE_LED1] = APU2_GPIO_REG_LED1, | ||
| 47 | [APU2_GPIO_LINE_LED2] = APU2_GPIO_REG_LED2, | ||
| 48 | [APU2_GPIO_LINE_LED3] = APU2_GPIO_REG_LED3, | ||
| 49 | [APU2_GPIO_LINE_MODESW] = APU2_GPIO_REG_MODESW, | ||
| 50 | [APU2_GPIO_LINE_SIMSWAP] = APU2_GPIO_REG_SIMSWAP, | ||
| 51 | }; | ||
| 52 | |||
| 53 | static const char * const apu2_gpio_names[] = { | ||
| 54 | [APU2_GPIO_LINE_LED1] = "front-led1", | ||
| 55 | [APU2_GPIO_LINE_LED2] = "front-led2", | ||
| 56 | [APU2_GPIO_LINE_LED3] = "front-led3", | ||
| 57 | [APU2_GPIO_LINE_MODESW] = "front-button", | ||
| 58 | [APU2_GPIO_LINE_SIMSWAP] = "simswap", | ||
| 59 | }; | ||
| 60 | |||
| 61 | static const struct amd_fch_gpio_pdata board_apu2 = { | ||
| 62 | .gpio_num = ARRAY_SIZE(apu2_gpio_regs), | ||
| 63 | .gpio_reg = apu2_gpio_regs, | ||
| 64 | .gpio_names = apu2_gpio_names, | ||
| 65 | }; | ||
| 66 | |||
| 67 | /* gpio leds device */ | ||
| 68 | |||
| 69 | static const struct gpio_led apu2_leds[] = { | ||
| 70 | { .name = "apu:green:1" }, | ||
| 71 | { .name = "apu:green:2" }, | ||
| 72 | { .name = "apu:green:3" } | ||
| 73 | }; | ||
| 74 | |||
| 75 | static const struct gpio_led_platform_data apu2_leds_pdata = { | ||
| 76 | .num_leds = ARRAY_SIZE(apu2_leds), | ||
| 77 | .leds = apu2_leds, | ||
| 78 | }; | ||
| 79 | |||
| 80 | struct gpiod_lookup_table gpios_led_table = { | ||
| 81 | .dev_id = "leds-gpio", | ||
| 82 | .table = { | ||
| 83 | GPIO_LOOKUP_IDX(AMD_FCH_GPIO_DRIVER_NAME, APU2_GPIO_LINE_LED1, | ||
| 84 | NULL, 0, GPIO_ACTIVE_LOW), | ||
| 85 | GPIO_LOOKUP_IDX(AMD_FCH_GPIO_DRIVER_NAME, APU2_GPIO_LINE_LED2, | ||
| 86 | NULL, 1, GPIO_ACTIVE_LOW), | ||
| 87 | GPIO_LOOKUP_IDX(AMD_FCH_GPIO_DRIVER_NAME, APU2_GPIO_LINE_LED3, | ||
| 88 | NULL, 2, GPIO_ACTIVE_LOW), | ||
| 89 | } | ||
| 90 | }; | ||
| 91 | |||
| 92 | /* gpio keyboard device */ | ||
| 93 | |||
| 94 | static struct gpio_keys_button apu2_keys_buttons[] = { | ||
| 95 | { | ||
| 96 | .code = KEY_SETUP, | ||
| 97 | .active_low = 1, | ||
| 98 | .desc = "front button", | ||
| 99 | .type = EV_KEY, | ||
| 100 | .debounce_interval = 10, | ||
| 101 | .value = 1, | ||
| 102 | }, | ||
| 103 | }; | ||
| 104 | |||
| 105 | static const struct gpio_keys_platform_data apu2_keys_pdata = { | ||
| 106 | .buttons = apu2_keys_buttons, | ||
| 107 | .nbuttons = ARRAY_SIZE(apu2_keys_buttons), | ||
| 108 | .poll_interval = 100, | ||
| 109 | .rep = 0, | ||
| 110 | .name = "apu2-keys", | ||
| 111 | }; | ||
| 112 | |||
| 113 | struct gpiod_lookup_table gpios_key_table = { | ||
| 114 | .dev_id = "gpio-keys-polled", | ||
| 115 | .table = { | ||
| 116 | GPIO_LOOKUP_IDX(AMD_FCH_GPIO_DRIVER_NAME, APU2_GPIO_LINE_MODESW, | ||
| 117 | NULL, 0, GPIO_ACTIVE_LOW), | ||
| 118 | } | ||
| 119 | }; | ||
| 120 | |||
| 121 | /* board setup */ | ||
| 122 | |||
| 123 | /* note: matching works on string prefix, so "apu2" must come before "apu" */ | ||
| 124 | static const struct dmi_system_id apu_gpio_dmi_table[] __initconst = { | ||
| 125 | |||
| 126 | /* APU2 w/ legacy bios < 4.0.8 */ | ||
| 127 | { | ||
| 128 | .ident = "apu2", | ||
| 129 | .matches = { | ||
| 130 | DMI_MATCH(DMI_SYS_VENDOR, "PC Engines"), | ||
| 131 | DMI_MATCH(DMI_BOARD_NAME, "APU2") | ||
| 132 | }, | ||
| 133 | .driver_data = (void *)&board_apu2, | ||
| 134 | }, | ||
| 135 | /* APU2 w/ legacy bios >= 4.0.8 */ | ||
| 136 | { | ||
| 137 | .ident = "apu2", | ||
| 138 | .matches = { | ||
| 139 | DMI_MATCH(DMI_SYS_VENDOR, "PC Engines"), | ||
| 140 | DMI_MATCH(DMI_BOARD_NAME, "apu2") | ||
| 141 | }, | ||
| 142 | .driver_data = (void *)&board_apu2, | ||
| 143 | }, | ||
| 144 | /* APU2 w/ maainline bios */ | ||
| 145 | { | ||
| 146 | .ident = "apu2", | ||
| 147 | .matches = { | ||
| 148 | DMI_MATCH(DMI_SYS_VENDOR, "PC Engines"), | ||
| 149 | DMI_MATCH(DMI_BOARD_NAME, "PC Engines apu2") | ||
| 150 | }, | ||
| 151 | .driver_data = (void *)&board_apu2, | ||
| 152 | }, | ||
| 153 | |||
| 154 | /* APU3 w/ legacy bios < 4.0.8 */ | ||
| 155 | { | ||
| 156 | .ident = "apu3", | ||
| 157 | .matches = { | ||
| 158 | DMI_MATCH(DMI_SYS_VENDOR, "PC Engines"), | ||
| 159 | DMI_MATCH(DMI_BOARD_NAME, "APU3") | ||
| 160 | }, | ||
| 161 | .driver_data = (void *)&board_apu2, | ||
| 162 | }, | ||
| 163 | /* APU3 w/ legacy bios >= 4.0.8 */ | ||
| 164 | { | ||
| 165 | .ident = "apu3", | ||
| 166 | .matches = { | ||
| 167 | DMI_MATCH(DMI_SYS_VENDOR, "PC Engines"), | ||
| 168 | DMI_MATCH(DMI_BOARD_NAME, "apu3") | ||
| 169 | }, | ||
| 170 | .driver_data = (void *)&board_apu2, | ||
| 171 | }, | ||
| 172 | /* APU3 w/ mainline bios */ | ||
| 173 | { | ||
| 174 | .ident = "apu3", | ||
| 175 | .matches = { | ||
| 176 | DMI_MATCH(DMI_SYS_VENDOR, "PC Engines"), | ||
| 177 | DMI_MATCH(DMI_BOARD_NAME, "PC Engines apu3") | ||
| 178 | }, | ||
| 179 | .driver_data = (void *)&board_apu2, | ||
| 180 | }, | ||
| 181 | {} | ||
| 182 | }; | ||
| 183 | |||
| 184 | static struct platform_device *apu_gpio_pdev; | ||
| 185 | static struct platform_device *apu_leds_pdev; | ||
| 186 | static struct platform_device *apu_keys_pdev; | ||
| 187 | |||
| 188 | static struct platform_device * __init apu_create_pdev( | ||
| 189 | const char *name, | ||
| 190 | const void *pdata, | ||
| 191 | size_t sz) | ||
| 192 | { | ||
| 193 | struct platform_device *pdev; | ||
| 194 | |||
| 195 | pdev = platform_device_register_resndata(NULL, | ||
| 196 | name, | ||
| 197 | PLATFORM_DEVID_NONE, | ||
| 198 | NULL, | ||
| 199 | 0, | ||
| 200 | pdata, | ||
| 201 | sz); | ||
| 202 | |||
| 203 | if (IS_ERR(pdev)) | ||
| 204 | pr_err("failed registering %s: %ld\n", name, PTR_ERR(pdev)); | ||
| 205 | |||
| 206 | return pdev; | ||
| 207 | } | ||
| 208 | |||
| 209 | static int __init apu_board_init(void) | ||
| 210 | { | ||
| 211 | const struct dmi_system_id *id; | ||
| 212 | |||
| 213 | id = dmi_first_match(apu_gpio_dmi_table); | ||
| 214 | if (!id) { | ||
| 215 | pr_err("failed to detect apu board via dmi\n"); | ||
| 216 | return -ENODEV; | ||
| 217 | } | ||
| 218 | |||
| 219 | gpiod_add_lookup_table(&gpios_led_table); | ||
| 220 | gpiod_add_lookup_table(&gpios_key_table); | ||
| 221 | |||
| 222 | apu_gpio_pdev = apu_create_pdev( | ||
| 223 | AMD_FCH_GPIO_DRIVER_NAME, | ||
| 224 | id->driver_data, | ||
| 225 | sizeof(struct amd_fch_gpio_pdata)); | ||
| 226 | |||
| 227 | apu_leds_pdev = apu_create_pdev( | ||
| 228 | "leds-gpio", | ||
| 229 | &apu2_leds_pdata, | ||
| 230 | sizeof(apu2_leds_pdata)); | ||
| 231 | |||
| 232 | apu_keys_pdev = apu_create_pdev( | ||
| 233 | "gpio-keys-polled", | ||
| 234 | &apu2_keys_pdata, | ||
| 235 | sizeof(apu2_keys_pdata)); | ||
| 236 | |||
| 237 | return 0; | ||
| 238 | } | ||
| 239 | |||
| 240 | static void __exit apu_board_exit(void) | ||
| 241 | { | ||
| 242 | gpiod_remove_lookup_table(&gpios_led_table); | ||
| 243 | gpiod_remove_lookup_table(&gpios_key_table); | ||
| 244 | |||
| 245 | platform_device_unregister(apu_keys_pdev); | ||
| 246 | platform_device_unregister(apu_leds_pdev); | ||
| 247 | platform_device_unregister(apu_gpio_pdev); | ||
| 248 | } | ||
| 249 | |||
| 250 | module_init(apu_board_init); | ||
| 251 | module_exit(apu_board_exit); | ||
| 252 | |||
| 253 | MODULE_AUTHOR("Enrico Weigelt, metux IT consult <info@metux.net>"); | ||
| 254 | MODULE_DESCRIPTION("PC Engines APUv2/APUv3 board GPIO/LED/keys driver"); | ||
| 255 | MODULE_LICENSE("GPL"); | ||
| 256 | MODULE_DEVICE_TABLE(dmi, apu_gpio_dmi_table); | ||
| 257 | MODULE_ALIAS("platform:pcengines-apuv2"); | ||
| 258 | MODULE_SOFTDEP("pre: platform:" AMD_FCH_GPIO_DRIVER_NAME); | ||
| 259 | MODULE_SOFTDEP("pre: platform:leds-gpio"); | ||
| 260 | MODULE_SOFTDEP("pre: platform:gpio_keys_polled"); | ||
diff --git a/drivers/spmi/Kconfig b/drivers/spmi/Kconfig index 0d3b70b3bda8..d48ed7c2c6c4 100644 --- a/drivers/spmi/Kconfig +++ b/drivers/spmi/Kconfig | |||
| @@ -12,7 +12,7 @@ if SPMI | |||
| 12 | 12 | ||
| 13 | config SPMI_MSM_PMIC_ARB | 13 | config SPMI_MSM_PMIC_ARB |
| 14 | tristate "Qualcomm MSM SPMI Controller (PMIC Arbiter)" | 14 | tristate "Qualcomm MSM SPMI Controller (PMIC Arbiter)" |
| 15 | select IRQ_DOMAIN | 15 | select IRQ_DOMAIN_HIERARCHY |
| 16 | depends on ARCH_QCOM || COMPILE_TEST | 16 | depends on ARCH_QCOM || COMPILE_TEST |
| 17 | depends on HAS_IOMEM | 17 | depends on HAS_IOMEM |
| 18 | default ARCH_QCOM | 18 | default ARCH_QCOM |
diff --git a/drivers/spmi/spmi-pmic-arb.c b/drivers/spmi/spmi-pmic-arb.c index 360b8218f322..928759242e42 100644 --- a/drivers/spmi/spmi-pmic-arb.c +++ b/drivers/spmi/spmi-pmic-arb.c | |||
| @@ -666,7 +666,8 @@ static int qpnpint_get_irqchip_state(struct irq_data *d, | |||
| 666 | return 0; | 666 | return 0; |
| 667 | } | 667 | } |
| 668 | 668 | ||
| 669 | static int qpnpint_irq_request_resources(struct irq_data *d) | 669 | static int qpnpint_irq_domain_activate(struct irq_domain *domain, |
| 670 | struct irq_data *d, bool reserve) | ||
| 670 | { | 671 | { |
| 671 | struct spmi_pmic_arb *pmic_arb = irq_data_get_irq_chip_data(d); | 672 | struct spmi_pmic_arb *pmic_arb = irq_data_get_irq_chip_data(d); |
| 672 | u16 periph = hwirq_to_per(d->hwirq); | 673 | u16 periph = hwirq_to_per(d->hwirq); |
| @@ -692,27 +693,25 @@ static struct irq_chip pmic_arb_irqchip = { | |||
| 692 | .irq_set_type = qpnpint_irq_set_type, | 693 | .irq_set_type = qpnpint_irq_set_type, |
| 693 | .irq_set_wake = qpnpint_irq_set_wake, | 694 | .irq_set_wake = qpnpint_irq_set_wake, |
| 694 | .irq_get_irqchip_state = qpnpint_get_irqchip_state, | 695 | .irq_get_irqchip_state = qpnpint_get_irqchip_state, |
| 695 | .irq_request_resources = qpnpint_irq_request_resources, | ||
| 696 | .flags = IRQCHIP_MASK_ON_SUSPEND, | 696 | .flags = IRQCHIP_MASK_ON_SUSPEND, |
| 697 | }; | 697 | }; |
| 698 | 698 | ||
| 699 | static int qpnpint_irq_domain_dt_translate(struct irq_domain *d, | 699 | static int qpnpint_irq_domain_translate(struct irq_domain *d, |
| 700 | struct device_node *controller, | 700 | struct irq_fwspec *fwspec, |
| 701 | const u32 *intspec, | 701 | unsigned long *out_hwirq, |
| 702 | unsigned int intsize, | 702 | unsigned int *out_type) |
| 703 | unsigned long *out_hwirq, | ||
| 704 | unsigned int *out_type) | ||
| 705 | { | 703 | { |
| 706 | struct spmi_pmic_arb *pmic_arb = d->host_data; | 704 | struct spmi_pmic_arb *pmic_arb = d->host_data; |
| 705 | u32 *intspec = fwspec->param; | ||
| 707 | u16 apid, ppid; | 706 | u16 apid, ppid; |
| 708 | int rc; | 707 | int rc; |
| 709 | 708 | ||
| 710 | dev_dbg(&pmic_arb->spmic->dev, "intspec[0] 0x%1x intspec[1] 0x%02x intspec[2] 0x%02x\n", | 709 | dev_dbg(&pmic_arb->spmic->dev, "intspec[0] 0x%1x intspec[1] 0x%02x intspec[2] 0x%02x\n", |
| 711 | intspec[0], intspec[1], intspec[2]); | 710 | intspec[0], intspec[1], intspec[2]); |
| 712 | 711 | ||
| 713 | if (irq_domain_get_of_node(d) != controller) | 712 | if (irq_domain_get_of_node(d) != pmic_arb->spmic->dev.of_node) |
| 714 | return -EINVAL; | 713 | return -EINVAL; |
| 715 | if (intsize != 4) | 714 | if (fwspec->param_count != 4) |
| 716 | return -EINVAL; | 715 | return -EINVAL; |
| 717 | if (intspec[0] > 0xF || intspec[1] > 0xFF || intspec[2] > 0x7) | 716 | if (intspec[0] > 0xF || intspec[1] > 0xFF || intspec[2] > 0x7) |
| 718 | return -EINVAL; | 717 | return -EINVAL; |
| @@ -740,17 +739,43 @@ static int qpnpint_irq_domain_dt_translate(struct irq_domain *d, | |||
| 740 | return 0; | 739 | return 0; |
| 741 | } | 740 | } |
| 742 | 741 | ||
| 743 | static int qpnpint_irq_domain_map(struct irq_domain *d, | 742 | |
| 744 | unsigned int virq, | 743 | static void qpnpint_irq_domain_map(struct spmi_pmic_arb *pmic_arb, |
| 745 | irq_hw_number_t hwirq) | 744 | struct irq_domain *domain, unsigned int virq, |
| 745 | irq_hw_number_t hwirq, unsigned int type) | ||
| 746 | { | 746 | { |
| 747 | struct spmi_pmic_arb *pmic_arb = d->host_data; | 747 | irq_flow_handler_t handler; |
| 748 | |||
| 749 | dev_dbg(&pmic_arb->spmic->dev, "virq = %u, hwirq = %lu, type = %u\n", | ||
| 750 | virq, hwirq, type); | ||
| 751 | |||
| 752 | if (type & IRQ_TYPE_EDGE_BOTH) | ||
| 753 | handler = handle_edge_irq; | ||
| 754 | else | ||
| 755 | handler = handle_level_irq; | ||
| 756 | |||
| 757 | irq_domain_set_info(domain, virq, hwirq, &pmic_arb_irqchip, pmic_arb, | ||
| 758 | handler, NULL, NULL); | ||
| 759 | } | ||
| 760 | |||
| 761 | static int qpnpint_irq_domain_alloc(struct irq_domain *domain, | ||
| 762 | unsigned int virq, unsigned int nr_irqs, | ||
| 763 | void *data) | ||
| 764 | { | ||
| 765 | struct spmi_pmic_arb *pmic_arb = domain->host_data; | ||
| 766 | struct irq_fwspec *fwspec = data; | ||
| 767 | irq_hw_number_t hwirq; | ||
| 768 | unsigned int type; | ||
| 769 | int ret, i; | ||
| 770 | |||
| 771 | ret = qpnpint_irq_domain_translate(domain, fwspec, &hwirq, &type); | ||
| 772 | if (ret) | ||
| 773 | return ret; | ||
| 748 | 774 | ||
| 749 | dev_dbg(&pmic_arb->spmic->dev, "virq = %u, hwirq = %lu\n", virq, hwirq); | 775 | for (i = 0; i < nr_irqs; i++) |
| 776 | qpnpint_irq_domain_map(pmic_arb, domain, virq + i, hwirq + i, | ||
| 777 | type); | ||
| 750 | 778 | ||
| 751 | irq_set_chip_and_handler(virq, &pmic_arb_irqchip, handle_level_irq); | ||
| 752 | irq_set_chip_data(virq, d->host_data); | ||
| 753 | irq_set_noprobe(virq); | ||
| 754 | return 0; | 779 | return 0; |
| 755 | } | 780 | } |
| 756 | 781 | ||
| @@ -1126,8 +1151,10 @@ static const struct pmic_arb_ver_ops pmic_arb_v5 = { | |||
| 1126 | }; | 1151 | }; |
| 1127 | 1152 | ||
| 1128 | static const struct irq_domain_ops pmic_arb_irq_domain_ops = { | 1153 | static const struct irq_domain_ops pmic_arb_irq_domain_ops = { |
| 1129 | .map = qpnpint_irq_domain_map, | 1154 | .activate = qpnpint_irq_domain_activate, |
| 1130 | .xlate = qpnpint_irq_domain_dt_translate, | 1155 | .alloc = qpnpint_irq_domain_alloc, |
| 1156 | .free = irq_domain_free_irqs_common, | ||
| 1157 | .translate = qpnpint_irq_domain_translate, | ||
| 1131 | }; | 1158 | }; |
| 1132 | 1159 | ||
| 1133 | static int spmi_pmic_arb_probe(struct platform_device *pdev) | 1160 | static int spmi_pmic_arb_probe(struct platform_device *pdev) |
diff --git a/include/dt-bindings/gpio/gpio.h b/include/dt-bindings/gpio/gpio.h index 2cc10ae4bbb7..c029467e828b 100644 --- a/include/dt-bindings/gpio/gpio.h +++ b/include/dt-bindings/gpio/gpio.h | |||
| @@ -33,4 +33,10 @@ | |||
| 33 | #define GPIO_PERSISTENT 0 | 33 | #define GPIO_PERSISTENT 0 |
| 34 | #define GPIO_TRANSITORY 8 | 34 | #define GPIO_TRANSITORY 8 |
| 35 | 35 | ||
| 36 | /* Bit 4 express pull up */ | ||
| 37 | #define GPIO_PULL_UP 16 | ||
| 38 | |||
| 39 | /* Bit 5 express pull down */ | ||
| 40 | #define GPIO_PULL_DOWN 32 | ||
| 41 | |||
| 36 | #endif | 42 | #endif |
diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h index 07cddbf45186..01497910f023 100644 --- a/include/linux/gpio/driver.h +++ b/include/linux/gpio/driver.h | |||
| @@ -472,6 +472,11 @@ int gpiochip_irq_map(struct irq_domain *d, unsigned int irq, | |||
| 472 | irq_hw_number_t hwirq); | 472 | irq_hw_number_t hwirq); |
| 473 | void gpiochip_irq_unmap(struct irq_domain *d, unsigned int irq); | 473 | void gpiochip_irq_unmap(struct irq_domain *d, unsigned int irq); |
| 474 | 474 | ||
| 475 | int gpiochip_irq_domain_activate(struct irq_domain *domain, | ||
| 476 | struct irq_data *data, bool reserve); | ||
| 477 | void gpiochip_irq_domain_deactivate(struct irq_domain *domain, | ||
| 478 | struct irq_data *data); | ||
| 479 | |||
| 475 | void gpiochip_set_chained_irqchip(struct gpio_chip *gpiochip, | 480 | void gpiochip_set_chained_irqchip(struct gpio_chip *gpiochip, |
| 476 | struct irq_chip *irqchip, | 481 | struct irq_chip *irqchip, |
| 477 | unsigned int parent_irq, | 482 | unsigned int parent_irq, |
diff --git a/include/linux/gpio/machine.h b/include/linux/gpio/machine.h index daa44eac9241..69673be10213 100644 --- a/include/linux/gpio/machine.h +++ b/include/linux/gpio/machine.h | |||
| @@ -12,6 +12,8 @@ enum gpio_lookup_flags { | |||
| 12 | GPIO_OPEN_SOURCE = (1 << 2), | 12 | GPIO_OPEN_SOURCE = (1 << 2), |
| 13 | GPIO_PERSISTENT = (0 << 3), | 13 | GPIO_PERSISTENT = (0 << 3), |
| 14 | GPIO_TRANSITORY = (1 << 3), | 14 | GPIO_TRANSITORY = (1 << 3), |
| 15 | GPIO_PULL_UP = (1 << 4), | ||
| 16 | GPIO_PULL_DOWN = (1 << 5), | ||
| 15 | }; | 17 | }; |
| 16 | 18 | ||
| 17 | /** | 19 | /** |
diff --git a/include/linux/irq.h b/include/linux/irq.h index 5e91f6bcaacd..d6160d479b14 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h | |||
| @@ -615,6 +615,7 @@ extern void irq_chip_disable_parent(struct irq_data *data); | |||
| 615 | extern void irq_chip_ack_parent(struct irq_data *data); | 615 | extern void irq_chip_ack_parent(struct irq_data *data); |
| 616 | extern int irq_chip_retrigger_hierarchy(struct irq_data *data); | 616 | extern int irq_chip_retrigger_hierarchy(struct irq_data *data); |
| 617 | extern void irq_chip_mask_parent(struct irq_data *data); | 617 | extern void irq_chip_mask_parent(struct irq_data *data); |
| 618 | extern void irq_chip_mask_ack_parent(struct irq_data *data); | ||
| 618 | extern void irq_chip_unmask_parent(struct irq_data *data); | 619 | extern void irq_chip_unmask_parent(struct irq_data *data); |
| 619 | extern void irq_chip_eoi_parent(struct irq_data *data); | 620 | extern void irq_chip_eoi_parent(struct irq_data *data); |
| 620 | extern int irq_chip_set_affinity_parent(struct irq_data *data, | 621 | extern int irq_chip_set_affinity_parent(struct irq_data *data, |
diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h index d2130dc7c0e6..61706b430907 100644 --- a/include/linux/irqdomain.h +++ b/include/linux/irqdomain.h | |||
| @@ -420,6 +420,11 @@ int irq_domain_xlate_onetwocell(struct irq_domain *d, struct device_node *ctrlr, | |||
| 420 | const u32 *intspec, unsigned int intsize, | 420 | const u32 *intspec, unsigned int intsize, |
| 421 | irq_hw_number_t *out_hwirq, unsigned int *out_type); | 421 | irq_hw_number_t *out_hwirq, unsigned int *out_type); |
| 422 | 422 | ||
| 423 | int irq_domain_translate_twocell(struct irq_domain *d, | ||
| 424 | struct irq_fwspec *fwspec, | ||
| 425 | unsigned long *out_hwirq, | ||
| 426 | unsigned int *out_type); | ||
| 427 | |||
| 423 | /* IPI functions */ | 428 | /* IPI functions */ |
| 424 | int irq_reserve_ipi(struct irq_domain *domain, const struct cpumask *dest); | 429 | int irq_reserve_ipi(struct irq_domain *domain, const struct cpumask *dest); |
| 425 | int irq_destroy_ipi(unsigned int irq, const struct cpumask *dest); | 430 | int irq_destroy_ipi(unsigned int irq, const struct cpumask *dest); |
diff --git a/include/linux/of_gpio.h b/include/linux/of_gpio.h index 163b79ecd01a..f9737dea9d1f 100644 --- a/include/linux/of_gpio.h +++ b/include/linux/of_gpio.h | |||
| @@ -28,6 +28,8 @@ enum of_gpio_flags { | |||
| 28 | OF_GPIO_SINGLE_ENDED = 0x2, | 28 | OF_GPIO_SINGLE_ENDED = 0x2, |
| 29 | OF_GPIO_OPEN_DRAIN = 0x4, | 29 | OF_GPIO_OPEN_DRAIN = 0x4, |
| 30 | OF_GPIO_TRANSITORY = 0x8, | 30 | OF_GPIO_TRANSITORY = 0x8, |
| 31 | OF_GPIO_PULL_UP = 0x10, | ||
| 32 | OF_GPIO_PULL_DOWN = 0x20, | ||
| 31 | }; | 33 | }; |
| 32 | 34 | ||
| 33 | #ifdef CONFIG_OF_GPIO | 35 | #ifdef CONFIG_OF_GPIO |
diff --git a/include/linux/platform_data/gpio/gpio-amd-fch.h b/include/linux/platform_data/gpio/gpio-amd-fch.h new file mode 100644 index 000000000000..a867637e172d --- /dev/null +++ b/include/linux/platform_data/gpio/gpio-amd-fch.h | |||
| @@ -0,0 +1,46 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL+ */ | ||
| 2 | |||
| 3 | /* | ||
| 4 | * AMD FCH gpio driver platform-data | ||
| 5 | * | ||
| 6 | * Copyright (C) 2018 metux IT consult | ||
| 7 | * Author: Enrico Weigelt <info@metux.net> | ||
| 8 | * | ||
| 9 | */ | ||
| 10 | |||
| 11 | #ifndef __LINUX_PLATFORM_DATA_GPIO_AMD_FCH_H | ||
| 12 | #define __LINUX_PLATFORM_DATA_GPIO_AMD_FCH_H | ||
| 13 | |||
| 14 | #define AMD_FCH_GPIO_DRIVER_NAME "gpio_amd_fch" | ||
| 15 | |||
| 16 | /* | ||
| 17 | * gpio register index definitions | ||
| 18 | */ | ||
| 19 | #define AMD_FCH_GPIO_REG_GPIO49 0x40 | ||
| 20 | #define AMD_FCH_GPIO_REG_GPIO50 0x41 | ||
| 21 | #define AMD_FCH_GPIO_REG_GPIO51 0x42 | ||
| 22 | #define AMD_FCH_GPIO_REG_GPIO59_DEVSLP0 0x43 | ||
| 23 | #define AMD_FCH_GPIO_REG_GPIO57 0x44 | ||
| 24 | #define AMD_FCH_GPIO_REG_GPIO58 0x45 | ||
| 25 | #define AMD_FCH_GPIO_REG_GPIO59_DEVSLP1 0x46 | ||
| 26 | #define AMD_FCH_GPIO_REG_GPIO64 0x47 | ||
| 27 | #define AMD_FCH_GPIO_REG_GPIO68 0x48 | ||
| 28 | #define AMD_FCH_GPIO_REG_GPIO66_SPKR 0x5B | ||
| 29 | #define AMD_FCH_GPIO_REG_GPIO71 0x4D | ||
| 30 | #define AMD_FCH_GPIO_REG_GPIO32_GE1 0x59 | ||
| 31 | #define AMD_FCH_GPIO_REG_GPIO33_GE2 0x5A | ||
| 32 | #define AMT_FCH_GPIO_REG_GEVT22 0x09 | ||
| 33 | |||
| 34 | /* | ||
| 35 | * struct amd_fch_gpio_pdata - GPIO chip platform data | ||
| 36 | * @gpio_num: number of entries | ||
| 37 | * @gpio_reg: array of gpio registers | ||
| 38 | * @gpio_names: array of gpio names | ||
| 39 | */ | ||
| 40 | struct amd_fch_gpio_pdata { | ||
| 41 | int gpio_num; | ||
| 42 | int *gpio_reg; | ||
| 43 | const char * const *gpio_names; | ||
| 44 | }; | ||
| 45 | |||
| 46 | #endif /* __LINUX_PLATFORM_DATA_GPIO_AMD_FCH_H */ | ||
diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h index 466a8d02e298..cc464850b71e 100644 --- a/include/linux/platform_device.h +++ b/include/linux/platform_device.h | |||
| @@ -52,6 +52,9 @@ extern struct device platform_bus; | |||
| 52 | extern void arch_setup_pdev_archdata(struct platform_device *); | 52 | extern void arch_setup_pdev_archdata(struct platform_device *); |
| 53 | extern struct resource *platform_get_resource(struct platform_device *, | 53 | extern struct resource *platform_get_resource(struct platform_device *, |
| 54 | unsigned int, unsigned int); | 54 | unsigned int, unsigned int); |
| 55 | extern void __iomem * | ||
| 56 | devm_platform_ioremap_resource(struct platform_device *pdev, | ||
| 57 | unsigned int index); | ||
| 55 | extern int platform_get_irq(struct platform_device *, unsigned int); | 58 | extern int platform_get_irq(struct platform_device *, unsigned int); |
| 56 | extern int platform_irq_count(struct platform_device *); | 59 | extern int platform_irq_count(struct platform_device *); |
| 57 | extern struct resource *platform_get_resource_byname(struct platform_device *, | 60 | extern struct resource *platform_get_resource_byname(struct platform_device *, |
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c index 99b7dd6982a4..3faef4a77f71 100644 --- a/kernel/irq/chip.c +++ b/kernel/irq/chip.c | |||
| @@ -1340,6 +1340,17 @@ void irq_chip_mask_parent(struct irq_data *data) | |||
| 1340 | EXPORT_SYMBOL_GPL(irq_chip_mask_parent); | 1340 | EXPORT_SYMBOL_GPL(irq_chip_mask_parent); |
| 1341 | 1341 | ||
| 1342 | /** | 1342 | /** |
| 1343 | * irq_chip_mask_ack_parent - Mask and acknowledge the parent interrupt | ||
| 1344 | * @data: Pointer to interrupt specific data | ||
| 1345 | */ | ||
| 1346 | void irq_chip_mask_ack_parent(struct irq_data *data) | ||
| 1347 | { | ||
| 1348 | data = data->parent_data; | ||
| 1349 | data->chip->irq_mask_ack(data); | ||
| 1350 | } | ||
| 1351 | EXPORT_SYMBOL_GPL(irq_chip_mask_ack_parent); | ||
| 1352 | |||
| 1353 | /** | ||
| 1343 | * irq_chip_unmask_parent - Unmask the parent interrupt | 1354 | * irq_chip_unmask_parent - Unmask the parent interrupt |
| 1344 | * @data: Pointer to interrupt specific data | 1355 | * @data: Pointer to interrupt specific data |
| 1345 | */ | 1356 | */ |
| @@ -1443,6 +1454,7 @@ int irq_chip_set_wake_parent(struct irq_data *data, unsigned int on) | |||
| 1443 | 1454 | ||
| 1444 | return -ENOSYS; | 1455 | return -ENOSYS; |
| 1445 | } | 1456 | } |
| 1457 | EXPORT_SYMBOL_GPL(irq_chip_set_wake_parent); | ||
| 1446 | #endif | 1458 | #endif |
| 1447 | 1459 | ||
| 1448 | /** | 1460 | /** |
diff --git a/kernel/irq/irq_sim.c b/kernel/irq/irq_sim.c index 98a20e1594ce..b992f88c5613 100644 --- a/kernel/irq/irq_sim.c +++ b/kernel/irq/irq_sim.c | |||
| @@ -25,10 +25,22 @@ static void irq_sim_irqunmask(struct irq_data *data) | |||
| 25 | irq_ctx->enabled = true; | 25 | irq_ctx->enabled = true; |
| 26 | } | 26 | } |
| 27 | 27 | ||
| 28 | static int irq_sim_set_type(struct irq_data *data, unsigned int type) | ||
| 29 | { | ||
| 30 | /* We only support rising and falling edge trigger types. */ | ||
| 31 | if (type & ~IRQ_TYPE_EDGE_BOTH) | ||
| 32 | return -EINVAL; | ||
| 33 | |||
| 34 | irqd_set_trigger_type(data, type); | ||
| 35 | |||
| 36 | return 0; | ||
| 37 | } | ||
| 38 | |||
| 28 | static struct irq_chip irq_sim_irqchip = { | 39 | static struct irq_chip irq_sim_irqchip = { |
| 29 | .name = "irq_sim", | 40 | .name = "irq_sim", |
| 30 | .irq_mask = irq_sim_irqmask, | 41 | .irq_mask = irq_sim_irqmask, |
| 31 | .irq_unmask = irq_sim_irqunmask, | 42 | .irq_unmask = irq_sim_irqunmask, |
| 43 | .irq_set_type = irq_sim_set_type, | ||
| 32 | }; | 44 | }; |
| 33 | 45 | ||
| 34 | static void irq_sim_handle_irq(struct irq_work *work) | 46 | static void irq_sim_handle_irq(struct irq_work *work) |
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c index 3bf9793d8825..9ed29e4a7dbf 100644 --- a/kernel/irq/irqdomain.c +++ b/kernel/irq/irqdomain.c | |||
| @@ -743,16 +743,17 @@ static int irq_domain_translate(struct irq_domain *d, | |||
| 743 | return 0; | 743 | return 0; |
| 744 | } | 744 | } |
| 745 | 745 | ||
| 746 | static void of_phandle_args_to_fwspec(struct of_phandle_args *irq_data, | 746 | static void of_phandle_args_to_fwspec(struct device_node *np, const u32 *args, |
| 747 | unsigned int count, | ||
| 747 | struct irq_fwspec *fwspec) | 748 | struct irq_fwspec *fwspec) |
| 748 | { | 749 | { |
| 749 | int i; | 750 | int i; |
| 750 | 751 | ||
| 751 | fwspec->fwnode = irq_data->np ? &irq_data->np->fwnode : NULL; | 752 | fwspec->fwnode = np ? &np->fwnode : NULL; |
| 752 | fwspec->param_count = irq_data->args_count; | 753 | fwspec->param_count = count; |
| 753 | 754 | ||
| 754 | for (i = 0; i < irq_data->args_count; i++) | 755 | for (i = 0; i < count; i++) |
| 755 | fwspec->param[i] = irq_data->args[i]; | 756 | fwspec->param[i] = args[i]; |
| 756 | } | 757 | } |
| 757 | 758 | ||
| 758 | unsigned int irq_create_fwspec_mapping(struct irq_fwspec *fwspec) | 759 | unsigned int irq_create_fwspec_mapping(struct irq_fwspec *fwspec) |
| @@ -850,7 +851,9 @@ unsigned int irq_create_of_mapping(struct of_phandle_args *irq_data) | |||
| 850 | { | 851 | { |
| 851 | struct irq_fwspec fwspec; | 852 | struct irq_fwspec fwspec; |
| 852 | 853 | ||
| 853 | of_phandle_args_to_fwspec(irq_data, &fwspec); | 854 | of_phandle_args_to_fwspec(irq_data->np, irq_data->args, |
| 855 | irq_data->args_count, &fwspec); | ||
| 856 | |||
| 854 | return irq_create_fwspec_mapping(&fwspec); | 857 | return irq_create_fwspec_mapping(&fwspec); |
| 855 | } | 858 | } |
| 856 | EXPORT_SYMBOL_GPL(irq_create_of_mapping); | 859 | EXPORT_SYMBOL_GPL(irq_create_of_mapping); |
| @@ -942,11 +945,10 @@ int irq_domain_xlate_twocell(struct irq_domain *d, struct device_node *ctrlr, | |||
| 942 | const u32 *intspec, unsigned int intsize, | 945 | const u32 *intspec, unsigned int intsize, |
| 943 | irq_hw_number_t *out_hwirq, unsigned int *out_type) | 946 | irq_hw_number_t *out_hwirq, unsigned int *out_type) |
| 944 | { | 947 | { |
| 945 | if (WARN_ON(intsize < 2)) | 948 | struct irq_fwspec fwspec; |
| 946 | return -EINVAL; | 949 | |
| 947 | *out_hwirq = intspec[0]; | 950 | of_phandle_args_to_fwspec(ctrlr, intspec, intsize, &fwspec); |
| 948 | *out_type = intspec[1] & IRQ_TYPE_SENSE_MASK; | 951 | return irq_domain_translate_twocell(d, &fwspec, out_hwirq, out_type); |
| 949 | return 0; | ||
| 950 | } | 952 | } |
| 951 | EXPORT_SYMBOL_GPL(irq_domain_xlate_twocell); | 953 | EXPORT_SYMBOL_GPL(irq_domain_xlate_twocell); |
| 952 | 954 | ||
| @@ -982,6 +984,27 @@ const struct irq_domain_ops irq_domain_simple_ops = { | |||
| 982 | }; | 984 | }; |
| 983 | EXPORT_SYMBOL_GPL(irq_domain_simple_ops); | 985 | EXPORT_SYMBOL_GPL(irq_domain_simple_ops); |
| 984 | 986 | ||
| 987 | /** | ||
| 988 | * irq_domain_translate_twocell() - Generic translate for direct two cell | ||
| 989 | * bindings | ||
| 990 | * | ||
| 991 | * Device Tree IRQ specifier translation function which works with two cell | ||
| 992 | * bindings where the cell values map directly to the hwirq number | ||
| 993 | * and linux irq flags. | ||
| 994 | */ | ||
| 995 | int irq_domain_translate_twocell(struct irq_domain *d, | ||
| 996 | struct irq_fwspec *fwspec, | ||
| 997 | unsigned long *out_hwirq, | ||
| 998 | unsigned int *out_type) | ||
| 999 | { | ||
| 1000 | if (WARN_ON(fwspec->param_count < 2)) | ||
| 1001 | return -EINVAL; | ||
| 1002 | *out_hwirq = fwspec->param[0]; | ||
| 1003 | *out_type = fwspec->param[1] & IRQ_TYPE_SENSE_MASK; | ||
| 1004 | return 0; | ||
| 1005 | } | ||
| 1006 | EXPORT_SYMBOL_GPL(irq_domain_translate_twocell); | ||
| 1007 | |||
| 985 | int irq_domain_alloc_descs(int virq, unsigned int cnt, irq_hw_number_t hwirq, | 1008 | int irq_domain_alloc_descs(int virq, unsigned int cnt, irq_hw_number_t hwirq, |
| 986 | int node, const struct irq_affinity_desc *affinity) | 1009 | int node, const struct irq_affinity_desc *affinity) |
| 987 | { | 1010 | { |
