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:
Linus Torvalds 2023-06-29 10:11:10 -07:00
commit e5476f57b3
89 changed files with 1798 additions and 988 deletions

View file

@ -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";

View 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>;
};

View 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>;
};
...

View 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>;
};

View file

@ -24,6 +24,10 @@ properties:
'#gpio-cells':
const: 2
gpio-line-names:
minItems: 4
maxItems: 8
required:
- compatible
- reg

View file

@ -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
};

View file

@ -61,6 +61,13 @@ properties:
gpio-ranges:
maxItems: 1
patternProperties:
"^.+-hog(-[0-9]+)?$":
type: object
required:
- gpio-hog
required:
- compatible
- reg

View file

@ -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;
};

View 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

View file

@ -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;
};

View file

@ -44,6 +44,7 @@ patternProperties:
- GPIO0
- GPIO1
- GPIO2
- GPIO3
function:
enum:

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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”

View file

@ -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」

View file

@ -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

View file

@ -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>

View file

@ -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();

View file

@ -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));
}

View file

@ -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);

View file

@ -9,7 +9,6 @@
* Copyright (C) 2007 Instituto Nokia de Tecnologia - INdT
*/
#include <linux/gpio.h>
#include <linux/platform_device.h>
#include "hardware.h"

View file

@ -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);
}

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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;
}

View file

@ -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;

View file

@ -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);

View file

@ -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 */ },
};

View file

@ -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);

View 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 */

View file

@ -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));

View file

@ -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;

View file

@ -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));

View file

@ -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) ?

View file

@ -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)
{

View file

@ -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

View file

@ -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

View file

@ -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);

View file

@ -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,
},
};

View file

@ -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);

View file

@ -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.
*/

View file

@ -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);

View file

@ -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);

View file

@ -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);

View file

@ -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>

View file

@ -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,
};

View file

@ -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
View 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");

View file

@ -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) {

View file

@ -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,
};

View file

@ -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);

View file

@ -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,
};

View file

@ -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;

View file

@ -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,
};

View file

@ -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;

View file

@ -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[] = {

View file

@ -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");

View file

@ -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");

View 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");

View file

@ -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);

View file

@ -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)

View file

@ -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>

View file

@ -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,

View file

@ -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:

View file

@ -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" : "");

View file

@ -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,

View file

@ -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",

View file

@ -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);

View file

@ -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);

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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);
}

View file

@ -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 */

View file

@ -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:

View file

@ -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 */

View file

@ -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 {

View file

@ -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);

View file

@ -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);

View file

@ -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);

View file

@ -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 */

View file

@ -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.