mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-08 14:13:53 +00:00
Pin control changes for the v6.9 kernel cycle:
No core changes this time around. New drivers: - New driver for Renesas R8A779H0 also known as R-Car V4M. - New driver for the Awinic AW9523/B I2C GPIO expander. I found this living out-of-tree in OpenWrt as an upstream attempt had stalled on the finishing line, so I picked it up and finished the job. Improvements: - The Nomadik pin control driver was for years re-used out of tree for the ST STA chips, and now the IP was re-used in a MIPS automotive SoC called MobilEyeq5, so it has been split in pin control and GPIO drivers so the latter can be reused by MobilEyeq5. (Along with a long list of cleanups.) - A lot of overall cleanup and tidying up. -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEElDRnuGcz/wPCXQWMQRCzN7AZXXMFAmXyJa8ACgkQQRCzN7AZ XXMQQw//aq+HJt4vtX4s9v+g/aYBDoasxOgryz96/yq+CqTBBiYh0ib7MJvy/rFs bBufH4DEvlpjzgsvaN14L6H+3hFDXKeN6VnAs3DPeBkda4bTS3VOpqNzSoOTeqG9 4a1jTe3SHche80SNW1YskTAMT0lG6WqC4RvipQ8K14DqIioX0AmgF7nJ1cddKaTK tXCWkqKY3TW2Z4edi9ZJLL6vRSQ9tJP9AugjkPX3F91yqwGHb8PV7Ggb1EXzC/X0 SW7F7Ke0lIvCYidDUpr04TOKdPTmzl2j6zoZfGU1WbypxG0LVhTKAMVk2DL2/v7T E8NNimVtGJtqxDfCVSbLc6jRgdYaLRa4dLhMCRWmevfEqFfrA79XFY6BS084T3oP 619RqbOtxc21AzlJjy2Kp7v3YpmXi6pX5E23L/d8U+0poEiM5qPqdYZaTbGNcGsV Yg4xCtxtBfPUdE3SqUCbHDzpWdSDGFsT3LSAUionvYyoW4iF8AXg8SBV1QpfzLM8 KTWTmsWG/15lCZyf7tq83EJjjVgYhGL4SMnkE8fT+smiXm95Muj1tzUjgapspMiU VpnhwtKj1hQrButWlN7+HXKseMrJ8zQJszcP5e3QdWOm7vzZGP3nXpgWosqGCImq ThjtyOKvc4+/AqgbIojDCz2BfxD8a7OPOkYHkLGJ96fA5JscBoU= =Pt9Y -----END PGP SIGNATURE----- Merge tag 'pinctrl-v6.9-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl Pull pin control updates from Linus Walleij: "No core changes this time around. New drivers: - New driver for Renesas R8A779H0 also known as R-Car V4M. - New driver for the Awinic AW9523/B I2C GPIO expander. I found this living out-of-tree in OpenWrt as an upstream attempt had stalled on the finishing line, so I picked it up and finished the job. Improvements: - The Nomadik pin control driver was for years re-used out of tree for the ST STA chips, and now the IP was re-used in a MIPS automotive SoC called MobilEyeq5, so it has been split in pin control and GPIO drivers so the latter can be reused by MobilEyeq5. (Along with a long list of cleanups) - A lot of overall cleanup and tidying up" * tag 'pinctrl-v6.9-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl: (87 commits) drivers/gpio/nomadik: move dummy nmk_gpio_dbg_show_one() to header gpio: nomadik: remove BUG_ON() in nmk_gpio_populate_chip() dt-bindings: pinctrl: qcom: update compatible name for match with driver pinctrl: aw9523: Make the driver tristate pinctrl: nomadik: fix dereference of error pointer gpio: nomadik: Back out some managed resources pinctrl: aw9523: Add proper terminator pinctrl: core: comment that pinctrl_add_gpio_range() is deprecated pinctrl: pinmux: Suppress error message for -EPROBE_DEFER pinctrl: Add driver for Awinic AW9523/B I2C GPIO Expander dt-bindings: pinctrl: Add bindings for Awinic AW9523/AW9523B gpio: nomadik: Finish conversion to use firmware node APIs gpio: nomadik: fix Kconfig dependencies inbetween pinctrl & GPIO pinctrl: da9062: Add OF table dt-bindings: pinctrl: at91: add sam9x7 pinctrl: ocelot: remove redundant assignment to variable ret gpio: nomadik: grab optional reset control and deassert it at probe gpio: nomadik: support mobileye,eyeq5-gpio gpio: nomadik: handle variadic GPIO count gpio: nomadik: support shared GPIO IRQs ...
This commit is contained in:
commit
a3df5d5422
@ -1,31 +0,0 @@
|
||||
Nomadik GPIO controller
|
||||
|
||||
Required properties:
|
||||
- compatible : Should be "st,nomadik-gpio".
|
||||
- reg : Physical base address and length of the controller's registers.
|
||||
- interrupts : The interrupt outputs from the controller.
|
||||
- #gpio-cells : Should be two:
|
||||
The first cell is the pin number.
|
||||
The second cell is used to specify optional parameters:
|
||||
- bits[3:0] trigger type and level flags:
|
||||
1 = low-to-high edge triggered.
|
||||
2 = high-to-low edge triggered.
|
||||
4 = active high level-sensitive.
|
||||
8 = active low level-sensitive.
|
||||
- gpio-controller : Marks the device node as a GPIO controller.
|
||||
- interrupt-controller : Marks the device node as an interrupt controller.
|
||||
- gpio-bank : Specifies which bank a controller owns.
|
||||
- st,supports-sleepmode : Specifies whether controller can sleep or not
|
||||
|
||||
Example:
|
||||
|
||||
gpio1: gpio@8012e080 {
|
||||
compatible = "st,nomadik-gpio";
|
||||
reg = <0x8012e080 0x80>;
|
||||
interrupts = <0 120 0x4>;
|
||||
#gpio-cells = <2>;
|
||||
gpio-controller;
|
||||
interrupt-controller;
|
||||
st,supports-sleepmode;
|
||||
gpio-bank = <1>;
|
||||
};
|
95
Documentation/devicetree/bindings/gpio/st,nomadik-gpio.yaml
Normal file
95
Documentation/devicetree/bindings/gpio/st,nomadik-gpio.yaml
Normal file
@ -0,0 +1,95 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/gpio/st,nomadik-gpio.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Nomadik GPIO controller
|
||||
|
||||
description:
|
||||
The Nomadik GPIO driver handles Nomadik SoC GPIO blocks. This block has also
|
||||
been called ST STA2X11. On the Nomadik platform, this driver is intertwined
|
||||
with pinctrl-nomadik.
|
||||
|
||||
maintainers:
|
||||
- Linus Walleij <linus.walleij@linaro.org>
|
||||
|
||||
properties:
|
||||
$nodename:
|
||||
pattern: "^gpio@[0-9a-f]+$"
|
||||
|
||||
compatible:
|
||||
enum:
|
||||
- st,nomadik-gpio
|
||||
- mobileye,eyeq5-gpio
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
"#gpio-cells":
|
||||
const: 2
|
||||
|
||||
gpio-controller: true
|
||||
|
||||
interrupt-controller: true
|
||||
|
||||
"#interrupt-cells":
|
||||
const: 2
|
||||
|
||||
gpio-bank:
|
||||
description: System-wide GPIO bank index.
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
|
||||
st,supports-sleepmode:
|
||||
description: Whether the controller can sleep or not.
|
||||
$ref: /schemas/types.yaml#/definitions/flag
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
|
||||
gpio-ranges:
|
||||
maxItems: 1
|
||||
|
||||
ngpios:
|
||||
minimum: 0
|
||||
maximum: 32
|
||||
|
||||
resets:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- "#gpio-cells"
|
||||
- gpio-controller
|
||||
- interrupt-controller
|
||||
- gpio-bank
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
allOf:
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: mobileye,eyeq5-gpio
|
||||
then:
|
||||
properties:
|
||||
st,supports-sleepmode: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
gpio@8012e080 {
|
||||
compatible = "st,nomadik-gpio";
|
||||
reg = <0x8012e080 0x80>;
|
||||
interrupts = <0 120 0x4>;
|
||||
#gpio-cells = <2>;
|
||||
gpio-controller;
|
||||
interrupt-controller;
|
||||
st,supports-sleepmode;
|
||||
gpio-bank = <1>;
|
||||
};
|
@ -24,7 +24,7 @@ required:
|
||||
- compatible
|
||||
|
||||
patternProperties:
|
||||
"^bank@[0-9a-z]+$":
|
||||
"^bank@[0-9a-f]+$":
|
||||
$ref: amlogic,meson-pinctrl-common.yaml#/$defs/meson-gpio
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
@ -21,7 +21,7 @@ required:
|
||||
- compatible
|
||||
|
||||
patternProperties:
|
||||
"^bank@[0-9a-z]+$":
|
||||
"^bank@[0-9a-f]+$":
|
||||
$ref: amlogic,meson-pinctrl-common.yaml#/$defs/meson-gpio
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
@ -21,7 +21,7 @@ required:
|
||||
- compatible
|
||||
|
||||
patternProperties:
|
||||
"^bank@[0-9a-z]+$":
|
||||
"^bank@[0-9a-f]+$":
|
||||
$ref: amlogic,meson-pinctrl-common.yaml#/$defs/meson-gpio
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
@ -29,7 +29,7 @@ required:
|
||||
- compatible
|
||||
|
||||
patternProperties:
|
||||
"^bank@[0-9a-z]+$":
|
||||
"^bank@[0-9a-f]+$":
|
||||
$ref: amlogic,meson-pinctrl-common.yaml#/$defs/meson-gpio
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
@ -29,7 +29,7 @@ required:
|
||||
- compatible
|
||||
|
||||
patternProperties:
|
||||
"^bank@[0-9a-z]+$":
|
||||
"^bank@[0-9a-f]+$":
|
||||
$ref: amlogic,meson-pinctrl-common.yaml#/$defs/meson-gpio
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
@ -20,6 +20,7 @@ such as pull-up, multi drive, etc.
|
||||
Required properties for iomux controller:
|
||||
- compatible: "atmel,at91rm9200-pinctrl" or "atmel,at91sam9x5-pinctrl"
|
||||
or "atmel,sama5d3-pinctrl" or "microchip,sam9x60-pinctrl"
|
||||
or "microchip,sam9x7-pinctrl", "microchip,sam9x60-pinctrl"
|
||||
- atmel,mux-mask: array of mask (periph per bank) to describe if a pin can be
|
||||
configured in this periph mode. All the periph and bank need to be describe.
|
||||
|
||||
@ -120,6 +121,7 @@ Some requirements for using atmel,at91rm9200-pinctrl binding:
|
||||
For each bank the required properties are:
|
||||
- compatible: "atmel,at91sam9x5-gpio" or "atmel,at91rm9200-gpio" or
|
||||
"microchip,sam9x60-gpio"
|
||||
or "microchip,sam9x7-gpio", "microchip,sam9x60-gpio", "atmel,at91rm9200-gpio"
|
||||
- reg: physical base address and length of the controller's registers
|
||||
- interrupts: interrupt outputs from the controller
|
||||
- interrupt-controller: marks the device node as an interrupt controller
|
||||
|
@ -0,0 +1,139 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/pinctrl/awinic,aw9523-pinctrl.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Awinic AW9523/AW9523B I2C GPIO Expander
|
||||
|
||||
maintainers:
|
||||
- AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
|
||||
|
||||
description: |
|
||||
The Awinic AW9523/AW9523B I2C GPIO Expander featuring 16 multi-function
|
||||
I/O, 256 steps PWM mode and interrupt support.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: awinic,aw9523-pinctrl
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
'#gpio-cells':
|
||||
description: |
|
||||
Specifying the pin number and flags, as defined in
|
||||
include/dt-bindings/gpio/gpio.h
|
||||
const: 2
|
||||
|
||||
gpio-controller: true
|
||||
|
||||
gpio-ranges:
|
||||
maxItems: 1
|
||||
|
||||
interrupt-controller: true
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
description: Specifies the INTN pin IRQ.
|
||||
|
||||
'#interrupt-cells':
|
||||
description:
|
||||
Specifies the PIN numbers and Flags, as defined in defined in
|
||||
include/dt-bindings/interrupt-controller/irq.h
|
||||
const: 2
|
||||
|
||||
reset-gpios:
|
||||
maxItems: 1
|
||||
|
||||
# PIN CONFIGURATION NODES
|
||||
patternProperties:
|
||||
'-pins$':
|
||||
type: object
|
||||
description:
|
||||
Pinctrl node's client devices use subnodes for desired pin configuration.
|
||||
Client device subnodes use below standard properties.
|
||||
$ref: /schemas/pinctrl/pincfg-node.yaml
|
||||
|
||||
properties:
|
||||
pins:
|
||||
description:
|
||||
List of gpio pins affected by the properties specified in
|
||||
this subnode.
|
||||
items:
|
||||
pattern: "^gpio([0-9]|1[0-5])$"
|
||||
minItems: 1
|
||||
maxItems: 16
|
||||
|
||||
function:
|
||||
description:
|
||||
Specify the alternative function to be configured for the
|
||||
specified pins.
|
||||
|
||||
enum: [ gpio, pwm ]
|
||||
|
||||
bias-disable: true
|
||||
bias-pull-down: true
|
||||
bias-pull-up: true
|
||||
drive-open-drain: true
|
||||
drive-push-pull: true
|
||||
input-enable: true
|
||||
input-disable: true
|
||||
output-high: true
|
||||
output-low: true
|
||||
|
||||
required:
|
||||
- pins
|
||||
- function
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- gpio-controller
|
||||
- '#gpio-cells'
|
||||
- gpio-ranges
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
# Example configuration to drive pins for a keyboard matrix
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
aw9523: gpio-expander@58 {
|
||||
compatible = "awinic,aw9523-pinctrl";
|
||||
reg = <0x58>;
|
||||
interrupt-parent = <&tlmm>;
|
||||
interrupts = <50 IRQ_TYPE_EDGE_FALLING>;
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
gpio-ranges = <&tlmm 0 0 16>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
reset-gpios = <&tlmm 51 GPIO_ACTIVE_HIGH>;
|
||||
|
||||
keyboard-matrix-col-pins {
|
||||
pins = "gpio8", "gpio9", "gpio10", "gpio11",
|
||||
"gpio12", "gpio13", "gpio14", "gpio15";
|
||||
function = "gpio";
|
||||
input-disable;
|
||||
output-low;
|
||||
};
|
||||
|
||||
keyboard-matrix-row-pins {
|
||||
pins = "gpio0", "gpio1", "gpio2", "gpio3",
|
||||
"gpio4", "gpio5", "gpio6", "gpio7";
|
||||
function = "gpio";
|
||||
bias-pull-up;
|
||||
drive-open-drain;
|
||||
input-enable;
|
||||
};
|
||||
};
|
||||
};
|
@ -93,7 +93,8 @@ properties:
|
||||
|
||||
input-schmitt-disable: true
|
||||
|
||||
input-debounce: true
|
||||
input-debounce:
|
||||
maxItems: 1
|
||||
|
||||
output-low: true
|
||||
|
||||
|
@ -45,7 +45,8 @@ properties:
|
||||
maxItems: 1
|
||||
|
||||
gpio-reserved-ranges:
|
||||
maxItems: 1
|
||||
minItems: 1
|
||||
maxItems: 60
|
||||
|
||||
vdd-supply:
|
||||
description:
|
||||
@ -85,6 +86,8 @@ patternProperties:
|
||||
|
||||
bias-disable: true
|
||||
|
||||
input-enable: true
|
||||
|
||||
output-high: true
|
||||
|
||||
output-low: true
|
||||
@ -133,6 +136,23 @@ examples:
|
||||
interrupts = <GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-controller;
|
||||
vdd-supply = <&p3v3>;
|
||||
gpio-reserved-ranges = <5 1>;
|
||||
gpio-reserved-ranges = <1 2>, <6 1>, <10 1>, <15 1>;
|
||||
|
||||
pinctrl-0 = <&U62160_pins>, <&U62160_ipins>;
|
||||
pinctrl-names = "default";
|
||||
|
||||
U62160_pins: cfg-pins {
|
||||
pins = "gp03", "gp16", "gp20", "gp50", "gp51";
|
||||
function = "gpio";
|
||||
input-enable;
|
||||
bias-pull-up;
|
||||
};
|
||||
|
||||
U62160_ipins: icfg-pins {
|
||||
pins = "gp04", "gp17", "gp21", "gp52", "gp53";
|
||||
function = "gpio";
|
||||
input-enable;
|
||||
bias-pull-up;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
@ -0,0 +1,242 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/pinctrl/mobileye,eyeq5-pinctrl.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Mobileye EyeQ5 pin controller
|
||||
|
||||
description: >
|
||||
The EyeQ5 pin controller handles the two pin banks of the system. It belongs
|
||||
to a system-controller block called OLB.
|
||||
|
||||
Pin control is about bias (pull-down, pull-up), drive strength and muxing. Pin
|
||||
muxing supports two functions for each pin: first is GPIO, second is
|
||||
pin-dependent.
|
||||
|
||||
Pins and groups are bijective.
|
||||
|
||||
maintainers:
|
||||
- Grégory Clement <gregory.clement@bootlin.com>
|
||||
- Théo Lebrun <theo.lebrun@bootlin.com>
|
||||
- Vladimir Kondratiev <vladimir.kondratiev@mobileye.com>
|
||||
|
||||
$ref: pinctrl.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- mobileye,eyeq5-pinctrl
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
patternProperties:
|
||||
"-pins?$":
|
||||
type: object
|
||||
description: Pin muxing configuration.
|
||||
$ref: pinmux-node.yaml#
|
||||
additionalProperties: false
|
||||
properties:
|
||||
pins: true
|
||||
function:
|
||||
enum: [gpio,
|
||||
# Bank A
|
||||
timer0, timer1, timer2, timer5, uart0, uart1, can0, can1, spi0,
|
||||
spi1, refclk0,
|
||||
# Bank B
|
||||
timer3, timer4, timer6, uart2, can2, spi2, spi3, mclk0]
|
||||
bias-disable: true
|
||||
bias-pull-down: true
|
||||
bias-pull-up: true
|
||||
drive-strength: true
|
||||
required:
|
||||
- pins
|
||||
- function
|
||||
allOf:
|
||||
- if:
|
||||
properties:
|
||||
function:
|
||||
const: gpio
|
||||
then:
|
||||
properties:
|
||||
pins:
|
||||
items: # PA0 - PA28, PB0 - PB22
|
||||
pattern: '^(P(A|B)1?[0-9]|PA2[0-8]|PB2[0-2])$'
|
||||
- if:
|
||||
properties:
|
||||
function:
|
||||
const: timer0
|
||||
then:
|
||||
properties:
|
||||
pins:
|
||||
items:
|
||||
enum: [PA0, PA1]
|
||||
- if:
|
||||
properties:
|
||||
function:
|
||||
const: timer1
|
||||
then:
|
||||
properties:
|
||||
pins:
|
||||
items:
|
||||
enum: [PA2, PA3]
|
||||
- if:
|
||||
properties:
|
||||
function:
|
||||
const: timer2
|
||||
then:
|
||||
properties:
|
||||
pins:
|
||||
items:
|
||||
enum: [PA4, PA5]
|
||||
- if:
|
||||
properties:
|
||||
function:
|
||||
const: timer5
|
||||
then:
|
||||
properties:
|
||||
pins:
|
||||
items:
|
||||
enum: [PA6, PA7, PA8, PA9]
|
||||
- if:
|
||||
properties:
|
||||
function:
|
||||
const: uart0
|
||||
then:
|
||||
properties:
|
||||
pins:
|
||||
items:
|
||||
enum: [PA10, PA11]
|
||||
- if:
|
||||
properties:
|
||||
function:
|
||||
const: uart1
|
||||
then:
|
||||
properties:
|
||||
pins:
|
||||
items:
|
||||
enum: [PA12, PA13]
|
||||
- if:
|
||||
properties:
|
||||
function:
|
||||
const: can0
|
||||
then:
|
||||
properties:
|
||||
pins:
|
||||
items:
|
||||
enum: [PA14, PA15]
|
||||
- if:
|
||||
properties:
|
||||
function:
|
||||
const: can1
|
||||
then:
|
||||
properties:
|
||||
pins:
|
||||
items:
|
||||
enum: [PA16, PA17]
|
||||
- if:
|
||||
properties:
|
||||
function:
|
||||
const: spi0
|
||||
then:
|
||||
properties:
|
||||
pins:
|
||||
items:
|
||||
enum: [PA18, PA19, PA20, PA21, PA22]
|
||||
- if:
|
||||
properties:
|
||||
function:
|
||||
const: spi1
|
||||
then:
|
||||
properties:
|
||||
pins:
|
||||
items:
|
||||
enum: [PA23, PA24, PA25, PA26, PA27]
|
||||
- if:
|
||||
properties:
|
||||
function:
|
||||
const: refclk0
|
||||
then:
|
||||
properties:
|
||||
pins:
|
||||
items:
|
||||
enum: [PA28]
|
||||
- if:
|
||||
properties:
|
||||
function:
|
||||
const: timer3
|
||||
then:
|
||||
properties:
|
||||
pins:
|
||||
items:
|
||||
enum: [PB0, PB1]
|
||||
- if:
|
||||
properties:
|
||||
function:
|
||||
const: timer4
|
||||
then:
|
||||
properties:
|
||||
pins:
|
||||
items:
|
||||
enum: [PB2, PB3]
|
||||
- if:
|
||||
properties:
|
||||
function:
|
||||
const: timer6
|
||||
then:
|
||||
properties:
|
||||
pins:
|
||||
items:
|
||||
enum: [PB4, PB5, PB6, PB7]
|
||||
- if:
|
||||
properties:
|
||||
function:
|
||||
const: uart2
|
||||
then:
|
||||
properties:
|
||||
pins:
|
||||
items:
|
||||
enum: [PB8, PB9]
|
||||
- if:
|
||||
properties:
|
||||
function:
|
||||
const: can2
|
||||
then:
|
||||
properties:
|
||||
pins:
|
||||
items:
|
||||
enum: [PB10, PB11]
|
||||
- if:
|
||||
properties:
|
||||
function:
|
||||
const: spi2
|
||||
then:
|
||||
properties:
|
||||
pins:
|
||||
items:
|
||||
enum: [PB12, PB13, PB14, PB15, PB16]
|
||||
- if:
|
||||
properties:
|
||||
function:
|
||||
const: spi3
|
||||
then:
|
||||
properties:
|
||||
pins:
|
||||
items:
|
||||
enum: [PB17, PB18, PB19, PB20, PB21]
|
||||
- if:
|
||||
properties:
|
||||
function:
|
||||
const: mclk0
|
||||
then:
|
||||
properties:
|
||||
pins:
|
||||
items:
|
||||
enum: [PB22]
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
additionalProperties: false
|
@ -152,7 +152,6 @@ patternProperties:
|
||||
description:
|
||||
Debouncing periods in microseconds, one period per interrupt
|
||||
bank found in the controller
|
||||
$ref: /schemas/types.yaml#/definitions/uint32-array
|
||||
minItems: 1
|
||||
maxItems: 4
|
||||
|
||||
@ -160,7 +159,6 @@ patternProperties:
|
||||
description: |
|
||||
0: Low rate
|
||||
1: High rate
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
enum: [0, 1]
|
||||
|
||||
drive-strength:
|
||||
|
@ -103,7 +103,8 @@ patternProperties:
|
||||
items:
|
||||
pattern: "^gpio1?[0-9]{1,2}$"
|
||||
|
||||
input-debounce: true
|
||||
input-debounce:
|
||||
maxItems: 1
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
|
@ -10,18 +10,21 @@ maintainers:
|
||||
- Thierry Reding <thierry.reding@gmail.com>
|
||||
- Jon Hunter <jonathanh@nvidia.com>
|
||||
|
||||
$ref: nvidia,tegra234-pinmux-common.yaml
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: nvidia,tegra234-pinmux-aon
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
patternProperties:
|
||||
"^pinmux(-[a-z0-9-]+)?$":
|
||||
type: object
|
||||
|
||||
# pin groups
|
||||
additionalProperties:
|
||||
$ref: nvidia,tegra234-pinmux-common.yaml
|
||||
|
||||
properties:
|
||||
nvidia,pins:
|
||||
items:
|
||||
|
@ -10,57 +10,43 @@ maintainers:
|
||||
- Thierry Reding <thierry.reding@gmail.com>
|
||||
- Jon Hunter <jonathanh@nvidia.com>
|
||||
|
||||
$ref: nvidia,tegra-pinmux-common.yaml
|
||||
|
||||
properties:
|
||||
reg:
|
||||
items:
|
||||
- description: pinmux registers
|
||||
nvidia,function:
|
||||
enum: [ gp, uartc, i2c8, spi2, i2c2, can1, can0, rsvd0, eth0, eth2,
|
||||
eth1, dp, eth3, i2c4, i2c7, i2c9, eqos, pe2, pe1, pe0, pe3,
|
||||
pe4, pe5, pe6, pe7, pe8, pe9, pe10, qspi0, qspi1, qpsi,
|
||||
sdmmc1, sce, soc, gpio, hdmi, ufs0, spi3, spi1, uartb, uarte,
|
||||
usb, extperiph2, extperiph1, i2c3, vi0, i2c5, uarta, uartd,
|
||||
i2c1, i2s4, i2s6, aud, spi5, touch, uartj, rsvd1, wdt, tsc,
|
||||
dmic3, led, vi0_alt, i2s5, nv, extperiph3, extperiph4, spi4,
|
||||
ccla, i2s1, i2s2, i2s3, i2s8, rsvd2, dmic5, dca, displayb,
|
||||
displaya, vi1, dcb, dmic1, dmic4, i2s7, dmic2, dspk0, rsvd3,
|
||||
tsc_alt, istctrl, vi1_alt, dspk1, igpu ]
|
||||
|
||||
patternProperties:
|
||||
"^pinmux(-[a-z0-9-]+)?$":
|
||||
type: object
|
||||
|
||||
# pin groups
|
||||
additionalProperties:
|
||||
$ref: nvidia,tegra-pinmux-common.yaml
|
||||
# We would typically use unevaluatedProperties here but that has the
|
||||
# downside that all the properties in the common bindings become valid
|
||||
# for all chip generations. In this case, however, we want the per-SoC
|
||||
# bindings to be able to override which of the common properties are
|
||||
# allowed, since not all pinmux generations support the same sets of
|
||||
# properties. This way, the common bindings define the format of the
|
||||
# properties but the per-SoC bindings define which of them apply to a
|
||||
# given chip.
|
||||
additionalProperties: false
|
||||
properties:
|
||||
nvidia,function:
|
||||
enum: [ gp, uartc, i2c8, spi2, i2c2, can1, can0, rsvd0, eth0, eth2,
|
||||
eth1, dp, eth3, i2c4, i2c7, i2c9, eqos, pe2, pe1, pe0, pe3,
|
||||
pe4, pe5, pe6, pe7, pe8, pe9, pe10, qspi0, qspi1, qpsi,
|
||||
sdmmc1, sce, soc, gpio, hdmi, ufs0, spi3, spi1, uartb, uarte,
|
||||
usb, extperiph2, extperiph1, i2c3, vi0, i2c5, uarta, uartd,
|
||||
i2c1, i2s4, i2s6, aud, spi5, touch, uartj, rsvd1, wdt, tsc,
|
||||
dmic3, led, vi0_alt, i2s5, nv, extperiph3, extperiph4, spi4,
|
||||
ccla, i2s1, i2s2, i2s3, i2s8, rsvd2, dmic5, dca, displayb,
|
||||
displaya, vi1, dcb, dmic1, dmic4, i2s7, dmic2, dspk0, rsvd3,
|
||||
tsc_alt, istctrl, vi1_alt, dspk1, igpu ]
|
||||
|
||||
# out of the common properties, only these are allowed for Tegra234
|
||||
nvidia,pins: true
|
||||
nvidia,pull: true
|
||||
nvidia,tristate: true
|
||||
nvidia,schmitt: true
|
||||
nvidia,enable-input: true
|
||||
nvidia,open-drain: true
|
||||
nvidia,lock: true
|
||||
nvidia,drive-type: true
|
||||
nvidia,io-hv: true
|
||||
|
||||
required:
|
||||
- nvidia,pins
|
||||
# out of the common properties, only these are allowed for Tegra234
|
||||
nvidia,pins: true
|
||||
nvidia,pull: true
|
||||
nvidia,tristate: true
|
||||
nvidia,schmitt: true
|
||||
nvidia,enable-input: true
|
||||
nvidia,open-drain: true
|
||||
nvidia,lock: true
|
||||
nvidia,drive-type: true
|
||||
nvidia,io-hv: true
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- nvidia,pins
|
||||
|
||||
# We would typically use unevaluatedProperties here but that has the
|
||||
# downside that all the properties in the common bindings become valid
|
||||
# for all chip generations. In this case, however, we want the per-SoC
|
||||
# bindings to be able to override which of the common properties are
|
||||
# allowed, since not all pinmux generations support the same sets of
|
||||
# properties. This way, the common bindings define the format of the
|
||||
# properties but the per-SoC bindings define which of them apply to a
|
||||
# given chip.
|
||||
additionalProperties: false
|
||||
|
||||
additionalProperties: true
|
||||
...
|
||||
|
@ -10,18 +10,21 @@ maintainers:
|
||||
- Thierry Reding <thierry.reding@gmail.com>
|
||||
- Jon Hunter <jonathanh@nvidia.com>
|
||||
|
||||
$ref: nvidia,tegra234-pinmux-common.yaml
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: nvidia,tegra234-pinmux
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
patternProperties:
|
||||
"^pinmux(-[a-z0-9-]+)?$":
|
||||
type: object
|
||||
|
||||
# pin groups
|
||||
additionalProperties:
|
||||
$ref: nvidia,tegra234-pinmux-common.yaml
|
||||
|
||||
properties:
|
||||
nvidia,pins:
|
||||
items:
|
||||
|
@ -97,7 +97,7 @@ properties:
|
||||
description: disable schmitt-trigger mode
|
||||
|
||||
input-debounce:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
$ref: /schemas/types.yaml#/definitions/uint32-array
|
||||
description: Takes the debounce time in usec as argument or 0 to disable
|
||||
debouncing
|
||||
|
||||
|
@ -17,7 +17,7 @@ allOf:
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: qcom,sm4450-pinctrl
|
||||
const: qcom,sm4450-tlmm
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
@ -46,6 +46,7 @@ properties:
|
||||
- renesas,pfc-r8a779a0 # R-Car V3U
|
||||
- renesas,pfc-r8a779f0 # R-Car S4-8
|
||||
- renesas,pfc-r8a779g0 # R-Car V4H
|
||||
- renesas,pfc-r8a779h0 # R-Car V4M
|
||||
- renesas,pfc-sh73a0 # SH-Mobile AG5
|
||||
|
||||
reg:
|
||||
|
@ -1,7 +1,7 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/pinctrl/xlnx,zynq-pinctrl.yaml#
|
||||
$id: http://devicetree.org/schemas/pinctrl/xlnx,pinctrl-zynq.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Xilinx Zynq Pinctrl
|
||||
@ -28,7 +28,7 @@ description: |
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: xlnx,zynq-pinctrl
|
||||
const: xlnx,pinctrl-zynq
|
||||
|
||||
reg:
|
||||
description: Specifies the base address and size of the SLCR space.
|
||||
@ -181,7 +181,7 @@ examples:
|
||||
- |
|
||||
#include <dt-bindings/pinctrl/pinctrl-zynq.h>
|
||||
pinctrl0: pinctrl@700 {
|
||||
compatible = "xlnx,zynq-pinctrl";
|
||||
compatible = "xlnx,pinctrl-zynq";
|
||||
reg = <0x700 0x200>;
|
||||
syscon = <&slcr>;
|
||||
|
@ -2471,6 +2471,7 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-nomadik.git
|
||||
F: Documentation/devicetree/bindings/arm/ste-*
|
||||
F: Documentation/devicetree/bindings/arm/ux500.yaml
|
||||
F: Documentation/devicetree/bindings/arm/ux500/
|
||||
F: Documentation/devicetree/bindings/gpio/st,nomadik-gpio.yaml
|
||||
F: Documentation/devicetree/bindings/i2c/st,nomadik-i2c.yaml
|
||||
F: arch/arm/boot/dts/st/ste-*
|
||||
F: arch/arm/mach-nomadik/
|
||||
@ -2479,6 +2480,7 @@ F: drivers/clk/clk-nomadik.c
|
||||
F: drivers/clocksource/clksrc-dbx500-prcmu.c
|
||||
F: drivers/dma/ste_dma40*
|
||||
F: drivers/pmdomain/st/ste-ux500-pm-domain.c
|
||||
F: drivers/gpio/gpio-nomadik.c
|
||||
F: drivers/hwspinlock/u8500_hsem.c
|
||||
F: drivers/i2c/busses/i2c-nomadik.c
|
||||
F: drivers/iio/adc/ab8500-gpadc.c
|
||||
|
@ -46,6 +46,10 @@ cpu0_intc: interrupt-controller {
|
||||
};
|
||||
};
|
||||
|
||||
&pinctrl {
|
||||
gpio-ranges = <&pinctrl 0 0 232>;
|
||||
};
|
||||
|
||||
&soc {
|
||||
dma-noncoherent;
|
||||
interrupt-parent = <&plic>;
|
||||
|
@ -478,6 +478,18 @@ config GPIO_MXS
|
||||
select GPIO_GENERIC
|
||||
select GENERIC_IRQ_CHIP
|
||||
|
||||
config GPIO_NOMADIK
|
||||
bool "Nomadik GPIO driver"
|
||||
depends on ARCH_U8500 || ARCH_NOMADIK || MACH_EYEQ5 || COMPILE_TEST
|
||||
select GPIOLIB_IRQCHIP
|
||||
help
|
||||
Say yes here to support the Nomadik SoC GPIO block. This block is also
|
||||
used by the Mobileye EyeQ5 SoC.
|
||||
|
||||
It handles up to 32 GPIOs per bank, that can all be interrupt sources.
|
||||
It is deeply interconnected with the associated pinctrl driver as GPIO
|
||||
registers handle muxing ("alternate functions") as well.
|
||||
|
||||
config GPIO_NPCM_SGPIO
|
||||
bool "Nuvoton SGPIO support"
|
||||
depends on ARCH_NPCM || COMPILE_TEST
|
||||
|
@ -117,6 +117,7 @@ obj-$(CONFIG_GPIO_MT7621) += gpio-mt7621.o
|
||||
obj-$(CONFIG_GPIO_MVEBU) += gpio-mvebu.o
|
||||
obj-$(CONFIG_GPIO_MXC) += gpio-mxc.o
|
||||
obj-$(CONFIG_GPIO_MXS) += gpio-mxs.o
|
||||
obj-$(CONFIG_GPIO_NOMADIK) += gpio-nomadik.o
|
||||
obj-$(CONFIG_GPIO_NPCM_SGPIO) += gpio-npcm-sgpio.o
|
||||
obj-$(CONFIG_GPIO_OCTEON) += gpio-octeon.o
|
||||
obj-$(CONFIG_GPIO_OMAP) += gpio-omap.o
|
||||
|
730
drivers/gpio/gpio-nomadik.c
Normal file
730
drivers/gpio/gpio-nomadik.c
Normal file
@ -0,0 +1,730 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* GPIO driver for the IP block found in the Nomadik SoC; it is an AMBA device,
|
||||
* managing 32 pins with alternate functions. It can also handle the STA2X11
|
||||
* block from ST.
|
||||
*
|
||||
* The GPIO chips are shared with pinctrl-nomadik if used; it needs access for
|
||||
* pinmuxing functionality and others.
|
||||
*
|
||||
* This driver also handles the mobileye,eyeq5-gpio compatible. It is an STA2X11
|
||||
* but with only data, direction and interrupts register active. We want to
|
||||
* avoid touching SLPM, RWIMSC, FWIMSC, AFSLA and AFSLB registers; that is,
|
||||
* wake and alternate function registers. It is NOT compatible with
|
||||
* pinctrl-nomadik.
|
||||
*
|
||||
* Copyright (C) 2008,2009 STMicroelectronics
|
||||
* Copyright (C) 2009 Alessandro Rubini <rubini@unipv.it>
|
||||
* Rewritten based on work by Prafulla WADASKAR <prafulla.wadaskar@st.com>
|
||||
* Copyright (C) 2011-2013 Linus Walleij <linus.walleij@linaro.org>
|
||||
*/
|
||||
#include <linux/cleanup.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/gpio/driver.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/pinctrl/pinctrl.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/property.h>
|
||||
#include <linux/reset.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#include <linux/gpio/gpio-nomadik.h>
|
||||
|
||||
#ifndef CONFIG_PINCTRL_NOMADIK
|
||||
static DEFINE_SPINLOCK(nmk_gpio_slpm_lock);
|
||||
#endif
|
||||
|
||||
void __nmk_gpio_set_slpm(struct nmk_gpio_chip *nmk_chip, unsigned int offset,
|
||||
enum nmk_gpio_slpm mode)
|
||||
{
|
||||
u32 slpm;
|
||||
|
||||
/* We should NOT have been called. */
|
||||
if (WARN_ON(nmk_chip->is_mobileye_soc))
|
||||
return;
|
||||
|
||||
slpm = readl(nmk_chip->addr + NMK_GPIO_SLPC);
|
||||
if (mode == NMK_GPIO_SLPM_NOCHANGE)
|
||||
slpm |= BIT(offset);
|
||||
else
|
||||
slpm &= ~BIT(offset);
|
||||
writel(slpm, nmk_chip->addr + NMK_GPIO_SLPC);
|
||||
}
|
||||
|
||||
static void __nmk_gpio_set_output(struct nmk_gpio_chip *nmk_chip,
|
||||
unsigned int offset, int val)
|
||||
{
|
||||
if (val)
|
||||
writel(BIT(offset), nmk_chip->addr + NMK_GPIO_DATS);
|
||||
else
|
||||
writel(BIT(offset), nmk_chip->addr + NMK_GPIO_DATC);
|
||||
}
|
||||
|
||||
void __nmk_gpio_make_output(struct nmk_gpio_chip *nmk_chip,
|
||||
unsigned int offset, int val)
|
||||
{
|
||||
writel(BIT(offset), nmk_chip->addr + NMK_GPIO_DIRS);
|
||||
__nmk_gpio_set_output(nmk_chip, offset, val);
|
||||
}
|
||||
|
||||
/* IRQ functions */
|
||||
|
||||
static void nmk_gpio_irq_ack(struct irq_data *d)
|
||||
{
|
||||
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
|
||||
struct nmk_gpio_chip *nmk_chip = gpiochip_get_data(gc);
|
||||
|
||||
clk_enable(nmk_chip->clk);
|
||||
writel(BIT(d->hwirq), nmk_chip->addr + NMK_GPIO_IC);
|
||||
clk_disable(nmk_chip->clk);
|
||||
}
|
||||
|
||||
enum nmk_gpio_irq_type {
|
||||
NORMAL,
|
||||
WAKE,
|
||||
};
|
||||
|
||||
static void __nmk_gpio_irq_modify(struct nmk_gpio_chip *nmk_chip,
|
||||
int offset, enum nmk_gpio_irq_type which,
|
||||
bool enable)
|
||||
{
|
||||
u32 *rimscval;
|
||||
u32 *fimscval;
|
||||
u32 rimscreg;
|
||||
u32 fimscreg;
|
||||
|
||||
if (which == NORMAL) {
|
||||
rimscreg = NMK_GPIO_RIMSC;
|
||||
fimscreg = NMK_GPIO_FIMSC;
|
||||
rimscval = &nmk_chip->rimsc;
|
||||
fimscval = &nmk_chip->fimsc;
|
||||
} else {
|
||||
/* We should NOT have been called. */
|
||||
if (WARN_ON(nmk_chip->is_mobileye_soc))
|
||||
return;
|
||||
rimscreg = NMK_GPIO_RWIMSC;
|
||||
fimscreg = NMK_GPIO_FWIMSC;
|
||||
rimscval = &nmk_chip->rwimsc;
|
||||
fimscval = &nmk_chip->fwimsc;
|
||||
}
|
||||
|
||||
/* we must individually set/clear the two edges */
|
||||
if (nmk_chip->edge_rising & BIT(offset)) {
|
||||
if (enable)
|
||||
*rimscval |= BIT(offset);
|
||||
else
|
||||
*rimscval &= ~BIT(offset);
|
||||
writel(*rimscval, nmk_chip->addr + rimscreg);
|
||||
}
|
||||
if (nmk_chip->edge_falling & BIT(offset)) {
|
||||
if (enable)
|
||||
*fimscval |= BIT(offset);
|
||||
else
|
||||
*fimscval &= ~BIT(offset);
|
||||
writel(*fimscval, nmk_chip->addr + fimscreg);
|
||||
}
|
||||
}
|
||||
|
||||
static void __nmk_gpio_set_wake(struct nmk_gpio_chip *nmk_chip,
|
||||
int offset, bool on)
|
||||
{
|
||||
/* We should NOT have been called. */
|
||||
if (WARN_ON(nmk_chip->is_mobileye_soc))
|
||||
return;
|
||||
|
||||
/*
|
||||
* Ensure WAKEUP_ENABLE is on. No need to disable it if wakeup is
|
||||
* disabled, since setting SLPM to 1 increases power consumption, and
|
||||
* wakeup is anyhow controlled by the RIMSC and FIMSC registers.
|
||||
*/
|
||||
if (nmk_chip->sleepmode && on) {
|
||||
__nmk_gpio_set_slpm(nmk_chip, offset,
|
||||
NMK_GPIO_SLPM_WAKEUP_ENABLE);
|
||||
}
|
||||
|
||||
__nmk_gpio_irq_modify(nmk_chip, offset, WAKE, on);
|
||||
}
|
||||
|
||||
static void nmk_gpio_irq_maskunmask(struct nmk_gpio_chip *nmk_chip,
|
||||
struct irq_data *d, bool enable)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
clk_enable(nmk_chip->clk);
|
||||
spin_lock_irqsave(&nmk_gpio_slpm_lock, flags);
|
||||
spin_lock(&nmk_chip->lock);
|
||||
|
||||
__nmk_gpio_irq_modify(nmk_chip, d->hwirq, NORMAL, enable);
|
||||
|
||||
if (!nmk_chip->is_mobileye_soc && !(nmk_chip->real_wake & BIT(d->hwirq)))
|
||||
__nmk_gpio_set_wake(nmk_chip, d->hwirq, enable);
|
||||
|
||||
spin_unlock(&nmk_chip->lock);
|
||||
spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags);
|
||||
clk_disable(nmk_chip->clk);
|
||||
}
|
||||
|
||||
static void nmk_gpio_irq_mask(struct irq_data *d)
|
||||
{
|
||||
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
|
||||
struct nmk_gpio_chip *nmk_chip = gpiochip_get_data(gc);
|
||||
|
||||
nmk_gpio_irq_maskunmask(nmk_chip, d, false);
|
||||
gpiochip_disable_irq(gc, irqd_to_hwirq(d));
|
||||
}
|
||||
|
||||
static void nmk_gpio_irq_unmask(struct irq_data *d)
|
||||
{
|
||||
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
|
||||
struct nmk_gpio_chip *nmk_chip = gpiochip_get_data(gc);
|
||||
|
||||
gpiochip_enable_irq(gc, irqd_to_hwirq(d));
|
||||
nmk_gpio_irq_maskunmask(nmk_chip, d, true);
|
||||
}
|
||||
|
||||
static int nmk_gpio_irq_set_wake(struct irq_data *d, unsigned int on)
|
||||
{
|
||||
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
|
||||
struct nmk_gpio_chip *nmk_chip = gpiochip_get_data(gc);
|
||||
unsigned long flags;
|
||||
|
||||
/* Handler is registered in all cases. */
|
||||
if (nmk_chip->is_mobileye_soc)
|
||||
return -ENXIO;
|
||||
|
||||
clk_enable(nmk_chip->clk);
|
||||
spin_lock_irqsave(&nmk_gpio_slpm_lock, flags);
|
||||
spin_lock(&nmk_chip->lock);
|
||||
|
||||
if (irqd_irq_disabled(d))
|
||||
__nmk_gpio_set_wake(nmk_chip, d->hwirq, on);
|
||||
|
||||
if (on)
|
||||
nmk_chip->real_wake |= BIT(d->hwirq);
|
||||
else
|
||||
nmk_chip->real_wake &= ~BIT(d->hwirq);
|
||||
|
||||
spin_unlock(&nmk_chip->lock);
|
||||
spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags);
|
||||
clk_disable(nmk_chip->clk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nmk_gpio_irq_set_type(struct irq_data *d, unsigned int type)
|
||||
{
|
||||
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
|
||||
struct nmk_gpio_chip *nmk_chip = gpiochip_get_data(gc);
|
||||
bool enabled = !irqd_irq_disabled(d);
|
||||
bool wake = irqd_is_wakeup_set(d);
|
||||
unsigned long flags;
|
||||
|
||||
if (type & IRQ_TYPE_LEVEL_HIGH)
|
||||
return -EINVAL;
|
||||
if (type & IRQ_TYPE_LEVEL_LOW)
|
||||
return -EINVAL;
|
||||
|
||||
clk_enable(nmk_chip->clk);
|
||||
spin_lock_irqsave(&nmk_chip->lock, flags);
|
||||
|
||||
if (enabled)
|
||||
__nmk_gpio_irq_modify(nmk_chip, d->hwirq, NORMAL, false);
|
||||
|
||||
if (!nmk_chip->is_mobileye_soc && (enabled || wake))
|
||||
__nmk_gpio_irq_modify(nmk_chip, d->hwirq, WAKE, false);
|
||||
|
||||
nmk_chip->edge_rising &= ~BIT(d->hwirq);
|
||||
if (type & IRQ_TYPE_EDGE_RISING)
|
||||
nmk_chip->edge_rising |= BIT(d->hwirq);
|
||||
|
||||
nmk_chip->edge_falling &= ~BIT(d->hwirq);
|
||||
if (type & IRQ_TYPE_EDGE_FALLING)
|
||||
nmk_chip->edge_falling |= BIT(d->hwirq);
|
||||
|
||||
if (enabled)
|
||||
__nmk_gpio_irq_modify(nmk_chip, d->hwirq, NORMAL, true);
|
||||
|
||||
if (!nmk_chip->is_mobileye_soc && (enabled || wake))
|
||||
__nmk_gpio_irq_modify(nmk_chip, d->hwirq, WAKE, true);
|
||||
|
||||
spin_unlock_irqrestore(&nmk_chip->lock, flags);
|
||||
clk_disable(nmk_chip->clk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned int nmk_gpio_irq_startup(struct irq_data *d)
|
||||
{
|
||||
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
|
||||
struct nmk_gpio_chip *nmk_chip = gpiochip_get_data(gc);
|
||||
|
||||
clk_enable(nmk_chip->clk);
|
||||
nmk_gpio_irq_unmask(d);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void nmk_gpio_irq_shutdown(struct irq_data *d)
|
||||
{
|
||||
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
|
||||
struct nmk_gpio_chip *nmk_chip = gpiochip_get_data(gc);
|
||||
|
||||
nmk_gpio_irq_mask(d);
|
||||
clk_disable(nmk_chip->clk);
|
||||
}
|
||||
|
||||
static irqreturn_t nmk_gpio_irq_handler(int irq, void *dev_id)
|
||||
{
|
||||
struct nmk_gpio_chip *nmk_chip = dev_id;
|
||||
struct gpio_chip *chip = &nmk_chip->chip;
|
||||
unsigned long mask = GENMASK(chip->ngpio - 1, 0);
|
||||
unsigned long status;
|
||||
int bit;
|
||||
|
||||
clk_enable(nmk_chip->clk);
|
||||
|
||||
status = readl(nmk_chip->addr + NMK_GPIO_IS);
|
||||
|
||||
/* Ensure we cannot leave pending bits; this should never occur. */
|
||||
if (unlikely(status & ~mask))
|
||||
writel(status & ~mask, nmk_chip->addr + NMK_GPIO_IC);
|
||||
|
||||
clk_disable(nmk_chip->clk);
|
||||
|
||||
for_each_set_bit(bit, &status, chip->ngpio)
|
||||
generic_handle_domain_irq_safe(chip->irq.domain, bit);
|
||||
|
||||
return IRQ_RETVAL((status & mask) != 0);
|
||||
}
|
||||
|
||||
/* I/O Functions */
|
||||
|
||||
static int nmk_gpio_get_dir(struct gpio_chip *chip, unsigned int offset)
|
||||
{
|
||||
struct nmk_gpio_chip *nmk_chip = gpiochip_get_data(chip);
|
||||
int dir;
|
||||
|
||||
clk_enable(nmk_chip->clk);
|
||||
|
||||
dir = readl(nmk_chip->addr + NMK_GPIO_DIR) & BIT(offset);
|
||||
|
||||
clk_disable(nmk_chip->clk);
|
||||
|
||||
if (dir)
|
||||
return GPIO_LINE_DIRECTION_OUT;
|
||||
|
||||
return GPIO_LINE_DIRECTION_IN;
|
||||
}
|
||||
|
||||
static int nmk_gpio_make_input(struct gpio_chip *chip, unsigned int offset)
|
||||
{
|
||||
struct nmk_gpio_chip *nmk_chip = gpiochip_get_data(chip);
|
||||
|
||||
clk_enable(nmk_chip->clk);
|
||||
|
||||
writel(BIT(offset), nmk_chip->addr + NMK_GPIO_DIRC);
|
||||
|
||||
clk_disable(nmk_chip->clk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nmk_gpio_get_input(struct gpio_chip *chip, unsigned int offset)
|
||||
{
|
||||
struct nmk_gpio_chip *nmk_chip = gpiochip_get_data(chip);
|
||||
int value;
|
||||
|
||||
clk_enable(nmk_chip->clk);
|
||||
|
||||
value = !!(readl(nmk_chip->addr + NMK_GPIO_DAT) & BIT(offset));
|
||||
|
||||
clk_disable(nmk_chip->clk);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
static void nmk_gpio_set_output(struct gpio_chip *chip, unsigned int offset,
|
||||
int val)
|
||||
{
|
||||
struct nmk_gpio_chip *nmk_chip = gpiochip_get_data(chip);
|
||||
|
||||
clk_enable(nmk_chip->clk);
|
||||
|
||||
__nmk_gpio_set_output(nmk_chip, offset, val);
|
||||
|
||||
clk_disable(nmk_chip->clk);
|
||||
}
|
||||
|
||||
static int nmk_gpio_make_output(struct gpio_chip *chip, unsigned int offset,
|
||||
int val)
|
||||
{
|
||||
struct nmk_gpio_chip *nmk_chip = gpiochip_get_data(chip);
|
||||
|
||||
clk_enable(nmk_chip->clk);
|
||||
|
||||
__nmk_gpio_make_output(nmk_chip, offset, val);
|
||||
|
||||
clk_disable(nmk_chip->clk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
|
||||
static int nmk_gpio_get_mode(struct nmk_gpio_chip *nmk_chip, int offset)
|
||||
{
|
||||
u32 afunc, bfunc;
|
||||
|
||||
/* We don't support modes. */
|
||||
if (nmk_chip->is_mobileye_soc)
|
||||
return NMK_GPIO_ALT_GPIO;
|
||||
|
||||
clk_enable(nmk_chip->clk);
|
||||
|
||||
afunc = readl(nmk_chip->addr + NMK_GPIO_AFSLA) & BIT(offset);
|
||||
bfunc = readl(nmk_chip->addr + NMK_GPIO_AFSLB) & BIT(offset);
|
||||
|
||||
clk_disable(nmk_chip->clk);
|
||||
|
||||
return (afunc ? NMK_GPIO_ALT_A : 0) | (bfunc ? NMK_GPIO_ALT_B : 0);
|
||||
}
|
||||
|
||||
void nmk_gpio_dbg_show_one(struct seq_file *s, struct pinctrl_dev *pctldev,
|
||||
struct gpio_chip *chip, unsigned int offset,
|
||||
unsigned int gpio)
|
||||
{
|
||||
struct nmk_gpio_chip *nmk_chip = gpiochip_get_data(chip);
|
||||
int mode;
|
||||
bool is_out;
|
||||
bool data_out;
|
||||
bool pull;
|
||||
static const char * const modes[] = {
|
||||
[NMK_GPIO_ALT_GPIO] = "gpio",
|
||||
[NMK_GPIO_ALT_A] = "altA",
|
||||
[NMK_GPIO_ALT_B] = "altB",
|
||||
[NMK_GPIO_ALT_C] = "altC",
|
||||
[NMK_GPIO_ALT_C + 1] = "altC1",
|
||||
[NMK_GPIO_ALT_C + 2] = "altC2",
|
||||
[NMK_GPIO_ALT_C + 3] = "altC3",
|
||||
[NMK_GPIO_ALT_C + 4] = "altC4",
|
||||
};
|
||||
|
||||
char *label = gpiochip_dup_line_label(chip, offset);
|
||||
if (IS_ERR(label))
|
||||
return;
|
||||
|
||||
clk_enable(nmk_chip->clk);
|
||||
is_out = !!(readl(nmk_chip->addr + NMK_GPIO_DIR) & BIT(offset));
|
||||
pull = !(readl(nmk_chip->addr + NMK_GPIO_PDIS) & BIT(offset));
|
||||
data_out = !!(readl(nmk_chip->addr + NMK_GPIO_DAT) & BIT(offset));
|
||||
mode = nmk_gpio_get_mode(nmk_chip, offset);
|
||||
#ifdef CONFIG_PINCTRL_NOMADIK
|
||||
if (mode == NMK_GPIO_ALT_C && pctldev)
|
||||
mode = nmk_prcm_gpiocr_get_mode(pctldev, gpio);
|
||||
#endif
|
||||
|
||||
if (is_out) {
|
||||
seq_printf(s, " gpio-%-3d (%-20.20s) out %s %s",
|
||||
gpio,
|
||||
label ?: "(none)",
|
||||
data_out ? "hi" : "lo",
|
||||
(mode < 0) ? "unknown" : modes[mode]);
|
||||
} else {
|
||||
int irq = chip->to_irq(chip, offset);
|
||||
const int pullidx = pull ? 1 : 0;
|
||||
int val;
|
||||
static const char * const pulls[] = {
|
||||
"none ",
|
||||
"pull enabled",
|
||||
};
|
||||
|
||||
seq_printf(s, " gpio-%-3d (%-20.20s) in %s %s",
|
||||
gpio,
|
||||
label ?: "(none)",
|
||||
pulls[pullidx],
|
||||
(mode < 0) ? "unknown" : modes[mode]);
|
||||
|
||||
val = nmk_gpio_get_input(chip, offset);
|
||||
seq_printf(s, " VAL %d", val);
|
||||
|
||||
/*
|
||||
* This races with request_irq(), set_irq_type(),
|
||||
* and set_irq_wake() ... but those are "rare".
|
||||
*/
|
||||
if (irq > 0 && irq_has_action(irq)) {
|
||||
char *trigger;
|
||||
bool wake;
|
||||
|
||||
if (nmk_chip->edge_rising & BIT(offset))
|
||||
trigger = "edge-rising";
|
||||
else if (nmk_chip->edge_falling & BIT(offset))
|
||||
trigger = "edge-falling";
|
||||
else
|
||||
trigger = "edge-undefined";
|
||||
|
||||
wake = !!(nmk_chip->real_wake & BIT(offset));
|
||||
|
||||
seq_printf(s, " irq-%d %s%s",
|
||||
irq, trigger, wake ? " wakeup" : "");
|
||||
}
|
||||
}
|
||||
clk_disable(nmk_chip->clk);
|
||||
}
|
||||
|
||||
static void nmk_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
|
||||
{
|
||||
unsigned int i, gpio = chip->base;
|
||||
|
||||
for (i = 0; i < chip->ngpio; i++, gpio++) {
|
||||
nmk_gpio_dbg_show_one(s, NULL, chip, i, gpio);
|
||||
seq_puts(s, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#define nmk_gpio_dbg_show NULL
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* We will allocate memory for the state container using devm* allocators
|
||||
* binding to the first device reaching this point, it doesn't matter if
|
||||
* it is the pin controller or GPIO driver. However we need to use the right
|
||||
* platform device when looking up resources so pay attention to pdev.
|
||||
*/
|
||||
struct nmk_gpio_chip *nmk_gpio_populate_chip(struct fwnode_handle *fwnode,
|
||||
struct platform_device *pdev)
|
||||
{
|
||||
struct nmk_gpio_chip *nmk_chip;
|
||||
struct platform_device *gpio_pdev;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct reset_control *reset;
|
||||
struct device *gpio_dev;
|
||||
struct gpio_chip *chip;
|
||||
struct resource *res;
|
||||
struct clk *clk;
|
||||
void __iomem *base;
|
||||
u32 id, ngpio;
|
||||
int ret;
|
||||
|
||||
gpio_dev = bus_find_device_by_fwnode(&platform_bus_type, fwnode);
|
||||
if (!gpio_dev) {
|
||||
dev_err(dev, "populate \"%pfwP\": device not found\n", fwnode);
|
||||
return ERR_PTR(-ENODEV);
|
||||
}
|
||||
gpio_pdev = to_platform_device(gpio_dev);
|
||||
|
||||
if (device_property_read_u32(gpio_dev, "gpio-bank", &id)) {
|
||||
dev_err(dev, "populate: gpio-bank property not found\n");
|
||||
platform_device_put(gpio_pdev);
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PINCTRL_NOMADIK
|
||||
if (id >= ARRAY_SIZE(nmk_gpio_chips)) {
|
||||
dev_err(dev, "populate: invalid id: %u\n", id);
|
||||
platform_device_put(gpio_pdev);
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
/* Already populated? */
|
||||
nmk_chip = nmk_gpio_chips[id];
|
||||
if (nmk_chip) {
|
||||
platform_device_put(gpio_pdev);
|
||||
return nmk_chip;
|
||||
}
|
||||
#endif
|
||||
|
||||
nmk_chip = devm_kzalloc(dev, sizeof(*nmk_chip), GFP_KERNEL);
|
||||
if (!nmk_chip) {
|
||||
platform_device_put(gpio_pdev);
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
if (device_property_read_u32(gpio_dev, "ngpios", &ngpio)) {
|
||||
ngpio = NMK_GPIO_PER_CHIP;
|
||||
dev_dbg(dev, "populate: using default ngpio (%u)\n", ngpio);
|
||||
}
|
||||
|
||||
nmk_chip->is_mobileye_soc = device_is_compatible(gpio_dev,
|
||||
"mobileye,eyeq5-gpio");
|
||||
nmk_chip->bank = id;
|
||||
chip = &nmk_chip->chip;
|
||||
chip->base = -1;
|
||||
chip->ngpio = ngpio;
|
||||
chip->label = dev_name(gpio_dev);
|
||||
chip->parent = gpio_dev;
|
||||
|
||||
/* NOTE: different devices! No devm_platform_ioremap_resource() here! */
|
||||
res = platform_get_resource(gpio_pdev, IORESOURCE_MEM, 0);
|
||||
base = devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(base)) {
|
||||
platform_device_put(gpio_pdev);
|
||||
return ERR_CAST(base);
|
||||
}
|
||||
nmk_chip->addr = base;
|
||||
|
||||
/* NOTE: do not use devm_ here! */
|
||||
clk = clk_get_optional(gpio_dev, NULL);
|
||||
if (IS_ERR(clk)) {
|
||||
platform_device_put(gpio_pdev);
|
||||
return ERR_CAST(clk);
|
||||
}
|
||||
clk_prepare(clk);
|
||||
nmk_chip->clk = clk;
|
||||
|
||||
/* NOTE: do not use devm_ here! */
|
||||
reset = reset_control_get_optional_shared(gpio_dev, NULL);
|
||||
if (IS_ERR(reset)) {
|
||||
clk_unprepare(clk);
|
||||
clk_put(clk);
|
||||
platform_device_put(gpio_pdev);
|
||||
dev_err(dev, "failed getting reset control: %pe\n",
|
||||
reset);
|
||||
return ERR_CAST(reset);
|
||||
}
|
||||
|
||||
/*
|
||||
* Reset might be shared and asserts/deasserts calls are unbalanced. We
|
||||
* only support sharing this reset with other gpio-nomadik devices that
|
||||
* use this reset to ensure deassertion at probe.
|
||||
*/
|
||||
ret = reset_control_deassert(reset);
|
||||
if (ret) {
|
||||
reset_control_put(reset);
|
||||
clk_unprepare(clk);
|
||||
clk_put(clk);
|
||||
platform_device_put(gpio_pdev);
|
||||
dev_err(dev, "failed reset deassert: %d\n", ret);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PINCTRL_NOMADIK
|
||||
nmk_gpio_chips[id] = nmk_chip;
|
||||
#endif
|
||||
return nmk_chip;
|
||||
}
|
||||
|
||||
static void nmk_gpio_irq_print_chip(struct irq_data *d, struct seq_file *p)
|
||||
{
|
||||
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
|
||||
struct nmk_gpio_chip *nmk_chip = gpiochip_get_data(gc);
|
||||
|
||||
seq_printf(p, "nmk%u-%u-%u", nmk_chip->bank,
|
||||
gc->base, gc->base + gc->ngpio - 1);
|
||||
}
|
||||
|
||||
static const struct irq_chip nmk_irq_chip = {
|
||||
.irq_ack = nmk_gpio_irq_ack,
|
||||
.irq_mask = nmk_gpio_irq_mask,
|
||||
.irq_unmask = nmk_gpio_irq_unmask,
|
||||
.irq_set_type = nmk_gpio_irq_set_type,
|
||||
.irq_set_wake = nmk_gpio_irq_set_wake,
|
||||
.irq_startup = nmk_gpio_irq_startup,
|
||||
.irq_shutdown = nmk_gpio_irq_shutdown,
|
||||
.irq_print_chip = nmk_gpio_irq_print_chip,
|
||||
.flags = IRQCHIP_MASK_ON_SUSPEND | IRQCHIP_IMMUTABLE,
|
||||
GPIOCHIP_IRQ_RESOURCE_HELPERS,
|
||||
};
|
||||
|
||||
static int nmk_gpio_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct nmk_gpio_chip *nmk_chip;
|
||||
struct gpio_irq_chip *girq;
|
||||
bool supports_sleepmode;
|
||||
struct gpio_chip *chip;
|
||||
int irq;
|
||||
int ret;
|
||||
|
||||
nmk_chip = nmk_gpio_populate_chip(dev_fwnode(dev), pdev);
|
||||
if (IS_ERR(nmk_chip)) {
|
||||
dev_err(dev, "could not populate nmk chip struct\n");
|
||||
return PTR_ERR(nmk_chip);
|
||||
}
|
||||
|
||||
supports_sleepmode =
|
||||
device_property_read_bool(dev, "st,supports-sleepmode");
|
||||
|
||||
/* Correct platform device ID */
|
||||
pdev->id = nmk_chip->bank;
|
||||
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq < 0)
|
||||
return irq;
|
||||
|
||||
/*
|
||||
* The virt address in nmk_chip->addr is in the nomadik register space,
|
||||
* so we can simply convert the resource address, without remapping
|
||||
*/
|
||||
nmk_chip->sleepmode = supports_sleepmode;
|
||||
spin_lock_init(&nmk_chip->lock);
|
||||
|
||||
chip = &nmk_chip->chip;
|
||||
chip->parent = dev;
|
||||
chip->request = gpiochip_generic_request;
|
||||
chip->free = gpiochip_generic_free;
|
||||
chip->get_direction = nmk_gpio_get_dir;
|
||||
chip->direction_input = nmk_gpio_make_input;
|
||||
chip->get = nmk_gpio_get_input;
|
||||
chip->direction_output = nmk_gpio_make_output;
|
||||
chip->set = nmk_gpio_set_output;
|
||||
chip->dbg_show = nmk_gpio_dbg_show;
|
||||
chip->can_sleep = false;
|
||||
chip->owner = THIS_MODULE;
|
||||
|
||||
girq = &chip->irq;
|
||||
gpio_irq_chip_set_chip(girq, &nmk_irq_chip);
|
||||
girq->parent_handler = NULL;
|
||||
girq->num_parents = 0;
|
||||
girq->parents = NULL;
|
||||
girq->default_type = IRQ_TYPE_NONE;
|
||||
girq->handler = handle_edge_irq;
|
||||
|
||||
ret = devm_request_irq(dev, irq, nmk_gpio_irq_handler, IRQF_SHARED,
|
||||
dev_name(dev), nmk_chip);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed requesting IRQ\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!nmk_chip->is_mobileye_soc) {
|
||||
clk_enable(nmk_chip->clk);
|
||||
nmk_chip->lowemi = readl_relaxed(nmk_chip->addr + NMK_GPIO_LOWEMI);
|
||||
clk_disable(nmk_chip->clk);
|
||||
}
|
||||
|
||||
ret = gpiochip_add_data(chip, nmk_chip);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
platform_set_drvdata(pdev, nmk_chip);
|
||||
|
||||
dev_info(dev, "chip registered\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id nmk_gpio_match[] = {
|
||||
{ .compatible = "st,nomadik-gpio", },
|
||||
{ .compatible = "mobileye,eyeq5-gpio", },
|
||||
{}
|
||||
};
|
||||
|
||||
static struct platform_driver nmk_gpio_driver = {
|
||||
.driver = {
|
||||
.name = "nomadik-gpio",
|
||||
.of_match_table = nmk_gpio_match,
|
||||
.suppress_bind_attrs = true,
|
||||
},
|
||||
.probe = nmk_gpio_probe,
|
||||
};
|
||||
|
||||
static int __init nmk_gpio_init(void)
|
||||
{
|
||||
return platform_driver_register(&nmk_gpio_driver);
|
||||
}
|
||||
subsys_initcall(nmk_gpio_init);
|
@ -127,6 +127,24 @@ config PINCTRL_AXP209
|
||||
selected.
|
||||
Say Y to enable pinctrl and GPIO support for the AXP209 PMIC.
|
||||
|
||||
config PINCTRL_AW9523
|
||||
tristate "Awinic AW9523/AW9523B I2C GPIO expander pinctrl driver"
|
||||
depends on OF && I2C
|
||||
select PINMUX
|
||||
select PINCONF
|
||||
select GENERIC_PINCONF
|
||||
select GPIOLIB
|
||||
select GPIOLIB_IRQCHIP
|
||||
select REGMAP
|
||||
select REGMAP_I2C
|
||||
help
|
||||
The Awinic AW9523/AW9523B is a multi-function I2C GPIO
|
||||
expander with PWM functionality. This driver bundles a
|
||||
pinctrl driver to select the function muxing and a GPIO
|
||||
driver to handle GPIO, when the GPIO function is selected.
|
||||
|
||||
Say yes to enable pinctrl and GPIO support for the AW9523(B).
|
||||
|
||||
config PINCTRL_BM1880
|
||||
bool "Bitmain BM1880 Pinctrl driver"
|
||||
depends on OF && (ARCH_BITMAIN || COMPILE_TEST)
|
||||
|
@ -15,6 +15,7 @@ obj-$(CONFIG_PINCTRL_ARTPEC6) += pinctrl-artpec6.o
|
||||
obj-$(CONFIG_PINCTRL_AS3722) += pinctrl-as3722.o
|
||||
obj-$(CONFIG_PINCTRL_AT91) += pinctrl-at91.o
|
||||
obj-$(CONFIG_PINCTRL_AT91PIO4) += pinctrl-at91-pio4.o
|
||||
obj-$(CONFIG_PINCTRL_AW9523) += pinctrl-aw9523.o
|
||||
obj-$(CONFIG_PINCTRL_AXP209) += pinctrl-axp209.o
|
||||
obj-$(CONFIG_PINCTRL_BM1880) += pinctrl-bm1880.o
|
||||
obj-$(CONFIG_PINCTRL_CY8C95X0) += pinctrl-cy8c95x0.o
|
||||
|
@ -5,10 +5,10 @@
|
||||
// Copyright (c) 2023 Cirrus Logic, Inc. and
|
||||
// Cirrus Logic International Semiconductor Ltd.
|
||||
|
||||
#include <linux/array_size.h>
|
||||
#include <linux/bits.h>
|
||||
#include <linux/build_bug.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/gpio/driver.h>
|
||||
#include <linux/mfd/cs42l43.h>
|
||||
#include <linux/mfd/cs42l43-regs.h>
|
||||
@ -17,7 +17,7 @@
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/string_helpers.h>
|
||||
#include <linux/string_choices.h>
|
||||
|
||||
#include <linux/pinctrl/consumer.h>
|
||||
#include <linux/pinctrl/pinctrl.h>
|
||||
@ -276,7 +276,7 @@ static const struct pinmux_ops cs42l43_pin_mux_ops = {
|
||||
|
||||
static const unsigned int cs42l43_pin_drv_str_ma[] = { 1, 2, 4, 8, 9, 10, 12, 16 };
|
||||
|
||||
static inline int cs42l43_pin_get_drv_str(struct cs42l43_pin *priv, unsigned int pin)
|
||||
static int cs42l43_pin_get_drv_str(struct cs42l43_pin *priv, unsigned int pin)
|
||||
{
|
||||
const struct cs42l43_pin_data *pdat = cs42l43_pin_pins[pin].drv_data;
|
||||
unsigned int val;
|
||||
@ -289,8 +289,8 @@ static inline int cs42l43_pin_get_drv_str(struct cs42l43_pin *priv, unsigned int
|
||||
return cs42l43_pin_drv_str_ma[(val & pdat->mask) >> pdat->shift];
|
||||
}
|
||||
|
||||
static inline int cs42l43_pin_set_drv_str(struct cs42l43_pin *priv, unsigned int pin,
|
||||
unsigned int ma)
|
||||
static int cs42l43_pin_set_drv_str(struct cs42l43_pin *priv, unsigned int pin,
|
||||
unsigned int ma)
|
||||
{
|
||||
const struct cs42l43_pin_data *pdat = cs42l43_pin_pins[pin].drv_data;
|
||||
int i;
|
||||
@ -314,7 +314,7 @@ static inline int cs42l43_pin_set_drv_str(struct cs42l43_pin *priv, unsigned int
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static inline int cs42l43_pin_get_db(struct cs42l43_pin *priv, unsigned int pin)
|
||||
static int cs42l43_pin_get_db(struct cs42l43_pin *priv, unsigned int pin)
|
||||
{
|
||||
unsigned int val;
|
||||
int ret;
|
||||
@ -332,8 +332,8 @@ static inline int cs42l43_pin_get_db(struct cs42l43_pin *priv, unsigned int pin)
|
||||
return 85; // Debounce is roughly 85uS
|
||||
}
|
||||
|
||||
static inline int cs42l43_pin_set_db(struct cs42l43_pin *priv, unsigned int pin,
|
||||
unsigned int us)
|
||||
static int cs42l43_pin_set_db(struct cs42l43_pin *priv, unsigned int pin,
|
||||
unsigned int us)
|
||||
{
|
||||
if (pin >= CS42L43_NUM_GPIOS)
|
||||
return -ENOTSUPP;
|
||||
@ -490,7 +490,7 @@ static void cs42l43_gpio_set(struct gpio_chip *chip, unsigned int offset, int va
|
||||
int ret;
|
||||
|
||||
dev_dbg(priv->dev, "Setting gpio%d to %s\n",
|
||||
offset + 1, value ? "high" : "low");
|
||||
offset + 1, str_high_low(value));
|
||||
|
||||
ret = pm_runtime_resume_and_get(priv->dev);
|
||||
if (ret) {
|
||||
|
@ -412,6 +412,10 @@ static int pinctrl_get_device_gpio_range(struct gpio_chip *gc,
|
||||
* @pctldev: pin controller device to add the range to
|
||||
* @range: the GPIO range to add
|
||||
*
|
||||
* DEPRECATED: Don't use this function in new code. See section 2 of
|
||||
* Documentation/devicetree/bindings/gpio/gpio.txt on how to bind pinctrl and
|
||||
* gpio drivers.
|
||||
*
|
||||
* This adds a range of GPIOs to be handled by a certain pin controller. Call
|
||||
* this to register handled ranges after registering your pin controller.
|
||||
*/
|
||||
|
@ -700,6 +700,15 @@ static int mt7981_drv_vbus_pins[] = { 14, };
|
||||
static int mt7981_drv_vbus_funcs[] = { 1, };
|
||||
|
||||
/* EMMC */
|
||||
static int mt7981_emmc_reset_pins[] = { 15, };
|
||||
static int mt7981_emmc_reset_funcs[] = { 2, };
|
||||
|
||||
static int mt7981_emmc_4_pins[] = { 16, 17, 18, 19, 24, 25, };
|
||||
static int mt7981_emmc_4_funcs[] = { 2, 2, 2, 2, 2, 2, };
|
||||
|
||||
static int mt7981_emmc_8_pins[] = { 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, };
|
||||
static int mt7981_emmc_8_funcs[] = { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, };
|
||||
|
||||
static int mt7981_emmc_45_pins[] = { 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, };
|
||||
static int mt7981_emmc_45_funcs[] = { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, };
|
||||
|
||||
@ -737,6 +746,9 @@ static int mt7981_uart1_1_funcs[] = { 2, 2, 2, 2, };
|
||||
static int mt7981_uart1_2_pins[] = { 9, 10, };
|
||||
static int mt7981_uart1_2_funcs[] = { 2, 2, };
|
||||
|
||||
static int mt7981_uart1_3_pins[] = { 26, 27, };
|
||||
static int mt7981_uart1_3_funcs[] = { 2, 2, };
|
||||
|
||||
/* UART2 */
|
||||
static int mt7981_uart2_1_pins[] = { 22, 23, 24, 25, };
|
||||
static int mt7981_uart2_1_funcs[] = { 3, 3, 3, 3, };
|
||||
@ -851,6 +863,12 @@ static const struct group_desc mt7981_groups[] = {
|
||||
PINCTRL_PIN_GROUP("udi", mt7981_udi),
|
||||
/* @GPIO(14) DRV_VBUS(1) */
|
||||
PINCTRL_PIN_GROUP("drv_vbus", mt7981_drv_vbus),
|
||||
/* @GPIO(15): EMMC_RSTB(2) */
|
||||
PINCTRL_PIN_GROUP("emmc_reset", mt7981_emmc_reset),
|
||||
/* @GPIO(16,17,18,19,24,25): EMMC_DATx, EMMC_CLK, EMMC_CMD */
|
||||
PINCTRL_PIN_GROUP("emmc_4", mt7981_emmc_4),
|
||||
/* @GPIO(16,17,18,19,20,21,22,23,24,25): EMMC_DATx, EMMC_CLK, EMMC_CMD */
|
||||
PINCTRL_PIN_GROUP("emmc_8", mt7981_emmc_8),
|
||||
/* @GPIO(15,25): EMMC(2) */
|
||||
PINCTRL_PIN_GROUP("emmc_45", mt7981_emmc_45),
|
||||
/* @GPIO(16,21): SNFI(3) */
|
||||
@ -871,6 +889,8 @@ static const struct group_desc mt7981_groups[] = {
|
||||
PINCTRL_PIN_GROUP("uart1_1", mt7981_uart1_1),
|
||||
/* @GPIO(9,10): UART1(2) */
|
||||
PINCTRL_PIN_GROUP("uart1_2", mt7981_uart1_2),
|
||||
/* @GPIO(26,27): UART1(2) */
|
||||
PINCTRL_PIN_GROUP("uart1_3", mt7981_uart1_3),
|
||||
/* @GPIO(22,25): UART1(3) */
|
||||
PINCTRL_PIN_GROUP("uart2_1", mt7981_uart2_1),
|
||||
/* @GPIO(22,24) PTA_EXT(4) */
|
||||
@ -933,7 +953,7 @@ static const struct group_desc mt7981_groups[] = {
|
||||
static const char *mt7981_wa_aice_groups[] = { "wa_aice1", "wa_aice2", "wm_aice1_1",
|
||||
"wa_aice3", "wm_aice1_2", };
|
||||
static const char *mt7981_uart_groups[] = { "net_wo0_uart_txd_0", "net_wo0_uart_txd_1",
|
||||
"net_wo0_uart_txd_2", "uart0", "uart1_0", "uart1_1", "uart1_2", "uart2_0",
|
||||
"net_wo0_uart_txd_2", "uart0", "uart1_0", "uart1_1", "uart1_2", "uart1_3", "uart2_0",
|
||||
"uart2_0_tx_rx", "uart2_1", "wm_uart_0", "wm_aurt_1", "wm_aurt_2", };
|
||||
static const char *mt7981_dfd_groups[] = { "dfd", "dfd_ntrst", };
|
||||
static const char *mt7981_wdt_groups[] = { "watchdog", "watchdog1", };
|
||||
@ -952,7 +972,7 @@ static const char *mt7981_i2c_groups[] = { "i2c0_0", "i2c0_1", "u2_phy_i2c",
|
||||
static const char *mt7981_pcm_groups[] = { "pcm", };
|
||||
static const char *mt7981_udi_groups[] = { "udi", };
|
||||
static const char *mt7981_usb_groups[] = { "drv_vbus", };
|
||||
static const char *mt7981_flash_groups[] = { "emmc_45", "snfi", };
|
||||
static const char *mt7981_flash_groups[] = { "emmc_reset", "emmc_4", "emmc_8", "emmc_45", "snfi", };
|
||||
static const char *mt7981_ethernet_groups[] = { "smi_mdc_mdio", "gbe_ext_mdc_mdio",
|
||||
"wf0_mode1", "wf0_mode3", "mt7531_int", };
|
||||
static const char *mt7981_ant_groups[] = { "ant_sel", };
|
||||
|
@ -16,7 +16,7 @@
|
||||
PIN_FIELD_CALC(_s_pin, _e_pin, _i_base, _s_addr, _x_addrs, _s_bit, \
|
||||
_x_bits, 32, 0)
|
||||
|
||||
/**
|
||||
/*
|
||||
* enum - Locking variants of the iocfg bases
|
||||
*
|
||||
* MT7986 have multiple bases to program pin configuration listed as the below:
|
||||
|
@ -1198,7 +1198,6 @@ static const struct mtk_pin_reg_calc mt8186_reg_cals[PINCTRL_PIN_REG_MAX] = {
|
||||
[PINCTRL_PIN_REG_DIR] = MTK_RANGE(mt8186_pin_dir_range),
|
||||
[PINCTRL_PIN_REG_DI] = MTK_RANGE(mt8186_pin_di_range),
|
||||
[PINCTRL_PIN_REG_DO] = MTK_RANGE(mt8186_pin_do_range),
|
||||
[PINCTRL_PIN_REG_SR] = MTK_RANGE(mt8186_pin_dir_range),
|
||||
[PINCTRL_PIN_REG_SMT] = MTK_RANGE(mt8186_pin_smt_range),
|
||||
[PINCTRL_PIN_REG_IES] = MTK_RANGE(mt8186_pin_ies_range),
|
||||
[PINCTRL_PIN_REG_PU] = MTK_RANGE(mt8186_pin_pu_range),
|
||||
|
@ -1379,7 +1379,6 @@ static const struct mtk_pin_reg_calc mt8192_reg_cals[PINCTRL_PIN_REG_MAX] = {
|
||||
[PINCTRL_PIN_REG_DIR] = MTK_RANGE(mt8192_pin_dir_range),
|
||||
[PINCTRL_PIN_REG_DI] = MTK_RANGE(mt8192_pin_di_range),
|
||||
[PINCTRL_PIN_REG_DO] = MTK_RANGE(mt8192_pin_do_range),
|
||||
[PINCTRL_PIN_REG_SR] = MTK_RANGE(mt8192_pin_dir_range),
|
||||
[PINCTRL_PIN_REG_SMT] = MTK_RANGE(mt8192_pin_smt_range),
|
||||
[PINCTRL_PIN_REG_IES] = MTK_RANGE(mt8192_pin_ies_range),
|
||||
[PINCTRL_PIN_REG_PU] = MTK_RANGE(mt8192_pin_pu_range),
|
||||
|
@ -18,15 +18,15 @@ config PINCTRL_AB8505
|
||||
|
||||
endif
|
||||
|
||||
if (ARCH_U8500 || ARCH_NOMADIK)
|
||||
if (ARCH_U8500 || ARCH_NOMADIK || COMPILE_TEST)
|
||||
|
||||
config PINCTRL_NOMADIK
|
||||
bool "Nomadik pin controller driver"
|
||||
depends on OF && GPIOLIB
|
||||
depends on OF
|
||||
select PINMUX
|
||||
select PINCONF
|
||||
select OF_GPIO
|
||||
select GPIOLIB_IRQCHIP
|
||||
select GPIOLIB
|
||||
select GPIO_NOMADIK
|
||||
|
||||
config PINCTRL_STN8815
|
||||
bool "STN8815 pin controller driver"
|
||||
|
@ -3,8 +3,9 @@
|
||||
#include <linux/types.h>
|
||||
|
||||
#include <linux/pinctrl/pinctrl.h>
|
||||
#include <linux/gpio/driver.h>
|
||||
|
||||
#include "pinctrl-nomadik.h"
|
||||
#include <linux/gpio/gpio-nomadik.h>
|
||||
|
||||
/* All the pins that can be used for GPIO and some other functions */
|
||||
#define _GPIO(offset) (offset)
|
||||
|
@ -3,8 +3,9 @@
|
||||
#include <linux/types.h>
|
||||
|
||||
#include <linux/pinctrl/pinctrl.h>
|
||||
#include <linux/gpio/driver.h>
|
||||
|
||||
#include "pinctrl-nomadik.h"
|
||||
#include <linux/gpio/gpio-nomadik.h>
|
||||
|
||||
/* All the pins that can be used for GPIO and some other functions */
|
||||
#define _GPIO(offset) (offset)
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -474,7 +474,7 @@ enum {
|
||||
#undef WPCM450_GRP
|
||||
};
|
||||
|
||||
static struct pingroup wpcm450_groups[] = {
|
||||
static const struct pingroup wpcm450_groups[] = {
|
||||
#define WPCM450_GRP(x) PINCTRL_PINGROUP(#x, x ## _pins, ARRAY_SIZE(x ## _pins))
|
||||
WPCM450_GRPS
|
||||
#undef WPCM450_GRP
|
||||
|
1119
drivers/pinctrl/pinctrl-aw9523.c
Normal file
1119
drivers/pinctrl/pinctrl-aw9523.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -281,10 +281,17 @@ static int da9062_pctl_probe(struct platform_device *pdev)
|
||||
return devm_gpiochip_add_data(&pdev->dev, &pctl->gc, pctl);
|
||||
}
|
||||
|
||||
static const struct of_device_id da9062_compatible_reg_id_table[] = {
|
||||
{ .compatible = "dlg,da9062-gpio" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, da9062_compatible_reg_id_table);
|
||||
|
||||
static struct platform_driver da9062_pctl_driver = {
|
||||
.probe = da9062_pctl_probe,
|
||||
.driver = {
|
||||
.name = "da9062-gpio",
|
||||
.of_match_table = da9062_compatible_reg_id_table,
|
||||
},
|
||||
};
|
||||
module_platform_driver(da9062_pctl_driver);
|
||||
|
@ -375,7 +375,8 @@ mcp23s08_direction_output(struct gpio_chip *chip, unsigned offset, int value)
|
||||
static irqreturn_t mcp23s08_irq(int irq, void *data)
|
||||
{
|
||||
struct mcp23s08 *mcp = data;
|
||||
int intcap, intcon, intf, i, gpio, gpio_orig, intcap_mask, defval;
|
||||
int intcap, intcon, intf, i, gpio, gpio_orig, intcap_mask, defval, gpinten;
|
||||
unsigned long int enabled_interrupts;
|
||||
unsigned int child_irq;
|
||||
bool intf_set, intcap_changed, gpio_bit_changed,
|
||||
defval_changed, gpio_set;
|
||||
@ -395,6 +396,9 @@ static irqreturn_t mcp23s08_irq(int irq, void *data)
|
||||
if (mcp_read(mcp, MCP_INTCON, &intcon))
|
||||
goto unlock;
|
||||
|
||||
if (mcp_read(mcp, MCP_GPINTEN, &gpinten))
|
||||
goto unlock;
|
||||
|
||||
if (mcp_read(mcp, MCP_DEFVAL, &defval))
|
||||
goto unlock;
|
||||
|
||||
@ -410,9 +414,12 @@ static irqreturn_t mcp23s08_irq(int irq, void *data)
|
||||
"intcap 0x%04X intf 0x%04X gpio_orig 0x%04X gpio 0x%04X\n",
|
||||
intcap, intf, gpio_orig, gpio);
|
||||
|
||||
for (i = 0; i < mcp->chip.ngpio; i++) {
|
||||
/* We must check all of the inputs on the chip,
|
||||
* otherwise we may not notice a change on >=2 pins.
|
||||
enabled_interrupts = gpinten;
|
||||
for_each_set_bit(i, &enabled_interrupts, mcp->chip.ngpio) {
|
||||
/*
|
||||
* We must check all of the inputs with enabled interrupts
|
||||
* on the chip, otherwise we may not notice a change
|
||||
* on more than one pin.
|
||||
*
|
||||
* On at least the mcp23s17, INTCAP is only updated
|
||||
* one byte at a time(INTCAPA and INTCAPB are
|
||||
|
@ -1401,7 +1401,6 @@ static int ocelot_hw_set_value(struct ocelot_pinctrl *info,
|
||||
if (info->pincfg) {
|
||||
const struct ocelot_pincfg_data *opd = info->pincfg_data;
|
||||
|
||||
ret = 0;
|
||||
switch (reg) {
|
||||
case PINCONF_BIAS:
|
||||
ret = ocelot_pincfg_clrsetbits(info, pin,
|
||||
|
@ -723,9 +723,8 @@ static int st_gpio_direction_output(struct gpio_chip *chip,
|
||||
struct st_gpio_bank *bank = gpiochip_get_data(chip);
|
||||
|
||||
__st_gpio_set(bank, offset, value);
|
||||
pinctrl_gpio_direction_output(chip, offset);
|
||||
|
||||
return 0;
|
||||
return pinctrl_gpio_direction_output(chip, offset);
|
||||
}
|
||||
|
||||
static int st_gpio_get_direction(struct gpio_chip *chip, unsigned offset)
|
||||
|
@ -562,7 +562,7 @@ static int zynqmp_pinctrl_prepare_func_groups(struct device *dev, u32 fid,
|
||||
const char **fgroups;
|
||||
int ret, index, i;
|
||||
|
||||
fgroups = devm_kzalloc(dev, sizeof(*fgroups) * func->ngroups, GFP_KERNEL);
|
||||
fgroups = devm_kcalloc(dev, func->ngroups, sizeof(*fgroups), GFP_KERNEL);
|
||||
if (!fgroups)
|
||||
return -ENOMEM;
|
||||
|
||||
@ -754,7 +754,7 @@ static int zynqmp_pinctrl_prepare_function_info(struct device *dev,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
funcs = devm_kzalloc(dev, sizeof(*funcs) * pctrl->nfuncs, GFP_KERNEL);
|
||||
funcs = devm_kcalloc(dev, pctrl->nfuncs, sizeof(*funcs), GFP_KERNEL);
|
||||
if (!funcs)
|
||||
return -ENOMEM;
|
||||
|
||||
@ -768,7 +768,7 @@ static int zynqmp_pinctrl_prepare_function_info(struct device *dev,
|
||||
pctrl->ngroups += funcs[i].ngroups;
|
||||
}
|
||||
|
||||
groups = devm_kzalloc(dev, sizeof(*groups) * pctrl->ngroups, GFP_KERNEL);
|
||||
groups = devm_kcalloc(dev, pctrl->ngroups, sizeof(*groups), GFP_KERNEL);
|
||||
if (!groups)
|
||||
return -ENOMEM;
|
||||
|
||||
@ -830,7 +830,7 @@ static int zynqmp_pinctrl_prepare_pin_desc(struct device *dev,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
pins = devm_kzalloc(dev, sizeof(*pins) * *npins, GFP_KERNEL);
|
||||
pins = devm_kcalloc(dev, *npins, sizeof(*pins), GFP_KERNEL);
|
||||
if (!pins)
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -188,8 +188,8 @@ static int pin_request(struct pinctrl_dev *pctldev,
|
||||
}
|
||||
out:
|
||||
if (status)
|
||||
dev_err(pctldev->dev, "pin-%d (%s) status %d\n",
|
||||
pin, owner, status);
|
||||
dev_err_probe(pctldev->dev, status, "pin-%d (%s)\n",
|
||||
pin, owner);
|
||||
|
||||
return status;
|
||||
}
|
||||
@ -441,7 +441,7 @@ int pinmux_enable_setting(const struct pinctrl_setting *setting)
|
||||
pname = desc ? desc->name : "non-existing";
|
||||
gname = pctlops->get_group_name(pctldev,
|
||||
setting->data.mux.group);
|
||||
dev_err(pctldev->dev,
|
||||
dev_err_probe(pctldev->dev, ret,
|
||||
"could not request pin %d (%s) from group %s "
|
||||
" on device %s\n",
|
||||
pins[i], pname, gname,
|
||||
|
@ -125,7 +125,7 @@ config PINCTRL_SM8550_LPASS_LPI
|
||||
platform.
|
||||
|
||||
config PINCTRL_SM8650_LPASS_LPI
|
||||
tristate "Qualcomm Technologies Inc SM8550 LPASS LPI pin controller driver"
|
||||
tristate "Qualcomm Technologies Inc SM8650 LPASS LPI pin controller driver"
|
||||
depends on ARM64 || COMPILE_TEST
|
||||
depends on PINCTRL_LPASS_LPI
|
||||
help
|
||||
|
@ -38,6 +38,7 @@ config PINCTRL_RENESAS
|
||||
select PINCTRL_PFC_R8A779A0 if ARCH_R8A779A0
|
||||
select PINCTRL_PFC_R8A779F0 if ARCH_R8A779F0
|
||||
select PINCTRL_PFC_R8A779G0 if ARCH_R8A779G0
|
||||
select PINCTRL_PFC_R8A779H0 if ARCH_R8A779H0
|
||||
select PINCTRL_RZG2L if ARCH_RZG2L
|
||||
select PINCTRL_RZV2M if ARCH_R9A09G011
|
||||
select PINCTRL_PFC_SH7203 if CPU_SUBTYPE_SH7203
|
||||
@ -154,6 +155,10 @@ config PINCTRL_PFC_R8A779G0
|
||||
bool "pin control support for R-Car V4H" if COMPILE_TEST
|
||||
select PINCTRL_SH_PFC
|
||||
|
||||
config PINCTRL_PFC_R8A779H0
|
||||
bool "pin control support for R-Car V4M" if COMPILE_TEST
|
||||
select PINCTRL_SH_PFC
|
||||
|
||||
config PINCTRL_PFC_R8A7740
|
||||
bool "pin control support for R-Mobile A1" if COMPILE_TEST
|
||||
select PINCTRL_SH_PFC_GPIO
|
||||
@ -187,9 +192,11 @@ config PINCTRL_RZG2L
|
||||
bool "pin control support for RZ/{G2L,G2UL,V2L}" if COMPILE_TEST
|
||||
depends on OF
|
||||
select GPIOLIB
|
||||
select GPIOLIB_IRQCHIP
|
||||
select GENERIC_PINCTRL_GROUPS
|
||||
select GENERIC_PINMUX_FUNCTIONS
|
||||
select GENERIC_PINCONF
|
||||
select IRQ_DOMAIN_HIERARCHY
|
||||
help
|
||||
This selects GPIO and pinctrl driver for Renesas RZ/{G2L,G2UL,V2L}
|
||||
platforms.
|
||||
|
@ -31,6 +31,7 @@ obj-$(CONFIG_PINCTRL_PFC_R8A77995) += pfc-r8a77995.o
|
||||
obj-$(CONFIG_PINCTRL_PFC_R8A779A0) += pfc-r8a779a0.o
|
||||
obj-$(CONFIG_PINCTRL_PFC_R8A779F0) += pfc-r8a779f0.o
|
||||
obj-$(CONFIG_PINCTRL_PFC_R8A779G0) += pfc-r8a779g0.o
|
||||
obj-$(CONFIG_PINCTRL_PFC_R8A779H0) += pfc-r8a779h0.o
|
||||
obj-$(CONFIG_PINCTRL_PFC_SH7203) += pfc-sh7203.o
|
||||
obj-$(CONFIG_PINCTRL_PFC_SH7264) += pfc-sh7264.o
|
||||
obj-$(CONFIG_PINCTRL_PFC_SH7269) += pfc-sh7269.o
|
||||
|
@ -638,6 +638,12 @@ static const struct of_device_id sh_pfc_of_table[] = {
|
||||
.data = &r8a779g0_pinmux_info,
|
||||
},
|
||||
#endif
|
||||
#ifdef CONFIG_PINCTRL_PFC_R8A779H0
|
||||
{
|
||||
.compatible = "renesas,pfc-r8a779h0",
|
||||
.data = &r8a779h0_pinmux_info,
|
||||
},
|
||||
#endif
|
||||
#ifdef CONFIG_PINCTRL_PFC_SH73A0
|
||||
{
|
||||
.compatible = "renesas,pfc-sh73a0",
|
||||
@ -731,10 +737,12 @@ static int sh_pfc_resume_noirq(struct device *dev)
|
||||
sh_pfc_walk_regs(pfc, sh_pfc_restore_reg);
|
||||
return 0;
|
||||
}
|
||||
#define pm_psci_sleep_ptr(_ptr) pm_sleep_ptr(_ptr)
|
||||
#else
|
||||
static int sh_pfc_suspend_init(struct sh_pfc *pfc) { return 0; }
|
||||
static int sh_pfc_suspend_noirq(struct device *dev) { return 0; }
|
||||
static int sh_pfc_resume_noirq(struct device *dev) { return 0; }
|
||||
#define pm_psci_sleep_ptr(_ptr) PTR_IF(false, (_ptr))
|
||||
#endif /* CONFIG_ARM_PSCI_FW */
|
||||
|
||||
static DEFINE_NOIRQ_DEV_PM_OPS(sh_pfc_pm, sh_pfc_suspend_noirq, sh_pfc_resume_noirq);
|
||||
@ -907,9 +915,11 @@ static void __init sh_pfc_check_cfg_reg(const char *drvname,
|
||||
sh_pfc_err("reg 0x%x: var_field_width declares %u instead of %u bits\n",
|
||||
cfg_reg->reg, rw, cfg_reg->reg_width);
|
||||
|
||||
if (n != cfg_reg->nr_enum_ids)
|
||||
if (n != cfg_reg->nr_enum_ids) {
|
||||
sh_pfc_err("reg 0x%x: enum_ids[] has %u instead of %u values\n",
|
||||
cfg_reg->reg, cfg_reg->nr_enum_ids, n);
|
||||
n = cfg_reg->nr_enum_ids;
|
||||
}
|
||||
|
||||
check_enum_ids:
|
||||
sh_pfc_check_reg_enums(drvname, cfg_reg->reg, cfg_reg->enum_ids, n);
|
||||
@ -1415,7 +1425,7 @@ static struct platform_driver sh_pfc_driver = {
|
||||
.driver = {
|
||||
.name = DRV_NAME,
|
||||
.of_match_table = of_match_ptr(sh_pfc_of_table),
|
||||
.pm = pm_sleep_ptr(&sh_pfc_pm),
|
||||
.pm = pm_psci_sleep_ptr(&sh_pfc_pm),
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -2384,6 +2384,14 @@ static const unsigned int scif_clk_mux[] = {
|
||||
SCIF_CLK_MARK,
|
||||
};
|
||||
|
||||
static const unsigned int scif_clk2_pins[] = {
|
||||
/* SCIF_CLK2 */
|
||||
RCAR_GP_PIN(8, 11),
|
||||
};
|
||||
static const unsigned int scif_clk2_mux[] = {
|
||||
SCIF_CLK2_MARK,
|
||||
};
|
||||
|
||||
/* - SSI ------------------------------------------------- */
|
||||
static const unsigned int ssi_data_pins[] = {
|
||||
/* SSI_SD */
|
||||
@ -2694,6 +2702,7 @@ static const struct sh_pfc_pin_group pinmux_groups[] = {
|
||||
SH_PFC_PIN_GROUP(scif4_clk),
|
||||
SH_PFC_PIN_GROUP(scif4_ctrl),
|
||||
SH_PFC_PIN_GROUP(scif_clk),
|
||||
SH_PFC_PIN_GROUP(scif_clk2),
|
||||
|
||||
SH_PFC_PIN_GROUP(ssi_data),
|
||||
SH_PFC_PIN_GROUP(ssi_ctrl),
|
||||
@ -3015,6 +3024,10 @@ static const char * const scif_clk_groups[] = {
|
||||
"scif_clk",
|
||||
};
|
||||
|
||||
static const char * const scif_clk2_groups[] = {
|
||||
"scif_clk2",
|
||||
};
|
||||
|
||||
static const char * const ssi_groups[] = {
|
||||
"ssi_data",
|
||||
"ssi_ctrl",
|
||||
@ -3102,6 +3115,7 @@ static const struct sh_pfc_function pinmux_functions[] = {
|
||||
SH_PFC_FUNCTION(scif3),
|
||||
SH_PFC_FUNCTION(scif4),
|
||||
SH_PFC_FUNCTION(scif_clk),
|
||||
SH_PFC_FUNCTION(scif_clk2),
|
||||
|
||||
SH_PFC_FUNCTION(ssi),
|
||||
|
||||
|
3967
drivers/pinctrl/renesas/pfc-r8a779h0.c
Normal file
3967
drivers/pinctrl/renesas/pfc-r8a779h0.c
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -322,6 +322,7 @@ extern const struct sh_pfc_soc_info r8a77995_pinmux_info;
|
||||
extern const struct sh_pfc_soc_info r8a779a0_pinmux_info;
|
||||
extern const struct sh_pfc_soc_info r8a779f0_pinmux_info;
|
||||
extern const struct sh_pfc_soc_info r8a779g0_pinmux_info;
|
||||
extern const struct sh_pfc_soc_info r8a779h0_pinmux_info;
|
||||
extern const struct sh_pfc_soc_info sh7203_pinmux_info;
|
||||
extern const struct sh_pfc_soc_info sh7264_pinmux_info;
|
||||
extern const struct sh_pfc_soc_info sh7269_pinmux_info;
|
||||
|
@ -1,16 +1,77 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef PINCTRL_PINCTRL_NOMADIK_H
|
||||
#define PINCTRL_PINCTRL_NOMADIK_H
|
||||
#ifndef __LINUX_GPIO_NOMADIK_H
|
||||
#define __LINUX_GPIO_NOMADIK_H
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#include <linux/pinctrl/pinctrl.h>
|
||||
struct fwnode_handle;
|
||||
|
||||
/* Package definitions */
|
||||
#define PINCTRL_NMK_STN8815 0
|
||||
#define PINCTRL_NMK_DB8500 1
|
||||
|
||||
#define GPIO_BLOCK_SHIFT 5
|
||||
#define NMK_GPIO_PER_CHIP BIT(GPIO_BLOCK_SHIFT)
|
||||
#define NMK_MAX_BANKS DIV_ROUND_UP(512, NMK_GPIO_PER_CHIP)
|
||||
|
||||
/* Register in the logic block */
|
||||
#define NMK_GPIO_DAT 0x00
|
||||
#define NMK_GPIO_DATS 0x04
|
||||
#define NMK_GPIO_DATC 0x08
|
||||
#define NMK_GPIO_PDIS 0x0c
|
||||
#define NMK_GPIO_DIR 0x10
|
||||
#define NMK_GPIO_DIRS 0x14
|
||||
#define NMK_GPIO_DIRC 0x18
|
||||
#define NMK_GPIO_SLPC 0x1c
|
||||
#define NMK_GPIO_AFSLA 0x20
|
||||
#define NMK_GPIO_AFSLB 0x24
|
||||
#define NMK_GPIO_LOWEMI 0x28
|
||||
|
||||
#define NMK_GPIO_RIMSC 0x40
|
||||
#define NMK_GPIO_FIMSC 0x44
|
||||
#define NMK_GPIO_IS 0x48
|
||||
#define NMK_GPIO_IC 0x4c
|
||||
#define NMK_GPIO_RWIMSC 0x50
|
||||
#define NMK_GPIO_FWIMSC 0x54
|
||||
#define NMK_GPIO_WKS 0x58
|
||||
/* These appear in DB8540 and later ASICs */
|
||||
#define NMK_GPIO_EDGELEVEL 0x5C
|
||||
#define NMK_GPIO_LEVEL 0x60
|
||||
|
||||
/* Pull up/down values */
|
||||
enum nmk_gpio_pull {
|
||||
NMK_GPIO_PULL_NONE,
|
||||
NMK_GPIO_PULL_UP,
|
||||
NMK_GPIO_PULL_DOWN,
|
||||
};
|
||||
|
||||
/* Sleep mode */
|
||||
enum nmk_gpio_slpm {
|
||||
NMK_GPIO_SLPM_INPUT,
|
||||
NMK_GPIO_SLPM_WAKEUP_ENABLE = NMK_GPIO_SLPM_INPUT,
|
||||
NMK_GPIO_SLPM_NOCHANGE,
|
||||
NMK_GPIO_SLPM_WAKEUP_DISABLE = NMK_GPIO_SLPM_NOCHANGE,
|
||||
};
|
||||
|
||||
struct nmk_gpio_chip {
|
||||
struct gpio_chip chip;
|
||||
void __iomem *addr;
|
||||
struct clk *clk;
|
||||
unsigned int bank;
|
||||
void (*set_ioforce)(bool enable);
|
||||
spinlock_t lock;
|
||||
bool sleepmode;
|
||||
bool is_mobileye_soc;
|
||||
/* Keep track of configured edges */
|
||||
u32 edge_rising;
|
||||
u32 edge_falling;
|
||||
u32 real_wake;
|
||||
u32 rwimsc;
|
||||
u32 fwimsc;
|
||||
u32 rimsc;
|
||||
u32 fimsc;
|
||||
u32 pull_up;
|
||||
u32 lowemi;
|
||||
};
|
||||
|
||||
/* Alternate functions: function C is set in hw by setting both A and B */
|
||||
#define NMK_GPIO_ALT_GPIO 0
|
||||
#define NMK_GPIO_ALT_A 1
|
||||
@ -104,7 +165,7 @@ struct prcm_gpiocr_altcx_pin_desc {
|
||||
struct nmk_function {
|
||||
const char *name;
|
||||
const char * const *groups;
|
||||
unsigned ngroups;
|
||||
unsigned int ngroups;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -141,13 +202,13 @@ struct nmk_pingroup {
|
||||
*/
|
||||
struct nmk_pinctrl_soc_data {
|
||||
const struct pinctrl_pin_desc *pins;
|
||||
unsigned npins;
|
||||
unsigned int npins;
|
||||
const struct nmk_function *functions;
|
||||
unsigned nfunctions;
|
||||
unsigned int nfunctions;
|
||||
const struct nmk_pingroup *groups;
|
||||
unsigned ngroups;
|
||||
unsigned int ngroups;
|
||||
const struct prcm_gpiocr_altcx_pin_desc *altcx_pins;
|
||||
unsigned npins_altcx;
|
||||
unsigned int npins_altcx;
|
||||
const u16 *prcm_gpiocr_registers;
|
||||
};
|
||||
|
||||
@ -177,4 +238,57 @@ nmk_pinctrl_db8500_init(const struct nmk_pinctrl_soc_data **soc)
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* PINCTRL_PINCTRL_NOMADIK_H */
|
||||
#ifdef CONFIG_PINCTRL_DB8540
|
||||
|
||||
void nmk_pinctrl_db8540_init(const struct nmk_pinctrl_soc_data **soc);
|
||||
|
||||
#else
|
||||
|
||||
static inline void
|
||||
nmk_pinctrl_db8540_init(const struct nmk_pinctrl_soc_data **soc)
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
struct platform_device;
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
|
||||
/*
|
||||
* Symbols declared in gpio-nomadik used by pinctrl-nomadik. If pinctrl-nomadik
|
||||
* is enabled, then gpio-nomadik is enabled as well; the reverse if not always
|
||||
* true.
|
||||
*/
|
||||
void nmk_gpio_dbg_show_one(struct seq_file *s, struct pinctrl_dev *pctldev,
|
||||
struct gpio_chip *chip, unsigned int offset,
|
||||
unsigned int gpio);
|
||||
|
||||
#else
|
||||
|
||||
static inline void nmk_gpio_dbg_show_one(struct seq_file *s,
|
||||
struct pinctrl_dev *pctldev,
|
||||
struct gpio_chip *chip,
|
||||
unsigned int offset,
|
||||
unsigned int gpio)
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void __nmk_gpio_make_output(struct nmk_gpio_chip *nmk_chip,
|
||||
unsigned int offset, int val);
|
||||
void __nmk_gpio_set_slpm(struct nmk_gpio_chip *nmk_chip, unsigned int offset,
|
||||
enum nmk_gpio_slpm mode);
|
||||
struct nmk_gpio_chip *nmk_gpio_populate_chip(struct fwnode_handle *fwnode,
|
||||
struct platform_device *pdev);
|
||||
|
||||
/* Symbols declared in pinctrl-nomadik used by gpio-nomadik. */
|
||||
#ifdef CONFIG_PINCTRL_NOMADIK
|
||||
extern struct nmk_gpio_chip *nmk_gpio_chips[NMK_MAX_BANKS];
|
||||
extern spinlock_t nmk_gpio_slpm_lock;
|
||||
int __maybe_unused nmk_prcm_gpiocr_get_mode(struct pinctrl_dev *pctldev,
|
||||
int gpio);
|
||||
#endif
|
||||
|
||||
#endif /* __LINUX_GPIO_NOMADIK_H */
|
Loading…
Reference in New Issue
Block a user