diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2023-06-29 10:11:10 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2023-06-29 10:11:10 -0700 |
commit | e5476f57b32621eb8eab892a908df4d0b4808835 (patch) | |
tree | 5b8afd97980b98201aba7aa24cf33c7b389e596d | |
parent | ff7ddcf0db48a7d9ae536eb0875428117be1d1f1 (diff) | |
parent | 0ff9f5e57c5bb45b6b807a4d466228de39d8cd2f (diff) | |
download | linux-stable-e5476f57b32621eb8eab892a908df4d0b4808835.tar.gz linux-stable-e5476f57b32621eb8eab892a908df4d0b4808835.tar.bz2 linux-stable-e5476f57b32621eb8eab892a908df4d0b4808835.zip |
Merge tag 'gpio-updates-for-v6.5' of git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux
Pull gpio updates from Bartosz Golaszewski:
"We have two new drivers, some improvements to the core code, lots of
different updates to existing GPIO drivers and some dt-bindings on
top.
There's nothing controversial in here and almost everything has been
in next for more than a week (95% a lot longer than this). The only
thing that has spent less time in next is a new driver so no risk of
regressions.
The single merge pulls in changes that remove all usage of global GPIO
numbers from arch/arm/mach-omap.
Core GPIO library:
- remove unused symbols
- don't spam the kernel log with messages about hogs
- remove old sysfs API cruft
- improve handling of GPIO masks
New drivers:
- add a driver for the BlueField-3 GPIO controller
- add GPIO support for the TPS65219 PMIC
Driver improvements:
- extend the gpio-aggregator driver to support ramp-up/ramp-down
delay
- remove unnecessary CONFIG_OF guards from gpio-aggregator
- readability improvements in gpio-tangier
- switch i2c drivers back to using probe() now that it's been
converted in the i2c subsystem to not taking the id parameter
- remove unused inclusions of of_gpio.h in several drivers
- make pm ops static in gpio-davinci and fix a comment
- use more devres in drivers to shrink and simplify the code
- add missing include in gpio-sa1100
- add HAS_IOPORT KConfig dependency where needed
- add permissions checks before accessing pins in gpio-tegra186
- convert the gpio-zynq driver to using immutable irqchips
- preserve output settings set by the bootloader in gpio-mpc8xxx
Selftests:
- tweak the variable naming in script tests
Device tree updates:
- convert gpio-mmio and gpio-stmpe to YAML
- add parsing of GPIO hogs to gpio-vf610
- add bindings for the Cirrus EP93xx GPIO controller
- add gpio-line-names property to the gpio-pca9570 bindings
- extend the binding for x-powers,axp209 with another block"
* tag 'gpio-updates-for-v6.5' of git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux: (58 commits)
of: unittest: drop assertions for GPIO hog messages
gpiolib: Drop unused domain_ops memeber of GPIO IRQ chip
gpio: synq: remove unused zynq_gpio_irq_reqres/zynq_gpio_irq_relres
dt-bindings: gpio: gpio-vf610: Add parsing of hogs
gpio: lpc18xx: Remove unused of_gpio.h inclusion
gpio: xra1403: Remove unused of_gpio.h inclusion
gpio: mpc8xxx: Remove unused of_gpio.h inclusion
dt-bindings: gpio: Add Cirrus EP93xx
gpio: mpc8xxx: latch GPIOs state on module load when configured as output
selftests: gpio: gpio-sim: Use same variable name for sysfs pathname
gpio: mlxbf3: Add gpio driver support
gpio: delay: Remove duplicative functionality
gpio: aggregator: Set up a parser of delay line parameters
gpio: aggregator: Support delay for setting up individual GPIOs
gpio: aggregator: Remove CONFIG_OF and of_match_ptr() protections
dt-bindings: gpio: pca9570: add gpio-line-names property
gpiolib: remove unused gpio_cansleep()
gpio: tps65219: add GPIO support for TPS65219 PMIC
gpio: zynq: fix zynqmp_gpio not an immutable chip warning
gpio: davinci: make davinci_gpio_dev_pm_ops static
...
89 files changed, 1798 insertions, 988 deletions
diff --git a/Documentation/devicetree/bindings/gpio/brcm,bcm6345-gpio.yaml b/Documentation/devicetree/bindings/gpio/brcm,bcm63xx-gpio.yaml index 4d69f79df859..62fcc2bd5d80 100644 --- a/Documentation/devicetree/bindings/gpio/brcm,bcm6345-gpio.yaml +++ b/Documentation/devicetree/bindings/gpio/brcm,bcm63xx-gpio.yaml @@ -1,10 +1,10 @@ # SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause %YAML 1.2 --- -$id: http://devicetree.org/schemas/gpio/brcm,bcm6345-gpio.yaml# +$id: http://devicetree.org/schemas/gpio/brcm,bcm63xx-gpio.yaml# $schema: http://devicetree.org/meta-schemas/core.yaml# -title: Broadcom BCM6345 GPIO controller +title: Broadcom BCM63xx GPIO controller maintainers: - Álvaro Fernández Rojas <noltari@gmail.com> @@ -18,8 +18,6 @@ description: |+ BCM6338 have 8-bit data and dirout registers, where GPIO state can be read and/or written, and the direction changed from input to output. - BCM6345 have 16-bit data and dirout registers, where GPIO state can be read - and/or written, and the direction changed from input to output. BCM6318, BCM6328, BCM6358, BCM6362, BCM6368 and BCM63268 have 32-bit data and dirout registers, where GPIO state can be read and/or written, and the direction changed from input to output. @@ -29,7 +27,6 @@ properties: enum: - brcm,bcm6318-gpio - brcm,bcm6328-gpio - - brcm,bcm6345-gpio - brcm,bcm6358-gpio - brcm,bcm6362-gpio - brcm,bcm6368-gpio @@ -64,17 +61,6 @@ additionalProperties: false examples: - | - gpio@fffe0406 { - compatible = "brcm,bcm6345-gpio"; - reg-names = "dirout", "dat"; - reg = <0xfffe0406 2>, <0xfffe040a 2>; - native-endian; - - gpio-controller; - #gpio-cells = <2>; - }; - - - | gpio@0 { compatible = "brcm,bcm63268-gpio"; reg-names = "dirout", "dat"; diff --git a/Documentation/devicetree/bindings/gpio/gpio-delay.yaml b/Documentation/devicetree/bindings/gpio/gpio-delay.yaml new file mode 100644 index 000000000000..1cebc4058e27 --- /dev/null +++ b/Documentation/devicetree/bindings/gpio/gpio-delay.yaml @@ -0,0 +1,79 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/gpio/gpio-delay.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: GPIO delay controller + +maintainers: + - Alexander Stein <linux@ew.tq-group.com> + +description: | + This binding describes an electrical setup where setting an GPIO output + is delayed by some external setup, e.g. RC circuit. + + +----------+ +-----------+ + | | VCC_B | | + | | | | | + | | VCC_A _ | | + | GPIO | | | R | Consumer | + |controller| ___ |_| | | + | | | | | | | + | [IOx|-------| |--+-----|-----+ | + | | |___| | | input | + | | | | | + +----------+ --- C +-----------+ + --- + | + - + GND + + If the input on the consumer is controlled by an open-drain signal + attached to an RC circuit the ramp-up delay is not under control + of the GPIO controller. + +properties: + compatible: + const: gpio-delay + + "#gpio-cells": + description: | + Specifies the pin, ramp-up and ramp-down delays. The + delays are specified in microseconds. + const: 3 + + gpios: + description: Array of GPIOs which output signal change is delayed + minItems: 1 + maxItems: 32 + + gpio-controller: true + + gpio-line-names: + minItems: 1 + maxItems: 32 + +required: + - compatible + - "#gpio-cells" + - gpio-controller + - gpios + +additionalProperties: false + +examples: + - | + #include <dt-bindings/gpio/gpio.h> + + enable_delay: enable-delay { + compatible = "gpio-delay"; + #gpio-cells = <3>; + gpio-controller; + gpios = <&gpio0 3 GPIO_ACTIVE_LOW>, + <&gpio3 1 GPIO_ACTIVE_HIGH>; + }; + + consumer { + enable-gpios = <&enable_delay 0 130000 30000>; + }; diff --git a/Documentation/devicetree/bindings/gpio/gpio-ep9301.yaml b/Documentation/devicetree/bindings/gpio/gpio-ep9301.yaml new file mode 100644 index 000000000000..daadfb4926c3 --- /dev/null +++ b/Documentation/devicetree/bindings/gpio/gpio-ep9301.yaml @@ -0,0 +1,154 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/gpio/gpio-ep9301.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: EP93xx GPIO controller + +maintainers: + - Linus Walleij <linus.walleij@linaro.org> + - Bartosz Golaszewski <brgl@bgdev.pl> + - Nikita Shubin <nikita.shubin@maquefel.me> + +properties: + compatible: + oneOf: + - const: cirrus,ep9301-gpio + - items: + - enum: + - cirrus,ep9302-gpio + - cirrus,ep9307-gpio + - cirrus,ep9312-gpio + - cirrus,ep9315-gpio + - const: cirrus,ep9301-gpio + + reg: + minItems: 2 + items: + - description: data register + - description: direction register + - description: interrupt registers base + + reg-names: + minItems: 2 + items: + - const: data + - const: dir + - const: intr + + gpio-controller: true + + gpio-ranges: true + + "#gpio-cells": + const: 2 + + interrupt-controller: true + + "#interrupt-cells": + const: 2 + + interrupts: + oneOf: + - maxItems: 1 + - description: port F has dedicated irq line for each gpio line + maxItems: 8 + +required: + - compatible + - reg + - gpio-controller + - "#gpio-cells" + +additionalProperties: false + +examples: + - | + gpio@80840000 { + compatible = "cirrus,ep9301-gpio"; + reg = <0x80840000 0x04>, + <0x80840010 0x04>, + <0x80840090 0x1c>; + reg-names = "data", "dir", "intr"; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + interrupt-parent = <&vic1>; + interrupts = <27>; + }; + + gpio@80840004 { + compatible = "cirrus,ep9301-gpio"; + reg = <0x80840004 0x04>, + <0x80840014 0x04>, + <0x808400ac 0x1c>; + reg-names = "data", "dir", "intr"; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + interrupt-parent = <&vic1>; + interrupts = <27>; + }; + + gpio@80840008 { + compatible = "cirrus,ep9301-gpio"; + reg = <0x80840008 0x04>, + <0x80840018 0x04>; + reg-names = "data", "dir"; + gpio-controller; + #gpio-cells = <2>; + }; + + gpio@8084000c { + compatible = "cirrus,ep9301-gpio"; + reg = <0x8084000c 0x04>, + <0x8084001c 0x04>; + reg-names = "data", "dir"; + gpio-controller; + #gpio-cells = <2>; + }; + + gpio@80840020 { + compatible = "cirrus,ep9301-gpio"; + reg = <0x80840020 0x04>, + <0x80840024 0x04>; + reg-names = "data", "dir"; + gpio-controller; + #gpio-cells = <2>; + }; + + gpio@80840030 { + compatible = "cirrus,ep9301-gpio"; + reg = <0x80840030 0x04>, + <0x80840034 0x04>, + <0x8084004c 0x1c>; + reg-names = "data", "dir", "intr"; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + interrupts-extended = <&vic0 19>, <&vic0 20>, + <&vic0 21>, <&vic0 22>, + <&vic1 15>, <&vic1 16>, + <&vic1 17>, <&vic1 18>; + }; + + gpio@80840038 { + compatible = "cirrus,ep9301-gpio"; + reg = <0x80840038 0x04>, + <0x8084003c 0x04>; + reg-names = "data", "dir"; + gpio-controller; + #gpio-cells = <2>; + }; + + gpio@80840040 { + compatible = "cirrus,ep9301-gpio"; + reg = <0x80840040 0x04>, + <0x80840044 0x04>; + reg-names = "data", "dir"; + gpio-controller; + #gpio-cells = <2>; + }; + +... diff --git a/Documentation/devicetree/bindings/gpio/gpio-mmio.yaml b/Documentation/devicetree/bindings/gpio/gpio-mmio.yaml new file mode 100644 index 000000000000..b394e058256e --- /dev/null +++ b/Documentation/devicetree/bindings/gpio/gpio-mmio.yaml @@ -0,0 +1,117 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/gpio/gpio-mmio.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Generic MMIO GPIO + +maintainers: + - Linus Walleij <linus.walleij@linaro.org> + - Bartosz Golaszewski <brgl@bgdev.pl> + +description: + Some simple GPIO controllers may consist of a single data register or a pair + of set/clear-bit registers. Such controllers are common for glue logic in + FPGAs or ASICs. Commonly, these controllers are accessed over memory-mapped + NAND-style parallel busses. + +properties: + compatible: + enum: + - brcm,bcm6345-gpio + - ni,169445-nand-gpio + - wd,mbl-gpio # Western Digital MyBook Live memory-mapped GPIO controller + + big-endian: true + + '#gpio-cells': + const: 2 + + gpio-controller: true + + little-endian: true + + reg: + minItems: 1 + description: + A list of registers in the controller. The width of each register is + determined by its size. All registers must have the same width. The number + of GPIOs is set by the width, with bit 0 corresponding to GPIO 0. + items: + - description: + Register to READ the value of the GPIO lines. If GPIO line is high, + the bit will be set. If the GPIO line is low, the bit will be cleared. + This register may also be used to drive GPIOs if the SET register is + omitted. + - description: + Register to SET the value of the GPIO lines. Setting a bit in this + register will drive the GPIO line high. + - description: + Register to CLEAR the value of the GPIO lines. Setting a bit in this + register will drive the GPIO line low. If this register is omitted, + the SET register will be used to clear the GPIO lines as well, by + actively writing the line with 0. + - description: + Register to set the line as OUTPUT. Setting a bit in this register + will turn that line into an output line. Conversely, clearing a bit + will turn that line into an input. + - description: + Register to set this line as INPUT. Setting a bit in this register + will turn that line into an input line. Conversely, clearing a bit + will turn that line into an output. + + reg-names: + minItems: 1 + maxItems: 5 + items: + enum: + - dat + - set + - clr + - dirout + - dirin + + native-endian: true + + no-output: + $ref: /schemas/types.yaml#/definitions/flag + description: + If this property is present, the controller cannot drive the GPIO lines. + +required: + - compatible + - reg + - reg-names + - '#gpio-cells' + - gpio-controller + +additionalProperties: false + +examples: + - | + gpio@1f300010 { + compatible = "ni,169445-nand-gpio"; + reg = <0x1f300010 0x4>; + reg-names = "dat"; + gpio-controller; + #gpio-cells = <2>; + }; + + gpio@e0100000 { + compatible = "wd,mbl-gpio"; + reg-names = "dat"; + reg = <0xe0100000 0x1>; + #gpio-cells = <2>; + gpio-controller; + no-output; + }; + + gpio@fffe0406 { + compatible = "brcm,bcm6345-gpio"; + reg-names = "dirout", "dat"; + reg = <0xfffe0406 2>, <0xfffe040a 2>; + native-endian; + gpio-controller; + #gpio-cells = <2>; + }; diff --git a/Documentation/devicetree/bindings/gpio/gpio-pca9570.yaml b/Documentation/devicetree/bindings/gpio/gpio-pca9570.yaml index 5b0134304e51..452f8972a965 100644 --- a/Documentation/devicetree/bindings/gpio/gpio-pca9570.yaml +++ b/Documentation/devicetree/bindings/gpio/gpio-pca9570.yaml @@ -24,6 +24,10 @@ properties: '#gpio-cells': const: 2 + gpio-line-names: + minItems: 4 + maxItems: 8 + required: - compatible - reg diff --git a/Documentation/devicetree/bindings/gpio/gpio-stmpe.txt b/Documentation/devicetree/bindings/gpio/gpio-stmpe.txt deleted file mode 100644 index b33f8f02c0d7..000000000000 --- a/Documentation/devicetree/bindings/gpio/gpio-stmpe.txt +++ /dev/null @@ -1,17 +0,0 @@ -STMPE gpio ----------- - -Required properties: - - compatible: "st,stmpe-gpio" - -Optional properties: - - st,norequest-mask: bitmask specifying which GPIOs should _not_ be requestable - due to different usage (e.g. touch, keypad) - -Node should be child node of stmpe node to which it belongs. - -Example: - stmpe_gpio { - compatible = "st,stmpe-gpio"; - st,norequest-mask = <0x20>; //gpio 5 can't be used - }; diff --git a/Documentation/devicetree/bindings/gpio/gpio-vf610.yaml b/Documentation/devicetree/bindings/gpio/gpio-vf610.yaml index d2c39dba56ad..7c2d152e8617 100644 --- a/Documentation/devicetree/bindings/gpio/gpio-vf610.yaml +++ b/Documentation/devicetree/bindings/gpio/gpio-vf610.yaml @@ -61,6 +61,13 @@ properties: gpio-ranges: maxItems: 1 +patternProperties: + "^.+-hog(-[0-9]+)?$": + type: object + + required: + - gpio-hog + required: - compatible - reg diff --git a/Documentation/devicetree/bindings/gpio/ni,169445-nand-gpio.txt b/Documentation/devicetree/bindings/gpio/ni,169445-nand-gpio.txt deleted file mode 100644 index ca2f8c745a27..000000000000 --- a/Documentation/devicetree/bindings/gpio/ni,169445-nand-gpio.txt +++ /dev/null @@ -1,38 +0,0 @@ -Bindings for the National Instruments 169445 GPIO NAND controller - -The 169445 GPIO NAND controller has two memory mapped GPIO registers, one -for input (the ready signal) and one for output (control signals). It is -intended to be used with the GPIO NAND driver. - -Required properties: - - compatible: should be "ni,169445-nand-gpio" - - reg-names: must contain - "dat" - data register - - reg: address + size pairs describing the GPIO register sets; - order must correspond with the order of entries in reg-names - - #gpio-cells: must be set to 2. The first cell is the pin number and - the second cell is used to specify the gpio polarity: - 0 = active high - 1 = active low - - gpio-controller: Marks the device node as a gpio controller. - -Optional properties: - - no-output: disables driving output on the pins - -Examples: - gpio1: nand-gpio-out@1f300010 { - compatible = "ni,169445-nand-gpio"; - reg = <0x1f300010 0x4>; - reg-names = "dat"; - gpio-controller; - #gpio-cells = <2>; - }; - - gpio2: nand-gpio-in@1f300014 { - compatible = "ni,169445-nand-gpio"; - reg = <0x1f300014 0x4>; - reg-names = "dat"; - gpio-controller; - #gpio-cells = <2>; - no-output; - }; diff --git a/Documentation/devicetree/bindings/gpio/st,stmpe-gpio.yaml b/Documentation/devicetree/bindings/gpio/st,stmpe-gpio.yaml new file mode 100644 index 000000000000..22c0cae73425 --- /dev/null +++ b/Documentation/devicetree/bindings/gpio/st,stmpe-gpio.yaml @@ -0,0 +1,53 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/gpio/st,stmpe-gpio.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: STMicroelectonics Port Expander (STMPE) GPIO Block + +description: + STMicroelectronics Port Expander (STMPE) is a series of slow + bus controllers for various expanded peripherals such as GPIO, keypad, + touchscreen, ADC, PWM or rotator. It can contain one or several different + peripherals connected to SPI or I2C. These bindings pertain to the + GPIO portions of these expanders. + +maintainers: + - Linus Walleij <linus.walleij@linaro.org> + +properties: + compatible: + const: st,stmpe-gpio + + "#gpio-cells": + const: 2 + + "#interrupt-cells": + const: 2 + + gpio-controller: true + + interrupt-controller: true + + st,norequest-mask: + description: + A bitmask of GPIO lines that cannot be requested because for + for example not being connected to anything on the system + $ref: /schemas/types.yaml#/definitions/uint32 + +patternProperties: + "^.+-hog(-[0-9]+)?$": + type: object + + required: + - gpio-hog + +additionalProperties: false + +required: + - compatible + - "#gpio-cells" + - "#interrupt-cells" + - gpio-controller + - interrupt-controller diff --git a/Documentation/devicetree/bindings/gpio/wd,mbl-gpio.txt b/Documentation/devicetree/bindings/gpio/wd,mbl-gpio.txt deleted file mode 100644 index 038c3a6a1f4d..000000000000 --- a/Documentation/devicetree/bindings/gpio/wd,mbl-gpio.txt +++ /dev/null @@ -1,38 +0,0 @@ -Bindings for the Western Digital's MyBook Live memory-mapped GPIO controllers. - -The Western Digital MyBook Live has two memory-mapped GPIO controllers. -Both GPIO controller only have a single 8-bit data register, where GPIO -state can be read and/or written. - -Required properties: - - compatible: should be "wd,mbl-gpio" - - reg-names: must contain - "dat" - data register - - reg: address + size pairs describing the GPIO register sets; - order must correspond with the order of entries in reg-names - - #gpio-cells: must be set to 2. The first cell is the pin number and - the second cell is used to specify the gpio polarity: - 0 = active high - 1 = active low - - gpio-controller: Marks the device node as a gpio controller. - -Optional properties: - - no-output: GPIOs are read-only. - -Examples: - gpio0: gpio0@e0000000 { - compatible = "wd,mbl-gpio"; - reg-names = "dat"; - reg = <0xe0000000 0x1>; - #gpio-cells = <2>; - gpio-controller; - }; - - gpio1: gpio1@e0100000 { - compatible = "wd,mbl-gpio"; - reg-names = "dat"; - reg = <0xe0100000 0x1>; - #gpio-cells = <2>; - gpio-controller; - no-output; - }; diff --git a/Documentation/devicetree/bindings/gpio/x-powers,axp209-gpio.yaml b/Documentation/devicetree/bindings/gpio/x-powers,axp209-gpio.yaml index 31906c253940..1638cfe90f1c 100644 --- a/Documentation/devicetree/bindings/gpio/x-powers,axp209-gpio.yaml +++ b/Documentation/devicetree/bindings/gpio/x-powers,axp209-gpio.yaml @@ -44,6 +44,7 @@ patternProperties: - GPIO0 - GPIO1 - GPIO2 + - GPIO3 function: enum: diff --git a/Documentation/devicetree/bindings/mfd/brcm,bcm6318-gpio-sysctl.yaml b/Documentation/devicetree/bindings/mfd/brcm,bcm6318-gpio-sysctl.yaml index 148f1da47603..9f9a14af875e 100644 --- a/Documentation/devicetree/bindings/mfd/brcm,bcm6318-gpio-sysctl.yaml +++ b/Documentation/devicetree/bindings/mfd/brcm,bcm6318-gpio-sysctl.yaml @@ -35,11 +35,11 @@ patternProperties: "^gpio@[0-9a-f]+$": # Child node type: object - $ref: "../gpio/brcm,bcm6345-gpio.yaml" + $ref: "../gpio/brcm,bcm63xx-gpio.yaml" description: GPIO controller for the SoC GPIOs. This child node definition should follow the bindings specified in - Documentation/devicetree/bindings/gpio/brcm,bcm6345-gpio.yaml. + Documentation/devicetree/bindings/gpio/brcm,bcm63xx-gpio.yaml. "^pinctrl@[0-9a-f]+$": # Child node diff --git a/Documentation/devicetree/bindings/mfd/brcm,bcm63268-gpio-sysctl.yaml b/Documentation/devicetree/bindings/mfd/brcm,bcm63268-gpio-sysctl.yaml index 7e582243ea76..803277dd2725 100644 --- a/Documentation/devicetree/bindings/mfd/brcm,bcm63268-gpio-sysctl.yaml +++ b/Documentation/devicetree/bindings/mfd/brcm,bcm63268-gpio-sysctl.yaml @@ -35,11 +35,11 @@ patternProperties: "^gpio@[0-9a-f]+$": # Child node type: object - $ref: "../gpio/brcm,bcm6345-gpio.yaml" + $ref: "../gpio/brcm,bcm63xx-gpio.yaml" description: GPIO controller for the SoC GPIOs. This child node definition should follow the bindings specified in - Documentation/devicetree/bindings/gpio/brcm,bcm6345-gpio.yaml. + Documentation/devicetree/bindings/gpio/brcm,bcm63xx-gpio.yaml. "^pinctrl@[0-9a-f]+$": # Child node diff --git a/Documentation/devicetree/bindings/mfd/brcm,bcm6328-gpio-sysctl.yaml b/Documentation/devicetree/bindings/mfd/brcm,bcm6328-gpio-sysctl.yaml index 2230848e11c3..b9a6856ce970 100644 --- a/Documentation/devicetree/bindings/mfd/brcm,bcm6328-gpio-sysctl.yaml +++ b/Documentation/devicetree/bindings/mfd/brcm,bcm6328-gpio-sysctl.yaml @@ -35,11 +35,11 @@ patternProperties: "^gpio@[0-9a-f]+$": # Child node type: object - $ref: "../gpio/brcm,bcm6345-gpio.yaml" + $ref: "../gpio/brcm,bcm63xx-gpio.yaml" description: GPIO controller for the SoC GPIOs. This child node definition should follow the bindings specified in - Documentation/devicetree/bindings/gpio/brcm,bcm6345-gpio.yaml. + Documentation/devicetree/bindings/gpio/brcm,bcm63xx-gpio.yaml. "^pinctrl@[0-9a-f]+$": # Child node diff --git a/Documentation/devicetree/bindings/mfd/brcm,bcm6358-gpio-sysctl.yaml b/Documentation/devicetree/bindings/mfd/brcm,bcm6358-gpio-sysctl.yaml index c06693b6f7aa..4651fe4dde07 100644 --- a/Documentation/devicetree/bindings/mfd/brcm,bcm6358-gpio-sysctl.yaml +++ b/Documentation/devicetree/bindings/mfd/brcm,bcm6358-gpio-sysctl.yaml @@ -35,11 +35,11 @@ patternProperties: "^gpio@[0-9a-f]+$": # Child node type: object - $ref: "../gpio/brcm,bcm6345-gpio.yaml" + $ref: "../gpio/brcm,bcm63xx-gpio.yaml" description: GPIO controller for the SoC GPIOs. This child node definition should follow the bindings specified in - Documentation/devicetree/bindings/gpio/brcm,bcm6345-gpio.yaml. + Documentation/devicetree/bindings/gpio/brcm,bcm63xx-gpio.yaml. "^pinctrl@[0-9a-f]+$": # Child node diff --git a/Documentation/devicetree/bindings/mfd/brcm,bcm6362-gpio-sysctl.yaml b/Documentation/devicetree/bindings/mfd/brcm,bcm6362-gpio-sysctl.yaml index c560bede0e37..0330b621fd38 100644 --- a/Documentation/devicetree/bindings/mfd/brcm,bcm6362-gpio-sysctl.yaml +++ b/Documentation/devicetree/bindings/mfd/brcm,bcm6362-gpio-sysctl.yaml @@ -35,11 +35,11 @@ patternProperties: "^gpio@[0-9a-f]+$": # Child node type: object - $ref: "../gpio/brcm,bcm6345-gpio.yaml" + $ref: "../gpio/brcm,bcm63xx-gpio.yaml" description: GPIO controller for the SoC GPIOs. This child node definition should follow the bindings specified in - Documentation/devicetree/bindings/gpio/brcm,bcm6345-gpio.yaml. + Documentation/devicetree/bindings/gpio/brcm,bcm63xx-gpio.yaml. "^pinctrl@[0-9a-f]+$": # Child node diff --git a/Documentation/devicetree/bindings/mfd/brcm,bcm6368-gpio-sysctl.yaml b/Documentation/devicetree/bindings/mfd/brcm,bcm6368-gpio-sysctl.yaml index c534f5f2404e..82d3e4415bda 100644 --- a/Documentation/devicetree/bindings/mfd/brcm,bcm6368-gpio-sysctl.yaml +++ b/Documentation/devicetree/bindings/mfd/brcm,bcm6368-gpio-sysctl.yaml @@ -35,11 +35,11 @@ patternProperties: "^gpio@[0-9a-f]+$": # Child node type: object - $ref: "../gpio/brcm,bcm6345-gpio.yaml" + $ref: "../gpio/brcm,bcm63xx-gpio.yaml" description: GPIO controller for the SoC GPIOs. This child node definition should follow the bindings specified in - Documentation/devicetree/bindings/gpio/brcm,bcm6345-gpio.yaml. + Documentation/devicetree/bindings/gpio/brcm,bcm63xx-gpio.yaml. "^pinctrl@[0-9a-f]+$": # Child node diff --git a/Documentation/driver-api/gpio/legacy.rst b/Documentation/driver-api/gpio/legacy.rst index 78372853c6d4..b6505914791c 100644 --- a/Documentation/driver-api/gpio/legacy.rst +++ b/Documentation/driver-api/gpio/legacy.rst @@ -165,8 +165,7 @@ Most GPIO controllers can be accessed with memory read/write instructions. Those don't need to sleep, and can safely be done from inside hard (nonthreaded) IRQ handlers and similar contexts. -Use the following calls to access such GPIOs, -for which gpio_cansleep() will always return false (see below):: +Use the following calls to access such GPIOs:: /* GPIO INPUT: return zero or nonzero */ int gpio_get_value(unsigned gpio); @@ -200,13 +199,6 @@ Some GPIO controllers must be accessed using message based busses like I2C or SPI. Commands to read or write those GPIO values require waiting to get to the head of a queue to transmit a command and get its response. This requires sleeping, which can't be done from inside IRQ handlers. - -Platforms that support this type of GPIO distinguish them from other GPIOs -by returning nonzero from this call (which requires a valid GPIO number, -which should have been previously allocated with gpio_request):: - - int gpio_cansleep(unsigned gpio); - To access such GPIOs, a different set of accessors is defined:: /* GPIO INPUT: return zero or nonzero, might sleep */ @@ -215,7 +207,6 @@ To access such GPIOs, a different set of accessors is defined:: /* GPIO OUTPUT, might sleep */ void gpio_set_value_cansleep(unsigned gpio, int value); - Accessing such GPIOs requires a context which may sleep, for example a threaded IRQ handler, and those accessors must be used instead of spinlock-safe accessors without the cansleep() name suffix. @@ -319,11 +310,6 @@ where 'flags' is currently defined to specify the following properties: * GPIOF_INIT_LOW - as output, set initial level to LOW * GPIOF_INIT_HIGH - as output, set initial level to HIGH - * GPIOF_OPEN_DRAIN - gpio pin is open drain type. - * GPIOF_OPEN_SOURCE - gpio pin is open source type. - - * GPIOF_EXPORT_DIR_FIXED - export gpio to sysfs, keep direction - * GPIOF_EXPORT_DIR_CHANGEABLE - also export, allow changing direction since GPIOF_INIT_* are only valid when configured as output, so group valid combinations as: @@ -332,20 +318,6 @@ combinations as: * GPIOF_OUT_INIT_LOW - configured as output, initial level LOW * GPIOF_OUT_INIT_HIGH - configured as output, initial level HIGH -When setting the flag as GPIOF_OPEN_DRAIN then it will assume that pins is -open drain type. Such pins will not be driven to 1 in output mode. It is -require to connect pull-up on such pins. By enabling this flag, gpio lib will -make the direction to input when it is asked to set value of 1 in output mode -to make the pin HIGH. The pin is make to LOW by driving value 0 in output mode. - -When setting the flag as GPIOF_OPEN_SOURCE then it will assume that pins is -open source type. Such pins will not be driven to 0 in output mode. It is -require to connect pull-down on such pin. By enabling this flag, gpio lib will -make the direction to input when it is asked to set value of 0 in output mode -to make the pin LOW. The pin is make to HIGH by driving value 1 in output mode. - -In the future, these flags can be extended to support more properties. - Further more, to ease the claim/release of multiple GPIOs, 'struct gpio' is introduced to encapsulate all three fields as:: @@ -556,7 +528,6 @@ code, which always dispatches through the gpio_chip:: #define gpio_get_value __gpio_get_value #define gpio_set_value __gpio_set_value - #define gpio_cansleep __gpio_cansleep Fancier implementations could instead define those as inline functions with logic optimizing access to specific SOC-based GPIOs. For example, if the diff --git a/Documentation/translations/zh_CN/driver-api/gpio/legacy.rst b/Documentation/translations/zh_CN/driver-api/gpio/legacy.rst index 84ce2322fdba..aeccff777170 100644 --- a/Documentation/translations/zh_CN/driver-api/gpio/legacy.rst +++ b/Documentation/translations/zh_CN/driver-api/gpio/legacy.rst @@ -153,8 +153,7 @@ get/set(获取/设置)函数调用没法返回错误,且有可能是配置错误 大多数 GPIO 控制器可以通过内存读/写指令来访问。这些指令不会休眠,可以 安全地在硬(非线程)中断例程和类似的上下文中完成。 -对于那些用 gpio_cansleep()测试总是返回失败的 GPIO(见下文),使用 -以下的函数访问:: +对于那些 GPIO,使用以下的函数访问:: /* GPIO 输入:返回零或非零 */ int gpio_get_value(unsigned gpio); @@ -186,11 +185,6 @@ GPIO值是布尔值,零表示低电平,非零表示高电平。当读取一 GPIO 值的命令需要等待其信息排到队首才发送命令,再获得其反馈。期间需要 休眠,这不能在 IRQ 例程(中断上下文)中执行。 -支持此类 GPIO 的平台通过以下函数返回非零值来区分出这种 GPIO。(此函数需要 -一个之前通过 gpio_request 分配到的有效 GPIO 编号):: - - int gpio_cansleep(unsigned gpio); - 为了访问这种 GPIO,内核定义了一套不同的函数:: /* GPIO 输入:返回零或非零 ,可能会休眠 */ @@ -199,7 +193,6 @@ GPIO 值的命令需要等待其信息排到队首才发送命令,再获得其 /* GPIO 输出,可能会休眠 */ void gpio_set_value_cansleep(unsigned gpio, int value); - 访问这样的 GPIO 需要一个允许休眠的上下文,例如线程 IRQ 处理例程,并用以上的 访问函数替换那些没有 cansleep()后缀的自旋锁安全访问函数。 @@ -294,11 +287,6 @@ gpio_request()前将这类细节配置好,例如使用引脚控制子系统的 * GPIOF_INIT_LOW - 在作为输出时,初始值为低电平 * GPIOF_INIT_HIGH - 在作为输出时,初始值为高电平 - * GPIOF_OPEN_DRAIN - gpio引脚为开漏信号 - * GPIOF_OPEN_SOURCE - gpio引脚为源极开路信号 - - * GPIOF_EXPORT_DIR_FIXED - 将 gpio 导出到 sysfs,并保持方向 - * GPIOF_EXPORT_DIR_CHANGEABLE - 同样是导出, 但允许改变方向 因为 GPIOF_INIT_* 仅有在配置为输出的时候才存在,所以有效的组合为: @@ -306,18 +294,6 @@ gpio_request()前将这类细节配置好,例如使用引脚控制子系统的 * GPIOF_OUT_INIT_LOW - 配置为输出,并初始化为低电平 * GPIOF_OUT_INIT_HIGH - 配置为输出,并初始化为高电平 -当设置 flag 为 GPIOF_OPEN_DRAIN 时,则假设引脚是开漏信号。这样的引脚 -将不会在输出模式下置1。这样的引脚需要连接上拉电阻。通过使能这个标志,gpio库 -将会在被要求输出模式下置1时将引脚变为输入状态来使引脚置高。引脚在输出模式下 -通过置0使其输出低电平。 - -当设置 flag 为 GPIOF_OPEN_SOURCE 时,则假设引脚为源极开路信号。这样的引脚 -将不会在输出模式下置0。这样的引脚需要连接下拉电阻。通过使能这个标志,gpio库 -将会在被要求输出模式下置0时将引脚变为输入状态来使引脚置低。引脚在输出模式下 -通过置1使其输出高电平。 - -将来这些标志可能扩展到支持更多的属性。 - 更进一步,为了更简单地声明/释放多个 GPIO,'struct gpio'被引进来封装所有 这三个领域:: @@ -500,8 +476,8 @@ GPIO 实现者的框架(可选) 为了支持这个框架,一个平台的 Kconfig 文件将会 "select"(选择) ARCH_REQUIRE_GPIOLIB 或 ARCH_WANT_OPTIONAL_GPIOLIB,并让它的 -<asm/gpio.h> 包含 <asm-generic/gpio.h>,同时定义三个方法: -gpio_get_value()、gpio_set_value()和 gpio_cansleep()。 +<asm/gpio.h> 包含 <asm-generic/gpio.h>,同时定义两个方法: +gpio_get_value()、gpio_set_value()。 它也应提供一个 ARCH_NR_GPIOS 的定义值,这样可以更好地反映该平台 GPIO 的实际数量,节省静态表的空间。(这个定义值应该包含片上系统内建 GPIO 和 @@ -519,7 +495,6 @@ ARCH_WANT_OPTIONAL_GPIOLIB 意味着 gpiolib 核心默认关闭,且用户可以 #define gpio_get_value __gpio_get_value #define gpio_set_value __gpio_set_value - #define gpio_cansleep __gpio_cansleep 这些定义可以用更理想的实现方法替代,那就是使用经过逻辑优化的内联函数来访问 基于特定片上系统的 GPIO。例如,若引用的 GPIO (寄存器位偏移)是常量“12”, diff --git a/Documentation/translations/zh_TW/gpio.txt b/Documentation/translations/zh_TW/gpio.txt index 62e560ffe628..b93788a2628b 100644 --- a/Documentation/translations/zh_TW/gpio.txt +++ b/Documentation/translations/zh_TW/gpio.txt @@ -161,8 +161,7 @@ get/set(獲取/設置)函數調用沒法返回錯誤,且有可能是配置錯誤 大多數 GPIO 控制器可以通過內存讀/寫指令來訪問。這些指令不會休眠,可以 安全地在硬(非線程)中斷例程和類似的上下文中完成。 -對於那些用 gpio_cansleep()測試總是返回失敗的 GPIO(見下文),使用 -以下的函數訪問: +對於那些 GPIO,使用以下的函數訪問: /* GPIO 輸入:返回零或非零 */ int gpio_get_value(unsigned gpio); @@ -193,11 +192,6 @@ GPIO值是布爾值,零表示低電平,非零表示高電平。當讀取一 GPIO 值的命令需要等待其信息排到隊首才發送命令,再獲得其反饋。期間需要 休眠,這不能在 IRQ 例程(中斷上下文)中執行。 -支持此類 GPIO 的平台通過以下函數返回非零值來區分出這種 GPIO。(此函數需要 -一個之前通過 gpio_request 分配到的有效 GPIO 編號): - - int gpio_cansleep(unsigned gpio); - 爲了訪問這種 GPIO,內核定義了一套不同的函數: /* GPIO 輸入:返回零或非零 ,可能會休眠 */ @@ -206,7 +200,6 @@ GPIO 值的命令需要等待其信息排到隊首才發送命令,再獲得其 /* GPIO 輸出,可能會休眠 */ void gpio_set_value_cansleep(unsigned gpio, int value); - 訪問這樣的 GPIO 需要一個允許休眠的上下文,例如線程 IRQ 處理例程,並用以上的 訪問函數替換那些沒有 cansleep()後綴的自旋鎖安全訪問函數。 @@ -300,11 +293,6 @@ gpio_request()前將這類細節配置好,例如使用 pinctrl 子系統的映 * GPIOF_INIT_LOW - 在作爲輸出時,初始值爲低電平 * GPIOF_INIT_HIGH - 在作爲輸出時,初始值爲高電平 - * GPIOF_OPEN_DRAIN - gpio引腳爲開漏信號 - * GPIOF_OPEN_SOURCE - gpio引腳爲源極開路信號 - - * GPIOF_EXPORT_DIR_FIXED - 將 gpio 導出到 sysfs,並保持方向 - * GPIOF_EXPORT_DIR_CHANGEABLE - 同樣是導出, 但允許改變方向 因爲 GPIOF_INIT_* 僅有在配置爲輸出的時候才存在,所以有效的組合爲: @@ -312,18 +300,6 @@ gpio_request()前將這類細節配置好,例如使用 pinctrl 子系統的映 * GPIOF_OUT_INIT_LOW - 配置爲輸出,並初始化爲低電平 * GPIOF_OUT_INIT_HIGH - 配置爲輸出,並初始化爲高電平 -當設置 flag 爲 GPIOF_OPEN_DRAIN 時,則假設引腳是開漏信號。這樣的引腳 -將不會在輸出模式下置1。這樣的引腳需要連接上拉電阻。通過使能這個標誌,gpio庫 -將會在被要求輸出模式下置1時將引腳變爲輸入狀態來使引腳置高。引腳在輸出模式下 -通過置0使其輸出低電平。 - -當設置 flag 爲 GPIOF_OPEN_SOURCE 時,則假設引腳爲源極開路信號。這樣的引腳 -將不會在輸出模式下置0。這樣的引腳需要連接下拉電阻。通過使能這個標誌,gpio庫 -將會在被要求輸出模式下置0時將引腳變爲輸入狀態來使引腳置低。引腳在輸出模式下 -通過置1使其輸出高電平。 - -將來這些標誌可能擴展到支持更多的屬性。 - 更進一步,爲了更簡單地聲明/釋放多個 GPIO,'struct gpio'被引進來封裝所有 這三個領域: @@ -466,8 +442,8 @@ GPIO 實現者的框架 (可選) ------- 爲了支持這個框架,一個平台的 Kconfig 文件將會 "select"(選擇) ARCH_REQUIRE_GPIOLIB 或 ARCH_WANT_OPTIONAL_GPIOLIB,並讓它的 -<asm/gpio.h> 包含 <asm-generic/gpio.h>,同時定義三個方法: -gpio_get_value()、gpio_set_value()和 gpio_cansleep()。 +<asm/gpio.h> 包含 <asm-generic/gpio.h>,同時定義二個方法: +gpio_get_value()、gpio_set_value()。 它也應提供一個 ARCH_NR_GPIOS 的定義值,這樣可以更好地反映該平台 GPIO 的實際數量,節省靜態表的空間。(這個定義值應該包含片上系統內建 GPIO 和 @@ -485,7 +461,6 @@ ARCH_WANT_OPTIONAL_GPIOLIB 意味著 gpiolib 核心默認關閉,且用戶可以 #define gpio_get_value __gpio_get_value #define gpio_set_value __gpio_set_value - #define gpio_cansleep __gpio_cansleep 這些定義可以用更理想的實現方法替代,那就是使用經過邏輯優化的內聯函數來訪問 基於特定片上系統的 GPIO。例如,若引用的 GPIO (寄存器位偏移)是常量「12」, diff --git a/MAINTAINERS b/MAINTAINERS index 9b67a9b7438c..11ed2b8aec2a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -15502,6 +15502,7 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap.git F: arch/arm/configs/omap2plus_defconfig F: arch/arm/mach-omap2/ F: drivers/bus/ti-sysc.c +F: drivers/gpio/gpio-tps65219.c F: drivers/i2c/busses/i2c-omap.c F: drivers/irqchip/irq-omap-intc.c F: drivers/mfd/*omap*.c diff --git a/arch/arm/mach-omap1/board-ams-delta.c b/arch/arm/mach-omap1/board-ams-delta.c index 88139200449e..9808cd27e2cf 100644 --- a/arch/arm/mach-omap1/board-ams-delta.c +++ b/arch/arm/mach-omap1/board-ams-delta.c @@ -11,7 +11,6 @@ #include <linux/gpio/driver.h> #include <linux/gpio/machine.h> #include <linux/gpio/consumer.h> -#include <linux/gpio.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/input.h> diff --git a/arch/arm/mach-omap1/board-nokia770.c b/arch/arm/mach-omap1/board-nokia770.c index b56cea9f9d2f..3312ef93355d 100644 --- a/arch/arm/mach-omap1/board-nokia770.c +++ b/arch/arm/mach-omap1/board-nokia770.c @@ -6,17 +6,18 @@ */ #include <linux/clkdev.h> #include <linux/irq.h> -#include <linux/gpio.h> +#include <linux/gpio/consumer.h> #include <linux/gpio/machine.h> +#include <linux/gpio/property.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/mutex.h> #include <linux/platform_device.h> +#include <linux/property.h> #include <linux/input.h> #include <linux/omapfb.h> #include <linux/spi/spi.h> -#include <linux/spi/ads7846.h> #include <linux/workqueue.h> #include <linux/delay.h> @@ -35,6 +36,25 @@ #include "clock.h" #include "mmc.h" +static const struct software_node nokia770_mpuio_gpiochip_node = { + .name = "mpuio", +}; + +static const struct software_node nokia770_gpiochip1_node = { + .name = "gpio-0-15", +}; + +static const struct software_node nokia770_gpiochip2_node = { + .name = "gpio-16-31", +}; + +static const struct software_node *nokia770_gpiochip_nodes[] = { + &nokia770_mpuio_gpiochip_node, + &nokia770_gpiochip1_node, + &nokia770_gpiochip2_node, + NULL +}; + #define ADS7846_PENDOWN_GPIO 15 static const unsigned int nokia770_keymap[] = { @@ -85,40 +105,47 @@ static struct platform_device *nokia770_devices[] __initdata = { &nokia770_kp_device, }; -static void mipid_shutdown(struct mipid_platform_data *pdata) -{ - if (pdata->nreset_gpio != -1) { - printk(KERN_INFO "shutdown LCD\n"); - gpio_set_value(pdata->nreset_gpio, 0); - msleep(120); - } -} - -static struct mipid_platform_data nokia770_mipid_platform_data = { - .shutdown = mipid_shutdown, -}; +static struct mipid_platform_data nokia770_mipid_platform_data = { }; static const struct omap_lcd_config nokia770_lcd_config __initconst = { .ctrl_name = "hwa742", }; +static const struct property_entry nokia770_mipid_props[] = { + PROPERTY_ENTRY_GPIO("reset-gpios", &nokia770_gpiochip1_node, + 13, GPIO_ACTIVE_LOW), + { } +}; + +static const struct software_node nokia770_mipid_swnode = { + .name = "lcd_mipid", + .properties = nokia770_mipid_props, +}; + static void __init mipid_dev_init(void) { - nokia770_mipid_platform_data.nreset_gpio = 13; nokia770_mipid_platform_data.data_lines = 16; omapfb_set_lcd_config(&nokia770_lcd_config); } -static struct ads7846_platform_data nokia770_ads7846_platform_data __initdata = { - .x_max = 0x0fff, - .y_max = 0x0fff, - .x_plate_ohms = 180, - .pressure_max = 255, - .debounce_max = 10, - .debounce_tol = 3, - .debounce_rep = 1, - .gpio_pendown = ADS7846_PENDOWN_GPIO, +static const struct property_entry nokia770_ads7846_props[] = { + PROPERTY_ENTRY_STRING("compatible", "ti,ads7846"), + PROPERTY_ENTRY_U32("touchscreen-size-x", 4096), + PROPERTY_ENTRY_U32("touchscreen-size-y", 4096), + PROPERTY_ENTRY_U32("touchscreen-max-pressure", 256), + PROPERTY_ENTRY_U32("touchscreen-average-samples", 10), + PROPERTY_ENTRY_U16("ti,x-plate-ohms", 180), + PROPERTY_ENTRY_U16("ti,debounce-tol", 3), + PROPERTY_ENTRY_U16("ti,debounce-rep", 1), + PROPERTY_ENTRY_GPIO("pendown-gpios", &nokia770_gpiochip1_node, + ADS7846_PENDOWN_GPIO, GPIO_ACTIVE_LOW), + { } +}; + +static const struct software_node nokia770_ads7846_swnode = { + .name = "ads7846", + .properties = nokia770_ads7846_props, }; static struct spi_board_info nokia770_spi_board_info[] __initdata = { @@ -128,13 +155,14 @@ static struct spi_board_info nokia770_spi_board_info[] __initdata = { .chip_select = 3, .max_speed_hz = 12000000, .platform_data = &nokia770_mipid_platform_data, + .swnode = &nokia770_mipid_swnode, }, [1] = { .modalias = "ads7846", .bus_num = 2, .chip_select = 0, .max_speed_hz = 2500000, - .platform_data = &nokia770_ads7846_platform_data, + .swnode = &nokia770_ads7846_swnode, }, }; @@ -156,27 +184,23 @@ static struct omap_usb_config nokia770_usb_config __initdata = { #if IS_ENABLED(CONFIG_MMC_OMAP) -#define NOKIA770_GPIO_MMC_POWER 41 -#define NOKIA770_GPIO_MMC_SWITCH 23 - -static int nokia770_mmc_set_power(struct device *dev, int slot, int power_on, - int vdd) -{ - gpio_set_value(NOKIA770_GPIO_MMC_POWER, power_on); - return 0; -} - -static int nokia770_mmc_get_cover_state(struct device *dev, int slot) -{ - return gpio_get_value(NOKIA770_GPIO_MMC_SWITCH); -} +static struct gpiod_lookup_table nokia770_mmc_gpio_table = { + .dev_id = "mmci-omap.1", + .table = { + /* Slot index 0, VSD power, GPIO 41 */ + GPIO_LOOKUP_IDX("gpio-32-47", 9, + "vsd", 0, GPIO_ACTIVE_HIGH), + /* Slot index 0, switch, GPIO 23 */ + GPIO_LOOKUP_IDX("gpio-16-31", 7, + "cover", 0, GPIO_ACTIVE_HIGH), + { } + }, +}; static struct omap_mmc_platform_data nokia770_mmc2_data = { .nr_slots = 1, .max_freq = 12000000, .slots[0] = { - .set_power = nokia770_mmc_set_power, - .get_cover_state = nokia770_mmc_get_cover_state, .ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34, .name = "mmcblk", }, @@ -186,20 +210,7 @@ static struct omap_mmc_platform_data *nokia770_mmc_data[OMAP16XX_NR_MMC]; static void __init nokia770_mmc_init(void) { - int ret; - - ret = gpio_request(NOKIA770_GPIO_MMC_POWER, "MMC power"); - if (ret < 0) - return; - gpio_direction_output(NOKIA770_GPIO_MMC_POWER, 0); - - ret = gpio_request(NOKIA770_GPIO_MMC_SWITCH, "MMC cover"); - if (ret < 0) { - gpio_free(NOKIA770_GPIO_MMC_POWER); - return; - } - gpio_direction_input(NOKIA770_GPIO_MMC_SWITCH); - + gpiod_add_lookup_table(&nokia770_mmc_gpio_table); /* Only the second MMC controller is used */ nokia770_mmc_data[1] = &nokia770_mmc2_data; omap1_init_mmc(nokia770_mmc_data, OMAP16XX_NR_MMC); @@ -212,14 +223,16 @@ static inline void nokia770_mmc_init(void) #endif #if IS_ENABLED(CONFIG_I2C_CBUS_GPIO) -static struct gpiod_lookup_table nokia770_cbus_gpio_table = { - .dev_id = "i2c-cbus-gpio.2", - .table = { - GPIO_LOOKUP_IDX("mpuio", 9, NULL, 0, 0), /* clk */ - GPIO_LOOKUP_IDX("mpuio", 10, NULL, 1, 0), /* dat */ - GPIO_LOOKUP_IDX("mpuio", 11, NULL, 2, 0), /* sel */ - { }, - }, + +static const struct software_node_ref_args nokia770_cbus_gpio_refs[] = { + SOFTWARE_NODE_REFERENCE(&nokia770_mpuio_gpiochip_node, 9, 0), + SOFTWARE_NODE_REFERENCE(&nokia770_mpuio_gpiochip_node, 10, 0), + SOFTWARE_NODE_REFERENCE(&nokia770_mpuio_gpiochip_node, 11, 0), +}; + +static const struct property_entry nokia770_cbus_props[] = { + PROPERTY_ENTRY_REF_ARRAY("gpios", nokia770_cbus_gpio_refs), + { } }; static struct platform_device nokia770_cbus_device = { @@ -238,22 +251,29 @@ static struct i2c_board_info nokia770_i2c_board_info_2[] __initdata = { static void __init nokia770_cbus_init(void) { - const int retu_irq_gpio = 62; - const int tahvo_irq_gpio = 40; - - if (gpio_request_one(retu_irq_gpio, GPIOF_IN, "Retu IRQ")) - return; - if (gpio_request_one(tahvo_irq_gpio, GPIOF_IN, "Tahvo IRQ")) { - gpio_free(retu_irq_gpio); - return; + struct gpio_desc *d; + int irq; + + d = gpiod_get(NULL, "retu_irq", GPIOD_IN); + if (IS_ERR(d)) { + pr_err("Unable to get CBUS Retu IRQ GPIO descriptor\n"); + } else { + irq = gpiod_to_irq(d); + irq_set_irq_type(irq, IRQ_TYPE_EDGE_RISING); + nokia770_i2c_board_info_2[0].irq = irq; + } + d = gpiod_get(NULL, "tahvo_irq", GPIOD_IN); + if (IS_ERR(d)) { + pr_err("Unable to get CBUS Tahvo IRQ GPIO descriptor\n"); + } else { + irq = gpiod_to_irq(d); + irq_set_irq_type(irq, IRQ_TYPE_EDGE_RISING); + nokia770_i2c_board_info_2[1].irq = irq; } - irq_set_irq_type(gpio_to_irq(retu_irq_gpio), IRQ_TYPE_EDGE_RISING); - irq_set_irq_type(gpio_to_irq(tahvo_irq_gpio), IRQ_TYPE_EDGE_RISING); - nokia770_i2c_board_info_2[0].irq = gpio_to_irq(retu_irq_gpio); - nokia770_i2c_board_info_2[1].irq = gpio_to_irq(tahvo_irq_gpio); i2c_register_board_info(2, nokia770_i2c_board_info_2, ARRAY_SIZE(nokia770_i2c_board_info_2)); - gpiod_add_lookup_table(&nokia770_cbus_gpio_table); + device_create_managed_software_node(&nokia770_cbus_device.dev, + nokia770_cbus_props, NULL); platform_device_register(&nokia770_cbus_device); } #else /* CONFIG_I2C_CBUS_GPIO */ @@ -262,8 +282,33 @@ static void __init nokia770_cbus_init(void) } #endif /* CONFIG_I2C_CBUS_GPIO */ +static struct gpiod_lookup_table nokia770_irq_gpio_table = { + .dev_id = NULL, + .table = { + /* GPIO used by SPI device 1 */ + GPIO_LOOKUP("gpio-0-15", 15, "ads7846_irq", + GPIO_ACTIVE_HIGH), + /* GPIO used for retu IRQ */ + GPIO_LOOKUP("gpio-48-63", 15, "retu_irq", + GPIO_ACTIVE_HIGH), + /* GPIO used for tahvo IRQ */ + GPIO_LOOKUP("gpio-32-47", 8, "tahvo_irq", + GPIO_ACTIVE_HIGH), + /* GPIOs used by serial wakeup IRQs */ + GPIO_LOOKUP_IDX("gpio-32-47", 5, "wakeup", 0, + GPIO_ACTIVE_HIGH), + GPIO_LOOKUP_IDX("gpio-16-31", 2, "wakeup", 1, + GPIO_ACTIVE_HIGH), + GPIO_LOOKUP_IDX("gpio-48-63", 1, "wakeup", 2, + GPIO_ACTIVE_HIGH), + { } + }, +}; + static void __init omap_nokia770_init(void) { + struct gpio_desc *d; + /* On Nokia 770, the SleepX signal is masked with an * MPUIO line by default. It has to be unmasked for it * to become functional */ @@ -273,8 +318,16 @@ static void __init omap_nokia770_init(void) /* Unmask SleepX signal */ omap_writew((omap_readw(0xfffb5004) & ~2), 0xfffb5004); + software_node_register_node_group(nokia770_gpiochip_nodes); platform_add_devices(nokia770_devices, ARRAY_SIZE(nokia770_devices)); - nokia770_spi_board_info[1].irq = gpio_to_irq(15); + + gpiod_add_lookup_table(&nokia770_irq_gpio_table); + d = gpiod_get(NULL, "ads7846_irq", GPIOD_IN); + if (IS_ERR(d)) + pr_err("Unable to get ADS7846 IRQ GPIO descriptor\n"); + else + nokia770_spi_board_info[1].irq = gpiod_to_irq(d); + spi_register_board_info(nokia770_spi_board_info, ARRAY_SIZE(nokia770_spi_board_info)); omap_serial_init(); diff --git a/arch/arm/mach-omap1/board-osk.c b/arch/arm/mach-omap1/board-osk.c index 46eda4ff4797..7d5e6f9039d5 100644 --- a/arch/arm/mach-omap1/board-osk.c +++ b/arch/arm/mach-omap1/board-osk.c @@ -25,7 +25,8 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include <linux/gpio.h> +#include <linux/gpio/consumer.h> +#include <linux/gpio/driver.h> #include <linux/gpio/machine.h> #include <linux/kernel.h> #include <linux/init.h> @@ -64,13 +65,12 @@ /* TPS65010 has four GPIOs. nPG and LED2 can be treated like GPIOs with * alternate pin configurations for hardware-controlled blinking. */ -#define OSK_TPS_GPIO_BASE (OMAP_MAX_GPIO_LINES + 16 /* MPUIO */) -# define OSK_TPS_GPIO_USB_PWR_EN (OSK_TPS_GPIO_BASE + 0) -# define OSK_TPS_GPIO_LED_D3 (OSK_TPS_GPIO_BASE + 1) -# define OSK_TPS_GPIO_LAN_RESET (OSK_TPS_GPIO_BASE + 2) -# define OSK_TPS_GPIO_DSP_PWR_EN (OSK_TPS_GPIO_BASE + 3) -# define OSK_TPS_GPIO_LED_D9 (OSK_TPS_GPIO_BASE + 4) -# define OSK_TPS_GPIO_LED_D2 (OSK_TPS_GPIO_BASE + 5) +#define OSK_TPS_GPIO_USB_PWR_EN 0 +#define OSK_TPS_GPIO_LED_D3 1 +#define OSK_TPS_GPIO_LAN_RESET 2 +#define OSK_TPS_GPIO_DSP_PWR_EN 3 +#define OSK_TPS_GPIO_LED_D9 4 +#define OSK_TPS_GPIO_LED_D2 5 static struct mtd_partition osk_partitions[] = { /* bootloader (U-Boot, etc) in first sector */ @@ -174,11 +174,20 @@ static const struct gpio_led tps_leds[] = { /* NOTE: D9 and D2 have hardware blink support. * Also, D9 requires non-battery power. */ - { .gpio = OSK_TPS_GPIO_LED_D9, .name = "d9", - .default_trigger = "disk-activity", }, - { .gpio = OSK_TPS_GPIO_LED_D2, .name = "d2", }, - { .gpio = OSK_TPS_GPIO_LED_D3, .name = "d3", .active_low = 1, - .default_trigger = "heartbeat", }, + { .name = "d9", .default_trigger = "disk-activity", }, + { .name = "d2", }, + { .name = "d3", .default_trigger = "heartbeat", }, +}; + +static struct gpiod_lookup_table tps_leds_gpio_table = { + .dev_id = "leds-gpio", + .table = { + /* Use local offsets on TPS65010 */ + GPIO_LOOKUP_IDX("tps65010", OSK_TPS_GPIO_LED_D9, NULL, 0, GPIO_ACTIVE_HIGH), + GPIO_LOOKUP_IDX("tps65010", OSK_TPS_GPIO_LED_D2, NULL, 1, GPIO_ACTIVE_HIGH), + GPIO_LOOKUP_IDX("tps65010", OSK_TPS_GPIO_LED_D3, NULL, 2, GPIO_ACTIVE_LOW), + { } + }, }; static struct gpio_led_platform_data tps_leds_data = { @@ -192,29 +201,34 @@ static struct platform_device osk5912_tps_leds = { .dev.platform_data = &tps_leds_data, }; -static int osk_tps_setup(struct i2c_client *client, void *context) +/* The board just hold these GPIOs hogged from setup to teardown */ +static struct gpio_desc *eth_reset; +static struct gpio_desc *vdd_dsp; + +static int osk_tps_setup(struct i2c_client *client, struct gpio_chip *gc) { + struct gpio_desc *d; if (!IS_BUILTIN(CONFIG_TPS65010)) return -ENOSYS; /* Set GPIO 1 HIGH to disable VBUS power supply; * OHCI driver powers it up/down as needed. */ - gpio_request(OSK_TPS_GPIO_USB_PWR_EN, "n_vbus_en"); - gpio_direction_output(OSK_TPS_GPIO_USB_PWR_EN, 1); + d = gpiochip_request_own_desc(gc, OSK_TPS_GPIO_USB_PWR_EN, "n_vbus_en", + GPIO_ACTIVE_HIGH, GPIOD_OUT_HIGH); /* Free the GPIO again as the driver will request it */ - gpio_free(OSK_TPS_GPIO_USB_PWR_EN); + gpiochip_free_own_desc(d); /* Set GPIO 2 high so LED D3 is off by default */ tps65010_set_gpio_out_value(GPIO2, HIGH); /* Set GPIO 3 low to take ethernet out of reset */ - gpio_request(OSK_TPS_GPIO_LAN_RESET, "smc_reset"); - gpio_direction_output(OSK_TPS_GPIO_LAN_RESET, 0); + eth_reset = gpiochip_request_own_desc(gc, OSK_TPS_GPIO_LAN_RESET, "smc_reset", + GPIO_ACTIVE_HIGH, GPIOD_OUT_LOW); /* GPIO4 is VDD_DSP */ - gpio_request(OSK_TPS_GPIO_DSP_PWR_EN, "dsp_power"); - gpio_direction_output(OSK_TPS_GPIO_DSP_PWR_EN, 1); + vdd_dsp = gpiochip_request_own_desc(gc, OSK_TPS_GPIO_DSP_PWR_EN, "dsp_power", + GPIO_ACTIVE_HIGH, GPIOD_OUT_HIGH); /* REVISIT if DSP support isn't configured, power it off ... */ /* Let LED1 (D9) blink; leds-gpio may override it */ @@ -232,15 +246,22 @@ static int osk_tps_setup(struct i2c_client *client, void *context) /* register these three LEDs */ osk5912_tps_leds.dev.parent = &client->dev; + gpiod_add_lookup_table(&tps_leds_gpio_table); platform_device_register(&osk5912_tps_leds); return 0; } +static void osk_tps_teardown(struct i2c_client *client, struct gpio_chip *gc) +{ + gpiochip_free_own_desc(eth_reset); + gpiochip_free_own_desc(vdd_dsp); +} + static struct tps65010_board tps_board = { - .base = OSK_TPS_GPIO_BASE, .outmask = 0x0f, .setup = osk_tps_setup, + .teardown = osk_tps_teardown, }; static struct i2c_board_info __initdata osk_i2c_board_info[] = { @@ -263,11 +284,6 @@ static void __init osk_init_smc91x(void) { u32 l; - if ((gpio_request(0, "smc_irq")) < 0) { - printk("Error requesting gpio 0 for smc91x irq\n"); - return; - } - /* Check EMIFS wait states to fix errors with SMC_GET_PKT_HDR */ l = omap_readl(EMIFS_CCS(1)); l |= 0x3; @@ -279,10 +295,6 @@ static void __init osk_init_cf(int seg) struct resource *res = &osk5912_cf_resources[1]; omap_cfg_reg(M7_1610_GPIO62); - if ((gpio_request(62, "cf_irq")) < 0) { - printk("Error requesting gpio 62 for CF irq\n"); - return; - } switch (seg) { /* NOTE: CS0 could be configured too ... */ @@ -308,18 +320,17 @@ static void __init osk_init_cf(int seg) seg, omap_readl(EMIFS_CCS(seg)), omap_readl(EMIFS_ACS(seg))); omap_writel(0x0004a1b3, EMIFS_CCS(seg)); /* synch mode 4 etc */ omap_writel(0x00000000, EMIFS_ACS(seg)); /* OE hold/setup */ - - /* the CF I/O IRQ is really active-low */ - irq_set_irq_type(gpio_to_irq(62), IRQ_TYPE_EDGE_FALLING); } static struct gpiod_lookup_table osk_usb_gpio_table = { .dev_id = "ohci", .table = { /* Power GPIO on the I2C-attached TPS65010 */ - GPIO_LOOKUP("tps65010", 0, "power", GPIO_ACTIVE_HIGH), + GPIO_LOOKUP("tps65010", OSK_TPS_GPIO_USB_PWR_EN, "power", + GPIO_ACTIVE_HIGH), GPIO_LOOKUP(OMAP_GPIO_LABEL, 9, "overcurrent", GPIO_ACTIVE_HIGH), + { } }, }; @@ -341,8 +352,32 @@ static struct omap_usb_config osk_usb_config __initdata = { #define EMIFS_CS3_VAL (0x88013141) +static struct gpiod_lookup_table osk_irq_gpio_table = { + .dev_id = NULL, + .table = { + /* GPIO used for SMC91x IRQ */ + GPIO_LOOKUP(OMAP_GPIO_LABEL, 0, "smc_irq", + GPIO_ACTIVE_HIGH), + /* GPIO used for CF IRQ */ + GPIO_LOOKUP("gpio-48-63", 14, "cf_irq", + GPIO_ACTIVE_HIGH), + /* GPIO used by the TPS65010 chip */ + GPIO_LOOKUP("mpuio", 1, "tps65010", + GPIO_ACTIVE_HIGH), + /* GPIOs used for serial wakeup IRQs */ + GPIO_LOOKUP_IDX("gpio-32-47", 5, "wakeup", 0, + GPIO_ACTIVE_HIGH), + GPIO_LOOKUP_IDX("gpio-16-31", 2, "wakeup", 1, + GPIO_ACTIVE_HIGH), + GPIO_LOOKUP_IDX("gpio-48-63", 1, "wakeup", 2, + GPIO_ACTIVE_HIGH), + { } + }, +}; + static void __init osk_init(void) { + struct gpio_desc *d; u32 l; osk_init_smc91x(); @@ -359,10 +394,31 @@ static void __init osk_init(void) osk_flash_resource.end = osk_flash_resource.start = omap_cs3_phys(); osk_flash_resource.end += SZ_32M - 1; - osk5912_smc91x_resources[1].start = gpio_to_irq(0); - osk5912_smc91x_resources[1].end = gpio_to_irq(0); - osk5912_cf_resources[0].start = gpio_to_irq(62); - osk5912_cf_resources[0].end = gpio_to_irq(62); + + /* + * Add the GPIOs to be used as IRQs and immediately look them up + * to be passed as an IRQ resource. This is ugly but should work + * until the day we convert to device tree. + */ + gpiod_add_lookup_table(&osk_irq_gpio_table); + + d = gpiod_get(NULL, "smc_irq", GPIOD_IN); + if (IS_ERR(d)) { + pr_err("Unable to get SMC IRQ GPIO descriptor\n"); + } else { + irq_set_irq_type(gpiod_to_irq(d), IRQ_TYPE_EDGE_RISING); + osk5912_smc91x_resources[1] = DEFINE_RES_IRQ(gpiod_to_irq(d)); + } + + d = gpiod_get(NULL, "cf_irq", GPIOD_IN); + if (IS_ERR(d)) { + pr_err("Unable to get CF IRQ GPIO descriptor\n"); + } else { + /* the CF I/O IRQ is really active-low */ + irq_set_irq_type(gpiod_to_irq(d), IRQ_TYPE_EDGE_FALLING); + osk5912_cf_resources[0] = DEFINE_RES_IRQ(gpiod_to_irq(d)); + } + platform_add_devices(osk5912_devices, ARRAY_SIZE(osk5912_devices)); l = omap_readl(USB_TRANSCEIVER_CTRL); @@ -372,13 +428,15 @@ static void __init osk_init(void) gpiod_add_lookup_table(&osk_usb_gpio_table); omap1_usb_init(&osk_usb_config); + omap_serial_init(); + /* irq for tps65010 chip */ /* bootloader effectively does: omap_cfg_reg(U19_1610_MPUIO1); */ - if (gpio_request(OMAP_MPUIO(1), "tps65010") == 0) - gpio_direction_input(OMAP_MPUIO(1)); - - omap_serial_init(); - osk_i2c_board_info[0].irq = gpio_to_irq(OMAP_MPUIO(1)); + d = gpiod_get(NULL, "tps65010", GPIOD_IN); + if (IS_ERR(d)) + pr_err("Unable to get TPS65010 IRQ GPIO descriptor\n"); + else + osk_i2c_board_info[0].irq = gpiod_to_irq(d); omap_register_i2c_bus(1, 400, osk_i2c_board_info, ARRAY_SIZE(osk_i2c_board_info)); } diff --git a/arch/arm/mach-omap1/board-palmte.c b/arch/arm/mach-omap1/board-palmte.c index 91df3dc365af..7e061d671fde 100644 --- a/arch/arm/mach-omap1/board-palmte.c +++ b/arch/arm/mach-omap1/board-palmte.c @@ -13,7 +13,8 @@ * * Copyright (c) 2006 Andrzej Zaborowski <balrog@zabor.org> */ -#include <linux/gpio.h> +#include <linux/gpio/machine.h> +#include <linux/gpio/consumer.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/input.h> @@ -187,23 +188,6 @@ static struct spi_board_info palmte_spi_info[] __initdata = { }, }; -static void __init palmte_misc_gpio_setup(void) -{ - /* Set TSC2102 PINTDAV pin as input (used by TSC2102 driver) */ - if (gpio_request(PALMTE_PINTDAV_GPIO, "TSC2102 PINTDAV") < 0) { - printk(KERN_ERR "Could not reserve PINTDAV GPIO!\n"); - return; - } - gpio_direction_input(PALMTE_PINTDAV_GPIO); - - /* Set USB-or-DC-IN pin as input (unused) */ - if (gpio_request(PALMTE_USB_OR_DC_GPIO, "USB/DC-IN") < 0) { - printk(KERN_ERR "Could not reserve cable signal GPIO!\n"); - return; - } - gpio_direction_input(PALMTE_USB_OR_DC_GPIO); -} - #if IS_ENABLED(CONFIG_MMC_OMAP) static struct omap_mmc_platform_data _palmte_mmc_config = { @@ -231,8 +215,23 @@ static void palmte_mmc_init(void) #endif /* CONFIG_MMC_OMAP */ +static struct gpiod_lookup_table palmte_irq_gpio_table = { + .dev_id = NULL, + .table = { + /* GPIO used for TSC2102 PINTDAV IRQ */ + GPIO_LOOKUP("gpio-0-15", PALMTE_PINTDAV_GPIO, "tsc2102_irq", + GPIO_ACTIVE_HIGH), + /* GPIO used for USB or DC input detection */ + GPIO_LOOKUP("gpio-0-15", PALMTE_USB_OR_DC_GPIO, "usb_dc_irq", + GPIO_ACTIVE_HIGH), + { } + }, +}; + static void __init omap_palmte_init(void) { + struct gpio_desc *d; + /* mux pins for uarts */ omap_cfg_reg(UART1_TX); omap_cfg_reg(UART1_RTS); @@ -243,9 +242,21 @@ static void __init omap_palmte_init(void) platform_add_devices(palmte_devices, ARRAY_SIZE(palmte_devices)); - palmte_spi_info[0].irq = gpio_to_irq(PALMTE_PINTDAV_GPIO); + gpiod_add_lookup_table(&palmte_irq_gpio_table); + d = gpiod_get(NULL, "tsc2102_irq", GPIOD_IN); + if (IS_ERR(d)) + pr_err("Unable to get TSC2102 IRQ GPIO descriptor\n"); + else + palmte_spi_info[0].irq = gpiod_to_irq(d); spi_register_board_info(palmte_spi_info, ARRAY_SIZE(palmte_spi_info)); - palmte_misc_gpio_setup(); + + /* We are getting this just to set it up as input */ + d = gpiod_get(NULL, "usb_dc_irq", GPIOD_IN); + if (IS_ERR(d)) + pr_err("Unable to get USB/DC IRQ GPIO descriptor\n"); + else + gpiod_put(d); + omap_serial_init(); omap1_usb_init(&palmte_usb_config); omap_register_i2c_bus(1, 100, NULL, 0); diff --git a/arch/arm/mach-omap1/board-sx1-mmc.c b/arch/arm/mach-omap1/board-sx1-mmc.c index f1c160924dfe..f183a8448a7b 100644 --- a/arch/arm/mach-omap1/board-sx1-mmc.c +++ b/arch/arm/mach-omap1/board-sx1-mmc.c @@ -9,7 +9,6 @@ * Copyright (C) 2007 Instituto Nokia de Tecnologia - INdT */ -#include <linux/gpio.h> #include <linux/platform_device.h> #include "hardware.h" diff --git a/arch/arm/mach-omap1/board-sx1.c b/arch/arm/mach-omap1/board-sx1.c index 3ae295af96fd..b869c7ba1a1b 100644 --- a/arch/arm/mach-omap1/board-sx1.c +++ b/arch/arm/mach-omap1/board-sx1.c @@ -11,7 +11,8 @@ * Maintainters : Vladimir Ananiev (aka Vovan888), Sergge * oslik.ru */ -#include <linux/gpio.h> +#include <linux/gpio/machine.h> +#include <linux/gpio/consumer.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/input.h> @@ -304,8 +305,23 @@ static struct platform_device *sx1_devices[] __initdata = { /*-----------------------------------------*/ +static struct gpiod_lookup_table sx1_gpio_table = { + .dev_id = NULL, + .table = { + GPIO_LOOKUP("gpio-0-15", 1, "irda_off", + GPIO_ACTIVE_HIGH), + GPIO_LOOKUP("gpio-0-15", 11, "switch", + GPIO_ACTIVE_HIGH), + GPIO_LOOKUP("gpio-0-15", 15, "usb_on", + GPIO_ACTIVE_HIGH), + { } + }, +}; + static void __init omap_sx1_init(void) { + struct gpio_desc *d; + /* mux pins for uarts */ omap_cfg_reg(UART1_TX); omap_cfg_reg(UART1_RTS); @@ -320,15 +336,25 @@ static void __init omap_sx1_init(void) omap_register_i2c_bus(1, 100, NULL, 0); omap1_usb_init(&sx1_usb_config); sx1_mmc_init(); + gpiod_add_lookup_table(&sx1_gpio_table); /* turn on USB power */ /* sx1_setusbpower(1); can't do it here because i2c is not ready */ - gpio_request(1, "A_IRDA_OFF"); - gpio_request(11, "A_SWITCH"); - gpio_request(15, "A_USB_ON"); - gpio_direction_output(1, 1); /*A_IRDA_OFF = 1 */ - gpio_direction_output(11, 0); /*A_SWITCH = 0 */ - gpio_direction_output(15, 0); /*A_USB_ON = 0 */ + d = gpiod_get(NULL, "irda_off", GPIOD_OUT_HIGH); + if (IS_ERR(d)) + pr_err("Unable to get IRDA OFF GPIO descriptor\n"); + else + gpiod_put(d); + d = gpiod_get(NULL, "switch", GPIOD_OUT_LOW); + if (IS_ERR(d)) + pr_err("Unable to get SWITCH GPIO descriptor\n"); + else + gpiod_put(d); + d = gpiod_get(NULL, "usb_on", GPIOD_OUT_LOW); + if (IS_ERR(d)) + pr_err("Unable to get USB ON GPIO descriptor\n"); + else + gpiod_put(d); omapfb_set_lcd_config(&sx1_lcd_config); } diff --git a/arch/arm/mach-omap1/devices.c b/arch/arm/mach-omap1/devices.c index 5304699c7a97..8b2c5f911e97 100644 --- a/arch/arm/mach-omap1/devices.c +++ b/arch/arm/mach-omap1/devices.c @@ -6,7 +6,6 @@ */ #include <linux/dma-mapping.h> -#include <linux/gpio.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> diff --git a/arch/arm/mach-omap1/gpio15xx.c b/arch/arm/mach-omap1/gpio15xx.c index 61fa26efd865..6724af4925f2 100644 --- a/arch/arm/mach-omap1/gpio15xx.c +++ b/arch/arm/mach-omap1/gpio15xx.c @@ -8,7 +8,6 @@ * Charulatha V <charu@ti.com> */ -#include <linux/gpio.h> #include <linux/platform_data/gpio-omap.h> #include <linux/soc/ti/omap1-soc.h> #include <asm/irq.h> diff --git a/arch/arm/mach-omap1/gpio16xx.c b/arch/arm/mach-omap1/gpio16xx.c index cf052714b3f8..55acec22fef4 100644 --- a/arch/arm/mach-omap1/gpio16xx.c +++ b/arch/arm/mach-omap1/gpio16xx.c @@ -8,7 +8,6 @@ * Charulatha V <charu@ti.com> */ -#include <linux/gpio.h> #include <linux/platform_data/gpio-omap.h> #include <linux/soc/ti/omap1-io.h> diff --git a/arch/arm/mach-omap1/irq.c b/arch/arm/mach-omap1/irq.c index 3d9e72e1eddc..9b587ecebb1c 100644 --- a/arch/arm/mach-omap1/irq.c +++ b/arch/arm/mach-omap1/irq.c @@ -35,7 +35,6 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include <linux/gpio.h> #include <linux/init.h> #include <linux/irq.h> #include <linux/module.h> diff --git a/arch/arm/mach-omap1/serial.c b/arch/arm/mach-omap1/serial.c index c7f590645774..3adceb97138f 100644 --- a/arch/arm/mach-omap1/serial.c +++ b/arch/arm/mach-omap1/serial.c @@ -4,7 +4,8 @@ * * OMAP1 serial support. */ -#include <linux/gpio.h> +#include <linux/gpio/machine.h> +#include <linux/gpio/consumer.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> @@ -196,39 +197,38 @@ void omap_serial_wake_trigger(int enable) } } -static void __init omap_serial_set_port_wakeup(int gpio_nr) +static void __init omap_serial_set_port_wakeup(int idx) { + struct gpio_desc *d; int ret; - ret = gpio_request(gpio_nr, "UART wake"); - if (ret < 0) { - printk(KERN_ERR "Could not request UART wake GPIO: %i\n", - gpio_nr); + d = gpiod_get_index(NULL, "wakeup", idx, GPIOD_IN); + if (IS_ERR(d)) { + pr_err("Unable to get UART wakeup GPIO descriptor\n"); return; } - gpio_direction_input(gpio_nr); - ret = request_irq(gpio_to_irq(gpio_nr), &omap_serial_wake_interrupt, + ret = request_irq(gpiod_to_irq(d), &omap_serial_wake_interrupt, IRQF_TRIGGER_RISING, "serial wakeup", NULL); if (ret) { - gpio_free(gpio_nr); - printk(KERN_ERR "No interrupt for UART wake GPIO: %i\n", - gpio_nr); + gpiod_put(d); + pr_err("No interrupt for UART%d wake GPIO\n", idx + 1); return; } - enable_irq_wake(gpio_to_irq(gpio_nr)); + enable_irq_wake(gpiod_to_irq(d)); } + int __init omap_serial_wakeup_init(void) { if (!cpu_is_omap16xx()) return 0; if (uart1_ck != NULL) - omap_serial_set_port_wakeup(37); + omap_serial_set_port_wakeup(0); if (uart2_ck != NULL) - omap_serial_set_port_wakeup(18); + omap_serial_set_port_wakeup(1); if (uart3_ck != NULL) - omap_serial_set_port_wakeup(49); + omap_serial_set_port_wakeup(2); return 0; } diff --git a/arch/arm/mach-omap2/board-n8x0.c b/arch/arm/mach-omap2/board-n8x0.c index 3353b0a923d9..564bf80a2621 100644 --- a/arch/arm/mach-omap2/board-n8x0.c +++ b/arch/arm/mach-omap2/board-n8x0.c @@ -10,7 +10,8 @@ #include <linux/clk.h> #include <linux/delay.h> -#include <linux/gpio.h> +#include <linux/gpio/machine.h> +#include <linux/gpio/consumer.h> #include <linux/init.h> #include <linux/io.h> #include <linux/irq.h> @@ -28,13 +29,12 @@ #include "common.h" #include "mmc.h" +#include "usb-tusb6010.h" #include "soc.h" #include "common-board-devices.h" #define TUSB6010_ASYNC_CS 1 #define TUSB6010_SYNC_CS 4 -#define TUSB6010_GPIO_INT 58 -#define TUSB6010_GPIO_ENABLE 0 #define TUSB6010_DMACHAN 0x3f #define NOKIA_N810_WIMAX (1 << 2) @@ -61,37 +61,6 @@ static void board_check_revision(void) } #if IS_ENABLED(CONFIG_USB_MUSB_TUSB6010) -/* - * Enable or disable power to TUSB6010. When enabling, turn on 3.3 V and - * 1.5 V voltage regulators of PM companion chip. Companion chip will then - * provide then PGOOD signal to TUSB6010 which will release it from reset. - */ -static int tusb_set_power(int state) -{ - int i, retval = 0; - - if (state) { - gpio_set_value(TUSB6010_GPIO_ENABLE, 1); - msleep(1); - - /* Wait until TUSB6010 pulls INT pin down */ - i = 100; - while (i && gpio_get_value(TUSB6010_GPIO_INT)) { - msleep(1); - i--; - } - - if (!i) { - printk(KERN_ERR "tusb: powerup failed\n"); - retval = -ENODEV; - } - } else { - gpio_set_value(TUSB6010_GPIO_ENABLE, 0); - msleep(10); - } - - return retval; -} static struct musb_hdrc_config musb_config = { .multipoint = 1, @@ -102,39 +71,36 @@ static struct musb_hdrc_config musb_config = { static struct musb_hdrc_platform_data tusb_data = { .mode = MUSB_OTG, - .set_power = tusb_set_power, .min_power = 25, /* x2 = 50 mA drawn from VBUS as peripheral */ .power = 100, /* Max 100 mA VBUS for host mode */ .config = &musb_config, }; +static struct gpiod_lookup_table tusb_gpio_table = { + .dev_id = "musb-tusb", + .table = { + GPIO_LOOKUP("gpio-0-15", 0, "enable", + GPIO_ACTIVE_HIGH), + GPIO_LOOKUP("gpio-48-63", 10, "int", + GPIO_ACTIVE_HIGH), + { } + }, +}; + static void __init n8x0_usb_init(void) { int ret = 0; - static const char announce[] __initconst = KERN_INFO "TUSB 6010\n"; - - /* PM companion chip power control pin */ - ret = gpio_request_one(TUSB6010_GPIO_ENABLE, GPIOF_OUT_INIT_LOW, - "TUSB6010 enable"); - if (ret != 0) { - printk(KERN_ERR "Could not get TUSB power GPIO%i\n", - TUSB6010_GPIO_ENABLE); - return; - } - tusb_set_power(0); + gpiod_add_lookup_table(&tusb_gpio_table); ret = tusb6010_setup_interface(&tusb_data, TUSB6010_REFCLK_19, 2, - TUSB6010_ASYNC_CS, TUSB6010_SYNC_CS, - TUSB6010_GPIO_INT, TUSB6010_DMACHAN); + TUSB6010_ASYNC_CS, TUSB6010_SYNC_CS, + TUSB6010_DMACHAN); if (ret != 0) - goto err; + return; - printk(announce); + pr_info("TUSB 6010\n"); return; - -err: - gpio_free(TUSB6010_GPIO_ENABLE); } #else @@ -170,22 +136,32 @@ static struct spi_board_info n800_spi_board_info[] __initdata = { * GPIO23 and GPIO9 slot 2 EMMC on N810 * */ -#define N8X0_SLOT_SWITCH_GPIO 96 -#define N810_EMMC_VSD_GPIO 23 -#define N810_EMMC_VIO_GPIO 9 - static int slot1_cover_open; static int slot2_cover_open; static struct device *mmc_device; -static int n8x0_mmc_switch_slot(struct device *dev, int slot) -{ -#ifdef CONFIG_MMC_DEBUG - dev_dbg(dev, "Choose slot %d\n", slot + 1); -#endif - gpio_set_value(N8X0_SLOT_SWITCH_GPIO, slot); - return 0; -} +static struct gpiod_lookup_table nokia8xx_mmc_gpio_table = { + .dev_id = "mmci-omap.0", + .table = { + /* Slot switch, GPIO 96 */ + GPIO_LOOKUP("gpio-80-111", 16, + "switch", GPIO_ACTIVE_HIGH), + { } + }, +}; + +static struct gpiod_lookup_table nokia810_mmc_gpio_table = { + .dev_id = "mmci-omap.0", + .table = { + /* Slot index 1, VSD power, GPIO 23 */ + GPIO_LOOKUP_IDX("gpio-16-31", 7, + "vsd", 1, GPIO_ACTIVE_HIGH), + /* Slot index 1, VIO power, GPIO 9 */ + GPIO_LOOKUP_IDX("gpio-0-15", 9, + "vsd", 1, GPIO_ACTIVE_HIGH), + { } + }, +}; static int n8x0_mmc_set_power_menelaus(struct device *dev, int slot, int power_on, int vdd) @@ -256,31 +232,13 @@ static int n8x0_mmc_set_power_menelaus(struct device *dev, int slot, return 0; } -static void n810_set_power_emmc(struct device *dev, - int power_on) -{ - dev_dbg(dev, "Set EMMC power %s\n", power_on ? "on" : "off"); - - if (power_on) { - gpio_set_value(N810_EMMC_VSD_GPIO, 1); - msleep(1); - gpio_set_value(N810_EMMC_VIO_GPIO, 1); - msleep(1); - } else { - gpio_set_value(N810_EMMC_VIO_GPIO, 0); - msleep(50); - gpio_set_value(N810_EMMC_VSD_GPIO, 0); - msleep(50); - } -} - static int n8x0_mmc_set_power(struct device *dev, int slot, int power_on, int vdd) { if (board_is_n800() || slot == 0) return n8x0_mmc_set_power_menelaus(dev, slot, power_on, vdd); - n810_set_power_emmc(dev, power_on); + /* The n810 power will be handled by GPIO code in the driver */ return 0; } @@ -418,13 +376,6 @@ static void n8x0_mmc_shutdown(struct device *dev) static void n8x0_mmc_cleanup(struct device *dev) { menelaus_unregister_mmc_callback(); - - gpio_free(N8X0_SLOT_SWITCH_GPIO); - - if (board_is_n810()) { - gpio_free(N810_EMMC_VSD_GPIO); - gpio_free(N810_EMMC_VIO_GPIO); - } } /* @@ -433,7 +384,6 @@ static void n8x0_mmc_cleanup(struct device *dev) */ static struct omap_mmc_platform_data mmc1_data = { .nr_slots = 0, - .switch_slot = n8x0_mmc_switch_slot, .init = n8x0_mmc_late_init, .cleanup = n8x0_mmc_cleanup, .shutdown = n8x0_mmc_shutdown, @@ -463,14 +413,9 @@ static struct omap_mmc_platform_data mmc1_data = { static struct omap_mmc_platform_data *mmc_data[OMAP24XX_NR_MMC]; -static struct gpio n810_emmc_gpios[] __initdata = { - { N810_EMMC_VSD_GPIO, GPIOF_OUT_INIT_LOW, "MMC slot 2 Vddf" }, - { N810_EMMC_VIO_GPIO, GPIOF_OUT_INIT_LOW, "MMC slot 2 Vdd" }, -}; - static void __init n8x0_mmc_init(void) { - int err; + gpiod_add_lookup_table(&nokia8xx_mmc_gpio_table); if (board_is_n810()) { mmc1_data.slots[0].name = "external"; @@ -483,20 +428,7 @@ static void __init n8x0_mmc_init(void) */ mmc1_data.slots[1].name = "internal"; mmc1_data.slots[1].ban_openended = 1; - } - - err = gpio_request_one(N8X0_SLOT_SWITCH_GPIO, GPIOF_OUT_INIT_LOW, - "MMC slot switch"); - if (err) - return; - - if (board_is_n810()) { - err = gpio_request_array(n810_emmc_gpios, - ARRAY_SIZE(n810_emmc_gpios)); - if (err) { - gpio_free(N8X0_SLOT_SWITCH_GPIO); - return; - } + gpiod_add_lookup_table(&nokia810_mmc_gpio_table); } mmc1_data.nr_slots = 2; diff --git a/arch/arm/mach-omap2/omap_device.c b/arch/arm/mach-omap2/omap_device.c index 4afa2f08e668..fca7869c8075 100644 --- a/arch/arm/mach-omap2/omap_device.c +++ b/arch/arm/mach-omap2/omap_device.c @@ -244,7 +244,6 @@ static int _omap_device_notifier_call(struct notifier_block *nb, case BUS_NOTIFY_ADD_DEVICE: if (pdev->dev.of_node) omap_device_build_from_dt(pdev); - omap_auxdata_legacy_init(dev); fallthrough; default: od = to_omap_device(pdev); diff --git a/arch/arm/mach-omap2/pdata-quirks.c b/arch/arm/mach-omap2/pdata-quirks.c index 04208cc52784..c1c0121f478d 100644 --- a/arch/arm/mach-omap2/pdata-quirks.c +++ b/arch/arm/mach-omap2/pdata-quirks.c @@ -6,8 +6,8 @@ */ #include <linux/clk.h> #include <linux/davinci_emac.h> +#include <linux/gpio/machine.h> #include <linux/gpio/consumer.h> -#include <linux/gpio.h> #include <linux/init.h> #include <linux/kernel.h> #include <linux/of_platform.h> @@ -41,7 +41,6 @@ struct pdata_init { }; static struct of_dev_auxdata omap_auxdata_lookup[]; -static struct twl4030_gpio_platform_data twl_gpio_auxdata; #ifdef CONFIG_MACH_NOKIA_N8X0 static void __init omap2420_n8x0_legacy_init(void) @@ -98,52 +97,43 @@ static struct iommu_platform_data omap3_iommu_isp_pdata = { }; #endif -static int omap3_sbc_t3730_twl_callback(struct device *dev, - unsigned gpio, - unsigned ngpio) +static void __init omap3_sbc_t3x_usb_hub_init(char *hub_name, int idx) { - int res; + struct gpio_desc *d; - res = gpio_request_one(gpio + 2, GPIOF_OUT_INIT_HIGH, - "wlan pwr"); - if (res) - return res; - - gpiod_export(gpio_to_desc(gpio), 0); - - return 0; -} - -static void __init omap3_sbc_t3x_usb_hub_init(int gpio, char *hub_name) -{ - int err = gpio_request_one(gpio, GPIOF_OUT_INIT_LOW, hub_name); - - if (err) { - pr_err("SBC-T3x: %s reset gpio request failed: %d\n", - hub_name, err); + /* This asserts the RESET line (reverse polarity) */ + d = gpiod_get_index(NULL, "reset", idx, GPIOD_OUT_HIGH); + if (IS_ERR(d)) { + pr_err("Unable to get T3x USB reset GPIO descriptor\n"); return; } - - gpiod_export(gpio_to_desc(gpio), 0); - + gpiod_set_consumer_name(d, hub_name); + gpiod_export(d, 0); udelay(10); - gpio_set_value(gpio, 1); + /* De-assert RESET */ + gpiod_set_value(d, 0); msleep(1); } -static void __init omap3_sbc_t3730_twl_init(void) -{ - twl_gpio_auxdata.setup = omap3_sbc_t3730_twl_callback; -} +static struct gpiod_lookup_table omap3_sbc_t3x_usb_gpio_table = { + .dev_id = NULL, + .table = { + GPIO_LOOKUP_IDX("gpio-160-175", 7, "reset", 0, + GPIO_ACTIVE_LOW), + { } + }, +}; static void __init omap3_sbc_t3730_legacy_init(void) { - omap3_sbc_t3x_usb_hub_init(167, "sb-t35 usb hub"); + gpiod_add_lookup_table(&omap3_sbc_t3x_usb_gpio_table); + omap3_sbc_t3x_usb_hub_init("sb-t35 usb hub", 0); } static void __init omap3_sbc_t3530_legacy_init(void) { - omap3_sbc_t3x_usb_hub_init(167, "sb-t35 usb hub"); + gpiod_add_lookup_table(&omap3_sbc_t3x_usb_gpio_table); + omap3_sbc_t3x_usb_hub_init("sb-t35 usb hub", 0); } static void __init omap3_evm_legacy_init(void) @@ -187,31 +177,59 @@ static void __init am35xx_emac_reset(void) omap_ctrl_readl(AM35XX_CONTROL_IP_SW_RESET); /* OCP barrier */ } -static struct gpio cm_t3517_wlan_gpios[] __initdata = { - { 56, GPIOF_OUT_INIT_HIGH, "wlan pwr" }, - { 4, GPIOF_OUT_INIT_HIGH, "xcvr noe" }, +static struct gpiod_lookup_table cm_t3517_wlan_gpio_table = { + .dev_id = NULL, + .table = { + GPIO_LOOKUP("gpio-48-53", 8, "power", + GPIO_ACTIVE_HIGH), + GPIO_LOOKUP("gpio-0-15", 4, "noe", + GPIO_ACTIVE_HIGH), + { } + }, }; static void __init omap3_sbc_t3517_wifi_init(void) { - int err = gpio_request_array(cm_t3517_wlan_gpios, - ARRAY_SIZE(cm_t3517_wlan_gpios)); - if (err) { - pr_err("SBC-T3517: wl12xx gpios request failed: %d\n", err); - return; - } + struct gpio_desc *d; + + gpiod_add_lookup_table(&cm_t3517_wlan_gpio_table); - gpiod_export(gpio_to_desc(cm_t3517_wlan_gpios[0].gpio), 0); - gpiod_export(gpio_to_desc(cm_t3517_wlan_gpios[1].gpio), 0); + /* This asserts the RESET line (reverse polarity) */ + d = gpiod_get(NULL, "power", GPIOD_OUT_HIGH); + if (IS_ERR(d)) { + pr_err("Unable to get CM T3517 WLAN power GPIO descriptor\n"); + } else { + gpiod_set_consumer_name(d, "wlan pwr"); + gpiod_export(d, 0); + } + d = gpiod_get(NULL, "noe", GPIOD_OUT_HIGH); + if (IS_ERR(d)) { + pr_err("Unable to get CM T3517 WLAN XCVR NOE GPIO descriptor\n"); + } else { + gpiod_set_consumer_name(d, "xcvr noe"); + gpiod_export(d, 0); + } msleep(100); - gpio_set_value(cm_t3517_wlan_gpios[1].gpio, 0); -} + gpiod_set_value(d, 0); +} + +static struct gpiod_lookup_table omap3_sbc_t3517_usb_gpio_table = { + .dev_id = NULL, + .table = { + GPIO_LOOKUP_IDX("gpio-144-159", 8, "reset", 0, + GPIO_ACTIVE_LOW), + GPIO_LOOKUP_IDX("gpio-96-111", 2, "reset", 1, + GPIO_ACTIVE_LOW), + { } + }, +}; static void __init omap3_sbc_t3517_legacy_init(void) { - omap3_sbc_t3x_usb_hub_init(152, "cm-t3517 usb hub"); - omap3_sbc_t3x_usb_hub_init(98, "sb-t35 usb hub"); + gpiod_add_lookup_table(&omap3_sbc_t3517_usb_gpio_table); + omap3_sbc_t3x_usb_hub_init("cm-t3517 usb hub", 0); + omap3_sbc_t3x_usb_hub_init("sb-t35 usb hub", 1); am35xx_emac_reset(); hsmmc2_internal_input_clk(); omap3_sbc_t3517_wifi_init(); @@ -393,21 +411,6 @@ static struct ti_prm_platform_data ti_prm_pdata = { .clkdm_lookup = clkdm_lookup, }; -/* - * GPIOs for TWL are initialized by the I2C bus and need custom - * handing until DSS has device tree bindings. - */ -void omap_auxdata_legacy_init(struct device *dev) -{ - if (dev->platform_data) - return; - - if (strcmp("twl4030-gpio", dev_name(dev))) - return; - - dev->platform_data = &twl_gpio_auxdata; -} - #if defined(CONFIG_ARCH_OMAP3) && IS_ENABLED(CONFIG_SND_SOC_OMAP_MCBSP) static struct omap_mcbsp_platform_data mcbsp_pdata; static void __init omap3_mcbsp_init(void) @@ -428,9 +431,6 @@ static struct pdata_init auxdata_quirks[] __initdata = { { "nokia,n810", omap2420_n8x0_legacy_init, }, { "nokia,n810-wimax", omap2420_n8x0_legacy_init, }, #endif -#ifdef CONFIG_ARCH_OMAP3 - { "compulab,omap3-sbc-t3730", omap3_sbc_t3730_twl_init, }, -#endif { /* sentinel */ }, }; diff --git a/arch/arm/mach-omap2/usb-tusb6010.c b/arch/arm/mach-omap2/usb-tusb6010.c index 18fa52f828dc..b46c254c2bc4 100644 --- a/arch/arm/mach-omap2/usb-tusb6010.c +++ b/arch/arm/mach-omap2/usb-tusb6010.c @@ -11,12 +11,12 @@ #include <linux/errno.h> #include <linux/delay.h> #include <linux/platform_device.h> -#include <linux/gpio.h> #include <linux/export.h> #include <linux/platform_data/usb-omap.h> #include <linux/usb/musb.h> +#include "usb-tusb6010.h" #include "gpmc.h" static u8 async_cs, sync_cs; @@ -132,10 +132,6 @@ static struct resource tusb_resources[] = { { /* Synchronous access */ .flags = IORESOURCE_MEM, }, - { /* IRQ */ - .name = "mc", - .flags = IORESOURCE_IRQ, - }, }; static u64 tusb_dmamask = ~(u32)0; @@ -154,9 +150,9 @@ static struct platform_device tusb_device = { /* this may be called only from board-*.c setup code */ int __init tusb6010_setup_interface(struct musb_hdrc_platform_data *data, - unsigned ps_refclk, unsigned waitpin, - unsigned async, unsigned sync, - unsigned irq, unsigned dmachan) + unsigned int ps_refclk, unsigned int waitpin, + unsigned int async, unsigned int sync, + unsigned int dmachan) { int status; static char error[] __initdata = @@ -192,14 +188,6 @@ int __init tusb6010_setup_interface(struct musb_hdrc_platform_data *data, if (status < 0) return status; - /* IRQ */ - status = gpio_request_one(irq, GPIOF_IN, "TUSB6010 irq"); - if (status < 0) { - printk(error, 3, status); - return status; - } - tusb_resources[2].start = gpio_to_irq(irq); - /* set up memory timings ... can speed them up later */ if (!ps_refclk) { printk(error, 4, status); diff --git a/arch/arm/mach-omap2/usb-tusb6010.h b/arch/arm/mach-omap2/usb-tusb6010.h new file mode 100644 index 000000000000..d210ff6238c2 --- /dev/null +++ b/arch/arm/mach-omap2/usb-tusb6010.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef __USB_TUSB6010_H +#define __USB_TUSB6010_H + +extern int __init tusb6010_setup_interface( + struct musb_hdrc_platform_data *data, + unsigned int ps_refclk, unsigned int waitpin, + unsigned int async_cs, unsigned int sync_cs, + unsigned int dmachan); + +#endif /* __USB_TUSB6010_H */ diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c index 042922a0a9d6..d01ea54b0b78 100644 --- a/arch/arm/mach-pxa/spitz.c +++ b/arch/arm/mach-pxa/spitz.c @@ -506,10 +506,18 @@ static struct ads7846_platform_data spitz_ads7846_info = { .x_plate_ohms = 419, .y_plate_ohms = 486, .pressure_max = 1024, - .gpio_pendown = SPITZ_GPIO_TP_INT, .wait_for_sync = spitz_ads7846_wait_for_hsync, }; +static struct gpiod_lookup_table spitz_ads7846_gpio_table = { + .dev_id = "spi2.0", + .table = { + GPIO_LOOKUP("gpio-pxa", SPITZ_GPIO_TP_INT, + "pendown", GPIO_ACTIVE_LOW), + { } + }, +}; + static void spitz_bl_kick_battery(void) { void (*kick_batt)(void); @@ -594,6 +602,7 @@ static void __init spitz_spi_init(void) else gpiod_add_lookup_table(&spitz_lcdcon_gpio_table); + gpiod_add_lookup_table(&spitz_ads7846_gpio_table); gpiod_add_lookup_table(&spitz_spi_gpio_table); pxa2xx_set_spi_info(2, &spitz_spi_info); spi_register_board_info(ARRAY_AND_SIZE(spitz_spi_devices)); diff --git a/arch/m68k/include/asm/mcfgpio.h b/arch/m68k/include/asm/mcfgpio.h index 2cefe8445980..7abd322c019f 100644 --- a/arch/m68k/include/asm/mcfgpio.h +++ b/arch/m68k/include/asm/mcfgpio.h @@ -34,14 +34,6 @@ static inline void __gpio_set_value(unsigned gpio, int value) __mcfgpio_set_value(gpio, value); } -static inline int __gpio_cansleep(unsigned gpio) -{ - if (gpio < MCFGPIO_PIN_MAX) - return 0; - else - return -EINVAL; -} - static inline int __gpio_to_irq(unsigned gpio) { return -EINVAL; diff --git a/arch/mips/alchemy/devboards/db1000.c b/arch/mips/alchemy/devboards/db1000.c index 2c52ee27b4f2..79d66faa8482 100644 --- a/arch/mips/alchemy/devboards/db1000.c +++ b/arch/mips/alchemy/devboards/db1000.c @@ -381,13 +381,21 @@ static struct platform_device db1100_mmc1_dev = { static struct ads7846_platform_data db1100_touch_pd = { .model = 7846, .vref_mv = 3300, - .gpio_pendown = 21, }; static struct spi_gpio_platform_data db1100_spictl_pd = { .num_chipselect = 1, }; +static struct gpiod_lookup_table db1100_touch_gpio_table = { + .dev_id = "spi0.0", + .table = { + GPIO_LOOKUP("alchemy-gpio2", 21, + "pendown", GPIO_ACTIVE_LOW), + { } + }, +}; + static struct spi_board_info db1100_spi_info[] __initdata = { [0] = { .modalias = "ads7846", @@ -474,6 +482,7 @@ int __init db1000_dev_setup(void) pfc |= (1 << 0); /* SSI0 pins as GPIOs */ alchemy_wrsys(pfc, AU1000_SYS_PINFUNC); + gpiod_add_lookup_table(&db1100_touch_gpio_table); spi_register_board_info(db1100_spi_info, ARRAY_SIZE(db1100_spi_info)); diff --git a/arch/mips/include/asm/mach-au1x00/gpio-au1000.h b/arch/mips/include/asm/mach-au1x00/gpio-au1000.h index adde1fa5097e..82bc2766e2ec 100644 --- a/arch/mips/include/asm/mach-au1x00/gpio-au1000.h +++ b/arch/mips/include/asm/mach-au1x00/gpio-au1000.h @@ -500,11 +500,6 @@ static inline int alchemy_gpio_is_valid(int gpio) alchemy_gpio1_is_valid(gpio); } -static inline int alchemy_gpio_cansleep(int gpio) -{ - return 0; /* Alchemy never gets tired */ -} - static inline int alchemy_gpio_to_irq(int gpio) { return (gpio >= ALCHEMY_GPIO2_BASE) ? diff --git a/arch/mips/include/asm/mach-au1x00/gpio-au1300.h b/arch/mips/include/asm/mach-au1x00/gpio-au1300.h index d16add7ba49d..43d44f384f97 100644 --- a/arch/mips/include/asm/mach-au1x00/gpio-au1300.h +++ b/arch/mips/include/asm/mach-au1x00/gpio-au1300.h @@ -98,11 +98,6 @@ static inline int au1300_gpio_is_valid(unsigned int gpio) return ret; } -static inline int au1300_gpio_cansleep(unsigned int gpio) -{ - return 0; -} - /* hardware remembers gpio 0-63 levels on powerup */ static inline int au1300_gpio_getinitlvl(unsigned int gpio) { diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index f45c6a36551c..e382dfebad7c 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -704,18 +704,6 @@ config GPIO_VISCONTI help Say yes here to support GPIO on Tohisba Visconti. -config GPIO_VX855 - tristate "VIA VX855/VX875 GPIO" - depends on (X86 || COMPILE_TEST) && PCI - select MFD_CORE - select MFD_VX855 - help - Support access to the VX855/VX875 GPIO lines through the GPIO library. - - This driver provides common support for accessing the device. - Additional drivers must be enabled in order to use the - functionality of the device. - config GPIO_WCD934X tristate "Qualcomm Technologies Inc WCD9340/WCD9341 GPIO controller driver" depends on MFD_WCD934X && OF_GPIO @@ -835,7 +823,19 @@ config GPIO_IDT3243X endmenu menu "Port-mapped I/O GPIO drivers" - depends on X86 # Unconditional I/O space access + depends on X86 && HAS_IOPORT # I/O space access + +config GPIO_VX855 + tristate "VIA VX855/VX875 GPIO" + depends on PCI + select MFD_CORE + select MFD_VX855 + help + Support access to the VX855/VX875 GPIO lines through the GPIO library. + + This driver provides common support for accessing the device. + Additional drivers must be enabled in order to use the + functionality of the device. config GPIO_I8255 tristate @@ -1440,6 +1440,22 @@ config GPIO_TPS65218 Select this option to enable GPIO driver for the TPS65218 chip family. +config GPIO_TPS65219 + tristate "TPS65219 GPIO" + depends on MFD_TPS65219 + default MFD_TPS65219 + help + Select this option to enable GPIO driver for the TPS65219 chip + family. + GPIO0 is statically configured as either input or output prior to + Linux boot. It is used for MULTI_DEVICE_ENABLE function. This setting + is statically configured by NVM. GPIO0 can't be used as a generic + GPIO. It's either a GPO when MULTI_DEVICE_EN=0 or a GPI when + MULTI_DEVICE_EN=1. + + This driver can also be built as a module. If so, the module will be + called gpio_tps65219. + config GPIO_TPS6586X bool "TPS6586X GPIO" depends on MFD_TPS6586X @@ -1583,6 +1599,19 @@ config GPIO_MLXBF2 help Say Y here if you want GPIO support on Mellanox BlueField 2 SoC. +config GPIO_MLXBF3 + tristate "Mellanox BlueField 3 SoC GPIO" + depends on (MELLANOX_PLATFORM && ARM64) || COMPILE_TEST + select GPIO_GENERIC + select GPIOLIB_IRQCHIP + help + Say Y if you want GPIO support on Mellanox BlueField 3 SoC. + This GPIO controller supports interrupt handling and enables the + manipulation of certain GPIO pins. + This controller should be used in parallel with pinctrl-mlxbf3 to + control the desired GPIOs. + This driver can also be built as a module called mlxbf3-gpio. + config GPIO_ML_IOH tristate "OKI SEMICONDUCTOR ML7213 IOH GPIO support" depends on X86 || COMPILE_TEST diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 20036af3acb1..c3ac51d47aa9 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -104,6 +104,7 @@ obj-$(CONFIG_GPIO_MERRIFIELD) += gpio-merrifield.o obj-$(CONFIG_GPIO_ML_IOH) += gpio-ml-ioh.o obj-$(CONFIG_GPIO_MLXBF) += gpio-mlxbf.o obj-$(CONFIG_GPIO_MLXBF2) += gpio-mlxbf2.o +obj-$(CONFIG_GPIO_MLXBF3) += gpio-mlxbf3.o obj-$(CONFIG_GPIO_MM_LANTIQ) += gpio-mm-lantiq.o obj-$(CONFIG_GPIO_MOCKUP) += gpio-mockup.o obj-$(CONFIG_GPIO_MOXTET) += gpio-moxtet.o @@ -160,6 +161,7 @@ obj-$(CONFIG_GPIO_TN48M_CPLD) += gpio-tn48m.o obj-$(CONFIG_GPIO_TPIC2810) += gpio-tpic2810.o obj-$(CONFIG_GPIO_TPS65086) += gpio-tps65086.o obj-$(CONFIG_GPIO_TPS65218) += gpio-tps65218.o +obj-$(CONFIG_GPIO_TPS65219) += gpio-tps65219.o obj-$(CONFIG_GPIO_TPS6586X) += gpio-tps6586x.o obj-$(CONFIG_GPIO_TPS65910) += gpio-tps65910.o obj-$(CONFIG_GPIO_TPS65912) += gpio-tps65912.o diff --git a/drivers/gpio/gpio-adnp.c b/drivers/gpio/gpio-adnp.c index 9b01c391efce..6dafab0cf964 100644 --- a/drivers/gpio/gpio-adnp.c +++ b/drivers/gpio/gpio-adnp.c @@ -535,7 +535,7 @@ static struct i2c_driver adnp_i2c_driver = { .name = "gpio-adnp", .of_match_table = adnp_of_match, }, - .probe_new = adnp_i2c_probe, + .probe = adnp_i2c_probe, .id_table = adnp_i2c_id, }; module_i2c_driver(adnp_i2c_driver); diff --git a/drivers/gpio/gpio-aggregator.c b/drivers/gpio/gpio-aggregator.c index 20a686f12df7..38e0fff9afe7 100644 --- a/drivers/gpio/gpio-aggregator.c +++ b/drivers/gpio/gpio-aggregator.c @@ -10,12 +10,15 @@ #include <linux/bitmap.h> #include <linux/bitops.h> #include <linux/ctype.h> +#include <linux/delay.h> #include <linux/idr.h> #include <linux/kernel.h> +#include <linux/mod_devicetable.h> #include <linux/module.h> #include <linux/mutex.h> #include <linux/overflow.h> #include <linux/platform_device.h> +#include <linux/property.h> #include <linux/slab.h> #include <linux/spinlock.h> #include <linux/string.h> @@ -239,6 +242,11 @@ static void __exit gpio_aggregator_remove_all(void) * GPIO Forwarder */ +struct gpiochip_fwd_timing { + u32 ramp_up_us; + u32 ramp_down_us; +}; + struct gpiochip_fwd { struct gpio_chip chip; struct gpio_desc **descs; @@ -246,6 +254,7 @@ struct gpiochip_fwd { struct mutex mlock; /* protects tmp[] if can_sleep */ spinlock_t slock; /* protects tmp[] if !can_sleep */ }; + struct gpiochip_fwd_timing *delay_timings; unsigned long tmp[]; /* values and descs for multiple ops */ }; @@ -330,6 +339,27 @@ static int gpio_fwd_get_multiple_locked(struct gpio_chip *chip, return error; } +static void gpio_fwd_delay(struct gpio_chip *chip, unsigned int offset, int value) +{ + struct gpiochip_fwd *fwd = gpiochip_get_data(chip); + const struct gpiochip_fwd_timing *delay_timings; + bool is_active_low = gpiod_is_active_low(fwd->descs[offset]); + u32 delay_us; + + delay_timings = &fwd->delay_timings[offset]; + if ((!is_active_low && value) || (is_active_low && !value)) + delay_us = delay_timings->ramp_up_us; + else + delay_us = delay_timings->ramp_down_us; + if (!delay_us) + return; + + if (chip->can_sleep) + fsleep(delay_us); + else + udelay(delay_us); +} + static void gpio_fwd_set(struct gpio_chip *chip, unsigned int offset, int value) { struct gpiochip_fwd *fwd = gpiochip_get_data(chip); @@ -338,6 +368,9 @@ static void gpio_fwd_set(struct gpio_chip *chip, unsigned int offset, int value) gpiod_set_value_cansleep(fwd->descs[offset], value); else gpiod_set_value(fwd->descs[offset], value); + + if (fwd->delay_timings) + gpio_fwd_delay(chip, offset, value); } static void gpio_fwd_set_multiple(struct gpiochip_fwd *fwd, unsigned long *mask, @@ -390,6 +423,59 @@ static int gpio_fwd_to_irq(struct gpio_chip *chip, unsigned int offset) return gpiod_to_irq(fwd->descs[offset]); } +/* + * The GPIO delay provides a way to configure platform specific delays + * for the GPIO ramp-up or ramp-down delays. This can serve the following + * purposes: + * - Open-drain output using an RC filter + */ +#define FWD_FEATURE_DELAY BIT(0) + +#ifdef CONFIG_OF_GPIO +static int gpiochip_fwd_delay_of_xlate(struct gpio_chip *chip, + const struct of_phandle_args *gpiospec, + u32 *flags) +{ + struct gpiochip_fwd *fwd = gpiochip_get_data(chip); + struct gpiochip_fwd_timing *timings; + u32 line; + + if (gpiospec->args_count != chip->of_gpio_n_cells) + return -EINVAL; + + line = gpiospec->args[0]; + if (line >= chip->ngpio) + return -EINVAL; + + timings = &fwd->delay_timings[line]; + timings->ramp_up_us = gpiospec->args[1]; + timings->ramp_down_us = gpiospec->args[2]; + + return line; +} + +static int gpiochip_fwd_setup_delay_line(struct device *dev, struct gpio_chip *chip, + struct gpiochip_fwd *fwd) +{ + fwd->delay_timings = devm_kcalloc(dev, chip->ngpio, + sizeof(*fwd->delay_timings), + GFP_KERNEL); + if (!fwd->delay_timings) + return -ENOMEM; + + chip->of_xlate = gpiochip_fwd_delay_of_xlate; + chip->of_gpio_n_cells = 3; + + return 0; +} +#else +static int gpiochip_fwd_setup_delay_line(struct device *dev, struct gpio_chip *chip, + struct gpiochip_fwd *fwd) +{ + return 0; +} +#endif /* !CONFIG_OF_GPIO */ + /** * gpiochip_fwd_create() - Create a new GPIO forwarder * @dev: Parent device pointer @@ -397,6 +483,7 @@ static int gpio_fwd_to_irq(struct gpio_chip *chip, unsigned int offset) * @descs: Array containing the GPIO descriptors to forward to. * This array must contain @ngpios entries, and must not be deallocated * before the forwarder has been destroyed again. + * @features: Bitwise ORed features as defined with FWD_FEATURE_*. * * This function creates a new gpiochip, which forwards all GPIO operations to * the passed GPIO descriptors. @@ -406,7 +493,8 @@ static int gpio_fwd_to_irq(struct gpio_chip *chip, unsigned int offset) */ static struct gpiochip_fwd *gpiochip_fwd_create(struct device *dev, unsigned int ngpios, - struct gpio_desc *descs[]) + struct gpio_desc *descs[], + unsigned long features) { const char *label = dev_name(dev); struct gpiochip_fwd *fwd; @@ -459,6 +547,12 @@ static struct gpiochip_fwd *gpiochip_fwd_create(struct device *dev, else spin_lock_init(&fwd->slock); + if (features & FWD_FEATURE_DELAY) { + error = gpiochip_fwd_setup_delay_line(dev, chip, fwd); + if (error) + return ERR_PTR(error); + } + error = devm_gpiochip_add_data(dev, chip, fwd); if (error) return ERR_PTR(error); @@ -476,6 +570,7 @@ static int gpio_aggregator_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct gpio_desc **descs; struct gpiochip_fwd *fwd; + unsigned long features; int i, n; n = gpiod_count(dev, NULL); @@ -492,7 +587,8 @@ static int gpio_aggregator_probe(struct platform_device *pdev) return PTR_ERR(descs[i]); } - fwd = gpiochip_fwd_create(dev, n, descs); + features = (uintptr_t)device_get_match_data(dev); + fwd = gpiochip_fwd_create(dev, n, descs, features); if (IS_ERR(fwd)) return PTR_ERR(fwd); @@ -500,23 +596,25 @@ static int gpio_aggregator_probe(struct platform_device *pdev) return 0; } -#ifdef CONFIG_OF static const struct of_device_id gpio_aggregator_dt_ids[] = { + { + .compatible = "gpio-delay", + .data = (void *)FWD_FEATURE_DELAY, + }, /* * Add GPIO-operated devices controlled from userspace below, - * or use "driver_override" in sysfs + * or use "driver_override" in sysfs. */ {} }; MODULE_DEVICE_TABLE(of, gpio_aggregator_dt_ids); -#endif static struct platform_driver gpio_aggregator_driver = { .probe = gpio_aggregator_probe, .driver = { .name = DRV_NAME, .groups = gpio_aggregator_groups, - .of_match_table = of_match_ptr(gpio_aggregator_dt_ids), + .of_match_table = gpio_aggregator_dt_ids, }, }; diff --git a/drivers/gpio/gpio-brcmstb.c b/drivers/gpio/gpio-brcmstb.c index c55b35da61a0..6566517fe0d8 100644 --- a/drivers/gpio/gpio-brcmstb.c +++ b/drivers/gpio/gpio-brcmstb.c @@ -609,8 +609,7 @@ static int brcmstb_gpio_probe(struct platform_device *pdev) platform_set_drvdata(pdev, priv); INIT_LIST_HEAD(&priv->bank_list); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - reg_base = devm_ioremap_resource(dev, res); + reg_base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); if (IS_ERR(reg_base)) return PTR_ERR(reg_base); diff --git a/drivers/gpio/gpio-davinci.c b/drivers/gpio/gpio-davinci.c index aaaf61dc2632..fff510d86e31 100644 --- a/drivers/gpio/gpio-davinci.c +++ b/drivers/gpio/gpio-davinci.c @@ -692,7 +692,7 @@ static int davinci_gpio_resume(struct device *dev) return 0; } -DEFINE_SIMPLE_DEV_PM_OPS(davinci_gpio_dev_pm_ops, davinci_gpio_suspend, +static DEFINE_SIMPLE_DEV_PM_OPS(davinci_gpio_dev_pm_ops, davinci_gpio_suspend, davinci_gpio_resume); static const struct of_device_id davinci_gpio_ids[] = { @@ -712,7 +712,7 @@ static struct platform_driver davinci_gpio_driver = { }, }; -/** +/* * GPIO driver registration needs to be done before machine_init functions * access GPIO. Hence davinci_gpio_drv_reg() is a postcore_initcall. */ diff --git a/drivers/gpio/gpio-fxl6408.c b/drivers/gpio/gpio-fxl6408.c index 208fa851e82a..c14b5cc5e519 100644 --- a/drivers/gpio/gpio-fxl6408.c +++ b/drivers/gpio/gpio-fxl6408.c @@ -148,7 +148,7 @@ static struct i2c_driver fxl6408_driver = { .name = "fxl6408", .of_match_table = fxl6408_dt_ids, }, - .probe_new = fxl6408_probe, + .probe = fxl6408_probe, .id_table = fxl6408_id, }; module_i2c_driver(fxl6408_driver); diff --git a/drivers/gpio/gpio-gw-pld.c b/drivers/gpio/gpio-gw-pld.c index 5057fa9ad610..899335da93c7 100644 --- a/drivers/gpio/gpio-gw-pld.c +++ b/drivers/gpio/gpio-gw-pld.c @@ -125,7 +125,7 @@ static struct i2c_driver gw_pld_driver = { .name = "gw_pld", .of_match_table = gw_pld_dt_ids, }, - .probe_new = gw_pld_probe, + .probe = gw_pld_probe, .id_table = gw_pld_id, }; module_i2c_driver(gw_pld_driver); diff --git a/drivers/gpio/gpio-ixp4xx.c b/drivers/gpio/gpio-ixp4xx.c index 56656fb519f8..1e29de1671d4 100644 --- a/drivers/gpio/gpio-ixp4xx.c +++ b/drivers/gpio/gpio-ixp4xx.c @@ -199,7 +199,6 @@ static int ixp4xx_gpio_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct device_node *np = dev->of_node; struct irq_domain *parent; - struct resource *res; struct ixp4xx_gpio *g; struct gpio_irq_chip *girq; struct device_node *irq_parent; @@ -210,8 +209,7 @@ static int ixp4xx_gpio_probe(struct platform_device *pdev) return -ENOMEM; g->dev = dev; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - g->base = devm_ioremap_resource(dev, res); + g->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(g->base)) return PTR_ERR(g->base); diff --git a/drivers/gpio/gpio-lpc18xx.c b/drivers/gpio/gpio-lpc18xx.c index d711ae06747e..ed3f653a1dfc 100644 --- a/drivers/gpio/gpio-lpc18xx.c +++ b/drivers/gpio/gpio-lpc18xx.c @@ -14,7 +14,6 @@ #include <linux/module.h> #include <linux/of.h> #include <linux/of_address.h> -#include <linux/of_gpio.h> #include <linux/of_irq.h> #include <linux/pinctrl/consumer.h> #include <linux/platform_device.h> diff --git a/drivers/gpio/gpio-max7300.c b/drivers/gpio/gpio-max7300.c index cf482f4f0098..31c2b95321cc 100644 --- a/drivers/gpio/gpio-max7300.c +++ b/drivers/gpio/gpio-max7300.c @@ -62,7 +62,7 @@ static struct i2c_driver max7300_driver = { .driver = { .name = "max7300", }, - .probe_new = max7300_probe, + .probe = max7300_probe, .remove = max7300_remove, .id_table = max7300_id, }; diff --git a/drivers/gpio/gpio-max732x.c b/drivers/gpio/gpio-max732x.c index 7f2fde191755..fca9ca68e387 100644 --- a/drivers/gpio/gpio-max732x.c +++ b/drivers/gpio/gpio-max732x.c @@ -711,7 +711,7 @@ static struct i2c_driver max732x_driver = { .name = "max732x", .of_match_table = of_match_ptr(max732x_of_table), }, - .probe_new = max732x_probe, + .probe = max732x_probe, .id_table = max732x_id, }; diff --git a/drivers/gpio/gpio-mlxbf3.c b/drivers/gpio/gpio-mlxbf3.c new file mode 100644 index 000000000000..e30cee108986 --- /dev/null +++ b/drivers/gpio/gpio-mlxbf3.c @@ -0,0 +1,248 @@ +// SPDX-License-Identifier: GPL-2.0-only or BSD-3-Clause +/* Copyright (C) 2022 NVIDIA CORPORATION & AFFILIATES */ + +#include <linux/bitfield.h> +#include <linux/bitops.h> +#include <linux/device.h> +#include <linux/err.h> +#include <linux/gpio/driver.h> +#include <linux/interrupt.h> +#include <linux/io.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/spinlock.h> +#include <linux/types.h> + +/* + * There are 2 YU GPIO blocks: + * gpio[0]: HOST_GPIO0->HOST_GPIO31 + * gpio[1]: HOST_GPIO32->HOST_GPIO55 + */ +#define MLXBF3_GPIO_MAX_PINS_PER_BLOCK 32 + +/* + * fw_gpio[x] block registers and their offset + */ +#define MLXBF_GPIO_FW_OUTPUT_ENABLE_SET 0x00 +#define MLXBF_GPIO_FW_DATA_OUT_SET 0x04 + +#define MLXBF_GPIO_FW_OUTPUT_ENABLE_CLEAR 0x00 +#define MLXBF_GPIO_FW_DATA_OUT_CLEAR 0x04 + +#define MLXBF_GPIO_CAUSE_RISE_EN 0x00 +#define MLXBF_GPIO_CAUSE_FALL_EN 0x04 +#define MLXBF_GPIO_READ_DATA_IN 0x08 + +#define MLXBF_GPIO_CAUSE_OR_CAUSE_EVTEN0 0x00 +#define MLXBF_GPIO_CAUSE_OR_EVTEN0 0x14 +#define MLXBF_GPIO_CAUSE_OR_CLRCAUSE 0x18 + +struct mlxbf3_gpio_context { + struct gpio_chip gc; + + /* YU GPIO block address */ + void __iomem *gpio_set_io; + void __iomem *gpio_clr_io; + void __iomem *gpio_io; + + /* YU GPIO cause block address */ + void __iomem *gpio_cause_io; +}; + +static void mlxbf3_gpio_irq_enable(struct irq_data *irqd) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd); + struct mlxbf3_gpio_context *gs = gpiochip_get_data(gc); + irq_hw_number_t offset = irqd_to_hwirq(irqd); + unsigned long flags; + u32 val; + + gpiochip_enable_irq(gc, offset); + + raw_spin_lock_irqsave(&gs->gc.bgpio_lock, flags); + writel(BIT(offset), gs->gpio_cause_io + MLXBF_GPIO_CAUSE_OR_CLRCAUSE); + + val = readl(gs->gpio_cause_io + MLXBF_GPIO_CAUSE_OR_EVTEN0); + val |= BIT(offset); + writel(val, gs->gpio_cause_io + MLXBF_GPIO_CAUSE_OR_EVTEN0); + raw_spin_unlock_irqrestore(&gs->gc.bgpio_lock, flags); +} + +static void mlxbf3_gpio_irq_disable(struct irq_data *irqd) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd); + struct mlxbf3_gpio_context *gs = gpiochip_get_data(gc); + irq_hw_number_t offset = irqd_to_hwirq(irqd); + unsigned long flags; + u32 val; + + raw_spin_lock_irqsave(&gs->gc.bgpio_lock, flags); + val = readl(gs->gpio_cause_io + MLXBF_GPIO_CAUSE_OR_EVTEN0); + val &= ~BIT(offset); + writel(val, gs->gpio_cause_io + MLXBF_GPIO_CAUSE_OR_EVTEN0); + raw_spin_unlock_irqrestore(&gs->gc.bgpio_lock, flags); + + gpiochip_disable_irq(gc, offset); +} + +static irqreturn_t mlxbf3_gpio_irq_handler(int irq, void *ptr) +{ + struct mlxbf3_gpio_context *gs = ptr; + struct gpio_chip *gc = &gs->gc; + unsigned long pending; + u32 level; + + pending = readl(gs->gpio_cause_io + MLXBF_GPIO_CAUSE_OR_CAUSE_EVTEN0); + writel(pending, gs->gpio_cause_io + MLXBF_GPIO_CAUSE_OR_CLRCAUSE); + + for_each_set_bit(level, &pending, gc->ngpio) + generic_handle_domain_irq(gc->irq.domain, level); + + return IRQ_RETVAL(pending); +} + +static int +mlxbf3_gpio_irq_set_type(struct irq_data *irqd, unsigned int type) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd); + struct mlxbf3_gpio_context *gs = gpiochip_get_data(gc); + irq_hw_number_t offset = irqd_to_hwirq(irqd); + unsigned long flags; + u32 val; + + raw_spin_lock_irqsave(&gs->gc.bgpio_lock, flags); + + switch (type & IRQ_TYPE_SENSE_MASK) { + case IRQ_TYPE_EDGE_BOTH: + val = readl(gs->gpio_io + MLXBF_GPIO_CAUSE_FALL_EN); + val |= BIT(offset); + writel(val, gs->gpio_io + MLXBF_GPIO_CAUSE_FALL_EN); + val = readl(gs->gpio_io + MLXBF_GPIO_CAUSE_RISE_EN); + val |= BIT(offset); + writel(val, gs->gpio_io + MLXBF_GPIO_CAUSE_RISE_EN); + break; + case IRQ_TYPE_EDGE_RISING: + val = readl(gs->gpio_io + MLXBF_GPIO_CAUSE_RISE_EN); + val |= BIT(offset); + writel(val, gs->gpio_io + MLXBF_GPIO_CAUSE_RISE_EN); + break; + case IRQ_TYPE_EDGE_FALLING: + val = readl(gs->gpio_io + MLXBF_GPIO_CAUSE_FALL_EN); + val |= BIT(offset); + writel(val, gs->gpio_io + MLXBF_GPIO_CAUSE_FALL_EN); + break; + default: + raw_spin_unlock_irqrestore(&gs->gc.bgpio_lock, flags); + return -EINVAL; + } + + raw_spin_unlock_irqrestore(&gs->gc.bgpio_lock, flags); + + irq_set_handler_locked(irqd, handle_edge_irq); + + return 0; +} + +/* This function needs to be defined for handle_edge_irq() */ +static void mlxbf3_gpio_irq_ack(struct irq_data *data) +{ +} + +static const struct irq_chip gpio_mlxbf3_irqchip = { + .name = "MLNXBF33", + .irq_ack = mlxbf3_gpio_irq_ack, + .irq_set_type = mlxbf3_gpio_irq_set_type, + .irq_enable = mlxbf3_gpio_irq_enable, + .irq_disable = mlxbf3_gpio_irq_disable, + .flags = IRQCHIP_IMMUTABLE, + GPIOCHIP_IRQ_RESOURCE_HELPERS, +}; + +static int mlxbf3_gpio_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct mlxbf3_gpio_context *gs; + struct gpio_irq_chip *girq; + struct gpio_chip *gc; + int ret, irq; + + gs = devm_kzalloc(dev, sizeof(*gs), GFP_KERNEL); + if (!gs) + return -ENOMEM; + + gs->gpio_io = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(gs->gpio_io)) + return PTR_ERR(gs->gpio_io); + + gs->gpio_cause_io = devm_platform_ioremap_resource(pdev, 1); + if (IS_ERR(gs->gpio_cause_io)) + return PTR_ERR(gs->gpio_cause_io); + + gs->gpio_set_io = devm_platform_ioremap_resource(pdev, 2); + if (IS_ERR(gs->gpio_set_io)) + return PTR_ERR(gs->gpio_set_io); + + gs->gpio_clr_io = devm_platform_ioremap_resource(pdev, 3); + if (IS_ERR(gs->gpio_clr_io)) + return PTR_ERR(gs->gpio_clr_io); + gc = &gs->gc; + + ret = bgpio_init(gc, dev, 4, + gs->gpio_io + MLXBF_GPIO_READ_DATA_IN, + gs->gpio_set_io + MLXBF_GPIO_FW_DATA_OUT_SET, + gs->gpio_clr_io + MLXBF_GPIO_FW_DATA_OUT_CLEAR, + gs->gpio_set_io + MLXBF_GPIO_FW_OUTPUT_ENABLE_SET, + gs->gpio_clr_io + MLXBF_GPIO_FW_OUTPUT_ENABLE_CLEAR, 0); + + gc->request = gpiochip_generic_request; + gc->free = gpiochip_generic_free; + gc->owner = THIS_MODULE; + + irq = platform_get_irq(pdev, 0); + if (irq >= 0) { + girq = &gs->gc.irq; + gpio_irq_chip_set_chip(girq, &gpio_mlxbf3_irqchip); + girq->default_type = IRQ_TYPE_NONE; + /* This will let us handle the parent IRQ in the driver */ + girq->num_parents = 0; + girq->parents = NULL; + girq->parent_handler = NULL; + girq->handler = handle_bad_irq; + + /* + * Directly request the irq here instead of passing + * a flow-handler because the irq is shared. + */ + ret = devm_request_irq(dev, irq, mlxbf3_gpio_irq_handler, + IRQF_SHARED, dev_name(dev), gs); + if (ret) + return dev_err_probe(dev, ret, "failed to request IRQ"); + } + + platform_set_drvdata(pdev, gs); + + ret = devm_gpiochip_add_data(dev, &gs->gc, gs); + if (ret) + dev_err_probe(dev, ret, "Failed adding memory mapped gpiochip\n"); + + return 0; +} + +static const struct acpi_device_id mlxbf3_gpio_acpi_match[] = { + { "MLNXBF33", 0 }, + {} +}; +MODULE_DEVICE_TABLE(acpi, mlxbf3_gpio_acpi_match); + +static struct platform_driver mlxbf3_gpio_driver = { + .driver = { + .name = "mlxbf3_gpio", + .acpi_match_table = mlxbf3_gpio_acpi_match, + }, + .probe = mlxbf3_gpio_probe, +}; +module_platform_driver(mlxbf3_gpio_driver); + +MODULE_DESCRIPTION("NVIDIA BlueField-3 GPIO Driver"); +MODULE_AUTHOR("Asmaa Mnebhi <asmaa@nvidia.com>"); +MODULE_LICENSE("Dual BSD/GPL"); diff --git a/drivers/gpio/gpio-mpc8xxx.c b/drivers/gpio/gpio-mpc8xxx.c index 3eb08cd1fdc0..5979a36bf754 100644 --- a/drivers/gpio/gpio-mpc8xxx.c +++ b/drivers/gpio/gpio-mpc8xxx.c @@ -12,7 +12,6 @@ #include <linux/spinlock.h> #include <linux/io.h> #include <linux/of.h> -#include <linux/of_gpio.h> #include <linux/of_address.h> #include <linux/of_irq.h> #include <linux/of_platform.h> @@ -375,8 +374,12 @@ static int mpc8xxx_probe(struct platform_device *pdev) if (of_device_is_compatible(np, "fsl,qoriq-gpio") || of_device_is_compatible(np, "fsl,ls1028a-gpio") || of_device_is_compatible(np, "fsl,ls1088a-gpio") || - is_acpi_node(fwnode)) + is_acpi_node(fwnode)) { gc->write_reg(mpc8xxx_gc->regs + GPIO_IBE, 0xffffffff); + /* Also, latch state of GPIOs configured as output by bootloader. */ + gc->bgpio_data = gc->read_reg(mpc8xxx_gc->regs + GPIO_DAT) & + gc->read_reg(mpc8xxx_gc->regs + GPIO_DIR); + } ret = devm_gpiochip_add_data(&pdev->dev, gc, mpc8xxx_gc); if (ret) { diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index 1286b22ef23a..a806a3c1b801 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -1375,7 +1375,7 @@ static struct i2c_driver pca953x_driver = { .of_match_table = pca953x_dt_ids, .acpi_match_table = pca953x_acpi_ids, }, - .probe_new = pca953x_probe, + .probe = pca953x_probe, .remove = pca953x_remove, .id_table = pca953x_id, }; diff --git a/drivers/gpio/gpio-pca9570.c b/drivers/gpio/gpio-pca9570.c index 6a5a8e593ed5..d8db80ef1293 100644 --- a/drivers/gpio/gpio-pca9570.c +++ b/drivers/gpio/gpio-pca9570.c @@ -175,7 +175,7 @@ static struct i2c_driver pca9570_driver = { .name = "pca9570", .of_match_table = pca9570_of_match_table, }, - .probe_new = pca9570_probe, + .probe = pca9570_probe, .id_table = pca9570_id_table, }; module_i2c_driver(pca9570_driver); diff --git a/drivers/gpio/gpio-pcf857x.c b/drivers/gpio/gpio-pcf857x.c index 3de1d3ad7472..c4c785548408 100644 --- a/drivers/gpio/gpio-pcf857x.c +++ b/drivers/gpio/gpio-pcf857x.c @@ -419,7 +419,7 @@ static struct i2c_driver pcf857x_driver = { .name = "pcf857x", .of_match_table = pcf857x_of_table, }, - .probe_new = pcf857x_probe, + .probe = pcf857x_probe, .shutdown = pcf857x_shutdown, .id_table = pcf857x_id, }; diff --git a/drivers/gpio/gpio-sa1100.c b/drivers/gpio/gpio-sa1100.c index edff5e81489f..242dad763ac4 100644 --- a/drivers/gpio/gpio-sa1100.c +++ b/drivers/gpio/gpio-sa1100.c @@ -12,6 +12,7 @@ #include <soc/sa1100/pwer.h> #include <mach/hardware.h> #include <mach/irqs.h> +#include <mach/generic.h> struct sa1100_gpio_chip { struct gpio_chip chip; diff --git a/drivers/gpio/gpio-sch311x.c b/drivers/gpio/gpio-sch311x.c index da01e1cad7cb..ba4fccf3cc94 100644 --- a/drivers/gpio/gpio-sch311x.c +++ b/drivers/gpio/gpio-sch311x.c @@ -281,8 +281,6 @@ static int sch311x_gpio_probe(struct platform_device *pdev) if (!priv) return -ENOMEM; - platform_set_drvdata(pdev, priv); - for (i = 0; i < ARRAY_SIZE(priv->blocks); i++) { block = &priv->blocks[i]; @@ -305,42 +303,22 @@ static int sch311x_gpio_probe(struct platform_device *pdev) block->data_reg = sch311x_gpio_blocks[i].data_reg; block->runtime_reg = pdata->runtime_reg; - err = gpiochip_add_data(&block->chip, block); + err = devm_gpiochip_add_data(&pdev->dev, &block->chip, block); if (err < 0) { dev_err(&pdev->dev, "Could not register gpiochip, %d\n", err); - goto exit_err; + return err; } dev_info(&pdev->dev, "SMSC SCH311x GPIO block %d registered.\n", i); } return 0; - -exit_err: - /* release already registered chips */ - for (--i; i >= 0; i--) - gpiochip_remove(&priv->blocks[i].chip); - return err; -} - -static int sch311x_gpio_remove(struct platform_device *pdev) -{ - struct sch311x_gpio_priv *priv = platform_get_drvdata(pdev); - int i; - - for (i = 0; i < ARRAY_SIZE(priv->blocks); i++) { - gpiochip_remove(&priv->blocks[i].chip); - dev_info(&pdev->dev, - "SMSC SCH311x GPIO block %d unregistered.\n", i); - } - return 0; } static struct platform_driver sch311x_gpio_driver = { .driver.name = DRV_NAME, .probe = sch311x_gpio_probe, - .remove = sch311x_gpio_remove, }; diff --git a/drivers/gpio/gpio-tangier.c b/drivers/gpio/gpio-tangier.c index e990781935ba..7ce3eddaed25 100644 --- a/drivers/gpio/gpio-tangier.c +++ b/drivers/gpio/gpio-tangier.c @@ -16,6 +16,7 @@ #include <linux/interrupt.h> #include <linux/io.h> #include <linux/irq.h> +#include <linux/math.h> #include <linux/module.h> #include <linux/pinctrl/pinconf-generic.h> #include <linux/spinlock.h> @@ -428,10 +429,11 @@ static int tng_gpio_add_pin_ranges(struct gpio_chip *chip) int devm_tng_gpio_probe(struct device *dev, struct tng_gpio *gpio) { const struct tng_gpio_info *info = &gpio->info; + size_t nctx = DIV_ROUND_UP(info->ngpio, 32); struct gpio_irq_chip *girq; int ret; - gpio->ctx = devm_kcalloc(dev, DIV_ROUND_UP(info->ngpio, 32), sizeof(*gpio->ctx), GFP_KERNEL); + gpio->ctx = devm_kcalloc(dev, nctx, sizeof(*gpio->ctx), GFP_KERNEL); if (!gpio->ctx) return -ENOMEM; diff --git a/drivers/gpio/gpio-tegra186.c b/drivers/gpio/gpio-tegra186.c index b904de0b1784..464b0ea3b6f1 100644 --- a/drivers/gpio/gpio-tegra186.c +++ b/drivers/gpio/gpio-tegra186.c @@ -27,6 +27,22 @@ #define TEGRA186_GPIO_INT_ROUTE_MAPPING(p, x) (0x14 + (p) * 0x20 + (x) * 4) +#define TEGRA186_GPIO_VM 0x00 +#define TEGRA186_GPIO_VM_RW_MASK 0x03 +#define TEGRA186_GPIO_SCR 0x04 +#define TEGRA186_GPIO_SCR_PIN_SIZE 0x08 +#define TEGRA186_GPIO_SCR_PORT_SIZE 0x40 +#define TEGRA186_GPIO_SCR_SEC_WEN BIT(28) +#define TEGRA186_GPIO_SCR_SEC_REN BIT(27) +#define TEGRA186_GPIO_SCR_SEC_G1W BIT(9) +#define TEGRA186_GPIO_SCR_SEC_G1R BIT(1) +#define TEGRA186_GPIO_FULL_ACCESS (TEGRA186_GPIO_SCR_SEC_WEN | \ + TEGRA186_GPIO_SCR_SEC_REN | \ + TEGRA186_GPIO_SCR_SEC_G1R | \ + TEGRA186_GPIO_SCR_SEC_G1W) +#define TEGRA186_GPIO_SCR_SEC_ENABLE (TEGRA186_GPIO_SCR_SEC_WEN | \ + TEGRA186_GPIO_SCR_SEC_REN) + /* control registers */ #define TEGRA186_GPIO_ENABLE_CONFIG 0x00 #define TEGRA186_GPIO_ENABLE_CONFIG_ENABLE BIT(0) @@ -81,6 +97,7 @@ struct tegra_gpio_soc { unsigned int num_pin_ranges; const char *pinmux; bool has_gte; + bool has_vm_support; }; struct tegra_gpio { @@ -130,6 +147,58 @@ static void __iomem *tegra186_gpio_get_base(struct tegra_gpio *gpio, return gpio->base + offset + pin * 0x20; } +static void __iomem *tegra186_gpio_get_secure_base(struct tegra_gpio *gpio, + unsigned int pin) +{ + const struct tegra_gpio_port *port; + unsigned int offset; + + port = tegra186_gpio_get_port(gpio, &pin); + if (!port) + return NULL; + + offset = port->bank * 0x1000 + port->port * TEGRA186_GPIO_SCR_PORT_SIZE; + + return gpio->secure + offset + pin * TEGRA186_GPIO_SCR_PIN_SIZE; +} + +static inline bool tegra186_gpio_is_accessible(struct tegra_gpio *gpio, unsigned int pin) +{ + void __iomem *secure; + u32 value; + + secure = tegra186_gpio_get_secure_base(gpio, pin); + + if (gpio->soc->has_vm_support) { + value = readl(secure + TEGRA186_GPIO_VM); + if ((value & TEGRA186_GPIO_VM_RW_MASK) != TEGRA186_GPIO_VM_RW_MASK) + return false; + } + + value = __raw_readl(secure + TEGRA186_GPIO_SCR); + + if ((value & TEGRA186_GPIO_SCR_SEC_ENABLE) == 0) + return true; + + if ((value & TEGRA186_GPIO_FULL_ACCESS) == TEGRA186_GPIO_FULL_ACCESS) + return true; + + return false; +} + +static int tegra186_init_valid_mask(struct gpio_chip *chip, + unsigned long *valid_mask, unsigned int ngpios) +{ + struct tegra_gpio *gpio = gpiochip_get_data(chip); + unsigned int j; + + for (j = 0; j < ngpios; j++) { + if (!tegra186_gpio_is_accessible(gpio, j)) + clear_bit(j, valid_mask); + } + return 0; +} + static int tegra186_gpio_get_direction(struct gpio_chip *chip, unsigned int offset) { @@ -816,6 +885,7 @@ static int tegra186_gpio_probe(struct platform_device *pdev) gpio->gpio.set = tegra186_gpio_set; gpio->gpio.set_config = tegra186_gpio_set_config; gpio->gpio.add_pin_ranges = tegra186_gpio_add_pin_ranges; + gpio->gpio.init_valid_mask = tegra186_init_valid_mask; if (gpio->soc->has_gte) { gpio->gpio.en_hw_timestamp = tegra186_gpio_en_hw_ts; gpio->gpio.dis_hw_timestamp = tegra186_gpio_dis_hw_ts; @@ -958,6 +1028,7 @@ static const struct tegra_gpio_soc tegra186_main_soc = { .name = "tegra186-gpio", .instance = 0, .num_irqs_per_bank = 1, + .has_vm_support = false, }; #define TEGRA186_AON_GPIO_PORT(_name, _bank, _port, _pins) \ @@ -985,6 +1056,7 @@ static const struct tegra_gpio_soc tegra186_aon_soc = { .name = "tegra186-gpio-aon", .instance = 1, .num_irqs_per_bank = 1, + .has_vm_support = false, }; #define TEGRA194_MAIN_GPIO_PORT(_name, _bank, _port, _pins) \ @@ -1040,6 +1112,7 @@ static const struct tegra_gpio_soc tegra194_main_soc = { .num_pin_ranges = ARRAY_SIZE(tegra194_main_pin_ranges), .pin_ranges = tegra194_main_pin_ranges, .pinmux = "nvidia,tegra194-pinmux", + .has_vm_support = true, }; #define TEGRA194_AON_GPIO_PORT(_name, _bank, _port, _pins) \ @@ -1065,6 +1138,7 @@ static const struct tegra_gpio_soc tegra194_aon_soc = { .instance = 1, .num_irqs_per_bank = 8, .has_gte = true, + .has_vm_support = false, }; #define TEGRA234_MAIN_GPIO_PORT(_name, _bank, _port, _pins) \ @@ -1109,6 +1183,7 @@ static const struct tegra_gpio_soc tegra234_main_soc = { .name = "tegra234-gpio", .instance = 0, .num_irqs_per_bank = 8, + .has_vm_support = true, }; #define TEGRA234_AON_GPIO_PORT(_name, _bank, _port, _pins) \ @@ -1135,6 +1210,7 @@ static const struct tegra_gpio_soc tegra234_aon_soc = { .instance = 1, .num_irqs_per_bank = 8, .has_gte = true, + .has_vm_support = false, }; #define TEGRA241_MAIN_GPIO_PORT(_name, _bank, _port, _pins) \ @@ -1165,6 +1241,7 @@ static const struct tegra_gpio_soc tegra241_main_soc = { .name = "tegra241-gpio", .instance = 0, .num_irqs_per_bank = 8, + .has_vm_support = false, }; #define TEGRA241_AON_GPIO_PORT(_name, _bank, _port, _pins) \ @@ -1186,6 +1263,7 @@ static const struct tegra_gpio_soc tegra241_aon_soc = { .name = "tegra241-gpio-aon", .instance = 1, .num_irqs_per_bank = 8, + .has_vm_support = false, }; static const struct of_device_id tegra186_gpio_of_match[] = { diff --git a/drivers/gpio/gpio-tpic2810.c b/drivers/gpio/gpio-tpic2810.c index 349c5fbd9b02..effb7b8ff81f 100644 --- a/drivers/gpio/gpio-tpic2810.c +++ b/drivers/gpio/gpio-tpic2810.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/ - * Andrew F. Davis <afd@ti.com> + * Copyright (C) 2015-2023 Texas Instruments Incorporated - https://www.ti.com/ + * Andrew Davis <afd@ti.com> */ #include <linux/gpio/driver.h> @@ -101,14 +101,11 @@ MODULE_DEVICE_TABLE(of, tpic2810_of_match_table); static int tpic2810_probe(struct i2c_client *client) { struct tpic2810 *gpio; - int ret; gpio = devm_kzalloc(&client->dev, sizeof(*gpio), GFP_KERNEL); if (!gpio) return -ENOMEM; - i2c_set_clientdata(client, gpio); - gpio->chip = template_chip; gpio->chip.parent = &client->dev; @@ -116,20 +113,7 @@ static int tpic2810_probe(struct i2c_client *client) mutex_init(&gpio->lock); - ret = gpiochip_add_data(&gpio->chip, gpio); - if (ret < 0) { - dev_err(&client->dev, "Unable to register gpiochip\n"); - return ret; - } - - return 0; -} - -static void tpic2810_remove(struct i2c_client *client) -{ - struct tpic2810 *gpio = i2c_get_clientdata(client); - - gpiochip_remove(&gpio->chip); + return devm_gpiochip_add_data(&client->dev, &gpio->chip, gpio); } static const struct i2c_device_id tpic2810_id_table[] = { @@ -143,12 +127,11 @@ static struct i2c_driver tpic2810_driver = { .name = "tpic2810", .of_match_table = tpic2810_of_match_table, }, - .probe_new = tpic2810_probe, - .remove = tpic2810_remove, + .probe = tpic2810_probe, .id_table = tpic2810_id_table, }; module_i2c_driver(tpic2810_driver); -MODULE_AUTHOR("Andrew F. Davis <afd@ti.com>"); +MODULE_AUTHOR("Andrew Davis <afd@ti.com>"); MODULE_DESCRIPTION("TPIC2810 8-Bit LED Driver GPIO Driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/gpio/gpio-tps65086.c b/drivers/gpio/gpio-tps65086.c index 1e9d8262d0ff..8f5827554e1e 100644 --- a/drivers/gpio/gpio-tps65086.c +++ b/drivers/gpio/gpio-tps65086.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/ - * Andrew F. Davis <afd@ti.com> + * Copyright (C) 2015-2023 Texas Instruments Incorporated - https://www.ti.com/ + * Andrew Davis <afd@ti.com> * * Based on the TPS65912 driver */ @@ -80,34 +80,16 @@ static const struct gpio_chip template_chip = { static int tps65086_gpio_probe(struct platform_device *pdev) { struct tps65086_gpio *gpio; - int ret; gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL); if (!gpio) return -ENOMEM; - platform_set_drvdata(pdev, gpio); - gpio->tps = dev_get_drvdata(pdev->dev.parent); gpio->chip = template_chip; gpio->chip.parent = gpio->tps->dev; - ret = gpiochip_add_data(&gpio->chip, gpio); - if (ret < 0) { - dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret); - return ret; - } - - return 0; -} - -static int tps65086_gpio_remove(struct platform_device *pdev) -{ - struct tps65086_gpio *gpio = platform_get_drvdata(pdev); - - gpiochip_remove(&gpio->chip); - - return 0; + return devm_gpiochip_add_data(&pdev->dev, &gpio->chip, gpio); } static const struct platform_device_id tps65086_gpio_id_table[] = { @@ -121,11 +103,10 @@ static struct platform_driver tps65086_gpio_driver = { .name = "tps65086-gpio", }, .probe = tps65086_gpio_probe, - .remove = tps65086_gpio_remove, .id_table = tps65086_gpio_id_table, }; module_platform_driver(tps65086_gpio_driver); -MODULE_AUTHOR("Andrew F. Davis <afd@ti.com>"); +MODULE_AUTHOR("Andrew Davis <afd@ti.com>"); MODULE_DESCRIPTION("TPS65086 GPIO driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/gpio/gpio-tps65219.c b/drivers/gpio/gpio-tps65219.c new file mode 100644 index 000000000000..7b38aa360112 --- /dev/null +++ b/drivers/gpio/gpio-tps65219.c @@ -0,0 +1,185 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * GPIO driver for TI TPS65219 PMICs + * + * Copyright (C) 2022 Texas Instruments Incorporated - http://www.ti.com/ + */ + +#include <linux/bits.h> +#include <linux/gpio/driver.h> +#include <linux/mfd/tps65219.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/regmap.h> + +#define TPS65219_GPIO0_DIR_MASK BIT(3) +#define TPS65219_GPIO0_OFFSET 2 +#define TPS65219_GPIO0_IDX 0 +#define TPS65219_GPIO_DIR_IN 1 +#define TPS65219_GPIO_DIR_OUT 0 + +struct tps65219_gpio { + struct gpio_chip gpio_chip; + struct tps65219 *tps; +}; + +static int tps65219_gpio_get_direction(struct gpio_chip *gc, unsigned int offset) +{ + struct tps65219_gpio *gpio = gpiochip_get_data(gc); + int ret, val; + + if (offset != TPS65219_GPIO0_IDX) + return GPIO_LINE_DIRECTION_OUT; + + ret = regmap_read(gpio->tps->regmap, TPS65219_REG_MFP_1_CONFIG, &val); + if (ret) + return ret; + + return !!(val & TPS65219_GPIO0_DIR_MASK); +} + +static int tps65219_gpio_get(struct gpio_chip *gc, unsigned int offset) +{ + struct tps65219_gpio *gpio = gpiochip_get_data(gc); + struct device *dev = gpio->tps->dev; + int ret, val; + + if (offset != TPS65219_GPIO0_IDX) { + dev_err(dev, "GPIO%d is output only, cannot get\n", offset); + return -ENOTSUPP; + } + + ret = regmap_read(gpio->tps->regmap, TPS65219_REG_MFP_CTRL, &val); + if (ret) + return ret; + + ret = !!(val & BIT(TPS65219_MFP_GPIO_STATUS_MASK)); + dev_warn(dev, "GPIO%d = %d, MULTI_DEVICE_ENABLE, not a standard GPIO\n", offset, ret); + + /* + * Depending on NVM config, return an error if direction is output, otherwise the GPIO0 + * status bit. + */ + + if (tps65219_gpio_get_direction(gc, offset) == TPS65219_GPIO_DIR_OUT) + return -ENOTSUPP; + + return ret; +} + +static void tps65219_gpio_set(struct gpio_chip *gc, unsigned int offset, int value) +{ + struct tps65219_gpio *gpio = gpiochip_get_data(gc); + struct device *dev = gpio->tps->dev; + int v, mask, bit; + + bit = (offset == TPS65219_GPIO0_IDX) ? TPS65219_GPIO0_OFFSET : offset - 1; + + mask = BIT(bit); + v = value ? mask : 0; + + if (regmap_update_bits(gpio->tps->regmap, TPS65219_REG_GENERAL_CONFIG, mask, v)) + dev_err(dev, "GPIO%d, set to value %d failed.\n", offset, value); +} + +static int tps65219_gpio_change_direction(struct gpio_chip *gc, unsigned int offset, + unsigned int direction) +{ + struct tps65219_gpio *gpio = gpiochip_get_data(gc); + struct device *dev = gpio->tps->dev; + + /* + * Documentation is stating that GPIO0 direction must not be changed in Linux: + * Table 8-34. MFP_1_CONFIG(3): MULTI_DEVICE_ENABLE, should only be changed in INITIALIZE + * state (prior to ON Request). + * Set statically by NVM, changing direction in application can cause a hang. + * Below can be used for test purpose only. + */ + + if (IS_ENABLED(CONFIG_DEBUG_GPIO)) { + int ret = regmap_update_bits(gpio->tps->regmap, TPS65219_REG_MFP_1_CONFIG, + TPS65219_GPIO0_DIR_MASK, direction); + if (ret) { + dev_err(dev, + "GPIO DEBUG enabled: Fail to change direction to %u for GPIO%d.\n", + direction, offset); + return ret; + } + } + + dev_err(dev, + "GPIO%d direction set by NVM, change to %u failed, not allowed by specification\n", + offset, direction); + + return -ENOTSUPP; +} + +static int tps65219_gpio_direction_input(struct gpio_chip *gc, unsigned int offset) +{ + struct tps65219_gpio *gpio = gpiochip_get_data(gc); + struct device *dev = gpio->tps->dev; + + if (offset != TPS65219_GPIO0_IDX) { + dev_err(dev, "GPIO%d is output only, cannot change to input\n", offset); + return -ENOTSUPP; + } + + if (tps65219_gpio_get_direction(gc, offset) == TPS65219_GPIO_DIR_IN) + return 0; + + return tps65219_gpio_change_direction(gc, offset, TPS65219_GPIO_DIR_IN); +} + +static int tps65219_gpio_direction_output(struct gpio_chip *gc, unsigned int offset, int value) +{ + tps65219_gpio_set(gc, offset, value); + if (offset != TPS65219_GPIO0_IDX) + return 0; + + if (tps65219_gpio_get_direction(gc, offset) == TPS65219_GPIO_DIR_OUT) + return 0; + + return tps65219_gpio_change_direction(gc, offset, TPS65219_GPIO_DIR_OUT); +} + +static const struct gpio_chip tps65219_template_chip = { + .label = "tps65219-gpio", + .owner = THIS_MODULE, + .get_direction = tps65219_gpio_get_direction, + .direction_input = tps65219_gpio_direction_input, + .direction_output = tps65219_gpio_direction_output, + .get = tps65219_gpio_get, + .set = tps65219_gpio_set, + .base = -1, + .ngpio = 3, + .can_sleep = true, +}; + +static int tps65219_gpio_probe(struct platform_device *pdev) +{ + struct tps65219 *tps = dev_get_drvdata(pdev->dev.parent); + struct tps65219_gpio *gpio; + + gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL); + if (!gpio) + return -ENOMEM; + + gpio->tps = tps; + gpio->gpio_chip = tps65219_template_chip; + gpio->gpio_chip.parent = tps->dev; + + return devm_gpiochip_add_data(&pdev->dev, &gpio->gpio_chip, gpio); +} + +static struct platform_driver tps65219_gpio_driver = { + .driver = { + .name = "tps65219-gpio", + }, + .probe = tps65219_gpio_probe, +}; +module_platform_driver(tps65219_gpio_driver); + +MODULE_ALIAS("platform:tps65219-gpio"); +MODULE_AUTHOR("Jonathan Cormier <jcormier@criticallink.com>"); +MODULE_DESCRIPTION("TPS65219 GPIO driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/gpio/gpio-ts4900.c b/drivers/gpio/gpio-ts4900.c index 43e8b66e04f7..eba96319dac2 100644 --- a/drivers/gpio/gpio-ts4900.c +++ b/drivers/gpio/gpio-ts4900.c @@ -185,7 +185,7 @@ static struct i2c_driver ts4900_gpio_driver = { .name = "ts4900-gpio", .of_match_table = ts4900_gpio_of_match_table, }, - .probe_new = ts4900_gpio_probe, + .probe = ts4900_gpio_probe, .id_table = ts4900_gpio_id_table, }; module_i2c_driver(ts4900_gpio_driver); diff --git a/drivers/gpio/gpio-twl4030.c b/drivers/gpio/gpio-twl4030.c index c1bb2c3ca6f2..bcd692229c7c 100644 --- a/drivers/gpio/gpio-twl4030.c +++ b/drivers/gpio/gpio-twl4030.c @@ -17,7 +17,9 @@ #include <linux/interrupt.h> #include <linux/kthread.h> #include <linux/irq.h> +#include <linux/gpio/machine.h> #include <linux/gpio/driver.h> +#include <linux/gpio/consumer.h> #include <linux/platform_device.h> #include <linux/of.h> #include <linux/irqdomain.h> @@ -465,8 +467,7 @@ static int gpio_twl4030_debounce(u32 debounce, u8 mmc_cd) REG_GPIO_DEBEN1, 3); } -static struct twl4030_gpio_platform_data *of_gpio_twl4030(struct device *dev, - struct twl4030_gpio_platform_data *pdata) +static struct twl4030_gpio_platform_data *of_gpio_twl4030(struct device *dev) { struct twl4030_gpio_platform_data *omap_twl_info; @@ -474,9 +475,6 @@ static struct twl4030_gpio_platform_data *of_gpio_twl4030(struct device *dev, if (!omap_twl_info) return NULL; - if (pdata) - *omap_twl_info = *pdata; - omap_twl_info->use_leds = of_property_read_bool(dev->of_node, "ti,use-leds"); @@ -492,21 +490,18 @@ static struct twl4030_gpio_platform_data *of_gpio_twl4030(struct device *dev, return omap_twl_info; } -/* Cannot use as gpio_twl4030_probe() calls us */ -static int gpio_twl4030_remove(struct platform_device *pdev) +/* Called from the registered devm action */ +static void gpio_twl4030_power_off_action(void *data) { - struct gpio_twl4030_priv *priv = platform_get_drvdata(pdev); - - gpiochip_remove(&priv->gpio_chip); + struct gpio_desc *d = data; - /* REVISIT no support yet for deregistering all the IRQs */ - WARN_ON(!is_module()); - return 0; + gpiod_unexport(d); + gpiochip_free_own_desc(d); } static int gpio_twl4030_probe(struct platform_device *pdev) { - struct twl4030_gpio_platform_data *pdata = dev_get_platdata(&pdev->dev); + struct twl4030_gpio_platform_data *pdata; struct device_node *node = pdev->dev.of_node; struct gpio_twl4030_priv *priv; int ret, irq_base; @@ -546,9 +541,7 @@ no_irqs: mutex_init(&priv->mutex); - if (node) - pdata = of_gpio_twl4030(&pdev->dev, pdata); - + pdata = of_gpio_twl4030(&pdev->dev); if (pdata == NULL) { dev_err(&pdev->dev, "Platform data is missing\n"); return -ENXIO; @@ -577,27 +570,39 @@ no_irqs: if (pdata->use_leds) priv->gpio_chip.ngpio += 2; - ret = gpiochip_add_data(&priv->gpio_chip, priv); + ret = devm_gpiochip_add_data(&pdev->dev, &priv->gpio_chip, priv); if (ret < 0) { dev_err(&pdev->dev, "could not register gpiochip, %d\n", ret); priv->gpio_chip.ngpio = 0; - gpio_twl4030_remove(pdev); - goto out; + return ret; } - platform_set_drvdata(pdev, priv); + /* + * Special quirk for the OMAP3 to hog and export a WLAN power + * GPIO. + */ + if (IS_ENABLED(CONFIG_ARCH_OMAP3) && + of_machine_is_compatible("compulab,omap3-sbc-t3730")) { + struct gpio_desc *d; + + d = gpiochip_request_own_desc(&priv->gpio_chip, + 2, "wlan pwr", + GPIO_ACTIVE_HIGH, + GPIOD_OUT_HIGH); + if (IS_ERR(d)) + return dev_err_probe(&pdev->dev, PTR_ERR(d), + "unable to hog wlan pwr GPIO\n"); + + gpiod_export(d, 0); - if (pdata->setup) { - int status; + ret = devm_add_action_or_reset(&pdev->dev, gpio_twl4030_power_off_action, d); + if (ret) + return dev_err_probe(&pdev->dev, ret, + "failed to install power off handler\n"); - status = pdata->setup(&pdev->dev, priv->gpio_chip.base, - TWL4030_GPIO_MAX); - if (status) - dev_dbg(&pdev->dev, "setup --> %d\n", status); } -out: - return ret; + return 0; } static const struct of_device_id twl_gpio_match[] = { @@ -615,7 +620,6 @@ static struct platform_driver gpio_twl4030_driver = { .of_match_table = twl_gpio_match, }, .probe = gpio_twl4030_probe, - .remove = gpio_twl4030_remove, }; static int __init gpio_twl4030_init(void) diff --git a/drivers/gpio/gpio-xra1403.c b/drivers/gpio/gpio-xra1403.c index 51d6119e1bb4..bbc06cdd9634 100644 --- a/drivers/gpio/gpio-xra1403.c +++ b/drivers/gpio/gpio-xra1403.c @@ -11,7 +11,6 @@ #include <linux/module.h> #include <linux/mutex.h> #include <linux/of_device.h> -#include <linux/of_gpio.h> #include <linux/seq_file.h> #include <linux/spi/spi.h> #include <linux/regmap.h> diff --git a/drivers/gpio/gpio-zynq.c b/drivers/gpio/gpio-zynq.c index 06c6401f02b8..0a7264aabe48 100644 --- a/drivers/gpio/gpio-zynq.c +++ b/drivers/gpio/gpio-zynq.c @@ -151,8 +151,8 @@ struct zynq_platform_data { int bank_max[ZYNQMP_GPIO_MAX_BANK]; }; -static struct irq_chip zynq_gpio_level_irqchip; -static struct irq_chip zynq_gpio_edge_irqchip; +static const struct irq_chip zynq_gpio_level_irqchip; +static const struct irq_chip zynq_gpio_edge_irqchip; /** * zynq_gpio_is_zynq - test if HW is zynq or zynqmp @@ -404,9 +404,12 @@ static int zynq_gpio_get_direction(struct gpio_chip *chip, unsigned int pin) static void zynq_gpio_irq_mask(struct irq_data *irq_data) { unsigned int device_pin_num, bank_num, bank_pin_num; + const unsigned long offset = irqd_to_hwirq(irq_data); + struct gpio_chip *chip = irq_data_get_irq_chip_data(irq_data); struct zynq_gpio *gpio = gpiochip_get_data(irq_data_get_irq_chip_data(irq_data)); + gpiochip_disable_irq(chip, offset); device_pin_num = irq_data->hwirq; zynq_gpio_get_bank_pin(device_pin_num, &bank_num, &bank_pin_num, gpio); writel_relaxed(BIT(bank_pin_num), @@ -425,9 +428,12 @@ static void zynq_gpio_irq_mask(struct irq_data *irq_data) static void zynq_gpio_irq_unmask(struct irq_data *irq_data) { unsigned int device_pin_num, bank_num, bank_pin_num; + const unsigned long offset = irqd_to_hwirq(irq_data); + struct gpio_chip *chip = irq_data_get_irq_chip_data(irq_data); struct zynq_gpio *gpio = gpiochip_get_data(irq_data_get_irq_chip_data(irq_data)); + gpiochip_enable_irq(chip, offset); device_pin_num = irq_data->hwirq; zynq_gpio_get_bank_pin(device_pin_num, &bank_num, &bank_pin_num, gpio); writel_relaxed(BIT(bank_pin_num), @@ -569,28 +575,8 @@ static int zynq_gpio_set_wake(struct irq_data *data, unsigned int on) return 0; } -static int zynq_gpio_irq_reqres(struct irq_data *d) -{ - struct gpio_chip *chip = irq_data_get_irq_chip_data(d); - int ret; - - ret = pm_runtime_resume_and_get(chip->parent); - if (ret < 0) - return ret; - - return gpiochip_reqres_irq(chip, d->hwirq); -} - -static void zynq_gpio_irq_relres(struct irq_data *d) -{ - struct gpio_chip *chip = irq_data_get_irq_chip_data(d); - - gpiochip_relres_irq(chip, d->hwirq); - pm_runtime_put(chip->parent); -} - /* irq chip descriptor */ -static struct irq_chip zynq_gpio_level_irqchip = { +static const struct irq_chip zynq_gpio_level_irqchip = { .name = DRIVER_NAME, .irq_enable = zynq_gpio_irq_enable, .irq_eoi = zynq_gpio_irq_ack, @@ -598,13 +584,12 @@ static struct irq_chip zynq_gpio_level_irqchip = { .irq_unmask = zynq_gpio_irq_unmask, .irq_set_type = zynq_gpio_set_irq_type, .irq_set_wake = zynq_gpio_set_wake, - .irq_request_resources = zynq_gpio_irq_reqres, - .irq_release_resources = zynq_gpio_irq_relres, .flags = IRQCHIP_EOI_THREADED | IRQCHIP_EOI_IF_HANDLED | - IRQCHIP_MASK_ON_SUSPEND, + IRQCHIP_MASK_ON_SUSPEND | IRQCHIP_IMMUTABLE, + GPIOCHIP_IRQ_RESOURCE_HELPERS, }; -static struct irq_chip zynq_gpio_edge_irqchip = { +static const struct irq_chip zynq_gpio_edge_irqchip = { .name = DRIVER_NAME, .irq_enable = zynq_gpio_irq_enable, .irq_ack = zynq_gpio_irq_ack, @@ -612,9 +597,8 @@ static struct irq_chip zynq_gpio_edge_irqchip = { .irq_unmask = zynq_gpio_irq_unmask, .irq_set_type = zynq_gpio_set_irq_type, .irq_set_wake = zynq_gpio_set_wake, - .irq_request_resources = zynq_gpio_irq_reqres, - .irq_release_resources = zynq_gpio_irq_relres, - .flags = IRQCHIP_MASK_ON_SUSPEND, + .flags = IRQCHIP_MASK_ON_SUSPEND | IRQCHIP_IMMUTABLE, + GPIOCHIP_IRQ_RESOURCE_HELPERS, }; static void zynq_gpio_handle_bank_irq(struct zynq_gpio *gpio, @@ -962,7 +946,7 @@ static int zynq_gpio_probe(struct platform_device *pdev) /* Set up the GPIO irqchip */ girq = &chip->irq; - girq->chip = &zynq_gpio_edge_irqchip; + gpio_irq_chip_set_chip(girq, &zynq_gpio_edge_irqchip); girq->parent_handler = zynq_gpio_irqhandler; girq->num_parents = 1; girq->parents = devm_kcalloc(&pdev->dev, 1, diff --git a/drivers/gpio/gpiolib-legacy.c b/drivers/gpio/gpiolib-legacy.c index 30e2476a6dc4..97f4b498e343 100644 --- a/drivers/gpio/gpiolib-legacy.c +++ b/drivers/gpio/gpiolib-legacy.c @@ -33,12 +33,6 @@ int gpio_request_one(unsigned gpio, unsigned long flags, const char *label) if (err) return err; - if (flags & GPIOF_OPEN_DRAIN) - set_bit(FLAG_OPEN_DRAIN, &desc->flags); - - if (flags & GPIOF_OPEN_SOURCE) - set_bit(FLAG_OPEN_SOURCE, &desc->flags); - if (flags & GPIOF_ACTIVE_LOW) set_bit(FLAG_ACTIVE_LOW, &desc->flags); @@ -51,12 +45,6 @@ int gpio_request_one(unsigned gpio, unsigned long flags, const char *label) if (err) goto free_gpio; - if (flags & GPIOF_EXPORT) { - err = gpiod_export(desc, flags & GPIOF_EXPORT_CHANGEABLE); - if (err) - goto free_gpio; - } - return 0; free_gpio: diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 5be8ad61523e..251c875b5c34 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -465,6 +465,12 @@ static unsigned long *gpiochip_allocate_mask(struct gpio_chip *gc) return p; } +static void gpiochip_free_mask(unsigned long **p) +{ + bitmap_free(*p); + *p = NULL; +} + static unsigned int gpiochip_count_reserved_ranges(struct gpio_chip *gc) { struct device *dev = &gc->gpiodev->dev; @@ -478,18 +484,6 @@ static unsigned int gpiochip_count_reserved_ranges(struct gpio_chip *gc) return 0; } -static int gpiochip_alloc_valid_mask(struct gpio_chip *gc) -{ - if (!(gpiochip_count_reserved_ranges(gc) || gc->init_valid_mask)) - return 0; - - gc->valid_mask = gpiochip_allocate_mask(gc); - if (!gc->valid_mask) - return -ENOMEM; - - return 0; -} - static int gpiochip_apply_reserved_ranges(struct gpio_chip *gc) { struct device *dev = &gc->gpiodev->dev; @@ -530,6 +524,13 @@ static int gpiochip_init_valid_mask(struct gpio_chip *gc) { int ret; + if (!(gpiochip_count_reserved_ranges(gc) || gc->init_valid_mask)) + return 0; + + gc->valid_mask = gpiochip_allocate_mask(gc); + if (!gc->valid_mask) + return -ENOMEM; + ret = gpiochip_apply_reserved_ranges(gc); if (ret) return ret; @@ -544,8 +545,7 @@ static int gpiochip_init_valid_mask(struct gpio_chip *gc) static void gpiochip_free_valid_mask(struct gpio_chip *gc) { - bitmap_free(gc->valid_mask); - gc->valid_mask = NULL; + gpiochip_free_mask(&gc->valid_mask); } static int gpiochip_add_pin_ranges(struct gpio_chip *gc) @@ -857,7 +857,7 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data, if (ret) goto err_remove_from_list; - ret = gpiochip_alloc_valid_mask(gc); + ret = gpiochip_init_valid_mask(gc); if (ret) goto err_remove_from_list; @@ -865,10 +865,6 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data, if (ret) goto err_free_gpiochip_mask; - ret = gpiochip_init_valid_mask(gc); - if (ret) - goto err_remove_of_chip; - for (i = 0; i < gc->ngpio; i++) { struct gpio_desc *desc = &gdev->descs[i]; @@ -1089,8 +1085,7 @@ static int gpiochip_irqchip_init_valid_mask(struct gpio_chip *gc) static void gpiochip_irqchip_free_valid_mask(struct gpio_chip *gc) { - bitmap_free(gc->irq.valid_mask); - gc->irq.valid_mask = NULL; + gpiochip_free_mask(&gc->irq.valid_mask); } bool gpiochip_irqchip_irq_valid(const struct gpio_chip *gc, @@ -1676,11 +1671,10 @@ static int gpiochip_add_irqchip(struct gpio_chip *gc, if (ret) return ret; } else { - /* Some drivers provide custom irqdomain ops */ gc->irq.domain = irq_domain_create_simple(fwnode, gc->ngpio, gc->irq.first, - gc->irq.domain_ops ?: &gpiochip_domain_ops, + &gpiochip_domain_ops, gc); if (!gc->irq.domain) return -EINVAL; @@ -2133,8 +2127,6 @@ static bool gpiod_free_commit(struct gpio_desc *desc) might_sleep(); - gpiod_unexport(desc); - spin_lock_irqsave(&gpio_lock, flags); gc = desc->gdev->chip; @@ -4252,7 +4244,7 @@ int gpiod_hog(struct gpio_desc *desc, const char *name, /* Mark GPIO as hogged so it can be identified and removed later */ set_bit(FLAG_IS_HOGGED, &desc->flags); - gpiod_info(desc, "hogged as %s%s\n", + gpiod_dbg(desc, "hogged as %s%s\n", (dflags & GPIOD_FLAGS_BIT_DIR_OUT) ? "output" : "input", (dflags & GPIOD_FLAGS_BIT_DIR_OUT) ? (dflags & GPIOD_FLAGS_BIT_DIR_VAL) ? "/high" : "/low" : ""); diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c index bb1058b1e7fd..40eb27f1b23f 100644 --- a/drivers/input/touchscreen/ads7846.c +++ b/drivers/input/touchscreen/ads7846.c @@ -24,11 +24,8 @@ #include <linux/interrupt.h> #include <linux/slab.h> #include <linux/pm.h> -#include <linux/of.h> -#include <linux/of_gpio.h> -#include <linux/of_device.h> +#include <linux/property.h> #include <linux/gpio/consumer.h> -#include <linux/gpio.h> #include <linux/spi/spi.h> #include <linux/spi/ads7846.h> #include <linux/regulator/consumer.h> @@ -140,7 +137,7 @@ struct ads7846 { int (*filter)(void *data, int data_idx, int *val); void *filter_data; int (*get_pendown_state)(void); - int gpio_pendown; + struct gpio_desc *gpio_pendown; void (*wait_for_sync)(void); }; @@ -223,7 +220,7 @@ static int get_pendown_state(struct ads7846 *ts) if (ts->get_pendown_state) return ts->get_pendown_state(); - return !gpio_get_value(ts->gpio_pendown); + return gpiod_get_value(ts->gpio_pendown); } static void ads7846_report_pen_up(struct ads7846 *ts) @@ -989,8 +986,6 @@ static int ads7846_setup_pendown(struct spi_device *spi, struct ads7846 *ts, const struct ads7846_platform_data *pdata) { - int err; - /* * REVISIT when the irq can be triggered active-low, or if for some * reason the touchscreen isn't hooked up, we don't need to access @@ -999,25 +994,15 @@ static int ads7846_setup_pendown(struct spi_device *spi, if (pdata->get_pendown_state) { ts->get_pendown_state = pdata->get_pendown_state; - } else if (gpio_is_valid(pdata->gpio_pendown)) { - - err = devm_gpio_request_one(&spi->dev, pdata->gpio_pendown, - GPIOF_IN, "ads7846_pendown"); - if (err) { - dev_err(&spi->dev, - "failed to request/setup pendown GPIO%d: %d\n", - pdata->gpio_pendown, err); - return err; + } else { + ts->gpio_pendown = gpiod_get(&spi->dev, "pendown", GPIOD_IN); + if (IS_ERR(ts->gpio_pendown)) { + dev_err(&spi->dev, "failed to request pendown GPIO\n"); + return PTR_ERR(ts->gpio_pendown); } - - ts->gpio_pendown = pdata->gpio_pendown; - if (pdata->gpio_pendown_debounce) - gpiod_set_debounce(gpio_to_desc(ts->gpio_pendown), + gpiod_set_debounce(ts->gpio_pendown, pdata->gpio_pendown_debounce); - } else { - dev_err(&spi->dev, "no get_pendown_state nor gpio_pendown?\n"); - return -EINVAL; } return 0; @@ -1119,7 +1104,6 @@ static int ads7846_setup_spi_msg(struct ads7846 *ts, return 0; } -#ifdef CONFIG_OF static const struct of_device_id ads7846_dt_ids[] = { { .compatible = "ti,tsc2046", .data = (void *) 7846 }, { .compatible = "ti,ads7843", .data = (void *) 7843 }, @@ -1130,20 +1114,14 @@ static const struct of_device_id ads7846_dt_ids[] = { }; MODULE_DEVICE_TABLE(of, ads7846_dt_ids); -static const struct ads7846_platform_data *ads7846_probe_dt(struct device *dev) +static const struct ads7846_platform_data *ads7846_get_props(struct device *dev) { struct ads7846_platform_data *pdata; - struct device_node *node = dev->of_node; - const struct of_device_id *match; + const struct platform_device_id *pdev_id; u32 value; - if (!node) { - dev_err(dev, "Device does not have associated DT data\n"); - return ERR_PTR(-EINVAL); - } - - match = of_match_device(ads7846_dt_ids, dev); - if (!match) { + pdev_id = device_get_match_data(dev); + if (!pdev_id) { dev_err(dev, "Unknown device model\n"); return ERR_PTR(-EINVAL); } @@ -1152,60 +1130,51 @@ static const struct ads7846_platform_data *ads7846_probe_dt(struct device *dev) if (!pdata) return ERR_PTR(-ENOMEM); - pdata->model = (unsigned long)match->data; + pdata->model = (unsigned long)pdev_id->driver_data; - of_property_read_u16(node, "ti,vref-delay-usecs", - &pdata->vref_delay_usecs); - of_property_read_u16(node, "ti,vref-mv", &pdata->vref_mv); - pdata->keep_vref_on = of_property_read_bool(node, "ti,keep-vref-on"); + device_property_read_u16(dev, "ti,vref-delay-usecs", + &pdata->vref_delay_usecs); + device_property_read_u16(dev, "ti,vref-mv", &pdata->vref_mv); + pdata->keep_vref_on = device_property_read_bool(dev, "ti,keep-vref-on"); - pdata->swap_xy = of_property_read_bool(node, "ti,swap-xy"); + pdata->swap_xy = device_property_read_bool(dev, "ti,swap-xy"); - of_property_read_u16(node, "ti,settle-delay-usec", - &pdata->settle_delay_usecs); - of_property_read_u16(node, "ti,penirq-recheck-delay-usecs", - &pdata->penirq_recheck_delay_usecs); + device_property_read_u16(dev, "ti,settle-delay-usec", + &pdata->settle_delay_usecs); + device_property_read_u16(dev, "ti,penirq-recheck-delay-usecs", + &pdata->penirq_recheck_delay_usecs); - of_property_read_u16(node, "ti,x-plate-ohms", &pdata->x_plate_ohms); - of_property_read_u16(node, "ti,y-plate-ohms", &pdata->y_plate_ohms); + device_property_read_u16(dev, "ti,x-plate-ohms", &pdata->x_plate_ohms); + device_property_read_u16(dev, "ti,y-plate-ohms", &pdata->y_plate_ohms); - of_property_read_u16(node, "ti,x-min", &pdata->x_min); - of_property_read_u16(node, "ti,y-min", &pdata->y_min); - of_property_read_u16(node, "ti,x-max", &pdata->x_max); - of_property_read_u16(node, "ti,y-max", &pdata->y_max); + device_property_read_u16(dev, "ti,x-min", &pdata->x_min); + device_property_read_u16(dev, "ti,y-min", &pdata->y_min); + device_property_read_u16(dev, "ti,x-max", &pdata->x_max); + device_property_read_u16(dev, "ti,y-max", &pdata->y_max); /* * touchscreen-max-pressure gets parsed during * touchscreen_parse_properties() */ - of_property_read_u16(node, "ti,pressure-min", &pdata->pressure_min); - if (!of_property_read_u32(node, "touchscreen-min-pressure", &value)) + device_property_read_u16(dev, "ti,pressure-min", &pdata->pressure_min); + if (!device_property_read_u32(dev, "touchscreen-min-pressure", &value)) pdata->pressure_min = (u16) value; - of_property_read_u16(node, "ti,pressure-max", &pdata->pressure_max); + device_property_read_u16(dev, "ti,pressure-max", &pdata->pressure_max); - of_property_read_u16(node, "ti,debounce-max", &pdata->debounce_max); - if (!of_property_read_u32(node, "touchscreen-average-samples", &value)) + device_property_read_u16(dev, "ti,debounce-max", &pdata->debounce_max); + if (!device_property_read_u32(dev, "touchscreen-average-samples", &value)) pdata->debounce_max = (u16) value; - of_property_read_u16(node, "ti,debounce-tol", &pdata->debounce_tol); - of_property_read_u16(node, "ti,debounce-rep", &pdata->debounce_rep); + device_property_read_u16(dev, "ti,debounce-tol", &pdata->debounce_tol); + device_property_read_u16(dev, "ti,debounce-rep", &pdata->debounce_rep); - of_property_read_u32(node, "ti,pendown-gpio-debounce", + device_property_read_u32(dev, "ti,pendown-gpio-debounce", &pdata->gpio_pendown_debounce); - pdata->wakeup = of_property_read_bool(node, "wakeup-source") || - of_property_read_bool(node, "linux,wakeup"); - - pdata->gpio_pendown = of_get_named_gpio(dev->of_node, "pendown-gpio", 0); + pdata->wakeup = device_property_read_bool(dev, "wakeup-source") || + device_property_read_bool(dev, "linux,wakeup"); return pdata; } -#else -static const struct ads7846_platform_data *ads7846_probe_dt(struct device *dev) -{ - dev_err(dev, "no platform data defined\n"); - return ERR_PTR(-EINVAL); -} -#endif static void ads7846_regulator_disable(void *regulator) { @@ -1269,7 +1238,7 @@ static int ads7846_probe(struct spi_device *spi) pdata = dev_get_platdata(dev); if (!pdata) { - pdata = ads7846_probe_dt(dev); + pdata = ads7846_get_props(dev); if (IS_ERR(pdata)) return PTR_ERR(pdata); } @@ -1426,7 +1395,7 @@ static struct spi_driver ads7846_driver = { .driver = { .name = "ads7846", .pm = pm_sleep_ptr(&ads7846_pm), - .of_match_table = of_match_ptr(ads7846_dt_ids), + .of_match_table = ads7846_dt_ids, }, .probe = ads7846_probe, .remove = ads7846_remove, diff --git a/drivers/mfd/tps65010.c b/drivers/mfd/tps65010.c index fb733288cca3..faea4ff44c6f 100644 --- a/drivers/mfd/tps65010.c +++ b/drivers/mfd/tps65010.c @@ -506,12 +506,8 @@ static void tps65010_remove(struct i2c_client *client) struct tps65010 *tps = i2c_get_clientdata(client); struct tps65010_board *board = dev_get_platdata(&client->dev); - if (board && board->teardown) { - int status = board->teardown(client, board->context); - if (status < 0) - dev_dbg(&client->dev, "board %s %s err %d\n", - "teardown", client->name, status); - } + if (board && board->teardown) + board->teardown(client, &tps->chip); if (client->irq > 0) free_irq(client->irq, tps); cancel_delayed_work_sync(&tps->work); @@ -619,7 +615,7 @@ static int tps65010_probe(struct i2c_client *client) tps, DEBUG_FOPS); /* optionally register GPIOs */ - if (board && board->base != 0) { + if (board) { tps->outmask = board->outmask; tps->chip.label = client->name; @@ -632,7 +628,7 @@ static int tps65010_probe(struct i2c_client *client) /* NOTE: only partial support for inputs; nyet IRQs */ tps->chip.get = tps65010_gpio_get; - tps->chip.base = board->base; + tps->chip.base = -1; tps->chip.ngpio = 7; tps->chip.can_sleep = 1; @@ -641,7 +637,7 @@ static int tps65010_probe(struct i2c_client *client) dev_err(&client->dev, "can't add gpiochip, err %d\n", status); else if (board->setup) { - status = board->setup(client, board->context); + status = board->setup(client, &tps->chip); if (status < 0) { dev_dbg(&client->dev, "board %s %s err %d\n", diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c index 86454f1182bb..6a259563690d 100644 --- a/drivers/mmc/host/omap.c +++ b/drivers/mmc/host/omap.c @@ -26,6 +26,7 @@ #include <linux/clk.h> #include <linux/scatterlist.h> #include <linux/slab.h> +#include <linux/gpio/consumer.h> #include <linux/platform_data/mmc-omap.h> @@ -111,6 +112,9 @@ struct mmc_omap_slot { struct mmc_request *mrq; struct mmc_omap_host *host; struct mmc_host *mmc; + struct gpio_desc *vsd; + struct gpio_desc *vio; + struct gpio_desc *cover; struct omap_mmc_slot_data *pdata; }; @@ -133,6 +137,7 @@ struct mmc_omap_host { int irq; unsigned char bus_mode; unsigned int reg_shift; + struct gpio_desc *slot_switch; struct work_struct cmd_abort_work; unsigned abort:1; @@ -216,8 +221,13 @@ no_claim: if (host->current_slot != slot) { OMAP_MMC_WRITE(host, CON, slot->saved_con & 0xFC00); - if (host->pdata->switch_slot != NULL) - host->pdata->switch_slot(mmc_dev(slot->mmc), slot->id); + if (host->slot_switch) + /* + * With two slots and a simple GPIO switch, setting + * the GPIO to 0 selects slot ID 0, setting it to 1 + * selects slot ID 1. + */ + gpiod_set_value(host->slot_switch, slot->id); host->current_slot = slot; } @@ -297,6 +307,9 @@ static void mmc_omap_release_slot(struct mmc_omap_slot *slot, int clk_enabled) static inline int mmc_omap_cover_is_open(struct mmc_omap_slot *slot) { + /* If we have a GPIO then use that */ + if (slot->cover) + return gpiod_get_value(slot->cover); if (slot->pdata->get_cover_state) return slot->pdata->get_cover_state(mmc_dev(slot->mmc), slot->id); @@ -1106,6 +1119,11 @@ static void mmc_omap_set_power(struct mmc_omap_slot *slot, int power_on, host = slot->host; + if (slot->vsd) + gpiod_set_value(slot->vsd, power_on); + if (slot->vio) + gpiod_set_value(slot->vio, power_on); + if (slot->pdata->set_power != NULL) slot->pdata->set_power(mmc_dev(slot->mmc), slot->id, power_on, vdd); @@ -1240,6 +1258,23 @@ static int mmc_omap_new_slot(struct mmc_omap_host *host, int id) slot->power_mode = MMC_POWER_UNDEFINED; slot->pdata = &host->pdata->slots[id]; + /* Check for some optional GPIO controls */ + slot->vsd = gpiod_get_index_optional(host->dev, "vsd", + id, GPIOD_OUT_LOW); + if (IS_ERR(slot->vsd)) + return dev_err_probe(host->dev, PTR_ERR(slot->vsd), + "error looking up VSD GPIO\n"); + slot->vio = gpiod_get_index_optional(host->dev, "vio", + id, GPIOD_OUT_LOW); + if (IS_ERR(slot->vio)) + return dev_err_probe(host->dev, PTR_ERR(slot->vio), + "error looking up VIO GPIO\n"); + slot->cover = gpiod_get_index_optional(host->dev, "cover", + id, GPIOD_IN); + if (IS_ERR(slot->cover)) + return dev_err_probe(host->dev, PTR_ERR(slot->cover), + "error looking up cover switch GPIO\n"); + host->slots[id] = slot; mmc->caps = 0; @@ -1349,6 +1384,13 @@ static int mmc_omap_probe(struct platform_device *pdev) if (IS_ERR(host->virt_base)) return PTR_ERR(host->virt_base); + host->slot_switch = gpiod_get_optional(host->dev, "switch", + GPIOD_OUT_LOW); + if (IS_ERR(host->slot_switch)) + return dev_err_probe(host->dev, PTR_ERR(host->slot_switch), + "error looking up slot switch GPIO\n"); + + INIT_WORK(&host->slot_release_work, mmc_omap_slot_release_work); INIT_WORK(&host->send_stop_work, mmc_omap_send_stop_work); diff --git a/drivers/of/unittest.c b/drivers/of/unittest.c index 2191c0136531..5386efeaf710 100644 --- a/drivers/of/unittest.c +++ b/drivers/of/unittest.c @@ -1844,26 +1844,10 @@ static void __init of_unittest_overlay_gpio(void) unittest(overlay_data_apply("overlay_gpio_02b", NULL), "Adding overlay 'overlay_gpio_02b' failed\n"); - /* - * messages are the result of the probes, after the - * driver is registered - */ - - EXPECT_BEGIN(KERN_INFO, - "gpio-<<int>> (line-B-input): hogged as input\n"); - - EXPECT_BEGIN(KERN_INFO, - "gpio-<<int>> (line-A-input): hogged as input\n"); - ret = platform_driver_register(&unittest_gpio_driver); if (unittest(ret == 0, "could not register unittest gpio driver\n")) return; - EXPECT_END(KERN_INFO, - "gpio-<<int>> (line-A-input): hogged as input\n"); - EXPECT_END(KERN_INFO, - "gpio-<<int>> (line-B-input): hogged as input\n"); - unittest(probe_pass_count + 2 == unittest_gpio_probe_pass_count, "unittest_gpio_probe() failed or not called\n"); @@ -1888,17 +1872,11 @@ static void __init of_unittest_overlay_gpio(void) probe_pass_count = unittest_gpio_probe_pass_count; chip_request_count = unittest_gpio_chip_request_count; - EXPECT_BEGIN(KERN_INFO, - "gpio-<<int>> (line-D-input): hogged as input\n"); - /* overlay_gpio_03 contains gpio node and child gpio hog node */ unittest(overlay_data_apply("overlay_gpio_03", NULL), "Adding overlay 'overlay_gpio_03' failed\n"); - EXPECT_END(KERN_INFO, - "gpio-<<int>> (line-D-input): hogged as input\n"); - unittest(probe_pass_count + 1 == unittest_gpio_probe_pass_count, "unittest_gpio_probe() failed or not called\n"); @@ -1935,17 +1913,11 @@ static void __init of_unittest_overlay_gpio(void) * - processing gpio for overlay_gpio_04b */ - EXPECT_BEGIN(KERN_INFO, - "gpio-<<int>> (line-C-input): hogged as input\n"); - /* overlay_gpio_04b contains child gpio hog node */ unittest(overlay_data_apply("overlay_gpio_04b", NULL), "Adding overlay 'overlay_gpio_04b' failed\n"); - EXPECT_END(KERN_INFO, - "gpio-<<int>> (line-C-input): hogged as input\n"); - unittest(chip_request_count + 1 == unittest_gpio_chip_request_count, "unittest_gpio_chip_request() called %d times (expected 1 time)\n", unittest_gpio_chip_request_count - chip_request_count); diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index d162afbbe19f..ecbd3784bec3 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -2330,7 +2330,6 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) spin_lock_init(&musb->lock); spin_lock_init(&musb->list_lock); - musb->board_set_power = plat->set_power; musb->min_power = plat->min_power; musb->ops = plat->platform_ops; musb->port_mode = plat->mode; diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h index b7588d11cfc5..91b5b6b66f96 100644 --- a/drivers/usb/musb/musb_core.h +++ b/drivers/usb/musb/musb_core.h @@ -352,8 +352,6 @@ struct musb { u16 epmask; u8 nr_endpoints; - int (*board_set_power)(int state); - u8 min_power; /* vbus for periph, in mA/2 */ enum musb_mode port_mode; diff --git a/drivers/usb/musb/tusb6010.c b/drivers/usb/musb/tusb6010.c index a1f29dbc62e6..cbc707fe570f 100644 --- a/drivers/usb/musb/tusb6010.c +++ b/drivers/usb/musb/tusb6010.c @@ -11,6 +11,8 @@ * interface. */ +#include <linux/gpio/consumer.h> +#include <linux/delay.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/errno.h> @@ -30,6 +32,8 @@ struct tusb6010_glue { struct device *dev; struct platform_device *musb; struct platform_device *phy; + struct gpio_desc *enable; + struct gpio_desc *intpin; }; static void tusb_musb_set_vbus(struct musb *musb, int is_on); @@ -1021,16 +1025,29 @@ static void tusb_setup_cpu_interface(struct musb *musb) static int tusb_musb_start(struct musb *musb) { + struct tusb6010_glue *glue = dev_get_drvdata(musb->controller->parent); void __iomem *tbase = musb->ctrl_base; - int ret = 0; unsigned long flags; u32 reg; + int i; - if (musb->board_set_power) - ret = musb->board_set_power(1); - if (ret != 0) { - printk(KERN_ERR "tusb: Cannot enable TUSB6010\n"); - return ret; + /* + * Enable or disable power to TUSB6010. When enabling, turn on 3.3 V and + * 1.5 V voltage regulators of PM companion chip. Companion chip will then + * provide then PGOOD signal to TUSB6010 which will release it from reset. + */ + gpiod_set_value(glue->enable, 1); + msleep(1); + + /* Wait for 100ms until TUSB6010 pulls INT pin down */ + i = 100; + while (i && gpiod_get_value(glue->intpin)) { + msleep(1); + i--; + } + if (!i) { + pr_err("tusb: Powerup respones failed\n"); + return -ENODEV; } spin_lock_irqsave(&musb->lock, flags); @@ -1083,8 +1100,8 @@ static int tusb_musb_start(struct musb *musb) err: spin_unlock_irqrestore(&musb->lock, flags); - if (musb->board_set_power) - musb->board_set_power(0); + gpiod_set_value(glue->enable, 0); + msleep(10); return -ENODEV; } @@ -1158,11 +1175,13 @@ done: static int tusb_musb_exit(struct musb *musb) { + struct tusb6010_glue *glue = dev_get_drvdata(musb->controller->parent); + del_timer_sync(&musb->dev_timer); the_musb = NULL; - if (musb->board_set_power) - musb->board_set_power(0); + gpiod_set_value(glue->enable, 0); + msleep(10); iounmap(musb->sync_va); @@ -1218,6 +1237,15 @@ static int tusb_probe(struct platform_device *pdev) glue->dev = &pdev->dev; + glue->enable = devm_gpiod_get(glue->dev, "enable", GPIOD_OUT_LOW); + if (IS_ERR(glue->enable)) + return dev_err_probe(glue->dev, PTR_ERR(glue->enable), + "could not obtain power on/off GPIO\n"); + glue->intpin = devm_gpiod_get(glue->dev, "int", GPIOD_IN); + if (IS_ERR(glue->intpin)) + return dev_err_probe(glue->dev, PTR_ERR(glue->intpin), + "could not obtain INT GPIO\n"); + pdata->platform_ops = &tusb_ops; usb_phy_generic_register(); @@ -1236,10 +1264,7 @@ static int tusb_probe(struct platform_device *pdev) musb_resources[1].end = pdev->resource[1].end; musb_resources[1].flags = pdev->resource[1].flags; - musb_resources[2].name = pdev->resource[2].name; - musb_resources[2].start = pdev->resource[2].start; - musb_resources[2].end = pdev->resource[2].end; - musb_resources[2].flags = pdev->resource[2].flags; + musb_resources[2] = DEFINE_RES_IRQ_NAMED(gpiod_to_irq(glue->intpin), "mc"); pinfo = tusb_dev_info; pinfo.parent = &pdev->dev; diff --git a/drivers/video/fbdev/omap/lcd_mipid.c b/drivers/video/fbdev/omap/lcd_mipid.c index 03cff39d392d..e4a7f0b824ff 100644 --- a/drivers/video/fbdev/omap/lcd_mipid.c +++ b/drivers/video/fbdev/omap/lcd_mipid.c @@ -7,6 +7,7 @@ */ #include <linux/device.h> #include <linux/delay.h> +#include <linux/gpio/consumer.h> #include <linux/slab.h> #include <linux/workqueue.h> #include <linux/spi/spi.h> @@ -41,6 +42,7 @@ struct mipid_device { when we can issue the next sleep in/out command */ unsigned long hw_guard_wait; /* max guard time in jiffies */ + struct gpio_desc *reset; struct omapfb_device *fbdev; struct spi_device *spi; @@ -556,6 +558,12 @@ static int mipid_spi_probe(struct spi_device *spi) return -ENOMEM; } + /* This will de-assert RESET if active */ + md->reset = gpiod_get(&spi->dev, "reset", GPIOD_OUT_LOW); + if (IS_ERR(md->reset)) + return dev_err_probe(&spi->dev, PTR_ERR(md->reset), + "no reset GPIO line\n"); + spi->mode = SPI_MODE_0; md->spi = spi; dev_set_drvdata(&spi->dev, md); @@ -574,6 +582,8 @@ static void mipid_spi_remove(struct spi_device *spi) { struct mipid_device *md = dev_get_drvdata(&spi->dev); + /* Asserts RESET */ + gpiod_set_value(md->reset, 1); mipid_disable(&md->panel); kfree(md); } diff --git a/include/linux/gpio.h b/include/linux/gpio.h index 8528353e073b..7ecc25c543ce 100644 --- a/include/linux/gpio.h +++ b/include/linux/gpio.h @@ -32,17 +32,6 @@ struct device; /* Gpio pin is active-low */ #define GPIOF_ACTIVE_LOW (1 << 2) -/* Gpio pin is open drain */ -#define GPIOF_OPEN_DRAIN (1 << 3) - -/* Gpio pin is open source */ -#define GPIOF_OPEN_SOURCE (1 << 4) - -#define GPIOF_EXPORT (1 << 5) -#define GPIOF_EXPORT_CHANGEABLE (1 << 6) -#define GPIOF_EXPORT_DIR_FIXED (GPIOF_EXPORT) -#define GPIOF_EXPORT_DIR_CHANGEABLE (GPIOF_EXPORT | GPIOF_EXPORT_CHANGEABLE) - /** * struct gpio - a structure describing a GPIO with configuration * @gpio: the GPIO number @@ -119,11 +108,6 @@ static inline void gpio_set_value(unsigned gpio, int value) return gpiod_set_raw_value(gpio_to_desc(gpio), value); } -static inline int gpio_cansleep(unsigned gpio) -{ - return gpiod_cansleep(gpio_to_desc(gpio)); -} - static inline int gpio_to_irq(unsigned gpio) { return gpiod_to_irq(gpio_to_desc(gpio)); @@ -206,13 +190,6 @@ static inline void gpio_set_value(unsigned gpio, int value) WARN_ON(1); } -static inline int gpio_cansleep(unsigned gpio) -{ - /* GPIO can never have been requested or set as {in,out}put */ - WARN_ON(1); - return 0; -} - static inline int gpio_get_value_cansleep(unsigned gpio) { /* GPIO can never have been requested or set as {in,out}put */ diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h index 67b8774eed8f..4f0c5d62c8f3 100644 --- a/include/linux/gpio/driver.h +++ b/include/linux/gpio/driver.h @@ -61,13 +61,6 @@ struct gpio_irq_chip { */ struct irq_domain *domain; - /** - * @domain_ops: - * - * Table of interrupt domain operations for this IRQ chip. - */ - const struct irq_domain_ops *domain_ops; - #ifdef CONFIG_IRQ_DOMAIN_HIERARCHY /** * @fwnode: diff --git a/include/linux/mfd/tps65010.h b/include/linux/mfd/tps65010.h index a1fb9bc5311d..5edf1aef1118 100644 --- a/include/linux/mfd/tps65010.h +++ b/include/linux/mfd/tps65010.h @@ -28,6 +28,8 @@ #ifndef __LINUX_I2C_TPS65010_H #define __LINUX_I2C_TPS65010_H +struct gpio_chip; + /* * ---------------------------------------------------------------------------- * Registers, all 8 bits @@ -176,12 +178,10 @@ struct i2c_client; /** * struct tps65010_board - packages GPIO and LED lines - * @base: the GPIO number to assign to GPIO-1 * @outmask: bit (N-1) is set to allow GPIO-N to be used as an * (open drain) output * @setup: optional callback issued once the GPIOs are valid * @teardown: optional callback issued before the GPIOs are invalidated - * @context: optional parameter passed to setup() and teardown() * * Board data may be used to package the GPIO (and LED) lines for use * in by the generic GPIO and LED frameworks. The first four GPIOs @@ -193,12 +193,9 @@ struct i2c_client; * devices in their initial states using these GPIOs. */ struct tps65010_board { - int base; unsigned outmask; - - int (*setup)(struct i2c_client *client, void *context); - int (*teardown)(struct i2c_client *client, void *context); - void *context; + int (*setup)(struct i2c_client *client, struct gpio_chip *gc); + void (*teardown)(struct i2c_client *client, struct gpio_chip *gc); }; #endif /* __LINUX_I2C_TPS65010_H */ diff --git a/include/linux/mfd/twl.h b/include/linux/mfd/twl.h index 6e3d99b7a0ee..c062d91a67d9 100644 --- a/include/linux/mfd/twl.h +++ b/include/linux/mfd/twl.h @@ -593,9 +593,6 @@ struct twl4030_gpio_platform_data { */ u32 pullups; u32 pulldowns; - - int (*setup)(struct device *dev, - unsigned gpio, unsigned ngpio); }; struct twl4030_madc_platform_data { diff --git a/include/linux/platform_data/lcd-mipid.h b/include/linux/platform_data/lcd-mipid.h index 63f05eb23827..4927cfc5158c 100644 --- a/include/linux/platform_data/lcd-mipid.h +++ b/include/linux/platform_data/lcd-mipid.h @@ -15,10 +15,8 @@ enum mipid_test_result { #ifdef __KERNEL__ struct mipid_platform_data { - int nreset_gpio; int data_lines; - void (*shutdown)(struct mipid_platform_data *pdata); void (*set_bklight_level)(struct mipid_platform_data *pdata, int level); int (*get_bklight_level)(struct mipid_platform_data *pdata); diff --git a/include/linux/platform_data/mmc-omap.h b/include/linux/platform_data/mmc-omap.h index 91051e9907f3..054d0c3c5ec5 100644 --- a/include/linux/platform_data/mmc-omap.h +++ b/include/linux/platform_data/mmc-omap.h @@ -20,8 +20,6 @@ struct omap_mmc_platform_data { * maximum frequency on the MMC bus */ unsigned int max_freq; - /* switch the bus to a new slot */ - int (*switch_slot)(struct device *dev, int slot); /* initialize board-specific MMC functionality, can be NULL if * not supported */ int (*init)(struct device *dev); diff --git a/include/linux/spi/ads7846.h b/include/linux/spi/ads7846.h index d424c1aadf38..a04c1c34c344 100644 --- a/include/linux/spi/ads7846.h +++ b/include/linux/spi/ads7846.h @@ -35,8 +35,6 @@ struct ads7846_platform_data { u16 debounce_tol; /* tolerance used for filtering */ u16 debounce_rep; /* additional consecutive good readings * required after the first two */ - int gpio_pendown; /* the GPIO used to decide the pendown - * state if get_pendown_state == NULL */ int gpio_pendown_debounce; /* platform specific debounce time for * the gpio_pendown */ int (*get_pendown_state)(void); diff --git a/include/linux/usb/musb.h b/include/linux/usb/musb.h index e4a3ad3c800f..3963e55e88a3 100644 --- a/include/linux/usb/musb.h +++ b/include/linux/usb/musb.h @@ -99,9 +99,6 @@ struct musb_hdrc_platform_data { /* (HOST or OTG) program PHY for external Vbus */ unsigned extvbus:1; - /* Power the device on or off */ - int (*set_power)(int state); - /* MUSB configuration-specific details */ const struct musb_hdrc_config *config; @@ -135,14 +132,4 @@ static inline int musb_mailbox(enum musb_vbus_id_status status) #define TUSB6010_REFCLK_24 41667 /* psec/clk @ 24.0 MHz XI */ #define TUSB6010_REFCLK_19 52083 /* psec/clk @ 19.2 MHz CLKIN */ -#ifdef CONFIG_ARCH_OMAP2 - -extern int __init tusb6010_setup_interface( - struct musb_hdrc_platform_data *data, - unsigned ps_refclk, unsigned waitpin, - unsigned async_cs, unsigned sync_cs, - unsigned irq, unsigned dmachan); - -#endif /* OMAP2 */ - #endif /* __LINUX_USB_MUSB_H */ diff --git a/tools/testing/selftests/gpio/gpio-sim.sh b/tools/testing/selftests/gpio/gpio-sim.sh index fa2ce2b9dd5f..6fb66a687f17 100755 --- a/tools/testing/selftests/gpio/gpio-sim.sh +++ b/tools/testing/selftests/gpio/gpio-sim.sh @@ -152,9 +152,9 @@ sysfs_set_pull() { local PULL=$4 local DEVNAME=`configfs_dev_name $DEV` local CHIPNAME=`configfs_chip_name $DEV $BANK` - local SYSFSPATH="/sys/devices/platform/$DEVNAME/$CHIPNAME/sim_gpio$OFFSET/pull" + local SYSFS_PATH="/sys/devices/platform/$DEVNAME/$CHIPNAME/sim_gpio$OFFSET/pull" - echo $PULL > $SYSFSPATH || fail "Unable to set line pull in sysfs" + echo $PULL > $SYSFS_PATH || fail "Unable to set line pull in sysfs" } # Load the gpio-sim module. This will pull in configfs if needed too. |