mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-12-29 17:25:38 +00:00
gpio updates for v6.5
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 -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEFp3rbAvDxGAT0sefEacuoBRx13IFAmSbB5YACgkQEacuoBRx 13I8xhAAoI9irAnAbh+Lgn0EdziMlqE6E8oohBtRY7rHK7Pi3IZNoATK3GT5bebF a0+EzqOTM22g2qIv41zkG7SyBgdkRg6Ld+/ogvlgddphhEGxY3MdRbSyPacHlzj1 BYnOJt+uQ46TwnzyTjVLn/1aGcD2LPB0j4rS1HnbsDHT8xGAjdq2O3YYNH7ZairA ZbIc/2Cpn4X1YWXX+s3a4B8w1eCEoRNG2Fvie6hmr518TSctP/MiFe6W7+eQrHwT GI491Rr4qT/lmRFVsxslYUPREUe/va8RM3uIC23zEkZYjsbRLJ2tvCGulm8D/H1n rUB9yXj+n5mCjTH7Gebg7J99NKpHo4uoXKrFhhetH9a0adsJCOwBr14YO8NP66jK hmZW8f8+QEAA4nhXx0VqpOp1FGw5unhPF/k8Apct8TeVJCv9i8g5QRreTf1030Hl l8x7JhsHlZGADGeLBPaNBIjuCB99YEMNtl4Ouzh7w1/1JsFcwI/cdASNxrsI4SCf Tl92+xAqZlfnnuHAQFiBBwKxnsHxclBwq3umMQD7kB3cdMELh2gqA3M8F+NGp5SB XMcE3gwDH53fXu74523G36sqNqkLNF0K974LwzSz0t4A8tSlwbt2esvzpxa0bDLe oqYD+TGAvX+uzr05KZ1kyUfD+95mMHsYY9sQWoUzHQelGmXV32M= =3KNJ -----END PGP SIGNATURE----- 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 ...
This commit is contained in:
commit
e5476f57b3
@ -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
|
||||
@ -63,17 +60,6 @@ required:
|
||||
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";
|
79
Documentation/devicetree/bindings/gpio/gpio-delay.yaml
Normal file
79
Documentation/devicetree/bindings/gpio/gpio-delay.yaml
Normal file
@ -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>;
|
||||
};
|
154
Documentation/devicetree/bindings/gpio/gpio-ep9301.yaml
Normal file
154
Documentation/devicetree/bindings/gpio/gpio-ep9301.yaml
Normal file
@ -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>;
|
||||
};
|
||||
|
||||
...
|
117
Documentation/devicetree/bindings/gpio/gpio-mmio.yaml
Normal file
117
Documentation/devicetree/bindings/gpio/gpio-mmio.yaml
Normal file
@ -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>;
|
||||
};
|
@ -24,6 +24,10 @@ properties:
|
||||
'#gpio-cells':
|
||||
const: 2
|
||||
|
||||
gpio-line-names:
|
||||
minItems: 4
|
||||
maxItems: 8
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
@ -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
|
||||
};
|
@ -61,6 +61,13 @@ properties:
|
||||
gpio-ranges:
|
||||
maxItems: 1
|
||||
|
||||
patternProperties:
|
||||
"^.+-hog(-[0-9]+)?$":
|
||||
type: object
|
||||
|
||||
required:
|
||||
- gpio-hog
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
@ -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;
|
||||
};
|
53
Documentation/devicetree/bindings/gpio/st,stmpe-gpio.yaml
Normal file
53
Documentation/devicetree/bindings/gpio/st,stmpe-gpio.yaml
Normal file
@ -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
|
@ -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;
|
||||
};
|
@ -44,6 +44,7 @@ patternProperties:
|
||||
- GPIO0
|
||||
- GPIO1
|
||||
- GPIO2
|
||||
- GPIO3
|
||||
|
||||
function:
|
||||
enum:
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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”,
|
||||
|
@ -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」,
|
||||
|
@ -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
|
||||
|
@ -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>
|
||||
|
@ -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;
|
||||
struct gpio_desc *d;
|
||||
int irq;
|
||||
|
||||
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;
|
||||
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();
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -9,7 +9,6 @@
|
||||
* Copyright (C) 2007 Instituto Nokia de Tecnologia - INdT
|
||||
*/
|
||||
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include "hardware.h"
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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>
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
gpiod_export(gpio_to_desc(cm_t3517_wlan_gpios[0].gpio), 0);
|
||||
gpiod_export(gpio_to_desc(cm_t3517_wlan_gpios[1].gpio), 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)
|
||||
@ -427,9 +430,6 @@ static struct pdata_init auxdata_quirks[] __initdata = {
|
||||
{ "nokia,n800", omap2420_n8x0_legacy_init, },
|
||||
{ "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 */ },
|
||||
};
|
||||
|
@ -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);
|
||||
|
12
arch/arm/mach-omap2/usb-tusb6010.h
Normal file
12
arch/arm/mach-omap2/usb-tusb6010.h
Normal file
@ -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 */
|
@ -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));
|
||||
|
@ -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;
|
||||
|
@ -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));
|
||||
|
||||
|
@ -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) ?
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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.
|
||||
*/
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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>
|
||||
|
@ -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,
|
||||
};
|
||||
|
@ -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,
|
||||
};
|
||||
|
||||
|
248
drivers/gpio/gpio-mlxbf3.c
Normal file
248
drivers/gpio/gpio-mlxbf3.c
Normal file
@ -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");
|
@ -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) {
|
||||
|
@ -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,
|
||||
};
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
};
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
};
|
||||
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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[] = {
|
||||
|
@ -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");
|
||||
|
@ -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");
|
||||
|
185
drivers/gpio/gpio-tps65219.c
Normal file
185
drivers/gpio/gpio-tps65219.c
Normal file
@ -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");
|
@ -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);
|
||||
|
@ -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);
|
||||
struct gpio_desc *d = data;
|
||||
|
||||
gpiochip_remove(&priv->gpio_chip);
|
||||
|
||||
/* 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 @@ static int gpio_twl4030_probe(struct platform_device *pdev)
|
||||
|
||||
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 @@ static int gpio_twl4030_probe(struct platform_device *pdev)
|
||||
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;
|
||||
|
||||
if (pdata->setup) {
|
||||
int status;
|
||||
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);
|
||||
|
||||
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)
|
||||
|
@ -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>
|
||||
|
@ -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,
|
||||
|
@ -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:
|
||||
|
@ -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" : "");
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
ts->gpio_pendown = pdata->gpio_pendown;
|
||||
|
||||
if (pdata->gpio_pendown_debounce)
|
||||
gpiod_set_debounce(gpio_to_desc(ts->gpio_pendown),
|
||||
pdata->gpio_pendown_debounce);
|
||||
} else {
|
||||
dev_err(&spi->dev, "no get_pendown_state nor gpio_pendown?\n");
|
||||
return -EINVAL;
|
||||
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);
|
||||
}
|
||||
if (pdata->gpio_pendown_debounce)
|
||||
gpiod_set_debounce(ts->gpio_pendown,
|
||||
pdata->gpio_pendown_debounce);
|
||||
}
|
||||
|
||||
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,
|
||||
|
@ -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",
|
||||
|
@ -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 @@ static void mmc_omap_select_slot(struct mmc_omap_slot *slot, int claimed)
|
||||
|
||||
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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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 @@ static int tusb_musb_init(struct musb *musb)
|
||||
|
||||
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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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:
|
||||
|
@ -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 */
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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 */
|
||||
|
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user