mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-28 06:34:12 +08:00
This is the bulk of pin control changes for the v5.12 kernel.
This time a calm set with no core changes. New drivers/subdrivers: - Renesas R8A7790A0 pin controller. - Allwinner H616 and H616-R pin controllers. - Qualcomm SM8350 and SC8180x pin controllers. Improvements: - Redo the DT bindings for Ralink RT2880. - A common Qualcomm TLMM DT binding in YAML. - Delete the unused drivers for U300, COH901, Sirf Atlas, and ZTE ZX. -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEElDRnuGcz/wPCXQWMQRCzN7AZXXMFAmAy848ACgkQQRCzN7AZ XXPR0BAArpuUx8elp/+y+gDzL/5Lsv3aJ3AQ9yLfBda380YFwGWZSqjAEovVbhKx 6Xm4g+MzQQ+sxcIHZY7tVWnrI1sbp6MaljVFLqPWWHeY4h4trsw6d+u2bMOFkJTl z0++Ybck+NTscTBvaN0wHqfao3IOU8FG5rL8y9azn9glfQg+xgKCbgAecUgjPXBI 9YLCGMl8mnzH1sl+aImKDszYEuc29NGJrstmkVWcYGVR/XYfxEqNhtT4FlO2P9X1 FNhQYgS0zJsu7UgOOgBsg0xRK5X9pWimwupxEH8MwqANivV3VGweQpcyqIlnA5Qe aXQEa+ZIndOoAsr5UvaHgDXucos7x1odm5AHuIb4V2aGOF5IYyj+iyR3Av4ODdpM +mYI+w9Nydlu1o1JiOb1hAxWNSb2NOBcrOcuiSAIJC7/rO/rqaAPpWmzxSYvGNFO xJTbMN3DtLokE/u9BxCVsXiEFXMy3IA5vu5o+Xks6HRLclWOAqeZJO3uhnlBc8Me qsijZxlugCUIvI7pdKblzOfO+PnB0rLX/7m05/ESTqh6vDcwrZjXLSH0bRWWZBvD CEtBtkIJGjdWsqMk0bqTXJkoqScaKdi0nLSFPK0qOCeqa0ShbxjqU4Vq/f4cQSu+ DzUhF5qBdIaJhDY7V5V7vWygp48+AKVvFtHHmTD+Wb9AJL0MZiY= =WKZ8 -----END PGP SIGNATURE----- Merge tag 'pinctrl-v5.12-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl Pull pin control updates from Linus Walleij: "This is the bulk of pin control changes for the v5.12 kernel. This time a calm set with no core changes. New drivers/subdrivers: - Renesas R8A7790A0 pin controller. - Allwinner H616 and H616-R pin controllers. - Qualcomm SM8350 and SC8180x pin controllers. Improvements: - Redo the DT bindings for Ralink RT2880. - A common Qualcomm TLMM DT binding in YAML. - Delete the unused drivers for U300, COH901, Sirf Atlas, and ZTE ZX" * tag 'pinctrl-v5.12-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl: (71 commits) pinctrl: mediatek: Fix trigger type setting follow for unexpected interrupt dt-bindings: pinctrl: Group tuples in pin control properties pinctrl: nuvoton: npcm7xx: Fix alignment of table header comment pinctrl: at91-pio4: fix "Prefer 'unsigned int' to bare use of 'unsigned'" pinctrl: at91-pio4: add support for slew-rate dt-bindings: pinctrl: at91-pio4: add slew-rate pinctrl: actions: Add depends on || COMPILE_TEST pinctrl: single: set function name when adding function pinctrl: qcom: Add sc8180x TLMM driver dt-bindings: pinctrl: qcom: Add sc8180x binding dt-bindings: pinctrl: qcom: Define common TLMM binding pinctrl: qcom: Add SM8350 pinctrl driver dt-bindings: pinctrl: qcom: Add SM8350 pinctrl bindings pinctrl: samsung: use raw_spinlock for s3c64xx dt-bindings: mediatek: mt8192: Fix dt_binding_check warning pinctrl: qcom: spmi-mpp: Add PM8019 compatible pinctrl: pinmux: add function selector to pinmux-functions pinctrl: samsung: use raw_spinlock for locking pinctrl: clarify #pinctrl-cells for pinctrl-single,pins pinctrl: actions: Add the platform dependency to drivers ...
This commit is contained in:
commit
3b9cdafb53
@ -1,50 +0,0 @@
|
||||
CSR SiRFatlas7 GPIO controller bindings
|
||||
|
||||
Required properties:
|
||||
- compatible : "sirf,atlas7-gpio"
|
||||
- reg : Address range of the pinctrl registers
|
||||
- interrupts : Interrupts used by every GPIO group
|
||||
- gpio-banks : How many gpio banks on this controller
|
||||
- gpio-controller : Indicates this device is a GPIO controller
|
||||
- interrupt-controller : Marks the device node as an interrupt controller
|
||||
|
||||
The GPIO controller also acts as an interrupt controller. It uses the default
|
||||
two cells specifier as described in Documentation/devicetree/bindings/
|
||||
interrupt-controller/interrupts.txt.
|
||||
|
||||
Example:
|
||||
|
||||
gpio_0: gpio_mediam@17040000 {
|
||||
compatible = "sirf,atlas7-gpio";
|
||||
reg = <0x17040000 0x1000>;
|
||||
interrupts = <0 13 0>, <0 14 0>;
|
||||
|
||||
#gpio-cells = <2>;
|
||||
#interrupt-cells = <2>;
|
||||
|
||||
gpio-controller;
|
||||
interrupt-controller;
|
||||
|
||||
gpio-banks = <2>;
|
||||
gpio-ranges = <&pinctrl 0 0 0>,
|
||||
<&pinctrl 32 0 0>;
|
||||
gpio-ranges-group-names = "lvds_gpio_grp",
|
||||
"uart_nand_gpio_grp";
|
||||
};
|
||||
|
||||
leds {
|
||||
compatible = "gpio-leds";
|
||||
|
||||
led1 {
|
||||
gpios = <&gpio_1 15 0>;
|
||||
...
|
||||
};
|
||||
|
||||
led2 {
|
||||
gpios = <&gpio_2 34 0>;
|
||||
...
|
||||
};
|
||||
};
|
||||
|
||||
Please refer to gpio.txt in this directory for details of the common
|
||||
gpio properties used by devices.
|
@ -1,7 +0,0 @@
|
||||
ST-Ericsson COH 901 571/3 GPIO controller
|
||||
|
||||
Required properties:
|
||||
- compatible: Compatible property value should be "stericsson,gpio-coh901"
|
||||
- reg: Physical base address of the controller and length of memory mapped
|
||||
region.
|
||||
- interrupts: the 0...n interrupts assigned to the different GPIO ports/banks.
|
@ -53,6 +53,8 @@ properties:
|
||||
- allwinner,sun50i-h5-pinctrl
|
||||
- allwinner,sun50i-h6-pinctrl
|
||||
- allwinner,sun50i-h6-r-pinctrl
|
||||
- allwinner,sun50i-h616-pinctrl
|
||||
- allwinner,sun50i-h616-r-pinctrl
|
||||
- allwinner,suniv-f1c100s-pinctrl
|
||||
- nextthing,gr8-pinctrl
|
||||
|
||||
@ -61,7 +63,7 @@ properties:
|
||||
|
||||
interrupts:
|
||||
minItems: 1
|
||||
maxItems: 7
|
||||
maxItems: 8
|
||||
description:
|
||||
One interrupt per external interrupt bank supported on the
|
||||
controller, sorted by bank number ascending order.
|
||||
@ -91,7 +93,7 @@ properties:
|
||||
bank found in the controller
|
||||
$ref: /schemas/types.yaml#/definitions/uint32-array
|
||||
minItems: 1
|
||||
maxItems: 5
|
||||
maxItems: 8
|
||||
|
||||
patternProperties:
|
||||
# It's pretty scary, but the basic idea is that:
|
||||
@ -145,6 +147,17 @@ allOf:
|
||||
# boards are defining it at the moment so it would generate a lot of
|
||||
# warnings.
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- allwinner,sun50i-h616-pinctrl
|
||||
|
||||
then:
|
||||
properties:
|
||||
interrupts:
|
||||
minItems: 8
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
|
@ -35,9 +35,11 @@ ioset settings. Use the macros from boot/dts/<soc>-pinfunc.h file to get the
|
||||
right representation of the pin.
|
||||
|
||||
Optional properties:
|
||||
- GENERIC_PINCONFIG: generic pinconfig options to use, bias-disable,
|
||||
bias-pull-down, bias-pull-up, drive-open-drain, input-schmitt-enable,
|
||||
input-debounce, output-low, output-high.
|
||||
- GENERIC_PINCONFIG: generic pinconfig options to use:
|
||||
- bias-disable, bias-pull-down, bias-pull-up, drive-open-drain,
|
||||
input-schmitt-enable, input-debounce, output-low, output-high.
|
||||
- for microchip,sama7g5-pinctrl only:
|
||||
- slew-rate: 0 - disabled, 1 - enabled (default)
|
||||
- atmel,drive-strength: 0 or 1 for low drive, 2 for medium drive and 3 for
|
||||
high drive. The default value is low drive.
|
||||
|
||||
|
@ -39,7 +39,7 @@ For example:
|
||||
<0x660009b0 0x40>;
|
||||
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&nand_sel &uart3_rx &sdio0_d4>;
|
||||
pinctrl-0 = <&nand_sel>, <&uart3_rx>, <&sdio0_d4>;
|
||||
|
||||
/* Select nand function */
|
||||
nand_sel: nand_sel {
|
||||
|
@ -30,7 +30,7 @@ For example:
|
||||
<0x1803f408 0x04>;
|
||||
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pwm &gpio_b &nand_sel>;
|
||||
pinctrl-0 = <&pwm>, <&gpio_b>, <&nand_sel>;
|
||||
|
||||
pwm: pwm {
|
||||
function = "pwm";
|
||||
|
@ -60,7 +60,7 @@ iomuxc-lpsr controller and SDA pad from iomuxc controller as:
|
||||
|
||||
i2c1: i2c@30a20000 {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinctrl_i2c1_1 &pinctrl_i2c1_2>;
|
||||
pinctrl-0 = <&pinctrl_i2c1_1>, <&pinctrl_i2c1_2>;
|
||||
};
|
||||
|
||||
iomuxc-lpsr@302c0000 {
|
||||
|
@ -99,8 +99,8 @@ patternProperties:
|
||||
|
||||
'#interrupt-cells':
|
||||
description:
|
||||
Specifies the pin (port and bit) and flags, as defined in
|
||||
defined in include/dt-bindings/interrupt-controller/irq.h
|
||||
Specifies the pin (port and bit) and flags, as defined in
|
||||
defined in include/dt-bindings/interrupt-controller/irq.h
|
||||
const: 3
|
||||
|
||||
ngpios:
|
||||
|
@ -1,109 +0,0 @@
|
||||
CSR SiRFatlas7 pinmux controller
|
||||
|
||||
Required properties:
|
||||
- compatible : "sirf,atlas7-ioc"
|
||||
- reg : Address range of the pinctrl registers
|
||||
|
||||
For example, pinctrl might have properties like the following:
|
||||
pinctrl: ioc@18880000 {
|
||||
compatible = "sirf,atlas7-ioc";
|
||||
reg = <0x18880000 0x1000>;
|
||||
|
||||
a_ac97_pmx: ac97@0 {
|
||||
ac97 {
|
||||
groups = "audio_ac97_grp";
|
||||
function = "audio_ac97";
|
||||
};
|
||||
};
|
||||
|
||||
...
|
||||
|
||||
sd2_pmx: sd2@0 {
|
||||
sd2 {
|
||||
groups = "sd2_grp0";
|
||||
function = "sd2";
|
||||
};
|
||||
};
|
||||
|
||||
...
|
||||
|
||||
|
||||
sample0_cfg: sample0@0 {
|
||||
sample0 {
|
||||
pins = "ldd_0", "ldd_1";
|
||||
bias-pull-up;
|
||||
};
|
||||
};
|
||||
|
||||
sample1_cfg: sample1@0 {
|
||||
sample1 {
|
||||
pins = "ldd_2", "ldd_3";
|
||||
input-schmitt-enable;
|
||||
};
|
||||
};
|
||||
|
||||
sample2_cfg: sample2@0 {
|
||||
sample2 {
|
||||
groups = "uart4_nopause_grp";
|
||||
bias-pull-down;
|
||||
};
|
||||
};
|
||||
|
||||
sample3_cfg: sample3@0 {
|
||||
sample3 {
|
||||
pins = "ldd_4", "ldd_5";
|
||||
drive-strength = <2>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
Please refer to pinctrl-bindings.txt in this directory for details of the common
|
||||
pinctrl bindings used by client devices.
|
||||
|
||||
SiRFatlas7's pinmux nodes act as a container for an arbitrary number of subnodes.
|
||||
Each of these subnodes represents some desired configuration for a group of pins.
|
||||
|
||||
Required subnode-properties:
|
||||
- groups : An array of strings. Each string contains the name of a group.
|
||||
- function: A string containing the name of the function to mux to the
|
||||
group.
|
||||
|
||||
Valid values for group and function names can be found from looking at the
|
||||
group and function arrays in driver files:
|
||||
drivers/pinctrl/pinctrl-sirf.c
|
||||
|
||||
For example, pinctrl might have subnodes like the following:
|
||||
sd0_pmx: sd0@0 {
|
||||
sd0 {
|
||||
groups = "sd0_grp";
|
||||
function = "sd0";
|
||||
};
|
||||
};
|
||||
|
||||
sd1_pmx0: sd1@0 {
|
||||
sd1 {
|
||||
groups = "sd1_grp0";
|
||||
function = "sd1_m0";
|
||||
};
|
||||
};
|
||||
|
||||
sd1_pmx1: sd1@1 {
|
||||
sd1 {
|
||||
groups = "sd1_grp1";
|
||||
function = "sd1_m1";
|
||||
};
|
||||
};
|
||||
|
||||
For a specific board, if it wants to use sd1,
|
||||
it can add the following to its board-specific .dts file.
|
||||
sd1: sd@12340000 {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&sd1_pmx0>;
|
||||
}
|
||||
|
||||
or
|
||||
|
||||
sd1: sd@12340000 {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&sd1_pmx1>;
|
||||
}
|
@ -77,13 +77,13 @@ For example:
|
||||
device {
|
||||
pinctrl-names = "active", "idle";
|
||||
pinctrl-0 = <&state_0_node_a>;
|
||||
pinctrl-1 = <&state_1_node_a &state_1_node_b>;
|
||||
pinctrl-1 = <&state_1_node_a>, <&state_1_node_b>;
|
||||
};
|
||||
|
||||
/* For the same device if using state IDs */
|
||||
device {
|
||||
pinctrl-0 = <&state_0_node_a>;
|
||||
pinctrl-1 = <&state_1_node_a &state_1_node_b>;
|
||||
pinctrl-1 = <&state_1_node_a>, <&state_1_node_b>;
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -134,7 +134,7 @@ gpio21: gpio@21 {
|
||||
#interrupt-cells = <0x2>;
|
||||
microchip,irq-mirror;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&i2cgpio0irq &gpio21pullups>;
|
||||
pinctrl-0 = <&i2cgpio0irq>, <&gpio21pullups>;
|
||||
|
||||
gpio21pullups: pinmux {
|
||||
pins = "gpio0", "gpio1", "gpio2", "gpio3",
|
||||
|
@ -91,7 +91,7 @@ Examples:
|
||||
pinctrl@1c20800 {
|
||||
compatible = "mediatek,mt8135-pinctrl";
|
||||
reg = <0 0x1000B000 0 0x1000>;
|
||||
mediatek,pctl-regmap = <&syscfg_pctl_a &syscfg_pctl_b>;
|
||||
mediatek,pctl-regmap = <&syscfg_pctl_a>, <&syscfg_pctl_b>;
|
||||
pins-are-numbered;
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
@ -8,7 +8,7 @@ Required properties:
|
||||
- reg : offset and length of the register set for the mux registers
|
||||
|
||||
- #pinctrl-cells : number of cells in addition to the index, set to 1
|
||||
for pinctrl-single,pins and 2 for pinctrl-single,bits
|
||||
or 2 for pinctrl-single,pins and set to 2 for pinctrl-single,bits
|
||||
|
||||
- pinctrl-single,register-width : pinmux register access width in bits
|
||||
|
||||
@ -80,7 +80,7 @@ Optional properties:
|
||||
property.
|
||||
|
||||
/* pin base, nr pins & gpio function */
|
||||
pinctrl-single,gpio-range = <&range 0 3 0 &range 3 9 1>;
|
||||
pinctrl-single,gpio-range = <&range 0 3 0>, <&range 3 9 1>;
|
||||
|
||||
- interrupt-controller : standard interrupt controller binding if using
|
||||
interrupts for wake-up events for example. In this case pinctrl-single
|
||||
@ -185,10 +185,10 @@ pmx_gpio: pinmux@d401e000 {
|
||||
pinctrl-single,function-mask = <7>;
|
||||
|
||||
/* sparse GPIO range could be supported */
|
||||
pinctrl-single,gpio-range = <&range 0 3 0 &range 3 9 1
|
||||
&range 12 1 0 &range 13 29 1
|
||||
&range 43 1 0 &range 44 49 1
|
||||
&range 94 1 1 &range 96 2 1>;
|
||||
pinctrl-single,gpio-range = <&range 0 3 0>, <&range 3 9 1>,
|
||||
<&range 12 1 0>, <&range 13 29 1>,
|
||||
<&range 43 1 0>, <&range 44 49 1>,
|
||||
<&range 94 1 1>, <&range 96 2 1>;
|
||||
|
||||
range: gpio-range {
|
||||
#pinctrl-single,gpio-range-cells = <3>;
|
||||
|
@ -1,84 +0,0 @@
|
||||
* ZTE ZX Pin Controller
|
||||
|
||||
The pin controller on ZTE ZX platforms is kinda of hybrid. It consists of
|
||||
a main controller and an auxiliary one. For example, on ZX296718 SoC, the
|
||||
main controller is TOP_PMM and the auxiliary one is AON_IOCFG. Both
|
||||
controllers work together to control pin multiplexing and configuration in
|
||||
the way illustrated as below.
|
||||
|
||||
|
||||
GMII_RXD3 ---+
|
||||
|
|
||||
DVI1_HS ---+----------------------------- GMII_RXD3 (TOP pin)
|
||||
|
|
||||
BGPIO16 ---+ ^
|
||||
| pinconf
|
||||
^ |
|
||||
| pinmux |
|
||||
| |
|
||||
|
||||
TOP_PMM (main) AON_IOCFG (aux)
|
||||
|
||||
| | |
|
||||
| pinmux | |
|
||||
| pinmux v |
|
||||
v | pinconf
|
||||
KEY_ROW2 ---+ v
|
||||
PORT1_LCD_TE ---+ |
|
||||
| AGPIO10 ---+------ KEY_ROW2 (AON pin)
|
||||
I2S0_DOUT3 ---+ |
|
||||
|-----------------------+
|
||||
PWM_OUT3 ---+
|
||||
|
|
||||
VGA_VS1 ---+
|
||||
|
||||
|
||||
For most of pins like GMII_RXD3 in the figure, the pinmux function is
|
||||
controlled by TOP_PMM block only, and this type of pins are meant by term
|
||||
'TOP pins'. For pins like KEY_ROW2, the pinmux is controlled by both
|
||||
TOP_PMM and AON_IOCFG blocks, as the available multiplexing functions for
|
||||
the pin spread in both controllers. This type of pins are called 'AON pins'.
|
||||
Though pinmux implementation is quite different, pinconf is same for both
|
||||
types of pins. Both are controlled by auxiliary controller, i.e. AON_IOCFG
|
||||
on ZX296718.
|
||||
|
||||
Required properties:
|
||||
- compatible: should be "zte,zx296718-pmm".
|
||||
- reg: the register physical address and length.
|
||||
- zte,auxiliary-controller: phandle to the auxiliary pin controller which
|
||||
implements pinmux for AON pins and pinconf for all pins.
|
||||
|
||||
The following pin configuration are supported. Please refer to
|
||||
pinctrl-bindings.txt in this directory for more details of the common
|
||||
pinctrl bindings used by client devices.
|
||||
|
||||
- bias-pull-up
|
||||
- bias-pull-down
|
||||
- drive-strength
|
||||
- input-enable
|
||||
- slew-rate
|
||||
|
||||
Examples:
|
||||
|
||||
iocfg: pin-controller@119000 {
|
||||
compatible = "zte,zx296718-iocfg";
|
||||
reg = <0x119000 0x1000>;
|
||||
};
|
||||
|
||||
pmm: pin-controller@1462000 {
|
||||
compatible = "zte,zx296718-pmm";
|
||||
reg = <0x1462000 0x1000>;
|
||||
zte,auxiliary-controller = <&iocfg>;
|
||||
};
|
||||
|
||||
&pmm {
|
||||
vga_pins: vga {
|
||||
pins = "KEY_COL1", "KEY_COL2", "KEY_ROW1", "KEY_ROW2";
|
||||
function = "VGA";
|
||||
};
|
||||
};
|
||||
|
||||
&vga {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&vga_pins>;
|
||||
};
|
@ -8,6 +8,7 @@ of PMIC's from Qualcomm.
|
||||
Value type: <string>
|
||||
Definition: Should contain one of:
|
||||
"qcom,pm8018-mpp",
|
||||
"qcom,pm8019-mpp",
|
||||
"qcom,pm8038-mpp",
|
||||
"qcom,pm8058-mpp",
|
||||
"qcom,pm8821-mpp",
|
||||
|
@ -0,0 +1,152 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/pinctrl/qcom,sc8180x-pinctrl.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Qualcomm Technologies, Inc. SC8180X TLMM block
|
||||
|
||||
maintainers:
|
||||
- Bjorn Andersson <bjorn.andersson@linaro.org>
|
||||
|
||||
description: |
|
||||
This binding describes the Top Level Mode Multiplexer block found in the
|
||||
SC8180X platform.
|
||||
|
||||
allOf:
|
||||
- $ref: /schemas/pinctrl/qcom,tlmm-common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: qcom,sc8180x-tlmm
|
||||
|
||||
reg:
|
||||
maxItems: 3
|
||||
|
||||
reg-names:
|
||||
items:
|
||||
- const: "west"
|
||||
- const: "east"
|
||||
- const: "south"
|
||||
|
||||
interrupts: true
|
||||
interrupt-controller: true
|
||||
'#interrupt-cells': true
|
||||
gpio-controller: true
|
||||
gpio-reserved-ranges: true
|
||||
'#gpio-cells': true
|
||||
gpio-ranges: true
|
||||
wakeup-parent: true
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- reg-names
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
patternProperties:
|
||||
'-state$':
|
||||
oneOf:
|
||||
- $ref: "#/$defs/qcom-sc8180x-tlmm-state"
|
||||
- patternProperties:
|
||||
".*":
|
||||
$ref: "#/$defs/qcom-sc8180x-tlmm-state"
|
||||
|
||||
'$defs':
|
||||
qcom-sc8180x-tlmm-state:
|
||||
type: object
|
||||
description:
|
||||
Pinctrl node's client devices use subnodes for desired pin configuration.
|
||||
Client device subnodes use below standard properties.
|
||||
$ref: "qcom,tlmm-common.yaml#/$defs/qcom-tlmm-state"
|
||||
|
||||
properties:
|
||||
pins:
|
||||
description:
|
||||
List of gpio pins affected by the properties specified in this
|
||||
subnode.
|
||||
items:
|
||||
oneOf:
|
||||
- pattern: "^gpio([0-9]|[1-9][0-9]|1[0-8][0-9])$"
|
||||
- enum: [ sdc2_clk, sdc2_cmd, sdc2_data, ufs_reset ]
|
||||
minItems: 1
|
||||
maxItems: 16
|
||||
|
||||
function:
|
||||
description:
|
||||
Specify the alternative function to be configured for the specified
|
||||
pins.
|
||||
|
||||
enum: [ adsp_ext, agera_pll, aoss_cti, atest_char, atest_tsens,
|
||||
atest_tsens2, atest_usb0, atest_usb1, atest_usb2, atest_usb3,
|
||||
atest_usb4, audio_ref, btfm_slimbus, cam_mclk, cci_async,
|
||||
cci_i2c, cci_timer0, cci_timer1, cci_timer2, cci_timer3,
|
||||
cci_timer4, cci_timer5, cci_timer6, cci_timer7, cci_timer8,
|
||||
cci_timer9, cri_trng, dbg_out, ddr_bist, ddr_pxi, debug_hot,
|
||||
dp_hot, edp_hot, edp_lcd, emac_phy, emac_pps, gcc_gp1, gcc_gp2,
|
||||
gcc_gp3, gcc_gp4, gcc_gp5, gpio, gps, grfc, hs1_mi2s, hs2_mi2s,
|
||||
hs3_mi2s, jitter_bist, lpass_slimbus, m_voc, mdp_vsync,
|
||||
mdp_vsync0, mdp_vsync1, mdp_vsync2, mdp_vsync3, mdp_vsync4,
|
||||
mdp_vsync5, mss_lte, nav_pps, pa_indicator, pci_e0, pci_e1,
|
||||
pci_e2, pci_e3, phase_flag, pll_bist, pll_bypassnl, pll_reset,
|
||||
pri_mi2s, pri_mi2s_ws, prng_rosc, qdss_cti, qdss_gpio, qlink,
|
||||
qspi0, qspi0_clk, qspi0_cs, qspi1, qspi1_clk, qspi1_cs,
|
||||
qua_mi2s, qup0, qup1, qup2, qup3, qup4, qup5, qup6, qup7, qup8,
|
||||
qup9, qup10, qup11, qup12, qup13, qup14, qup15, qup16, qup17,
|
||||
qup18, qup19, qup_l4, qup_l5, qup_l6, rgmii, sd_write, sdc4,
|
||||
sdc4_clk, sdc4_cmd, sec_mi2s, sp_cmu, spkr_i2s, ter_mi2s, tgu,
|
||||
tsense_pwm1, tsense_pwm2, tsif1, tsif2, uim1, uim2, uim_batt,
|
||||
usb0_phy, usb1_phy, usb2phy_ac, vfr_1, vsense_trigger,
|
||||
wlan1_adc, wlan2_adc, wmss_reset ]
|
||||
|
||||
bias-disable: true
|
||||
bias-pull-down: true
|
||||
bias-pull-up: true
|
||||
drive-strength: true
|
||||
input-enable: true
|
||||
output-high: true
|
||||
output-low: true
|
||||
|
||||
required:
|
||||
- pins
|
||||
- function
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
pinctrl@3100000 {
|
||||
compatible = "qcom,sc8180x-tlmm";
|
||||
reg = <0x03100000 0x300000>,
|
||||
<0x03500000 0x700000>,
|
||||
<0x03d00000 0x300000>;
|
||||
reg-names = "west", "east", "south";
|
||||
interrupts = <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>;
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
gpio-ranges = <&tlmm 0 0 190>;
|
||||
|
||||
gpio-wo-subnode-state {
|
||||
pins = "gpio1";
|
||||
function = "gpio";
|
||||
};
|
||||
|
||||
uart-w-subnodes-state {
|
||||
rx {
|
||||
pins = "gpio4";
|
||||
function = "qup6";
|
||||
bias-pull-up;
|
||||
};
|
||||
|
||||
tx {
|
||||
pins = "gpio5";
|
||||
function = "qup6";
|
||||
bias-disable;
|
||||
};
|
||||
};
|
||||
};
|
||||
...
|
@ -0,0 +1,145 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/pinctrl/qcom,sm8350-pinctrl.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Qualcomm Technologies, Inc. SM8350 TLMM block
|
||||
|
||||
maintainers:
|
||||
- Vinod Koul <vkoul@kernel.org>
|
||||
|
||||
description: |
|
||||
This binding describes the Top Level Mode Multiplexer (TLMM) block found
|
||||
in the SM8350 platform.
|
||||
|
||||
allOf:
|
||||
- $ref: /schemas/pinctrl/qcom,tlmm-common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: qcom,sm8350-tlmm
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts: true
|
||||
interrupt-controller: true
|
||||
'#interrupt-cells': true
|
||||
gpio-controller: true
|
||||
gpio-reserved-ranges: true
|
||||
'#gpio-cells': true
|
||||
gpio-ranges: true
|
||||
wakeup-parent: true
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
patternProperties:
|
||||
'-state$':
|
||||
oneOf:
|
||||
- $ref: "#/$defs/qcom-sm8350-tlmm-state"
|
||||
- patternProperties:
|
||||
".*":
|
||||
$ref: "#/$defs/qcom-sm8350-tlmm-state"
|
||||
|
||||
$defs:
|
||||
qcom-sm8350-tlmm-state:
|
||||
type: object
|
||||
description:
|
||||
Pinctrl node's client devices use subnodes for desired pin configuration.
|
||||
Client device subnodes use below standard properties.
|
||||
$ref: "qcom,tlmm-common.yaml#/$defs/qcom-tlmm-state"
|
||||
|
||||
properties:
|
||||
pins:
|
||||
description:
|
||||
List of gpio pins affected by the properties specified in this
|
||||
subnode.
|
||||
items:
|
||||
oneOf:
|
||||
- pattern: "^gpio([0-9]|[1-9][0-9]|1[0-9][0-9]|20[0-3])$"
|
||||
- enum: [ sdc1_clk, sdc1_cmd, sdc1_data, sdc2_clk, sdc2_cmd, sdc2_data ]
|
||||
minItems: 1
|
||||
maxItems: 36
|
||||
|
||||
function:
|
||||
description:
|
||||
Specify the alternative function to be configured for the specified
|
||||
pins.
|
||||
|
||||
enum: [ atest_char, atest_usb, audio_ref, cam_mclk, cci_async,
|
||||
cci_i2c, cci_timer, cmu_rng, coex_uart1, coex_uart2, cri_trng,
|
||||
cri_trng0, cri_trng1, dbg_out, ddr_bist, ddr_pxi0, ddr_pxi1,
|
||||
ddr_pxi2, ddr_pxi3, dp_hot, dp_lcd, gcc_gp1, gcc_gp2, gcc_gp3,
|
||||
gpio, ibi_i3c, jitter_bist, lpass_slimbus, mdp_vsync, mdp_vsync0,
|
||||
mdp_vsync1, mdp_vsync2, mdp_vsync3, mi2s0_data0, mi2s0_data1,
|
||||
mi2s0_sck, mi2s0_ws, mi2s1_data0, mi2s1_data1, mi2s1_sck,
|
||||
mi2s1_ws, mi2s2_data0, mi2s2_data1, mi2s2_sck, mi2s2_ws,
|
||||
mss_grfc0, mss_grfc1, mss_grfc10, mss_grfc11, mss_grfc12,
|
||||
mss_grfc2, mss_grfc3, mss_grfc4, mss_grfc5, mss_grfc6,
|
||||
mss_grfc7, mss_grfc8, mss_grfc9, nav_gpio, pa_indicator,
|
||||
pcie0_clkreqn, pcie1_clkreqn, phase_flag, pll_bist, pll_clk,
|
||||
pri_mi2s, prng_rosc, qdss_cti, qdss_gpio, qlink0_enable,
|
||||
qlink0_request, qlink0_wmss, qlink1_enable, qlink1_request,
|
||||
qlink1_wmss, qlink2_enable, qlink2_request, qlink2_wmss, qspi0,
|
||||
qspi1, qspi2, qspi3, qspi_clk, qspi_cs, qup0, qup1, qup10,
|
||||
qup11, qup12, qup13, qup14, qup15, qup16, qup17, qup18, qup19,
|
||||
qup2, qup3, qup4, qup5, qup6, qup7, qup8, qup9, qup_l4, qup_l5,
|
||||
qup_l6, sd_write, sdc40, sdc41, sdc42, sdc43, sdc4_clk,
|
||||
sdc4_cmd, sec_mi2s, tb_trig, tgu_ch0, tgu_ch1, tgu_ch2,
|
||||
tgu_ch3, tsense_pwm1, tsense_pwm2, uim0_clk, uim0_data,
|
||||
uim0_present, uim0_reset, uim1_clk, uim1_data, uim1_present,
|
||||
uim1_reset, usb2phy_ac, usb_phy, vfr_0, vfr_1, vsense_trigger ]
|
||||
|
||||
|
||||
bias-disable: true
|
||||
bias-pull-down: true
|
||||
bias-pull-up: true
|
||||
drive-strength: true
|
||||
input-enable: true
|
||||
output-high: true
|
||||
output-low: true
|
||||
|
||||
required:
|
||||
- pins
|
||||
- function
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
pinctrl@f100000 {
|
||||
compatible = "qcom,sm8350-tlmm";
|
||||
reg = <0x0f100000 0x300000>;
|
||||
interrupts = <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>;
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
gpio-ranges = <&tlmm 0 0 203>;
|
||||
|
||||
gpio-wo-subnode-state {
|
||||
pins = "gpio1";
|
||||
function = "gpio";
|
||||
};
|
||||
|
||||
uart-w-subnodes-state {
|
||||
rx {
|
||||
pins = "gpio18";
|
||||
function = "qup3";
|
||||
bias-pull-up;
|
||||
};
|
||||
|
||||
tx {
|
||||
pins = "gpio19";
|
||||
function = "qup3";
|
||||
bias-disable;
|
||||
};
|
||||
};
|
||||
};
|
||||
...
|
@ -0,0 +1,85 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/pinctrl/qcom,tlmm-common.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Qualcomm Technologies, Inc. Top Level Mode Multiplexer (TLMM) definitions
|
||||
|
||||
maintainers:
|
||||
- Bjorn Andersson <bjorn.andersson@linaro.org>
|
||||
|
||||
description:
|
||||
This defines the common properties used to describe all Qualcomm Top Level
|
||||
Mode Multiplexer bindings and pinconf/pinmux states for these.
|
||||
|
||||
properties:
|
||||
interrupts:
|
||||
description:
|
||||
Specifies the TLMM summary IRQ
|
||||
maxItems: 1
|
||||
|
||||
interrupt-controller: true
|
||||
|
||||
'#interrupt-cells':
|
||||
description:
|
||||
Specifies the PIN numbers and Flags, as defined in defined in
|
||||
include/dt-bindings/interrupt-controller/irq.h
|
||||
const: 2
|
||||
|
||||
gpio-controller: true
|
||||
|
||||
'#gpio-cells':
|
||||
description:
|
||||
Specifying the pin number and flags, as defined in
|
||||
include/dt-bindings/gpio/gpio.h
|
||||
const: 2
|
||||
|
||||
gpio-ranges:
|
||||
maxItems: 1
|
||||
|
||||
wakeup-parent:
|
||||
description:
|
||||
Specifying the interrupt-controller used to wake up the system when the
|
||||
TLMM block has been powered down.
|
||||
maxItems: 1
|
||||
|
||||
gpio-reserved-ranges:
|
||||
description:
|
||||
Pins can be reserved for trusted applications and thereby unaccessible
|
||||
from the OS. This property can be used to mark the pins which resources
|
||||
should not be accessed by the OS. Please see the ../gpio/gpio.txt for more
|
||||
information.
|
||||
|
||||
required:
|
||||
- interrupts
|
||||
- interrupt-controller
|
||||
- '#interrupt-cells'
|
||||
- gpio-controller
|
||||
- '#gpio-cells'
|
||||
- gpio-ranges
|
||||
|
||||
additionalProperties: true
|
||||
|
||||
$defs:
|
||||
qcom-tlmm-state:
|
||||
allOf:
|
||||
- $ref: pincfg-node.yaml#
|
||||
- $ref: pinmux-node.yaml#
|
||||
|
||||
properties:
|
||||
drive-strength:
|
||||
enum: [2, 4, 6, 8, 10, 12, 14, 16]
|
||||
default: 2
|
||||
description:
|
||||
Selects the drive strength for the specified pins, in mA.
|
||||
|
||||
bias-pull-down: true
|
||||
bias-pull-up: true
|
||||
bias-disable: true
|
||||
input-enable: true
|
||||
output-high: true
|
||||
output-low: true
|
||||
|
||||
additionalProperties: true
|
||||
...
|
@ -15,39 +15,38 @@ description:
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- ralink,rt2880-pinmux
|
||||
const: ralink,rt2880-pinmux
|
||||
|
||||
pinctrl-0:
|
||||
description:
|
||||
A phandle to the node containing the subnodes containing default
|
||||
configurations. This is for pinctrl hogs.
|
||||
patternProperties:
|
||||
'-pins$':
|
||||
type: object
|
||||
patternProperties:
|
||||
'^(.*-)?pinmux$':
|
||||
type: object
|
||||
description: node for pinctrl.
|
||||
$ref: pinmux-node.yaml#
|
||||
|
||||
pinctrl-names:
|
||||
description:
|
||||
A pinctrl state named "default" can be defined.
|
||||
const: default
|
||||
properties:
|
||||
groups:
|
||||
description: Name of the pin group to use for the functions.
|
||||
enum: [i2c, spi, uart1, uart2, uart3, rgmii1, rgmii2, mdio,
|
||||
pcie, sdhci]
|
||||
function:
|
||||
description: The mux function to select
|
||||
enum: [gpio, i2c, spi, uart1, uart2, uart3, rgmii1, rgmii2,
|
||||
mdio, nand1, nand2, sdhci]
|
||||
|
||||
required:
|
||||
- groups
|
||||
- function
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
|
||||
patternProperties:
|
||||
'[a-z0-9_-]+':
|
||||
if:
|
||||
type: object
|
||||
description: node for pinctrl.
|
||||
$ref: "pinmux-node.yaml"
|
||||
then:
|
||||
properties:
|
||||
groups:
|
||||
description: Name of the pin group to use for the functions.
|
||||
enum: [i2c, spi, uart1, uart2, uart3, rgmii1, rgmii2, mdio,
|
||||
pcie, sdhci]
|
||||
function:
|
||||
description: The mux function to select
|
||||
enum: [gpio, i2c, spi, uart1, uart2, uart3, rgmii1, rgmii2,
|
||||
mdio, nand1, nand2, sdhci]
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
@ -55,14 +54,9 @@ examples:
|
||||
- |
|
||||
pinctrl {
|
||||
compatible = "ralink,rt2880-pinmux";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&state_default>;
|
||||
|
||||
state_default: pinctrl0 {
|
||||
};
|
||||
|
||||
i2c_pins: i2c0 {
|
||||
i2c0 {
|
||||
i2c_pins: i2c0-pins {
|
||||
pinmux {
|
||||
groups = "i2c";
|
||||
function = "i2c";
|
||||
};
|
||||
|
@ -43,11 +43,12 @@ properties:
|
||||
- renesas,pfc-r8a77980 # R-Car V3H
|
||||
- renesas,pfc-r8a77990 # R-Car E3
|
||||
- renesas,pfc-r8a77995 # R-Car D3
|
||||
- renesas,pfc-r8a779a0 # R-Car V3U
|
||||
- renesas,pfc-sh73a0 # SH-Mobile AG5
|
||||
|
||||
reg:
|
||||
minItems: 1
|
||||
maxItems: 2
|
||||
maxItems: 10
|
||||
|
||||
gpio-controller: true
|
||||
|
||||
|
@ -336,7 +336,7 @@ Example 3: A uart client node that supports 'default' and 'flow-control' states.
|
||||
interrupts = <0 52 0>;
|
||||
pinctrl-names = "default", "flow-control;
|
||||
pinctrl-0 = <&uart0_data>;
|
||||
pinctrl-1 = <&uart0_data &uart0_fctl>;
|
||||
pinctrl-1 = <&uart0_data>, <&uart0_fctl>;
|
||||
};
|
||||
|
||||
Example 4: Set up the default pin state for uart controller.
|
||||
|
@ -226,14 +226,6 @@ config PINCTRL_SINGLE
|
||||
help
|
||||
This selects the device tree based generic pinctrl driver.
|
||||
|
||||
config PINCTRL_SIRF
|
||||
bool "CSR SiRFprimaII pin controller driver"
|
||||
depends on ARCH_SIRF
|
||||
select PINMUX
|
||||
select PINCONF
|
||||
select GENERIC_PINCONF
|
||||
select GPIOLIB_IRQCHIP
|
||||
|
||||
config PINCTRL_SX150X
|
||||
bool "Semtech SX150x I2C GPIO expander pinctrl driver"
|
||||
depends on I2C=y
|
||||
@ -279,22 +271,6 @@ config PINCTRL_STMFX
|
||||
and configuring push-pull, open-drain, and can also be used as
|
||||
interrupt-controller.
|
||||
|
||||
config PINCTRL_U300
|
||||
bool "U300 pin controller driver"
|
||||
depends on ARCH_U300
|
||||
select PINMUX
|
||||
select GENERIC_PINCONF
|
||||
|
||||
config PINCTRL_COH901
|
||||
bool "ST-Ericsson U300 COH 901 335/571 GPIO"
|
||||
depends on GPIOLIB && ARCH_U300 && PINCTRL_U300
|
||||
select GPIOLIB_IRQCHIP
|
||||
help
|
||||
Say yes here to support GPIO interface on ST-Ericsson U300.
|
||||
The names of the two IP block variants supported are
|
||||
COH 901 335 and COH 901 571/3. They contain 3, 5 or 7
|
||||
ports of 8 GPIO pins each.
|
||||
|
||||
config PINCTRL_MAX77620
|
||||
tristate "MAX77620/MAX20024 Pincontrol support"
|
||||
depends on MFD_MAX77620 && OF
|
||||
@ -417,7 +393,6 @@ source "drivers/pinctrl/ti/Kconfig"
|
||||
source "drivers/pinctrl/uniphier/Kconfig"
|
||||
source "drivers/pinctrl/vt8500/Kconfig"
|
||||
source "drivers/pinctrl/mediatek/Kconfig"
|
||||
source "drivers/pinctrl/zte/Kconfig"
|
||||
source "drivers/pinctrl/meson/Kconfig"
|
||||
source "drivers/pinctrl/cirrus/Kconfig"
|
||||
source "drivers/pinctrl/visconti/Kconfig"
|
||||
|
@ -31,11 +31,8 @@ obj-$(CONFIG_PINCTRL_PIC32) += pinctrl-pic32.o
|
||||
obj-$(CONFIG_PINCTRL_PISTACHIO) += pinctrl-pistachio.o
|
||||
obj-$(CONFIG_PINCTRL_ROCKCHIP) += pinctrl-rockchip.o
|
||||
obj-$(CONFIG_PINCTRL_SINGLE) += pinctrl-single.o
|
||||
obj-$(CONFIG_PINCTRL_SIRF) += sirf/
|
||||
obj-$(CONFIG_PINCTRL_SX150X) += pinctrl-sx150x.o
|
||||
obj-$(CONFIG_ARCH_TEGRA) += tegra/
|
||||
obj-$(CONFIG_PINCTRL_U300) += pinctrl-u300.o
|
||||
obj-$(CONFIG_PINCTRL_COH901) += pinctrl-coh901.o
|
||||
obj-$(CONFIG_PINCTRL_XWAY) += pinctrl-xway.o
|
||||
obj-$(CONFIG_PINCTRL_LANTIQ) += pinctrl-lantiq.o
|
||||
obj-$(CONFIG_PINCTRL_LPC18XX) += pinctrl-lpc18xx.o
|
||||
@ -71,6 +68,5 @@ obj-y += ti/
|
||||
obj-$(CONFIG_PINCTRL_UNIPHIER) += uniphier/
|
||||
obj-$(CONFIG_ARCH_VT8500) += vt8500/
|
||||
obj-y += mediatek/
|
||||
obj-$(CONFIG_PINCTRL_ZX) += zte/
|
||||
obj-y += cirrus/
|
||||
obj-$(CONFIG_PINCTRL_VISCONTI) += visconti/
|
||||
|
@ -12,18 +12,21 @@ config PINCTRL_OWL
|
||||
|
||||
config PINCTRL_S500
|
||||
bool "Actions Semi S500 pinctrl driver"
|
||||
depends on ARM || COMPILE_TEST
|
||||
depends on PINCTRL_OWL
|
||||
help
|
||||
Say Y here to enable Actions Semi S500 pinctrl driver
|
||||
|
||||
config PINCTRL_S700
|
||||
bool "Actions Semi S700 pinctrl driver"
|
||||
depends on ARM64 || COMPILE_TEST
|
||||
depends on PINCTRL_OWL
|
||||
help
|
||||
Say Y here to enable Actions Semi S700 pinctrl driver
|
||||
|
||||
config PINCTRL_S900
|
||||
bool "Actions Semi S900 pinctrl driver"
|
||||
depends on ARM64 || COMPILE_TEST
|
||||
depends on PINCTRL_OWL
|
||||
help
|
||||
Say Y here to enable Actions Semi S900 pinctrl driver
|
||||
|
@ -444,7 +444,6 @@ static int owl_group_config_get(struct pinctrl_dev *pctrldev,
|
||||
*config = pinconf_to_config_packed(param, arg);
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
static int owl_group_config_set(struct pinctrl_dev *pctrldev,
|
||||
|
@ -853,7 +853,7 @@ static int ns2_pin_config_get(struct pinctrl_dev *pctldev, unsigned int pin,
|
||||
switch (param) {
|
||||
case PIN_CONFIG_BIAS_DISABLE:
|
||||
ns2_pin_get_pull(pctldev, pin, &pull_up, &pull_down);
|
||||
if ((pull_up == false) && (pull_down == false))
|
||||
if (!pull_up && !pull_down)
|
||||
return 0;
|
||||
else
|
||||
return -EINVAL;
|
||||
|
@ -2117,7 +2117,6 @@ struct pinctrl_dev *pinctrl_register(struct pinctrl_desc *pctldesc,
|
||||
return ERR_PTR(error);
|
||||
|
||||
return pctldev;
|
||||
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pinctrl_register);
|
||||
|
||||
|
@ -290,7 +290,6 @@ static const struct pinctrl_ops imx1_pctrl_ops = {
|
||||
.pin_dbg_show = imx1_pin_dbg_show,
|
||||
.dt_node_to_map = imx1_dt_node_to_map,
|
||||
.dt_free_map = imx1_dt_free_map,
|
||||
|
||||
};
|
||||
|
||||
static int imx1_pmx_set(struct pinctrl_dev *pctldev, unsigned selector,
|
||||
|
@ -29,6 +29,16 @@
|
||||
#define REVID_SHIFT 16
|
||||
#define REVID_MASK GENMASK(31, 16)
|
||||
|
||||
#define CAPLIST 0x004
|
||||
#define CAPLIST_ID_SHIFT 16
|
||||
#define CAPLIST_ID_MASK GENMASK(23, 16)
|
||||
#define CAPLIST_ID_GPIO_HW_INFO 1
|
||||
#define CAPLIST_ID_PWM 2
|
||||
#define CAPLIST_ID_BLINK 3
|
||||
#define CAPLIST_ID_EXP 4
|
||||
#define CAPLIST_NEXT_SHIFT 0
|
||||
#define CAPLIST_NEXT_MASK GENMASK(15, 0)
|
||||
|
||||
#define PADBAR 0x00c
|
||||
|
||||
#define PADOWN_BITS 4
|
||||
@ -1321,34 +1331,19 @@ static int intel_gpio_probe(struct intel_pinctrl *pctrl, int irq)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int intel_pinctrl_add_padgroups(struct intel_pinctrl *pctrl,
|
||||
struct intel_community *community)
|
||||
static int intel_pinctrl_add_padgroups_by_gpps(struct intel_pinctrl *pctrl,
|
||||
struct intel_community *community)
|
||||
{
|
||||
struct intel_padgroup *gpps;
|
||||
unsigned int npins = community->npins;
|
||||
unsigned int padown_num = 0;
|
||||
size_t ngpps, i;
|
||||
|
||||
if (community->gpps)
|
||||
ngpps = community->ngpps;
|
||||
else
|
||||
ngpps = DIV_ROUND_UP(community->npins, community->gpp_size);
|
||||
size_t i, ngpps = community->ngpps;
|
||||
|
||||
gpps = devm_kcalloc(pctrl->dev, ngpps, sizeof(*gpps), GFP_KERNEL);
|
||||
if (!gpps)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < ngpps; i++) {
|
||||
if (community->gpps) {
|
||||
gpps[i] = community->gpps[i];
|
||||
} else {
|
||||
unsigned int gpp_size = community->gpp_size;
|
||||
|
||||
gpps[i].reg_num = i;
|
||||
gpps[i].base = community->pin_base + i * gpp_size;
|
||||
gpps[i].size = min(gpp_size, npins);
|
||||
npins -= gpps[i].size;
|
||||
}
|
||||
gpps[i] = community->gpps[i];
|
||||
|
||||
if (gpps[i].size > 32)
|
||||
return -EINVAL;
|
||||
@ -1366,6 +1361,38 @@ static int intel_pinctrl_add_padgroups(struct intel_pinctrl *pctrl,
|
||||
break;
|
||||
}
|
||||
|
||||
gpps[i].padown_num = padown_num;
|
||||
padown_num += DIV_ROUND_UP(gpps[i].size * 4, 32);
|
||||
}
|
||||
|
||||
community->gpps = gpps;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int intel_pinctrl_add_padgroups_by_size(struct intel_pinctrl *pctrl,
|
||||
struct intel_community *community)
|
||||
{
|
||||
struct intel_padgroup *gpps;
|
||||
unsigned int npins = community->npins;
|
||||
unsigned int padown_num = 0;
|
||||
size_t i, ngpps = DIV_ROUND_UP(npins, community->gpp_size);
|
||||
|
||||
if (community->gpp_size > 32)
|
||||
return -EINVAL;
|
||||
|
||||
gpps = devm_kcalloc(pctrl->dev, ngpps, sizeof(*gpps), GFP_KERNEL);
|
||||
if (!gpps)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < ngpps; i++) {
|
||||
unsigned int gpp_size = community->gpp_size;
|
||||
|
||||
gpps[i].reg_num = i;
|
||||
gpps[i].base = community->pin_base + i * gpp_size;
|
||||
gpps[i].size = min(gpp_size, npins);
|
||||
npins -= gpps[i].size;
|
||||
|
||||
gpps[i].padown_num = padown_num;
|
||||
|
||||
/*
|
||||
@ -1455,7 +1482,8 @@ static int intel_pinctrl_probe(struct platform_device *pdev,
|
||||
for (i = 0; i < pctrl->ncommunities; i++) {
|
||||
struct intel_community *community = &pctrl->communities[i];
|
||||
void __iomem *regs;
|
||||
u32 padbar;
|
||||
u32 offset;
|
||||
u32 value;
|
||||
|
||||
*community = pctrl->soc->communities[i];
|
||||
|
||||
@ -1463,27 +1491,48 @@ static int intel_pinctrl_probe(struct platform_device *pdev,
|
||||
if (IS_ERR(regs))
|
||||
return PTR_ERR(regs);
|
||||
|
||||
/*
|
||||
* Determine community features based on the revision if
|
||||
* not specified already.
|
||||
*/
|
||||
if (!community->features) {
|
||||
u32 rev;
|
||||
|
||||
rev = (readl(regs + REVID) & REVID_MASK) >> REVID_SHIFT;
|
||||
if (rev >= 0x94) {
|
||||
community->features |= PINCTRL_FEATURE_DEBOUNCE;
|
||||
community->features |= PINCTRL_FEATURE_1K_PD;
|
||||
}
|
||||
/* Determine community features based on the revision */
|
||||
value = readl(regs + REVID);
|
||||
if (((value & REVID_MASK) >> REVID_SHIFT) >= 0x94) {
|
||||
community->features |= PINCTRL_FEATURE_DEBOUNCE;
|
||||
community->features |= PINCTRL_FEATURE_1K_PD;
|
||||
}
|
||||
|
||||
/* Determine community features based on the capabilities */
|
||||
offset = CAPLIST;
|
||||
do {
|
||||
value = readl(regs + offset);
|
||||
switch ((value & CAPLIST_ID_MASK) >> CAPLIST_ID_SHIFT) {
|
||||
case CAPLIST_ID_GPIO_HW_INFO:
|
||||
community->features |= PINCTRL_FEATURE_GPIO_HW_INFO;
|
||||
break;
|
||||
case CAPLIST_ID_PWM:
|
||||
community->features |= PINCTRL_FEATURE_PWM;
|
||||
break;
|
||||
case CAPLIST_ID_BLINK:
|
||||
community->features |= PINCTRL_FEATURE_BLINK;
|
||||
break;
|
||||
case CAPLIST_ID_EXP:
|
||||
community->features |= PINCTRL_FEATURE_EXP;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
offset = (value & CAPLIST_NEXT_MASK) >> CAPLIST_NEXT_SHIFT;
|
||||
} while (offset);
|
||||
|
||||
dev_dbg(&pdev->dev, "Community%d features: %#08x\n", i, community->features);
|
||||
|
||||
/* Read offset of the pad configuration registers */
|
||||
padbar = readl(regs + PADBAR);
|
||||
offset = readl(regs + PADBAR);
|
||||
|
||||
community->regs = regs;
|
||||
community->pad_regs = regs + padbar;
|
||||
community->pad_regs = regs + offset;
|
||||
|
||||
ret = intel_pinctrl_add_padgroups(pctrl, community);
|
||||
if (community->gpps)
|
||||
ret = intel_pinctrl_add_padgroups_by_gpps(pctrl, community);
|
||||
else
|
||||
ret = intel_pinctrl_add_padgroups_by_size(pctrl, community);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
@ -143,6 +143,10 @@ struct intel_community {
|
||||
/* Additional features supported by the hardware */
|
||||
#define PINCTRL_FEATURE_DEBOUNCE BIT(0)
|
||||
#define PINCTRL_FEATURE_1K_PD BIT(1)
|
||||
#define PINCTRL_FEATURE_GPIO_HW_INFO BIT(2)
|
||||
#define PINCTRL_FEATURE_PWM BIT(3)
|
||||
#define PINCTRL_FEATURE_BLINK BIT(4)
|
||||
#define PINCTRL_FEATURE_EXP BIT(5)
|
||||
|
||||
/**
|
||||
* PIN_GROUP - Declare a pin group
|
||||
|
@ -748,6 +748,7 @@ static const struct intel_pinctrl_soc_data tglh_soc_data = {
|
||||
static const struct acpi_device_id tgl_pinctrl_acpi_match[] = {
|
||||
{ "INT34C5", (kernel_ulong_t)&tgllp_soc_data },
|
||||
{ "INT34C6", (kernel_ulong_t)&tglh_soc_data },
|
||||
{ "INTC1055", (kernel_ulong_t)&tgllp_soc_data },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(acpi, tgl_pinctrl_acpi_match);
|
||||
|
@ -157,6 +157,7 @@ static void mtk_eint_ack(struct irq_data *d)
|
||||
static int mtk_eint_set_type(struct irq_data *d, unsigned int type)
|
||||
{
|
||||
struct mtk_eint *eint = irq_data_get_irq_chip_data(d);
|
||||
bool masked;
|
||||
u32 mask = BIT(d->hwirq & 0x1f);
|
||||
void __iomem *reg;
|
||||
|
||||
@ -173,6 +174,13 @@ static int mtk_eint_set_type(struct irq_data *d, unsigned int type)
|
||||
else
|
||||
eint->dual_edge[d->hwirq] = 0;
|
||||
|
||||
if (!mtk_eint_get_mask(eint, d->hwirq)) {
|
||||
mtk_eint_mask(d);
|
||||
masked = false;
|
||||
} else {
|
||||
masked = true;
|
||||
}
|
||||
|
||||
if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_EDGE_FALLING)) {
|
||||
reg = mtk_eint_get_offset(eint, d->hwirq, eint->regs->pol_clr);
|
||||
writel(mask, reg);
|
||||
@ -189,8 +197,9 @@ static int mtk_eint_set_type(struct irq_data *d, unsigned int type)
|
||||
writel(mask, reg);
|
||||
}
|
||||
|
||||
if (eint->dual_edge[d->hwirq])
|
||||
mtk_eint_flip_edge(eint, d->hwirq);
|
||||
mtk_eint_ack(d);
|
||||
if (!masked)
|
||||
mtk_eint_unmask(d);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -514,8 +514,8 @@ static int mtk_build_gpiochip(struct mtk_pinctrl *hw, struct device_node *np)
|
||||
chip->direction_output = mtk_gpio_direction_output;
|
||||
chip->get = mtk_gpio_get;
|
||||
chip->set = mtk_gpio_set;
|
||||
chip->to_irq = mtk_gpio_to_irq,
|
||||
chip->set_config = mtk_gpio_set_config,
|
||||
chip->to_irq = mtk_gpio_to_irq;
|
||||
chip->set_config = mtk_gpio_set_config;
|
||||
chip->base = -1;
|
||||
chip->ngpio = hw->soc->npins;
|
||||
chip->of_node = np;
|
||||
|
@ -891,8 +891,8 @@ static int mtk_build_gpiochip(struct mtk_pinctrl *hw, struct device_node *np)
|
||||
chip->direction_output = mtk_gpio_direction_output;
|
||||
chip->get = mtk_gpio_get;
|
||||
chip->set = mtk_gpio_set;
|
||||
chip->to_irq = mtk_gpio_to_irq,
|
||||
chip->set_config = mtk_gpio_set_config,
|
||||
chip->to_irq = mtk_gpio_to_irq;
|
||||
chip->set_config = mtk_gpio_set_config;
|
||||
chip->base = -1;
|
||||
chip->ngpio = hw->soc->npins;
|
||||
chip->of_node = np;
|
||||
|
@ -188,7 +188,6 @@ static struct armada_37xx_pin_group armada_37xx_nb_groups[] = {
|
||||
PIN_GRP_GPIO_2("led1_od", 12, 1, BIT(21), BIT(21), 0, "led"),
|
||||
PIN_GRP_GPIO_2("led2_od", 13, 1, BIT(22), BIT(22), 0, "led"),
|
||||
PIN_GRP_GPIO_2("led3_od", 14, 1, BIT(23), BIT(23), 0, "led"),
|
||||
|
||||
};
|
||||
|
||||
static struct armada_37xx_pin_group armada_37xx_sb_groups[] = {
|
||||
|
@ -923,7 +923,7 @@ struct npcm7xx_pincfg {
|
||||
};
|
||||
|
||||
static const struct npcm7xx_pincfg pincfg[] = {
|
||||
/* PIN FUNCTION 1 FUNCTION 2 FUNCTION 3 FLAGS */
|
||||
/* PIN FUNCTION 1 FUNCTION 2 FUNCTION 3 FLAGS */
|
||||
NPCM7XX_PINCFG(0, iox1, MFSEL1, 30, none, NONE, 0, none, NONE, 0, 0),
|
||||
NPCM7XX_PINCFG(1, iox1, MFSEL1, 30, none, NONE, 0, none, NONE, 0, DS(8, 12)),
|
||||
NPCM7XX_PINCFG(2, iox1, MFSEL1, 30, none, NONE, 0, none, NONE, 0, DS(8, 12)),
|
||||
|
@ -36,6 +36,7 @@
|
||||
#define ATMEL_PIO_DIR_MASK BIT(8)
|
||||
#define ATMEL_PIO_PUEN_MASK BIT(9)
|
||||
#define ATMEL_PIO_PDEN_MASK BIT(10)
|
||||
#define ATMEL_PIO_SR_MASK BIT(11)
|
||||
#define ATMEL_PIO_IFEN_MASK BIT(12)
|
||||
#define ATMEL_PIO_IFSCEN_MASK BIT(13)
|
||||
#define ATMEL_PIO_OPD_MASK BIT(14)
|
||||
@ -76,10 +77,12 @@
|
||||
* @nbanks: number of PIO banks
|
||||
* @last_bank_count: number of lines in the last bank (can be less than
|
||||
* the rest of the banks).
|
||||
* @slew_rate_support: slew rate support
|
||||
*/
|
||||
struct atmel_pioctrl_data {
|
||||
unsigned nbanks;
|
||||
unsigned last_bank_count;
|
||||
unsigned int nbanks;
|
||||
unsigned int last_bank_count;
|
||||
unsigned int slew_rate_support;
|
||||
};
|
||||
|
||||
struct atmel_group {
|
||||
@ -88,11 +91,11 @@ struct atmel_group {
|
||||
};
|
||||
|
||||
struct atmel_pin {
|
||||
unsigned pin_id;
|
||||
unsigned mux;
|
||||
unsigned ioset;
|
||||
unsigned bank;
|
||||
unsigned line;
|
||||
unsigned int pin_id;
|
||||
unsigned int mux;
|
||||
unsigned int ioset;
|
||||
unsigned int bank;
|
||||
unsigned int line;
|
||||
const char *device;
|
||||
};
|
||||
|
||||
@ -117,20 +120,21 @@ struct atmel_pin {
|
||||
* @pm_suspend_backup: backup/restore register values on suspend/resume
|
||||
* @dev: device entry for the Atmel PIO controller.
|
||||
* @node: node of the Atmel PIO controller.
|
||||
* @slew_rate_support: slew rate support
|
||||
*/
|
||||
struct atmel_pioctrl {
|
||||
void __iomem *reg_base;
|
||||
struct clk *clk;
|
||||
unsigned nbanks;
|
||||
unsigned int nbanks;
|
||||
struct pinctrl_dev *pinctrl_dev;
|
||||
struct atmel_group *groups;
|
||||
const char * const *group_names;
|
||||
struct atmel_pin **pins;
|
||||
unsigned npins;
|
||||
unsigned int npins;
|
||||
struct gpio_chip *gpio_chip;
|
||||
struct irq_domain *irq_domain;
|
||||
int *irqs;
|
||||
unsigned *pm_wakeup_sources;
|
||||
unsigned int *pm_wakeup_sources;
|
||||
struct {
|
||||
u32 imr;
|
||||
u32 odsr;
|
||||
@ -138,6 +142,7 @@ struct atmel_pioctrl {
|
||||
} *pm_suspend_backup;
|
||||
struct device *dev;
|
||||
struct device_node *node;
|
||||
unsigned int slew_rate_support;
|
||||
};
|
||||
|
||||
static const char * const atmel_functions[] = {
|
||||
@ -172,11 +177,11 @@ static void atmel_gpio_irq_ack(struct irq_data *d)
|
||||
*/
|
||||
}
|
||||
|
||||
static int atmel_gpio_irq_set_type(struct irq_data *d, unsigned type)
|
||||
static int atmel_gpio_irq_set_type(struct irq_data *d, unsigned int type)
|
||||
{
|
||||
struct atmel_pioctrl *atmel_pioctrl = irq_data_get_irq_chip_data(d);
|
||||
struct atmel_pin *pin = atmel_pioctrl->pins[d->hwirq];
|
||||
unsigned reg;
|
||||
unsigned int reg;
|
||||
|
||||
atmel_gpio_write(atmel_pioctrl, pin->bank, ATMEL_PIO_MSKR,
|
||||
BIT(pin->line));
|
||||
@ -263,7 +268,7 @@ static struct irq_chip atmel_gpio_irq_chip = {
|
||||
.irq_set_wake = atmel_gpio_irq_set_wake,
|
||||
};
|
||||
|
||||
static int atmel_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
|
||||
static int atmel_gpio_to_irq(struct gpio_chip *chip, unsigned int offset)
|
||||
{
|
||||
struct atmel_pioctrl *atmel_pioctrl = gpiochip_get_data(chip);
|
||||
|
||||
@ -311,11 +316,12 @@ static void atmel_gpio_irq_handler(struct irq_desc *desc)
|
||||
chained_irq_exit(chip, desc);
|
||||
}
|
||||
|
||||
static int atmel_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
|
||||
static int atmel_gpio_direction_input(struct gpio_chip *chip,
|
||||
unsigned int offset)
|
||||
{
|
||||
struct atmel_pioctrl *atmel_pioctrl = gpiochip_get_data(chip);
|
||||
struct atmel_pin *pin = atmel_pioctrl->pins[offset];
|
||||
unsigned reg;
|
||||
unsigned int reg;
|
||||
|
||||
atmel_gpio_write(atmel_pioctrl, pin->bank, ATMEL_PIO_MSKR,
|
||||
BIT(pin->line));
|
||||
@ -326,11 +332,11 @@ static int atmel_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int atmel_gpio_get(struct gpio_chip *chip, unsigned offset)
|
||||
static int atmel_gpio_get(struct gpio_chip *chip, unsigned int offset)
|
||||
{
|
||||
struct atmel_pioctrl *atmel_pioctrl = gpiochip_get_data(chip);
|
||||
struct atmel_pin *pin = atmel_pioctrl->pins[offset];
|
||||
unsigned reg;
|
||||
unsigned int reg;
|
||||
|
||||
reg = atmel_gpio_read(atmel_pioctrl, pin->bank, ATMEL_PIO_PDSR);
|
||||
|
||||
@ -364,12 +370,13 @@ static int atmel_gpio_get_multiple(struct gpio_chip *chip, unsigned long *mask,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int atmel_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
|
||||
static int atmel_gpio_direction_output(struct gpio_chip *chip,
|
||||
unsigned int offset,
|
||||
int value)
|
||||
{
|
||||
struct atmel_pioctrl *atmel_pioctrl = gpiochip_get_data(chip);
|
||||
struct atmel_pin *pin = atmel_pioctrl->pins[offset];
|
||||
unsigned reg;
|
||||
unsigned int reg;
|
||||
|
||||
atmel_gpio_write(atmel_pioctrl, pin->bank,
|
||||
value ? ATMEL_PIO_SODR : ATMEL_PIO_CODR,
|
||||
@ -384,7 +391,7 @@ static int atmel_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void atmel_gpio_set(struct gpio_chip *chip, unsigned offset, int val)
|
||||
static void atmel_gpio_set(struct gpio_chip *chip, unsigned int offset, int val)
|
||||
{
|
||||
struct atmel_pioctrl *atmel_pioctrl = gpiochip_get_data(chip);
|
||||
struct atmel_pin *pin = atmel_pioctrl->pins[offset];
|
||||
@ -440,11 +447,11 @@ static struct gpio_chip atmel_gpio_chip = {
|
||||
|
||||
/* --- PINCTRL --- */
|
||||
static unsigned int atmel_pin_config_read(struct pinctrl_dev *pctldev,
|
||||
unsigned pin_id)
|
||||
unsigned int pin_id)
|
||||
{
|
||||
struct atmel_pioctrl *atmel_pioctrl = pinctrl_dev_get_drvdata(pctldev);
|
||||
unsigned bank = atmel_pioctrl->pins[pin_id]->bank;
|
||||
unsigned line = atmel_pioctrl->pins[pin_id]->line;
|
||||
unsigned int bank = atmel_pioctrl->pins[pin_id]->bank;
|
||||
unsigned int line = atmel_pioctrl->pins[pin_id]->line;
|
||||
void __iomem *addr = atmel_pioctrl->reg_base
|
||||
+ bank * ATMEL_PIO_BANK_OFFSET;
|
||||
|
||||
@ -456,11 +463,11 @@ static unsigned int atmel_pin_config_read(struct pinctrl_dev *pctldev,
|
||||
}
|
||||
|
||||
static void atmel_pin_config_write(struct pinctrl_dev *pctldev,
|
||||
unsigned pin_id, u32 conf)
|
||||
unsigned int pin_id, u32 conf)
|
||||
{
|
||||
struct atmel_pioctrl *atmel_pioctrl = pinctrl_dev_get_drvdata(pctldev);
|
||||
unsigned bank = atmel_pioctrl->pins[pin_id]->bank;
|
||||
unsigned line = atmel_pioctrl->pins[pin_id]->line;
|
||||
unsigned int bank = atmel_pioctrl->pins[pin_id]->bank;
|
||||
unsigned int line = atmel_pioctrl->pins[pin_id]->line;
|
||||
void __iomem *addr = atmel_pioctrl->reg_base
|
||||
+ bank * ATMEL_PIO_BANK_OFFSET;
|
||||
|
||||
@ -478,7 +485,7 @@ static int atmel_pctl_get_groups_count(struct pinctrl_dev *pctldev)
|
||||
}
|
||||
|
||||
static const char *atmel_pctl_get_group_name(struct pinctrl_dev *pctldev,
|
||||
unsigned selector)
|
||||
unsigned int selector)
|
||||
{
|
||||
struct atmel_pioctrl *atmel_pioctrl = pinctrl_dev_get_drvdata(pctldev);
|
||||
|
||||
@ -486,19 +493,20 @@ static const char *atmel_pctl_get_group_name(struct pinctrl_dev *pctldev,
|
||||
}
|
||||
|
||||
static int atmel_pctl_get_group_pins(struct pinctrl_dev *pctldev,
|
||||
unsigned selector, const unsigned **pins,
|
||||
unsigned *num_pins)
|
||||
unsigned int selector,
|
||||
const unsigned int **pins,
|
||||
unsigned int *num_pins)
|
||||
{
|
||||
struct atmel_pioctrl *atmel_pioctrl = pinctrl_dev_get_drvdata(pctldev);
|
||||
|
||||
*pins = (unsigned *)&atmel_pioctrl->groups[selector].pin;
|
||||
*pins = (unsigned int *)&atmel_pioctrl->groups[selector].pin;
|
||||
*num_pins = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct atmel_group *
|
||||
atmel_pctl_find_group_by_pin(struct pinctrl_dev *pctldev, unsigned pin)
|
||||
atmel_pctl_find_group_by_pin(struct pinctrl_dev *pctldev, unsigned int pin)
|
||||
{
|
||||
struct atmel_pioctrl *atmel_pioctrl = pinctrl_dev_get_drvdata(pctldev);
|
||||
int i;
|
||||
@ -519,7 +527,7 @@ static int atmel_pctl_xlate_pinfunc(struct pinctrl_dev *pctldev,
|
||||
const char **func_name)
|
||||
{
|
||||
struct atmel_pioctrl *atmel_pioctrl = pinctrl_dev_get_drvdata(pctldev);
|
||||
unsigned pin_id, func_id;
|
||||
unsigned int pin_id, func_id;
|
||||
struct atmel_group *grp;
|
||||
|
||||
pin_id = ATMEL_GET_PIN_NO(pinfunc);
|
||||
@ -549,10 +557,10 @@ static int atmel_pctl_xlate_pinfunc(struct pinctrl_dev *pctldev,
|
||||
static int atmel_pctl_dt_subnode_to_map(struct pinctrl_dev *pctldev,
|
||||
struct device_node *np,
|
||||
struct pinctrl_map **map,
|
||||
unsigned *reserved_maps,
|
||||
unsigned *num_maps)
|
||||
unsigned int *reserved_maps,
|
||||
unsigned int *num_maps)
|
||||
{
|
||||
unsigned num_pins, num_configs, reserve;
|
||||
unsigned int num_pins, num_configs, reserve;
|
||||
unsigned long *configs;
|
||||
struct property *pins;
|
||||
u32 pinfunc;
|
||||
@ -623,10 +631,10 @@ exit:
|
||||
static int atmel_pctl_dt_node_to_map(struct pinctrl_dev *pctldev,
|
||||
struct device_node *np_config,
|
||||
struct pinctrl_map **map,
|
||||
unsigned *num_maps)
|
||||
unsigned int *num_maps)
|
||||
{
|
||||
struct device_node *np;
|
||||
unsigned reserved_maps;
|
||||
unsigned int reserved_maps;
|
||||
int ret;
|
||||
|
||||
*map = NULL;
|
||||
@ -674,13 +682,13 @@ static int atmel_pmx_get_functions_count(struct pinctrl_dev *pctldev)
|
||||
}
|
||||
|
||||
static const char *atmel_pmx_get_function_name(struct pinctrl_dev *pctldev,
|
||||
unsigned selector)
|
||||
unsigned int selector)
|
||||
{
|
||||
return atmel_functions[selector];
|
||||
}
|
||||
|
||||
static int atmel_pmx_get_function_groups(struct pinctrl_dev *pctldev,
|
||||
unsigned selector,
|
||||
unsigned int selector,
|
||||
const char * const **groups,
|
||||
unsigned * const num_groups)
|
||||
{
|
||||
@ -693,11 +701,11 @@ static int atmel_pmx_get_function_groups(struct pinctrl_dev *pctldev,
|
||||
}
|
||||
|
||||
static int atmel_pmx_set_mux(struct pinctrl_dev *pctldev,
|
||||
unsigned function,
|
||||
unsigned group)
|
||||
unsigned int function,
|
||||
unsigned int group)
|
||||
{
|
||||
struct atmel_pioctrl *atmel_pioctrl = pinctrl_dev_get_drvdata(pctldev);
|
||||
unsigned pin;
|
||||
unsigned int pin;
|
||||
u32 conf;
|
||||
|
||||
dev_dbg(pctldev->dev, "enable function %s group %s\n",
|
||||
@ -721,13 +729,13 @@ static const struct pinmux_ops atmel_pmxops = {
|
||||
};
|
||||
|
||||
static int atmel_conf_pin_config_group_get(struct pinctrl_dev *pctldev,
|
||||
unsigned group,
|
||||
unsigned int group,
|
||||
unsigned long *config)
|
||||
{
|
||||
struct atmel_pioctrl *atmel_pioctrl = pinctrl_dev_get_drvdata(pctldev);
|
||||
unsigned param = pinconf_to_config_param(*config), arg = 0;
|
||||
unsigned int param = pinconf_to_config_param(*config), arg = 0;
|
||||
struct atmel_group *grp = atmel_pioctrl->groups + group;
|
||||
unsigned pin_id = grp->pin;
|
||||
unsigned int pin_id = grp->pin;
|
||||
u32 res;
|
||||
|
||||
res = atmel_pin_config_read(pctldev, pin_id);
|
||||
@ -760,6 +768,13 @@ static int atmel_conf_pin_config_group_get(struct pinctrl_dev *pctldev,
|
||||
return -EINVAL;
|
||||
arg = 1;
|
||||
break;
|
||||
case PIN_CONFIG_SLEW_RATE:
|
||||
if (!atmel_pioctrl->slew_rate_support)
|
||||
return -EOPNOTSUPP;
|
||||
if (!(res & ATMEL_PIO_SR_MASK))
|
||||
return -EINVAL;
|
||||
arg = 1;
|
||||
break;
|
||||
case ATMEL_PIN_CONFIG_DRIVE_STRENGTH:
|
||||
if (!(res & ATMEL_PIO_DRVSTR_MASK))
|
||||
return -EINVAL;
|
||||
@ -774,25 +789,29 @@ static int atmel_conf_pin_config_group_get(struct pinctrl_dev *pctldev,
|
||||
}
|
||||
|
||||
static int atmel_conf_pin_config_group_set(struct pinctrl_dev *pctldev,
|
||||
unsigned group,
|
||||
unsigned int group,
|
||||
unsigned long *configs,
|
||||
unsigned num_configs)
|
||||
unsigned int num_configs)
|
||||
{
|
||||
struct atmel_pioctrl *atmel_pioctrl = pinctrl_dev_get_drvdata(pctldev);
|
||||
struct atmel_group *grp = atmel_pioctrl->groups + group;
|
||||
unsigned bank, pin, pin_id = grp->pin;
|
||||
unsigned int bank, pin, pin_id = grp->pin;
|
||||
u32 mask, conf = 0;
|
||||
int i;
|
||||
|
||||
conf = atmel_pin_config_read(pctldev, pin_id);
|
||||
|
||||
for (i = 0; i < num_configs; i++) {
|
||||
unsigned param = pinconf_to_config_param(configs[i]);
|
||||
unsigned arg = pinconf_to_config_argument(configs[i]);
|
||||
unsigned int param = pinconf_to_config_param(configs[i]);
|
||||
unsigned int arg = pinconf_to_config_argument(configs[i]);
|
||||
|
||||
dev_dbg(pctldev->dev, "%s: pin=%u, config=0x%lx\n",
|
||||
__func__, pin_id, configs[i]);
|
||||
|
||||
/* Keep slew rate enabled by default. */
|
||||
if (atmel_pioctrl->slew_rate_support)
|
||||
conf |= ATMEL_PIO_SR_MASK;
|
||||
|
||||
switch (param) {
|
||||
case PIN_CONFIG_BIAS_DISABLE:
|
||||
conf &= (~ATMEL_PIO_PUEN_MASK);
|
||||
@ -850,6 +869,13 @@ static int atmel_conf_pin_config_group_set(struct pinctrl_dev *pctldev,
|
||||
ATMEL_PIO_SODR);
|
||||
}
|
||||
break;
|
||||
case PIN_CONFIG_SLEW_RATE:
|
||||
if (!atmel_pioctrl->slew_rate_support)
|
||||
break;
|
||||
/* And remove it if explicitly requested. */
|
||||
if (arg == 0)
|
||||
conf &= ~ATMEL_PIO_SR_MASK;
|
||||
break;
|
||||
case ATMEL_PIN_CONFIG_DRIVE_STRENGTH:
|
||||
switch (arg) {
|
||||
case ATMEL_PIO_DRVSTR_LO:
|
||||
@ -877,7 +903,8 @@ static int atmel_conf_pin_config_group_set(struct pinctrl_dev *pctldev,
|
||||
}
|
||||
|
||||
static void atmel_conf_pin_config_dbg_show(struct pinctrl_dev *pctldev,
|
||||
struct seq_file *s, unsigned pin_id)
|
||||
struct seq_file *s,
|
||||
unsigned int pin_id)
|
||||
{
|
||||
struct atmel_pioctrl *atmel_pioctrl = pinctrl_dev_get_drvdata(pctldev);
|
||||
u32 conf;
|
||||
@ -901,6 +928,8 @@ static void atmel_conf_pin_config_dbg_show(struct pinctrl_dev *pctldev,
|
||||
seq_printf(s, "%s ", "open-drain");
|
||||
if (conf & ATMEL_PIO_SCHMITT_MASK)
|
||||
seq_printf(s, "%s ", "schmitt");
|
||||
if (atmel_pioctrl->slew_rate_support && (conf & ATMEL_PIO_SR_MASK))
|
||||
seq_printf(s, "%s ", "slew-rate");
|
||||
if (conf & ATMEL_PIO_DRVSTR_MASK) {
|
||||
switch ((conf & ATMEL_PIO_DRVSTR_MASK) >> ATMEL_PIO_DRVSTR_OFFSET) {
|
||||
case ATMEL_PIO_DRVSTR_ME:
|
||||
@ -994,6 +1023,7 @@ static const struct atmel_pioctrl_data atmel_sama5d2_pioctrl_data = {
|
||||
static const struct atmel_pioctrl_data microchip_sama7g5_pioctrl_data = {
|
||||
.nbanks = 5,
|
||||
.last_bank_count = 8, /* sama7g5 has only PE0 to PE7 */
|
||||
.slew_rate_support = 1,
|
||||
};
|
||||
|
||||
static const struct of_device_id atmel_pctrl_of_match[] = {
|
||||
@ -1039,6 +1069,7 @@ static int atmel_pinctrl_probe(struct platform_device *pdev)
|
||||
atmel_pioctrl->npins -= ATMEL_PIO_NPINS_PER_BANK;
|
||||
atmel_pioctrl->npins += atmel_pioctrl_data->last_bank_count;
|
||||
}
|
||||
atmel_pioctrl->slew_rate_support = atmel_pioctrl_data->slew_rate_support;
|
||||
|
||||
atmel_pioctrl->reg_base = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(atmel_pioctrl->reg_base))
|
||||
@ -1081,8 +1112,8 @@ static int atmel_pinctrl_probe(struct platform_device *pdev)
|
||||
return -ENOMEM;
|
||||
for (i = 0 ; i < atmel_pioctrl->npins; i++) {
|
||||
struct atmel_group *group = atmel_pioctrl->groups + i;
|
||||
unsigned bank = ATMEL_PIO_BANK(i);
|
||||
unsigned line = ATMEL_PIO_LINE(i);
|
||||
unsigned int bank = ATMEL_PIO_BANK(i);
|
||||
unsigned int line = ATMEL_PIO_LINE(i);
|
||||
|
||||
atmel_pioctrl->pins[i] = devm_kzalloc(dev,
|
||||
sizeof(**atmel_pioctrl->pins), GFP_KERNEL);
|
||||
|
@ -733,7 +733,6 @@ static const struct at91_pinctrl_mux_ops sam9x60_ops = {
|
||||
.get_slewrate = at91_mux_sam9x60_get_slewrate,
|
||||
.set_slewrate = at91_mux_sam9x60_set_slewrate,
|
||||
.irq_type = alt_gpio_irq_type,
|
||||
|
||||
};
|
||||
|
||||
static struct at91_pinctrl_mux_ops sama5d3_ops = {
|
||||
@ -1742,7 +1741,7 @@ static int at91_gpio_of_irq_setup(struct platform_device *pdev,
|
||||
gpio_irqchip->irq_disable = gpio_irq_mask;
|
||||
gpio_irqchip->irq_mask = gpio_irq_mask;
|
||||
gpio_irqchip->irq_unmask = gpio_irq_unmask;
|
||||
gpio_irqchip->irq_set_wake = gpio_irq_set_wake,
|
||||
gpio_irqchip->irq_set_wake = gpio_irq_set_wake;
|
||||
gpio_irqchip->irq_set_type = at91_gpio->ops->irq_type;
|
||||
|
||||
/* Disable irqs of this PIO controller */
|
||||
|
@ -1,774 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* U300 GPIO module.
|
||||
*
|
||||
* Copyright (C) 2007-2012 ST-Ericsson AB
|
||||
* COH 901 571/3 - Used in DB3210 (U365 2.0) and DB3350 (U335 1.0)
|
||||
* Author: Linus Walleij <linus.walleij@linaro.org>
|
||||
* Author: Jonas Aaberg <jonas.aberg@stericsson.com>
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/gpio/driver.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/pinctrl/consumer.h>
|
||||
#include <linux/pinctrl/pinconf-generic.h>
|
||||
#include "pinctrl-coh901.h"
|
||||
|
||||
#define U300_GPIO_PORT_STRIDE (0x30)
|
||||
/*
|
||||
* Control Register 32bit (R/W)
|
||||
* bit 15-9 (mask 0x0000FE00) contains the number of cores. 8*cores
|
||||
* gives the number of GPIO pins.
|
||||
* bit 8-2 (mask 0x000001FC) contains the core version ID.
|
||||
*/
|
||||
#define U300_GPIO_CR (0x00)
|
||||
#define U300_GPIO_CR_SYNC_SEL_ENABLE (0x00000002UL)
|
||||
#define U300_GPIO_CR_BLOCK_CLKRQ_ENABLE (0x00000001UL)
|
||||
#define U300_GPIO_PXPDIR (0x04)
|
||||
#define U300_GPIO_PXPDOR (0x08)
|
||||
#define U300_GPIO_PXPCR (0x0C)
|
||||
#define U300_GPIO_PXPCR_ALL_PINS_MODE_MASK (0x0000FFFFUL)
|
||||
#define U300_GPIO_PXPCR_PIN_MODE_MASK (0x00000003UL)
|
||||
#define U300_GPIO_PXPCR_PIN_MODE_SHIFT (0x00000002UL)
|
||||
#define U300_GPIO_PXPCR_PIN_MODE_INPUT (0x00000000UL)
|
||||
#define U300_GPIO_PXPCR_PIN_MODE_OUTPUT_PUSH_PULL (0x00000001UL)
|
||||
#define U300_GPIO_PXPCR_PIN_MODE_OUTPUT_OPEN_DRAIN (0x00000002UL)
|
||||
#define U300_GPIO_PXPCR_PIN_MODE_OUTPUT_OPEN_SOURCE (0x00000003UL)
|
||||
#define U300_GPIO_PXPER (0x10)
|
||||
#define U300_GPIO_PXPER_ALL_PULL_UP_DISABLE_MASK (0x000000FFUL)
|
||||
#define U300_GPIO_PXPER_PULL_UP_DISABLE (0x00000001UL)
|
||||
#define U300_GPIO_PXIEV (0x14)
|
||||
#define U300_GPIO_PXIEN (0x18)
|
||||
#define U300_GPIO_PXIFR (0x1C)
|
||||
#define U300_GPIO_PXICR (0x20)
|
||||
#define U300_GPIO_PXICR_ALL_IRQ_CONFIG_MASK (0x000000FFUL)
|
||||
#define U300_GPIO_PXICR_IRQ_CONFIG_MASK (0x00000001UL)
|
||||
#define U300_GPIO_PXICR_IRQ_CONFIG_FALLING_EDGE (0x00000000UL)
|
||||
#define U300_GPIO_PXICR_IRQ_CONFIG_RISING_EDGE (0x00000001UL)
|
||||
|
||||
/* 8 bits per port, no version has more than 7 ports */
|
||||
#define U300_GPIO_NUM_PORTS 7
|
||||
#define U300_GPIO_PINS_PER_PORT 8
|
||||
#define U300_GPIO_MAX (U300_GPIO_PINS_PER_PORT * U300_GPIO_NUM_PORTS)
|
||||
|
||||
struct u300_gpio_port {
|
||||
struct u300_gpio *gpio;
|
||||
char name[8];
|
||||
int irq;
|
||||
int number;
|
||||
u8 toggle_edge_mode;
|
||||
};
|
||||
|
||||
struct u300_gpio {
|
||||
struct gpio_chip chip;
|
||||
struct u300_gpio_port ports[U300_GPIO_NUM_PORTS];
|
||||
struct clk *clk;
|
||||
void __iomem *base;
|
||||
struct device *dev;
|
||||
u32 stride;
|
||||
/* Register offsets */
|
||||
u32 pcr;
|
||||
u32 dor;
|
||||
u32 dir;
|
||||
u32 per;
|
||||
u32 icr;
|
||||
u32 ien;
|
||||
u32 iev;
|
||||
};
|
||||
|
||||
/*
|
||||
* Macro to expand to read a specific register found in the "gpio"
|
||||
* struct. It requires the struct u300_gpio *gpio variable to exist in
|
||||
* its context. It calculates the port offset from the given pin
|
||||
* offset, muliplies by the port stride and adds the register offset
|
||||
* so it provides a pointer to the desired register.
|
||||
*/
|
||||
#define U300_PIN_REG(pin, reg) \
|
||||
(gpio->base + (pin >> 3) * gpio->stride + gpio->reg)
|
||||
|
||||
/*
|
||||
* Provides a bitmask for a specific gpio pin inside an 8-bit GPIO
|
||||
* register.
|
||||
*/
|
||||
#define U300_PIN_BIT(pin) \
|
||||
(1 << (pin & 0x07))
|
||||
|
||||
struct u300_gpio_confdata {
|
||||
u16 bias_mode;
|
||||
bool output;
|
||||
int outval;
|
||||
};
|
||||
|
||||
#define U300_FLOATING_INPUT { \
|
||||
.bias_mode = PIN_CONFIG_BIAS_HIGH_IMPEDANCE, \
|
||||
.output = false, \
|
||||
}
|
||||
|
||||
#define U300_PULL_UP_INPUT { \
|
||||
.bias_mode = PIN_CONFIG_BIAS_PULL_UP, \
|
||||
.output = false, \
|
||||
}
|
||||
|
||||
#define U300_OUTPUT_LOW { \
|
||||
.output = true, \
|
||||
.outval = 0, \
|
||||
}
|
||||
|
||||
#define U300_OUTPUT_HIGH { \
|
||||
.output = true, \
|
||||
.outval = 1, \
|
||||
}
|
||||
|
||||
/* Initial configuration */
|
||||
static const struct u300_gpio_confdata __initconst
|
||||
bs335_gpio_config[U300_GPIO_NUM_PORTS][U300_GPIO_PINS_PER_PORT] = {
|
||||
/* Port 0, pins 0-7 */
|
||||
{
|
||||
U300_FLOATING_INPUT,
|
||||
U300_OUTPUT_HIGH,
|
||||
U300_FLOATING_INPUT,
|
||||
U300_OUTPUT_LOW,
|
||||
U300_OUTPUT_LOW,
|
||||
U300_OUTPUT_LOW,
|
||||
U300_OUTPUT_LOW,
|
||||
U300_OUTPUT_LOW,
|
||||
},
|
||||
/* Port 1, pins 0-7 */
|
||||
{
|
||||
U300_OUTPUT_LOW,
|
||||
U300_OUTPUT_LOW,
|
||||
U300_OUTPUT_LOW,
|
||||
U300_PULL_UP_INPUT,
|
||||
U300_FLOATING_INPUT,
|
||||
U300_OUTPUT_HIGH,
|
||||
U300_OUTPUT_LOW,
|
||||
U300_OUTPUT_LOW,
|
||||
},
|
||||
/* Port 2, pins 0-7 */
|
||||
{
|
||||
U300_FLOATING_INPUT,
|
||||
U300_FLOATING_INPUT,
|
||||
U300_FLOATING_INPUT,
|
||||
U300_FLOATING_INPUT,
|
||||
U300_OUTPUT_LOW,
|
||||
U300_PULL_UP_INPUT,
|
||||
U300_OUTPUT_LOW,
|
||||
U300_PULL_UP_INPUT,
|
||||
},
|
||||
/* Port 3, pins 0-7 */
|
||||
{
|
||||
U300_PULL_UP_INPUT,
|
||||
U300_OUTPUT_LOW,
|
||||
U300_FLOATING_INPUT,
|
||||
U300_FLOATING_INPUT,
|
||||
U300_FLOATING_INPUT,
|
||||
U300_FLOATING_INPUT,
|
||||
U300_FLOATING_INPUT,
|
||||
U300_FLOATING_INPUT,
|
||||
},
|
||||
/* Port 4, pins 0-7 */
|
||||
{
|
||||
U300_FLOATING_INPUT,
|
||||
U300_FLOATING_INPUT,
|
||||
U300_FLOATING_INPUT,
|
||||
U300_FLOATING_INPUT,
|
||||
U300_FLOATING_INPUT,
|
||||
U300_FLOATING_INPUT,
|
||||
U300_FLOATING_INPUT,
|
||||
U300_FLOATING_INPUT,
|
||||
},
|
||||
/* Port 5, pins 0-7 */
|
||||
{
|
||||
U300_FLOATING_INPUT,
|
||||
U300_FLOATING_INPUT,
|
||||
U300_FLOATING_INPUT,
|
||||
U300_FLOATING_INPUT,
|
||||
U300_FLOATING_INPUT,
|
||||
U300_FLOATING_INPUT,
|
||||
U300_FLOATING_INPUT,
|
||||
U300_FLOATING_INPUT,
|
||||
},
|
||||
/* Port 6, pind 0-7 */
|
||||
{
|
||||
U300_FLOATING_INPUT,
|
||||
U300_FLOATING_INPUT,
|
||||
U300_FLOATING_INPUT,
|
||||
U300_FLOATING_INPUT,
|
||||
U300_FLOATING_INPUT,
|
||||
U300_FLOATING_INPUT,
|
||||
U300_FLOATING_INPUT,
|
||||
U300_FLOATING_INPUT,
|
||||
}
|
||||
};
|
||||
|
||||
static int u300_gpio_get(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
struct u300_gpio *gpio = gpiochip_get_data(chip);
|
||||
|
||||
return !!(readl(U300_PIN_REG(offset, dir)) & U300_PIN_BIT(offset));
|
||||
}
|
||||
|
||||
static void u300_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
|
||||
{
|
||||
struct u300_gpio *gpio = gpiochip_get_data(chip);
|
||||
unsigned long flags;
|
||||
u32 val;
|
||||
|
||||
local_irq_save(flags);
|
||||
|
||||
val = readl(U300_PIN_REG(offset, dor));
|
||||
if (value)
|
||||
writel(val | U300_PIN_BIT(offset), U300_PIN_REG(offset, dor));
|
||||
else
|
||||
writel(val & ~U300_PIN_BIT(offset), U300_PIN_REG(offset, dor));
|
||||
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
static int u300_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
struct u300_gpio *gpio = gpiochip_get_data(chip);
|
||||
unsigned long flags;
|
||||
u32 val;
|
||||
|
||||
local_irq_save(flags);
|
||||
val = readl(U300_PIN_REG(offset, pcr));
|
||||
/* Mask out this pin, note 2 bits per setting */
|
||||
val &= ~(U300_GPIO_PXPCR_PIN_MODE_MASK << ((offset & 0x07) << 1));
|
||||
writel(val, U300_PIN_REG(offset, pcr));
|
||||
local_irq_restore(flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int u300_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
|
||||
int value)
|
||||
{
|
||||
struct u300_gpio *gpio = gpiochip_get_data(chip);
|
||||
unsigned long flags;
|
||||
u32 oldmode;
|
||||
u32 val;
|
||||
|
||||
local_irq_save(flags);
|
||||
val = readl(U300_PIN_REG(offset, pcr));
|
||||
/*
|
||||
* Drive mode must be set by the special mode set function, set
|
||||
* push/pull mode by default if no mode has been selected.
|
||||
*/
|
||||
oldmode = val & (U300_GPIO_PXPCR_PIN_MODE_MASK <<
|
||||
((offset & 0x07) << 1));
|
||||
/* mode = 0 means input, else some mode is already set */
|
||||
if (oldmode == 0) {
|
||||
val &= ~(U300_GPIO_PXPCR_PIN_MODE_MASK <<
|
||||
((offset & 0x07) << 1));
|
||||
val |= (U300_GPIO_PXPCR_PIN_MODE_OUTPUT_PUSH_PULL
|
||||
<< ((offset & 0x07) << 1));
|
||||
writel(val, U300_PIN_REG(offset, pcr));
|
||||
}
|
||||
u300_gpio_set(chip, offset, value);
|
||||
local_irq_restore(flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Returning -EINVAL means "supported but not available" */
|
||||
int u300_gpio_config_get(struct gpio_chip *chip,
|
||||
unsigned offset,
|
||||
unsigned long *config)
|
||||
{
|
||||
struct u300_gpio *gpio = gpiochip_get_data(chip);
|
||||
enum pin_config_param param = (enum pin_config_param) *config;
|
||||
bool biasmode;
|
||||
u32 drmode;
|
||||
|
||||
/* One bit per pin, clamp to bool range */
|
||||
biasmode = !!(readl(U300_PIN_REG(offset, per)) & U300_PIN_BIT(offset));
|
||||
|
||||
/* Mask out the two bits for this pin and shift to bits 0,1 */
|
||||
drmode = readl(U300_PIN_REG(offset, pcr));
|
||||
drmode &= (U300_GPIO_PXPCR_PIN_MODE_MASK << ((offset & 0x07) << 1));
|
||||
drmode >>= ((offset & 0x07) << 1);
|
||||
|
||||
switch (param) {
|
||||
case PIN_CONFIG_BIAS_HIGH_IMPEDANCE:
|
||||
*config = 0;
|
||||
if (biasmode)
|
||||
return 0;
|
||||
else
|
||||
return -EINVAL;
|
||||
break;
|
||||
case PIN_CONFIG_BIAS_PULL_UP:
|
||||
*config = 0;
|
||||
if (!biasmode)
|
||||
return 0;
|
||||
else
|
||||
return -EINVAL;
|
||||
break;
|
||||
case PIN_CONFIG_DRIVE_PUSH_PULL:
|
||||
*config = 0;
|
||||
if (drmode == U300_GPIO_PXPCR_PIN_MODE_OUTPUT_PUSH_PULL)
|
||||
return 0;
|
||||
else
|
||||
return -EINVAL;
|
||||
break;
|
||||
case PIN_CONFIG_DRIVE_OPEN_DRAIN:
|
||||
*config = 0;
|
||||
if (drmode == U300_GPIO_PXPCR_PIN_MODE_OUTPUT_OPEN_DRAIN)
|
||||
return 0;
|
||||
else
|
||||
return -EINVAL;
|
||||
break;
|
||||
case PIN_CONFIG_DRIVE_OPEN_SOURCE:
|
||||
*config = 0;
|
||||
if (drmode == U300_GPIO_PXPCR_PIN_MODE_OUTPUT_OPEN_SOURCE)
|
||||
return 0;
|
||||
else
|
||||
return -EINVAL;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
int u300_gpio_config_set(struct gpio_chip *chip, unsigned offset,
|
||||
enum pin_config_param param)
|
||||
{
|
||||
struct u300_gpio *gpio = gpiochip_get_data(chip);
|
||||
unsigned long flags;
|
||||
u32 val;
|
||||
|
||||
local_irq_save(flags);
|
||||
switch (param) {
|
||||
case PIN_CONFIG_BIAS_DISABLE:
|
||||
case PIN_CONFIG_BIAS_HIGH_IMPEDANCE:
|
||||
val = readl(U300_PIN_REG(offset, per));
|
||||
writel(val | U300_PIN_BIT(offset), U300_PIN_REG(offset, per));
|
||||
break;
|
||||
case PIN_CONFIG_BIAS_PULL_UP:
|
||||
val = readl(U300_PIN_REG(offset, per));
|
||||
writel(val & ~U300_PIN_BIT(offset), U300_PIN_REG(offset, per));
|
||||
break;
|
||||
case PIN_CONFIG_DRIVE_PUSH_PULL:
|
||||
val = readl(U300_PIN_REG(offset, pcr));
|
||||
val &= ~(U300_GPIO_PXPCR_PIN_MODE_MASK
|
||||
<< ((offset & 0x07) << 1));
|
||||
val |= (U300_GPIO_PXPCR_PIN_MODE_OUTPUT_PUSH_PULL
|
||||
<< ((offset & 0x07) << 1));
|
||||
writel(val, U300_PIN_REG(offset, pcr));
|
||||
break;
|
||||
case PIN_CONFIG_DRIVE_OPEN_DRAIN:
|
||||
val = readl(U300_PIN_REG(offset, pcr));
|
||||
val &= ~(U300_GPIO_PXPCR_PIN_MODE_MASK
|
||||
<< ((offset & 0x07) << 1));
|
||||
val |= (U300_GPIO_PXPCR_PIN_MODE_OUTPUT_OPEN_DRAIN
|
||||
<< ((offset & 0x07) << 1));
|
||||
writel(val, U300_PIN_REG(offset, pcr));
|
||||
break;
|
||||
case PIN_CONFIG_DRIVE_OPEN_SOURCE:
|
||||
val = readl(U300_PIN_REG(offset, pcr));
|
||||
val &= ~(U300_GPIO_PXPCR_PIN_MODE_MASK
|
||||
<< ((offset & 0x07) << 1));
|
||||
val |= (U300_GPIO_PXPCR_PIN_MODE_OUTPUT_OPEN_SOURCE
|
||||
<< ((offset & 0x07) << 1));
|
||||
writel(val, U300_PIN_REG(offset, pcr));
|
||||
break;
|
||||
default:
|
||||
local_irq_restore(flags);
|
||||
dev_err(gpio->dev, "illegal configuration requested\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
local_irq_restore(flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct gpio_chip u300_gpio_chip = {
|
||||
.label = "u300-gpio-chip",
|
||||
.owner = THIS_MODULE,
|
||||
.request = gpiochip_generic_request,
|
||||
.free = gpiochip_generic_free,
|
||||
.get = u300_gpio_get,
|
||||
.set = u300_gpio_set,
|
||||
.direction_input = u300_gpio_direction_input,
|
||||
.direction_output = u300_gpio_direction_output,
|
||||
};
|
||||
|
||||
static void u300_toggle_trigger(struct u300_gpio *gpio, unsigned offset)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
val = readl(U300_PIN_REG(offset, icr));
|
||||
/* Set mode depending on state */
|
||||
if (u300_gpio_get(&gpio->chip, offset)) {
|
||||
/* High now, let's trigger on falling edge next then */
|
||||
writel(val & ~U300_PIN_BIT(offset), U300_PIN_REG(offset, icr));
|
||||
dev_dbg(gpio->dev, "next IRQ on falling edge on pin %d\n",
|
||||
offset);
|
||||
} else {
|
||||
/* Low now, let's trigger on rising edge next then */
|
||||
writel(val | U300_PIN_BIT(offset), U300_PIN_REG(offset, icr));
|
||||
dev_dbg(gpio->dev, "next IRQ on rising edge on pin %d\n",
|
||||
offset);
|
||||
}
|
||||
}
|
||||
|
||||
static int u300_gpio_irq_type(struct irq_data *d, unsigned trigger)
|
||||
{
|
||||
struct gpio_chip *chip = irq_data_get_irq_chip_data(d);
|
||||
struct u300_gpio *gpio = gpiochip_get_data(chip);
|
||||
struct u300_gpio_port *port = &gpio->ports[d->hwirq >> 3];
|
||||
int offset = d->hwirq;
|
||||
u32 val;
|
||||
|
||||
if ((trigger & IRQF_TRIGGER_RISING) &&
|
||||
(trigger & IRQF_TRIGGER_FALLING)) {
|
||||
/*
|
||||
* The GPIO block can only trigger on falling OR rising edges,
|
||||
* not both. So we need to toggle the mode whenever the pin
|
||||
* goes from one state to the other with a special state flag
|
||||
*/
|
||||
dev_dbg(gpio->dev,
|
||||
"trigger on both rising and falling edge on pin %d\n",
|
||||
offset);
|
||||
port->toggle_edge_mode |= U300_PIN_BIT(offset);
|
||||
u300_toggle_trigger(gpio, offset);
|
||||
} else if (trigger & IRQF_TRIGGER_RISING) {
|
||||
dev_dbg(gpio->dev, "trigger on rising edge on pin %d\n",
|
||||
offset);
|
||||
val = readl(U300_PIN_REG(offset, icr));
|
||||
writel(val | U300_PIN_BIT(offset), U300_PIN_REG(offset, icr));
|
||||
port->toggle_edge_mode &= ~U300_PIN_BIT(offset);
|
||||
} else if (trigger & IRQF_TRIGGER_FALLING) {
|
||||
dev_dbg(gpio->dev, "trigger on falling edge on pin %d\n",
|
||||
offset);
|
||||
val = readl(U300_PIN_REG(offset, icr));
|
||||
writel(val & ~U300_PIN_BIT(offset), U300_PIN_REG(offset, icr));
|
||||
port->toggle_edge_mode &= ~U300_PIN_BIT(offset);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void u300_gpio_irq_enable(struct irq_data *d)
|
||||
{
|
||||
struct gpio_chip *chip = irq_data_get_irq_chip_data(d);
|
||||
struct u300_gpio *gpio = gpiochip_get_data(chip);
|
||||
struct u300_gpio_port *port = &gpio->ports[d->hwirq >> 3];
|
||||
int offset = d->hwirq;
|
||||
u32 val;
|
||||
unsigned long flags;
|
||||
|
||||
dev_dbg(gpio->dev, "enable IRQ for hwirq %lu on port %s, offset %d\n",
|
||||
d->hwirq, port->name, offset);
|
||||
local_irq_save(flags);
|
||||
val = readl(U300_PIN_REG(offset, ien));
|
||||
writel(val | U300_PIN_BIT(offset), U300_PIN_REG(offset, ien));
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
static void u300_gpio_irq_disable(struct irq_data *d)
|
||||
{
|
||||
struct gpio_chip *chip = irq_data_get_irq_chip_data(d);
|
||||
struct u300_gpio *gpio = gpiochip_get_data(chip);
|
||||
int offset = d->hwirq;
|
||||
u32 val;
|
||||
unsigned long flags;
|
||||
|
||||
local_irq_save(flags);
|
||||
val = readl(U300_PIN_REG(offset, ien));
|
||||
writel(val & ~U300_PIN_BIT(offset), U300_PIN_REG(offset, ien));
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
static struct irq_chip u300_gpio_irqchip = {
|
||||
.name = "u300-gpio-irqchip",
|
||||
.irq_enable = u300_gpio_irq_enable,
|
||||
.irq_disable = u300_gpio_irq_disable,
|
||||
.irq_set_type = u300_gpio_irq_type,
|
||||
};
|
||||
|
||||
static void u300_gpio_irq_handler(struct irq_desc *desc)
|
||||
{
|
||||
unsigned int irq = irq_desc_get_irq(desc);
|
||||
struct irq_chip *parent_chip = irq_desc_get_chip(desc);
|
||||
struct gpio_chip *chip = irq_desc_get_handler_data(desc);
|
||||
struct u300_gpio *gpio = gpiochip_get_data(chip);
|
||||
struct u300_gpio_port *port = &gpio->ports[irq - chip->base];
|
||||
int pinoffset = port->number << 3; /* get the right stride */
|
||||
unsigned long val;
|
||||
|
||||
chained_irq_enter(parent_chip, desc);
|
||||
|
||||
/* Read event register */
|
||||
val = readl(U300_PIN_REG(pinoffset, iev));
|
||||
/* Mask relevant bits */
|
||||
val &= 0xFFU; /* 8 bits per port */
|
||||
/* ACK IRQ (clear event) */
|
||||
writel(val, U300_PIN_REG(pinoffset, iev));
|
||||
|
||||
/* Call IRQ handler */
|
||||
if (val != 0) {
|
||||
int irqoffset;
|
||||
|
||||
for_each_set_bit(irqoffset, &val, U300_GPIO_PINS_PER_PORT) {
|
||||
int offset = pinoffset + irqoffset;
|
||||
int pin_irq = irq_find_mapping(chip->irq.domain, offset);
|
||||
|
||||
dev_dbg(gpio->dev, "GPIO IRQ %d on pin %d\n",
|
||||
pin_irq, offset);
|
||||
generic_handle_irq(pin_irq);
|
||||
/*
|
||||
* Triggering IRQ on both rising and falling edge
|
||||
* needs mockery
|
||||
*/
|
||||
if (port->toggle_edge_mode & U300_PIN_BIT(offset))
|
||||
u300_toggle_trigger(gpio, offset);
|
||||
}
|
||||
}
|
||||
|
||||
chained_irq_exit(parent_chip, desc);
|
||||
}
|
||||
|
||||
static void __init u300_gpio_init_pin(struct u300_gpio *gpio,
|
||||
int offset,
|
||||
const struct u300_gpio_confdata *conf)
|
||||
{
|
||||
/* Set mode: input or output */
|
||||
if (conf->output) {
|
||||
u300_gpio_direction_output(&gpio->chip, offset, conf->outval);
|
||||
|
||||
/* Deactivate bias mode for output */
|
||||
u300_gpio_config_set(&gpio->chip, offset,
|
||||
PIN_CONFIG_BIAS_HIGH_IMPEDANCE);
|
||||
|
||||
/* Set drive mode for output */
|
||||
u300_gpio_config_set(&gpio->chip, offset,
|
||||
PIN_CONFIG_DRIVE_PUSH_PULL);
|
||||
|
||||
dev_dbg(gpio->dev, "set up pin %d as output, value: %d\n",
|
||||
offset, conf->outval);
|
||||
} else {
|
||||
u300_gpio_direction_input(&gpio->chip, offset);
|
||||
|
||||
/* Always set output low on input pins */
|
||||
u300_gpio_set(&gpio->chip, offset, 0);
|
||||
|
||||
/* Set bias mode for input */
|
||||
u300_gpio_config_set(&gpio->chip, offset, conf->bias_mode);
|
||||
|
||||
dev_dbg(gpio->dev, "set up pin %d as input, bias: %04x\n",
|
||||
offset, conf->bias_mode);
|
||||
}
|
||||
}
|
||||
|
||||
static void __init u300_gpio_init_coh901571(struct u300_gpio *gpio)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
/* Write default config and values to all pins */
|
||||
for (i = 0; i < U300_GPIO_NUM_PORTS; i++) {
|
||||
for (j = 0; j < 8; j++) {
|
||||
const struct u300_gpio_confdata *conf;
|
||||
int offset = (i*8) + j;
|
||||
|
||||
conf = &bs335_gpio_config[i][j];
|
||||
u300_gpio_init_pin(gpio, offset, conf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Here we map a GPIO in the local gpio_chip pin space to a pin in
|
||||
* the local pinctrl pin space. The pin controller used is
|
||||
* pinctrl-u300.
|
||||
*/
|
||||
struct coh901_pinpair {
|
||||
unsigned int offset;
|
||||
unsigned int pin_base;
|
||||
};
|
||||
|
||||
#define COH901_PINRANGE(a, b) { .offset = a, .pin_base = b }
|
||||
|
||||
static struct coh901_pinpair coh901_pintable[] = {
|
||||
COH901_PINRANGE(10, 426),
|
||||
COH901_PINRANGE(11, 180),
|
||||
COH901_PINRANGE(12, 165), /* MS/MMC card insertion */
|
||||
COH901_PINRANGE(13, 179),
|
||||
COH901_PINRANGE(14, 178),
|
||||
COH901_PINRANGE(16, 194),
|
||||
COH901_PINRANGE(17, 193),
|
||||
COH901_PINRANGE(18, 192),
|
||||
COH901_PINRANGE(19, 191),
|
||||
COH901_PINRANGE(20, 186),
|
||||
COH901_PINRANGE(21, 185),
|
||||
COH901_PINRANGE(22, 184),
|
||||
COH901_PINRANGE(23, 183),
|
||||
COH901_PINRANGE(24, 182),
|
||||
COH901_PINRANGE(25, 181),
|
||||
};
|
||||
|
||||
static int __init u300_gpio_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct u300_gpio *gpio;
|
||||
struct gpio_irq_chip *girq;
|
||||
int err = 0;
|
||||
int portno;
|
||||
u32 val;
|
||||
u32 ifr;
|
||||
int i;
|
||||
|
||||
gpio = devm_kzalloc(&pdev->dev, sizeof(struct u300_gpio), GFP_KERNEL);
|
||||
if (gpio == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
gpio->chip = u300_gpio_chip;
|
||||
gpio->chip.ngpio = U300_GPIO_NUM_PORTS * U300_GPIO_PINS_PER_PORT;
|
||||
gpio->chip.parent = &pdev->dev;
|
||||
gpio->chip.base = 0;
|
||||
gpio->dev = &pdev->dev;
|
||||
|
||||
gpio->base = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(gpio->base))
|
||||
return PTR_ERR(gpio->base);
|
||||
|
||||
gpio->clk = devm_clk_get(gpio->dev, NULL);
|
||||
if (IS_ERR(gpio->clk)) {
|
||||
err = PTR_ERR(gpio->clk);
|
||||
dev_err(gpio->dev, "could not get GPIO clock\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
err = clk_prepare_enable(gpio->clk);
|
||||
if (err) {
|
||||
dev_err(gpio->dev, "could not enable GPIO clock\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
dev_info(gpio->dev,
|
||||
"initializing GPIO Controller COH 901 571/3\n");
|
||||
gpio->stride = U300_GPIO_PORT_STRIDE;
|
||||
gpio->pcr = U300_GPIO_PXPCR;
|
||||
gpio->dor = U300_GPIO_PXPDOR;
|
||||
gpio->dir = U300_GPIO_PXPDIR;
|
||||
gpio->per = U300_GPIO_PXPER;
|
||||
gpio->icr = U300_GPIO_PXICR;
|
||||
gpio->ien = U300_GPIO_PXIEN;
|
||||
gpio->iev = U300_GPIO_PXIEV;
|
||||
ifr = U300_GPIO_PXIFR;
|
||||
|
||||
val = readl(gpio->base + U300_GPIO_CR);
|
||||
dev_info(gpio->dev, "COH901571/3 block version: %d, " \
|
||||
"number of cores: %d totalling %d pins\n",
|
||||
((val & 0x000001FC) >> 2),
|
||||
((val & 0x0000FE00) >> 9),
|
||||
((val & 0x0000FE00) >> 9) * 8);
|
||||
writel(U300_GPIO_CR_BLOCK_CLKRQ_ENABLE,
|
||||
gpio->base + U300_GPIO_CR);
|
||||
u300_gpio_init_coh901571(gpio);
|
||||
|
||||
girq = &gpio->chip.irq;
|
||||
girq->chip = &u300_gpio_irqchip;
|
||||
girq->parent_handler = u300_gpio_irq_handler;
|
||||
girq->num_parents = U300_GPIO_NUM_PORTS;
|
||||
girq->parents = devm_kcalloc(gpio->dev, U300_GPIO_NUM_PORTS,
|
||||
sizeof(*girq->parents),
|
||||
GFP_KERNEL);
|
||||
if (!girq->parents) {
|
||||
err = -ENOMEM;
|
||||
goto err_dis_clk;
|
||||
}
|
||||
for (portno = 0 ; portno < U300_GPIO_NUM_PORTS; portno++) {
|
||||
struct u300_gpio_port *port = &gpio->ports[portno];
|
||||
|
||||
snprintf(port->name, 8, "gpio%d", portno);
|
||||
port->number = portno;
|
||||
port->gpio = gpio;
|
||||
|
||||
port->irq = platform_get_irq(pdev, portno);
|
||||
girq->parents[portno] = port->irq;
|
||||
|
||||
/* Turns off irq force (test register) for this port */
|
||||
writel(0x0, gpio->base + portno * gpio->stride + ifr);
|
||||
}
|
||||
girq->default_type = IRQ_TYPE_EDGE_FALLING;
|
||||
girq->handler = handle_simple_irq;
|
||||
#ifdef CONFIG_OF_GPIO
|
||||
gpio->chip.of_node = pdev->dev.of_node;
|
||||
#endif
|
||||
err = gpiochip_add_data(&gpio->chip, gpio);
|
||||
if (err) {
|
||||
dev_err(gpio->dev, "unable to add gpiochip: %d\n", err);
|
||||
goto err_dis_clk;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add pinctrl pin ranges, the pin controller must be registered
|
||||
* at this point
|
||||
*/
|
||||
for (i = 0; i < ARRAY_SIZE(coh901_pintable); i++) {
|
||||
struct coh901_pinpair *p = &coh901_pintable[i];
|
||||
|
||||
err = gpiochip_add_pin_range(&gpio->chip, "pinctrl-u300",
|
||||
p->offset, p->pin_base, 1);
|
||||
if (err)
|
||||
goto err_no_range;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, gpio);
|
||||
|
||||
return 0;
|
||||
|
||||
err_no_range:
|
||||
gpiochip_remove(&gpio->chip);
|
||||
err_dis_clk:
|
||||
clk_disable_unprepare(gpio->clk);
|
||||
dev_err(&pdev->dev, "module ERROR:%d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int __exit u300_gpio_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct u300_gpio *gpio = platform_get_drvdata(pdev);
|
||||
|
||||
/* Turn off the GPIO block */
|
||||
writel(0x00000000U, gpio->base + U300_GPIO_CR);
|
||||
|
||||
gpiochip_remove(&gpio->chip);
|
||||
clk_disable_unprepare(gpio->clk);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id u300_gpio_match[] = {
|
||||
{ .compatible = "stericsson,gpio-coh901" },
|
||||
{},
|
||||
};
|
||||
|
||||
static struct platform_driver u300_gpio_driver = {
|
||||
.driver = {
|
||||
.name = "u300-gpio",
|
||||
.of_match_table = u300_gpio_match,
|
||||
},
|
||||
.remove = __exit_p(u300_gpio_remove),
|
||||
};
|
||||
|
||||
static int __init u300_gpio_init(void)
|
||||
{
|
||||
return platform_driver_probe(&u300_gpio_driver, u300_gpio_probe);
|
||||
}
|
||||
|
||||
static void __exit u300_gpio_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&u300_gpio_driver);
|
||||
}
|
||||
|
||||
arch_initcall(u300_gpio_init);
|
||||
module_exit(u300_gpio_exit);
|
||||
|
||||
MODULE_AUTHOR("Linus Walleij <linus.walleij@stericsson.com>");
|
||||
MODULE_DESCRIPTION("ST-Ericsson AB COH 901 335/COH 901 571/3 GPIO driver");
|
||||
MODULE_LICENSE("GPL");
|
@ -1,6 +0,0 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
int u300_gpio_config_get(struct gpio_chip *chip,
|
||||
unsigned offset,
|
||||
unsigned long *config);
|
||||
int u300_gpio_config_set(struct gpio_chip *chip, unsigned offset,
|
||||
enum pin_config_param param);
|
@ -376,12 +376,21 @@ static int jz4760_cim_pins[] = {
|
||||
0x26, 0x27, 0x28, 0x29,
|
||||
0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31,
|
||||
};
|
||||
static int jz4760_lcd_24bit_pins[] = {
|
||||
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
|
||||
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
|
||||
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
|
||||
0x58, 0x59, 0x5a, 0x5b,
|
||||
static int jz4760_lcd_8bit_pins[] = {
|
||||
0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x4c,
|
||||
0x4d, 0x52, 0x53,
|
||||
};
|
||||
static int jz4760_lcd_16bit_pins[] = {
|
||||
0x4e, 0x4f, 0x50, 0x51, 0x56, 0x57, 0x58, 0x59,
|
||||
};
|
||||
static int jz4760_lcd_18bit_pins[] = {
|
||||
0x5a, 0x5b,
|
||||
};
|
||||
static int jz4760_lcd_24bit_pins[] = {
|
||||
0x40, 0x41, 0x4a, 0x4b, 0x54, 0x55,
|
||||
};
|
||||
static int jz4760_lcd_special_pins[] = { 0x40, 0x41, 0x4a, 0x54 };
|
||||
static int jz4760_lcd_generic_pins[] = { 0x49, };
|
||||
static int jz4760_pwm_pwm0_pins[] = { 0x80, };
|
||||
static int jz4760_pwm_pwm1_pins[] = { 0x81, };
|
||||
static int jz4760_pwm_pwm2_pins[] = { 0x82, };
|
||||
@ -390,6 +399,7 @@ static int jz4760_pwm_pwm4_pins[] = { 0x84, };
|
||||
static int jz4760_pwm_pwm5_pins[] = { 0x85, };
|
||||
static int jz4760_pwm_pwm6_pins[] = { 0x6a, };
|
||||
static int jz4760_pwm_pwm7_pins[] = { 0x6b, };
|
||||
static int jz4760_otg_pins[] = { 0x8a, };
|
||||
|
||||
static u8 jz4760_uart3_data_funcs[] = { 0, 1, };
|
||||
static u8 jz4760_mmc0_1bit_a_funcs[] = { 1, 1, 0, };
|
||||
@ -436,8 +446,12 @@ static const struct group_desc jz4760_groups[] = {
|
||||
INGENIC_PIN_GROUP("i2c0-data", jz4760_i2c0, 0),
|
||||
INGENIC_PIN_GROUP("i2c1-data", jz4760_i2c1, 0),
|
||||
INGENIC_PIN_GROUP("cim-data", jz4760_cim, 0),
|
||||
INGENIC_PIN_GROUP("lcd-8bit", jz4760_lcd_8bit, 0),
|
||||
INGENIC_PIN_GROUP("lcd-16bit", jz4760_lcd_16bit, 0),
|
||||
INGENIC_PIN_GROUP("lcd-18bit", jz4760_lcd_18bit, 0),
|
||||
INGENIC_PIN_GROUP("lcd-24bit", jz4760_lcd_24bit, 0),
|
||||
{ "lcd-no-pins", },
|
||||
INGENIC_PIN_GROUP("lcd-generic", jz4760_lcd_generic, 0),
|
||||
INGENIC_PIN_GROUP("lcd-special", jz4760_lcd_special, 1),
|
||||
INGENIC_PIN_GROUP("pwm0", jz4760_pwm_pwm0, 0),
|
||||
INGENIC_PIN_GROUP("pwm1", jz4760_pwm_pwm1, 0),
|
||||
INGENIC_PIN_GROUP("pwm2", jz4760_pwm_pwm2, 0),
|
||||
@ -446,6 +460,7 @@ static const struct group_desc jz4760_groups[] = {
|
||||
INGENIC_PIN_GROUP("pwm5", jz4760_pwm_pwm5, 0),
|
||||
INGENIC_PIN_GROUP("pwm6", jz4760_pwm_pwm6, 0),
|
||||
INGENIC_PIN_GROUP("pwm7", jz4760_pwm_pwm7, 0),
|
||||
INGENIC_PIN_GROUP("otg-vbus", jz4760_otg, 0),
|
||||
};
|
||||
|
||||
static const char *jz4760_uart0_groups[] = { "uart0-data", "uart0-hwflow", };
|
||||
@ -477,7 +492,10 @@ static const char *jz4760_cs6_groups[] = { "nemc-cs6", };
|
||||
static const char *jz4760_i2c0_groups[] = { "i2c0-data", };
|
||||
static const char *jz4760_i2c1_groups[] = { "i2c1-data", };
|
||||
static const char *jz4760_cim_groups[] = { "cim-data", };
|
||||
static const char *jz4760_lcd_groups[] = { "lcd-24bit", "lcd-no-pins", };
|
||||
static const char *jz4760_lcd_groups[] = {
|
||||
"lcd-8bit", "lcd-16bit", "lcd-18bit", "lcd-24bit",
|
||||
"lcd-special", "lcd-generic",
|
||||
};
|
||||
static const char *jz4760_pwm0_groups[] = { "pwm0", };
|
||||
static const char *jz4760_pwm1_groups[] = { "pwm1", };
|
||||
static const char *jz4760_pwm2_groups[] = { "pwm2", };
|
||||
@ -486,6 +504,7 @@ static const char *jz4760_pwm4_groups[] = { "pwm4", };
|
||||
static const char *jz4760_pwm5_groups[] = { "pwm5", };
|
||||
static const char *jz4760_pwm6_groups[] = { "pwm6", };
|
||||
static const char *jz4760_pwm7_groups[] = { "pwm7", };
|
||||
static const char *jz4760_otg_groups[] = { "otg-vbus", };
|
||||
|
||||
static const struct function_desc jz4760_functions[] = {
|
||||
{ "uart0", jz4760_uart0_groups, ARRAY_SIZE(jz4760_uart0_groups), },
|
||||
@ -514,6 +533,7 @@ static const struct function_desc jz4760_functions[] = {
|
||||
{ "pwm5", jz4760_pwm5_groups, ARRAY_SIZE(jz4760_pwm5_groups), },
|
||||
{ "pwm6", jz4760_pwm6_groups, ARRAY_SIZE(jz4760_pwm6_groups), },
|
||||
{ "pwm7", jz4760_pwm7_groups, ARRAY_SIZE(jz4760_pwm7_groups), },
|
||||
{ "otg", jz4760_otg_groups, ARRAY_SIZE(jz4760_otg_groups), },
|
||||
};
|
||||
|
||||
static const struct ingenic_chip_info jz4760_chip_info = {
|
||||
@ -648,7 +668,6 @@ static int jz4770_mac_rmii_pins[] = {
|
||||
0xa9, 0xab, 0xaa, 0xac, 0xa5, 0xa4, 0xad, 0xae, 0xa6, 0xa8,
|
||||
};
|
||||
static int jz4770_mac_mii_pins[] = { 0xa7, 0xaf, };
|
||||
static int jz4770_otg_pins[] = { 0x8a, };
|
||||
|
||||
static const struct group_desc jz4770_groups[] = {
|
||||
INGENIC_PIN_GROUP("uart0-data", jz4770_uart0_data, 0),
|
||||
@ -747,7 +766,7 @@ static const struct group_desc jz4770_groups[] = {
|
||||
INGENIC_PIN_GROUP("pwm7", jz4770_pwm_pwm7, 0),
|
||||
INGENIC_PIN_GROUP("mac-rmii", jz4770_mac_rmii, 0),
|
||||
INGENIC_PIN_GROUP("mac-mii", jz4770_mac_mii, 0),
|
||||
INGENIC_PIN_GROUP("otg-vbus", jz4770_otg, 0),
|
||||
INGENIC_PIN_GROUP("otg-vbus", jz4760_otg, 0),
|
||||
};
|
||||
|
||||
static const char *jz4770_uart0_groups[] = { "uart0-data", "uart0-hwflow", };
|
||||
@ -808,7 +827,6 @@ static const char *jz4770_pwm5_groups[] = { "pwm5", };
|
||||
static const char *jz4770_pwm6_groups[] = { "pwm6", };
|
||||
static const char *jz4770_pwm7_groups[] = { "pwm7", };
|
||||
static const char *jz4770_mac_groups[] = { "mac-rmii", "mac-mii", };
|
||||
static const char *jz4770_otg_groups[] = { "otg-vbus", };
|
||||
|
||||
static const struct function_desc jz4770_functions[] = {
|
||||
{ "uart0", jz4770_uart0_groups, ARRAY_SIZE(jz4770_uart0_groups), },
|
||||
@ -841,7 +859,7 @@ static const struct function_desc jz4770_functions[] = {
|
||||
{ "pwm6", jz4770_pwm6_groups, ARRAY_SIZE(jz4770_pwm6_groups), },
|
||||
{ "pwm7", jz4770_pwm7_groups, ARRAY_SIZE(jz4770_pwm7_groups), },
|
||||
{ "mac", jz4770_mac_groups, ARRAY_SIZE(jz4770_mac_groups), },
|
||||
{ "otg", jz4770_otg_groups, ARRAY_SIZE(jz4770_otg_groups), },
|
||||
{ "otg", jz4760_otg_groups, ARRAY_SIZE(jz4760_otg_groups), },
|
||||
};
|
||||
|
||||
static const struct ingenic_chip_info jz4770_chip_info = {
|
||||
@ -2384,6 +2402,12 @@ static int __init ingenic_pinctrl_probe(struct platform_device *pdev)
|
||||
unsigned int i;
|
||||
int err;
|
||||
|
||||
chip_info = of_device_get_match_data(dev);
|
||||
if (!chip_info) {
|
||||
dev_err(dev, "Unsupported SoC\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
jzpc = devm_kzalloc(dev, sizeof(*jzpc), GFP_KERNEL);
|
||||
if (!jzpc)
|
||||
return -ENOMEM;
|
||||
@ -2400,7 +2424,7 @@ static int __init ingenic_pinctrl_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
jzpc->dev = dev;
|
||||
jzpc->info = chip_info = of_device_get_match_data(dev);
|
||||
jzpc->info = chip_info;
|
||||
|
||||
pctl_desc = devm_kzalloc(&pdev->dev, sizeof(*pctl_desc), GFP_KERNEL);
|
||||
if (!pctl_desc)
|
||||
@ -2470,17 +2494,47 @@ static int __init ingenic_pinctrl_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
static const struct of_device_id ingenic_pinctrl_of_match[] = {
|
||||
{ .compatible = "ingenic,jz4740-pinctrl", .data = &jz4740_chip_info },
|
||||
{ .compatible = "ingenic,jz4725b-pinctrl", .data = &jz4725b_chip_info },
|
||||
{ .compatible = "ingenic,jz4760-pinctrl", .data = &jz4760_chip_info },
|
||||
{ .compatible = "ingenic,jz4760b-pinctrl", .data = &jz4760_chip_info },
|
||||
{ .compatible = "ingenic,jz4770-pinctrl", .data = &jz4770_chip_info },
|
||||
{ .compatible = "ingenic,jz4780-pinctrl", .data = &jz4780_chip_info },
|
||||
{ .compatible = "ingenic,x1000-pinctrl", .data = &x1000_chip_info },
|
||||
{ .compatible = "ingenic,x1000e-pinctrl", .data = &x1000_chip_info },
|
||||
{ .compatible = "ingenic,x1500-pinctrl", .data = &x1500_chip_info },
|
||||
{ .compatible = "ingenic,x1830-pinctrl", .data = &x1830_chip_info },
|
||||
{},
|
||||
{
|
||||
.compatible = "ingenic,jz4740-pinctrl",
|
||||
.data = IF_ENABLED(CONFIG_MACH_JZ4740, &jz4740_chip_info)
|
||||
},
|
||||
{
|
||||
.compatible = "ingenic,jz4725b-pinctrl",
|
||||
.data = IF_ENABLED(CONFIG_MACH_JZ4725B, &jz4725b_chip_info)
|
||||
},
|
||||
{
|
||||
.compatible = "ingenic,jz4760-pinctrl",
|
||||
.data = IF_ENABLED(CONFIG_MACH_JZ4760, &jz4760_chip_info)
|
||||
},
|
||||
{
|
||||
.compatible = "ingenic,jz4760b-pinctrl",
|
||||
.data = IF_ENABLED(CONFIG_MACH_JZ4760, &jz4760_chip_info)
|
||||
},
|
||||
{
|
||||
.compatible = "ingenic,jz4770-pinctrl",
|
||||
.data = IF_ENABLED(CONFIG_MACH_JZ4770, &jz4770_chip_info)
|
||||
},
|
||||
{
|
||||
.compatible = "ingenic,jz4780-pinctrl",
|
||||
.data = IF_ENABLED(CONFIG_MACH_JZ4780, &jz4780_chip_info)
|
||||
},
|
||||
{
|
||||
.compatible = "ingenic,x1000-pinctrl",
|
||||
.data = IF_ENABLED(CONFIG_MACH_X1000, &x1000_chip_info)
|
||||
},
|
||||
{
|
||||
.compatible = "ingenic,x1000e-pinctrl",
|
||||
.data = IF_ENABLED(CONFIG_MACH_X1000, &x1000_chip_info)
|
||||
},
|
||||
{
|
||||
.compatible = "ingenic,x1500-pinctrl",
|
||||
.data = IF_ENABLED(CONFIG_MACH_X1500, &x1500_chip_info)
|
||||
},
|
||||
{
|
||||
.compatible = "ingenic,x1830-pinctrl",
|
||||
.data = IF_ENABLED(CONFIG_MACH_X1830, &x1830_chip_info)
|
||||
},
|
||||
{ /* sentinel */ },
|
||||
};
|
||||
|
||||
static struct platform_driver ingenic_pinctrl_driver = {
|
||||
|
@ -777,6 +777,7 @@ static int pcs_add_function(struct pcs_device *pcs,
|
||||
|
||||
function->vals = vals;
|
||||
function->nvals = nvals;
|
||||
function->name = name;
|
||||
|
||||
selector = pinmux_generic_add_function(pcs->pctl, name,
|
||||
pgnames, npgnames,
|
||||
|
@ -541,7 +541,6 @@ static void st_pinconf_set_retime_packed(struct st_pinctrl *info,
|
||||
st_regmap_field_bit_set_clear_pin(rt_p->delay_0, delay & 0x1, pin);
|
||||
/* 2 bit delay, msb */
|
||||
st_regmap_field_bit_set_clear_pin(rt_p->delay_1, delay & 0x2, pin);
|
||||
|
||||
}
|
||||
|
||||
static void st_pinconf_set_retime_dedicated(struct st_pinctrl *info,
|
||||
|
@ -443,7 +443,6 @@ static void sx150x_gpio_set(struct gpio_chip *chip, unsigned int offset,
|
||||
sx150x_gpio_oscio_set(pctl, value);
|
||||
else
|
||||
__sx150x_gpio_set(pctl, offset, value);
|
||||
|
||||
}
|
||||
|
||||
static void sx150x_gpio_set_multiple(struct gpio_chip *chip,
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -564,7 +564,7 @@ static int pinmux_functions_show(struct seq_file *s, void *what)
|
||||
continue;
|
||||
}
|
||||
|
||||
seq_printf(s, "function: %s, groups = [ ", func);
|
||||
seq_printf(s, "function %d: %s, groups = [ ", func_selector, func);
|
||||
for (i = 0; i < num_groups; i++)
|
||||
seq_printf(s, "%s ", groups[i]);
|
||||
seq_puts(s, "]\n");
|
||||
|
@ -220,6 +220,15 @@ config PINCTRL_SC7280
|
||||
Qualcomm Technologies Inc TLMM block found on the Qualcomm
|
||||
Technologies Inc SC7280 platform.
|
||||
|
||||
config PINCTRL_SC8180X
|
||||
tristate "Qualcomm Technologies Inc SC8180x pin controller driver"
|
||||
depends on GPIOLIB && OF
|
||||
select PINCTRL_MSM
|
||||
help
|
||||
This is the pinctrl, pinmux, pinconf and gpiolib driver for the
|
||||
Qualcomm Technologies Inc TLMM block found on the Qualcomm
|
||||
Technologies Inc SC8180x platform.
|
||||
|
||||
config PINCTRL_SDM660
|
||||
tristate "Qualcomm Technologies Inc SDM660 pin controller driver"
|
||||
depends on GPIOLIB && OF
|
||||
@ -265,6 +274,15 @@ config PINCTRL_SM8250
|
||||
Qualcomm Technologies Inc TLMM block found on the Qualcomm
|
||||
Technologies Inc SM8250 platform.
|
||||
|
||||
config PINCTRL_SM8350
|
||||
tristate "Qualcomm Technologies Inc SM8350 pin controller driver"
|
||||
depends on GPIOLIB && OF
|
||||
select PINCTRL_MSM
|
||||
help
|
||||
This is the pinctrl, pinmux, pinconf and gpiolib driver for the
|
||||
Qualcomm Technologies Inc TLMM block found on the Qualcomm
|
||||
Technologies Inc SM8350 platform.
|
||||
|
||||
config PINCTRL_LPASS_LPI
|
||||
tristate "Qualcomm Technologies Inc LPASS LPI pin controller driver"
|
||||
select PINMUX
|
||||
|
@ -26,9 +26,11 @@ obj-$(CONFIG_PINCTRL_QCOM_SSBI_PMIC) += pinctrl-ssbi-gpio.o
|
||||
obj-$(CONFIG_PINCTRL_QCOM_SSBI_PMIC) += pinctrl-ssbi-mpp.o
|
||||
obj-$(CONFIG_PINCTRL_SC7180) += pinctrl-sc7180.o
|
||||
obj-$(CONFIG_PINCTRL_SC7280) += pinctrl-sc7280.o
|
||||
obj-$(CONFIG_PINCTRL_SC8180X) += pinctrl-sc8180x.o
|
||||
obj-$(CONFIG_PINCTRL_SDM660) += pinctrl-sdm660.o
|
||||
obj-$(CONFIG_PINCTRL_SDM845) += pinctrl-sdm845.o
|
||||
obj-$(CONFIG_PINCTRL_SDX55) += pinctrl-sdx55.o
|
||||
obj-$(CONFIG_PINCTRL_SM8150) += pinctrl-sm8150.o
|
||||
obj-$(CONFIG_PINCTRL_SM8250) += pinctrl-sm8250.o
|
||||
obj-$(CONFIG_PINCTRL_SM8350) += pinctrl-sm8350.o
|
||||
obj-$(CONFIG_PINCTRL_LPASS_LPI) += pinctrl-lpass-lpi.o
|
||||
|
1624
drivers/pinctrl/qcom/pinctrl-sc8180x.c
Normal file
1624
drivers/pinctrl/qcom/pinctrl-sc8180x.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -1310,7 +1310,6 @@ static const struct msm_pinctrl_soc_data sdm845_pinctrl = {
|
||||
.ngpios = 151,
|
||||
.wakeirq_map = sdm845_pdc_map,
|
||||
.nwakeirq_map = ARRAY_SIZE(sdm845_pdc_map),
|
||||
|
||||
};
|
||||
|
||||
static const struct msm_pinctrl_soc_data sdm845_acpi_pinctrl = {
|
||||
|
1649
drivers/pinctrl/qcom/pinctrl-sm8350.c
Normal file
1649
drivers/pinctrl/qcom/pinctrl-sm8350.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -912,6 +912,7 @@ static int pmic_mpp_remove(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
static const struct of_device_id pmic_mpp_of_match[] = {
|
||||
{ .compatible = "qcom,pm8019-mpp" }, /* 6 MPP's */
|
||||
{ .compatible = "qcom,pm8841-mpp" }, /* 4 MPP's */
|
||||
{ .compatible = "qcom,pm8916-mpp" }, /* 4 MPP's */
|
||||
{ .compatible = "qcom,pm8941-mpp" }, /* 8 MPP's */
|
||||
|
@ -617,7 +617,6 @@ static void pm8xxx_mpp_dbg_show_one(struct seq_file *s,
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void pm8xxx_mpp_dbg_show(struct seq_file *s, struct gpio_chip *chip)
|
||||
|
@ -193,7 +193,6 @@ static struct rt2880_pmx_func gpio_func = {
|
||||
|
||||
static int rt2880_pinmux_index(struct rt2880_priv *p)
|
||||
{
|
||||
struct rt2880_pmx_func **f;
|
||||
struct rt2880_pmx_group *mux = p->groups;
|
||||
int i, j, c = 0;
|
||||
|
||||
@ -207,7 +206,7 @@ static int rt2880_pinmux_index(struct rt2880_priv *p)
|
||||
p->group_names = devm_kcalloc(p->dev, p->group_count,
|
||||
sizeof(char *), GFP_KERNEL);
|
||||
if (!p->group_names)
|
||||
return -1;
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < p->group_count; i++) {
|
||||
p->group_names[i] = p->groups[i].name;
|
||||
@ -218,31 +217,31 @@ static int rt2880_pinmux_index(struct rt2880_priv *p)
|
||||
p->func_count++;
|
||||
|
||||
/* allocate our function and group mapping index buffers */
|
||||
f = p->func = devm_kcalloc(p->dev,
|
||||
p->func_count,
|
||||
sizeof(*p->func),
|
||||
GFP_KERNEL);
|
||||
p->func = devm_kcalloc(p->dev, p->func_count,
|
||||
sizeof(*p->func), GFP_KERNEL);
|
||||
gpio_func.groups = devm_kcalloc(p->dev, p->group_count, sizeof(int),
|
||||
GFP_KERNEL);
|
||||
if (!f || !gpio_func.groups)
|
||||
return -1;
|
||||
if (!p->func || !gpio_func.groups)
|
||||
return -ENOMEM;
|
||||
|
||||
/* add a backpointer to the function so it knows its group */
|
||||
gpio_func.group_count = p->group_count;
|
||||
for (i = 0; i < gpio_func.group_count; i++)
|
||||
gpio_func.groups[i] = i;
|
||||
|
||||
f[c] = &gpio_func;
|
||||
p->func[c] = &gpio_func;
|
||||
c++;
|
||||
|
||||
/* add remaining functions */
|
||||
for (i = 0; i < p->group_count; i++) {
|
||||
for (j = 0; j < p->groups[i].func_count; j++) {
|
||||
f[c] = &p->groups[i].func[j];
|
||||
f[c]->groups = devm_kzalloc(p->dev, sizeof(int),
|
||||
p->func[c] = &p->groups[i].func[j];
|
||||
p->func[c]->groups = devm_kzalloc(p->dev, sizeof(int),
|
||||
GFP_KERNEL);
|
||||
f[c]->groups[0] = i;
|
||||
f[c]->group_count = 1;
|
||||
if (!p->func[c]->groups)
|
||||
return -ENOMEM;
|
||||
p->func[c]->groups[0] = i;
|
||||
p->func[c]->group_count = 1;
|
||||
c++;
|
||||
}
|
||||
}
|
||||
@ -280,10 +279,8 @@ static int rt2880_pinmux_pins(struct rt2880_priv *p)
|
||||
/* the pads needed to tell pinctrl about our pins */
|
||||
p->pads = devm_kcalloc(p->dev, p->max_pins,
|
||||
sizeof(struct pinctrl_pin_desc), GFP_KERNEL);
|
||||
if (!p->pads || !p->gpio) {
|
||||
dev_err(p->dev, "Failed to allocate gpio data\n");
|
||||
if (!p->pads || !p->gpio)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
memset(p->gpio, 1, sizeof(u8) * p->max_pins);
|
||||
for (i = 0; i < p->func_count; i++) {
|
||||
@ -318,6 +315,7 @@ static int rt2880_pinmux_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct rt2880_priv *p;
|
||||
struct pinctrl_dev *dev;
|
||||
int err;
|
||||
|
||||
if (!rt2880_pinmux_data)
|
||||
return -ENOTSUPP;
|
||||
@ -333,19 +331,20 @@ static int rt2880_pinmux_probe(struct platform_device *pdev)
|
||||
platform_set_drvdata(pdev, p);
|
||||
|
||||
/* init the device */
|
||||
if (rt2880_pinmux_index(p)) {
|
||||
err = rt2880_pinmux_index(p);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "failed to load index\n");
|
||||
return -EINVAL;
|
||||
return err;
|
||||
}
|
||||
if (rt2880_pinmux_pins(p)) {
|
||||
|
||||
err = rt2880_pinmux_pins(p);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "failed to load pins\n");
|
||||
return -EINVAL;
|
||||
return err;
|
||||
}
|
||||
dev = pinctrl_register(p->desc, &pdev->dev, p);
|
||||
if (IS_ERR(dev))
|
||||
return PTR_ERR(dev);
|
||||
|
||||
return 0;
|
||||
return PTR_ERR_OR_ZERO(dev);
|
||||
}
|
||||
|
||||
static const struct of_device_id rt2880_pinmux_match[] = {
|
||||
@ -362,7 +361,7 @@ static struct platform_driver rt2880_pinmux_driver = {
|
||||
},
|
||||
};
|
||||
|
||||
int __init rt2880_pinmux_init(void)
|
||||
static int __init rt2880_pinmux_init(void)
|
||||
{
|
||||
return platform_driver_register(&rt2880_pinmux_driver);
|
||||
}
|
||||
|
@ -36,6 +36,7 @@ config PINCTRL_RENESAS
|
||||
select PINCTRL_PFC_R8A77980 if ARCH_R8A77980
|
||||
select PINCTRL_PFC_R8A77990 if ARCH_R8A77990
|
||||
select PINCTRL_PFC_R8A77995 if ARCH_R8A77995
|
||||
select PINCTRL_PFC_R8A779A0 if ARCH_R8A779A0
|
||||
select PINCTRL_PFC_SH7203 if CPU_SUBTYPE_SH7203
|
||||
select PINCTRL_PFC_SH7264 if CPU_SUBTYPE_SH7264
|
||||
select PINCTRL_PFC_SH7269 if CPU_SUBTYPE_SH7269
|
||||
@ -142,6 +143,10 @@ config PINCTRL_PFC_R8A77970
|
||||
bool "pin control support for R-Car V3M" if COMPILE_TEST
|
||||
select PINCTRL_SH_PFC
|
||||
|
||||
config PINCTRL_PFC_R8A779A0
|
||||
bool "pin control support for R-Car V3U" 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
|
||||
|
@ -29,6 +29,7 @@ obj-$(CONFIG_PINCTRL_PFC_R8A77970) += pfc-r8a77970.o
|
||||
obj-$(CONFIG_PINCTRL_PFC_R8A77980) += pfc-r8a77980.o
|
||||
obj-$(CONFIG_PINCTRL_PFC_R8A77990) += pfc-r8a77990.o
|
||||
obj-$(CONFIG_PINCTRL_PFC_R8A77995) += pfc-r8a77995.o
|
||||
obj-$(CONFIG_PINCTRL_PFC_R8A779A0) += pfc-r8a779a0.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
|
||||
|
@ -175,13 +175,25 @@ u32 sh_pfc_read(struct sh_pfc *pfc, u32 reg)
|
||||
return sh_pfc_read_raw_reg(sh_pfc_phys_to_virt(pfc, reg), 32);
|
||||
}
|
||||
|
||||
static void sh_pfc_unlock_reg(struct sh_pfc *pfc, u32 reg, u32 data)
|
||||
{
|
||||
u32 unlock;
|
||||
|
||||
if (!pfc->info->unlock_reg)
|
||||
return;
|
||||
|
||||
if (pfc->info->unlock_reg >= 0x80000000UL)
|
||||
unlock = pfc->info->unlock_reg;
|
||||
else
|
||||
/* unlock_reg is a mask */
|
||||
unlock = reg & ~pfc->info->unlock_reg;
|
||||
|
||||
sh_pfc_write_raw_reg(sh_pfc_phys_to_virt(pfc, unlock), 32, ~data);
|
||||
}
|
||||
|
||||
void sh_pfc_write(struct sh_pfc *pfc, u32 reg, u32 data)
|
||||
{
|
||||
if (pfc->info->unlock_reg)
|
||||
sh_pfc_write_raw_reg(
|
||||
sh_pfc_phys_to_virt(pfc, pfc->info->unlock_reg), 32,
|
||||
~data);
|
||||
|
||||
sh_pfc_unlock_reg(pfc, reg, data);
|
||||
sh_pfc_write_raw_reg(sh_pfc_phys_to_virt(pfc, reg), 32, data);
|
||||
}
|
||||
|
||||
@ -227,11 +239,7 @@ static void sh_pfc_write_config_reg(struct sh_pfc *pfc,
|
||||
data &= mask;
|
||||
data |= value;
|
||||
|
||||
if (pfc->info->unlock_reg)
|
||||
sh_pfc_write_raw_reg(
|
||||
sh_pfc_phys_to_virt(pfc, pfc->info->unlock_reg), 32,
|
||||
~data);
|
||||
|
||||
sh_pfc_unlock_reg(pfc, crp->reg, data);
|
||||
sh_pfc_write_raw_reg(mapped_reg, crp->reg_width, data);
|
||||
}
|
||||
|
||||
@ -638,6 +646,12 @@ static const struct of_device_id sh_pfc_of_table[] = {
|
||||
.data = &r8a77995_pinmux_info,
|
||||
},
|
||||
#endif
|
||||
#ifdef CONFIG_PINCTRL_PFC_R8A779A0
|
||||
{
|
||||
.compatible = "renesas,pfc-r8a779a0",
|
||||
.data = &r8a779a0_pinmux_info,
|
||||
},
|
||||
#endif
|
||||
#ifdef CONFIG_PINCTRL_PFC_SH73A0
|
||||
{
|
||||
.compatible = "renesas,pfc-sh73a0",
|
||||
@ -1052,6 +1066,10 @@ static void __init sh_pfc_check_driver(const struct platform_driver *pdrv)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
if (!IS_ENABLED(CONFIG_SUPERH) &&
|
||||
!of_find_matching_node(NULL, pdrv->driver.of_match_table))
|
||||
return;
|
||||
|
||||
sh_pfc_regs = kcalloc(SH_PFC_MAX_REGS, sizeof(*sh_pfc_regs),
|
||||
GFP_KERNEL);
|
||||
if (!sh_pfc_regs)
|
||||
|
@ -1668,7 +1668,6 @@ static const unsigned int avb_mii_pins[] = {
|
||||
PIN_AVB_RX_CTL, PIN_AVB_RXC, PIN_AVB_RD0,
|
||||
PIN_AVB_RD1, PIN_AVB_RD2, PIN_AVB_RD3,
|
||||
PIN_AVB_TXCREFCLK,
|
||||
|
||||
};
|
||||
static const unsigned int avb_mii_mux[] = {
|
||||
AVB_TX_CTL_MARK, AVB_TXC_MARK, AVB_TD0_MARK,
|
||||
|
@ -1727,7 +1727,6 @@ static const unsigned int avb_mii_pins[] = {
|
||||
PIN_AVB_RX_CTL, PIN_AVB_RXC, PIN_AVB_RD0,
|
||||
PIN_AVB_RD1, PIN_AVB_RD2, PIN_AVB_RD3,
|
||||
PIN_AVB_TXCREFCLK,
|
||||
|
||||
};
|
||||
static const unsigned int avb_mii_mux[] = {
|
||||
AVB_TX_CTL_MARK, AVB_TXC_MARK, AVB_TD0_MARK,
|
||||
|
@ -1731,7 +1731,6 @@ static const unsigned int avb_mii_pins[] = {
|
||||
PIN_AVB_RX_CTL, PIN_AVB_RXC, PIN_AVB_RD0,
|
||||
PIN_AVB_RD1, PIN_AVB_RD2, PIN_AVB_RD3,
|
||||
PIN_AVB_TXCREFCLK,
|
||||
|
||||
};
|
||||
static const unsigned int avb_mii_mux[] = {
|
||||
AVB_TX_CTL_MARK, AVB_TXC_MARK, AVB_TD0_MARK,
|
||||
|
@ -1736,7 +1736,6 @@ static const unsigned int avb_mii_pins[] = {
|
||||
PIN_AVB_RX_CTL, PIN_AVB_RXC, PIN_AVB_RD0,
|
||||
PIN_AVB_RD1, PIN_AVB_RD2, PIN_AVB_RD3,
|
||||
PIN_AVB_TXCREFCLK,
|
||||
|
||||
};
|
||||
static const unsigned int avb_mii_mux[] = {
|
||||
AVB_TX_CTL_MARK, AVB_TXC_MARK, AVB_TD0_MARK,
|
||||
|
4460
drivers/pinctrl/renesas/pfc-r8a779a0.c
Normal file
4460
drivers/pinctrl/renesas/pfc-r8a779a0.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -634,6 +634,9 @@ static int sh_pfc_pinconf_get(struct pinctrl_dev *pctldev, unsigned _pin,
|
||||
}
|
||||
|
||||
case PIN_CONFIG_POWER_SOURCE: {
|
||||
int idx = sh_pfc_get_pin_index(pfc, _pin);
|
||||
const struct sh_pfc_pin *pin = &pfc->info->pins[idx];
|
||||
unsigned int lower_voltage;
|
||||
u32 pocctrl, val;
|
||||
int bit;
|
||||
|
||||
@ -648,7 +651,10 @@ static int sh_pfc_pinconf_get(struct pinctrl_dev *pctldev, unsigned _pin,
|
||||
val = sh_pfc_read(pfc, pocctrl);
|
||||
spin_unlock_irqrestore(&pfc->lock, flags);
|
||||
|
||||
arg = (val & BIT(bit)) ? 3300 : 1800;
|
||||
lower_voltage = (pin->configs & SH_PFC_PIN_VOLTAGE_25_33) ?
|
||||
2500 : 1800;
|
||||
|
||||
arg = (val & BIT(bit)) ? 3300 : lower_voltage;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -702,6 +708,9 @@ static int sh_pfc_pinconf_set(struct pinctrl_dev *pctldev, unsigned _pin,
|
||||
|
||||
case PIN_CONFIG_POWER_SOURCE: {
|
||||
unsigned int mV = pinconf_to_config_argument(configs[i]);
|
||||
int idx = sh_pfc_get_pin_index(pfc, _pin);
|
||||
const struct sh_pfc_pin *pin = &pfc->info->pins[idx];
|
||||
unsigned int lower_voltage;
|
||||
u32 pocctrl, val;
|
||||
int bit;
|
||||
|
||||
@ -712,7 +721,10 @@ static int sh_pfc_pinconf_set(struct pinctrl_dev *pctldev, unsigned _pin,
|
||||
if (WARN(bit < 0, "invalid pin %#x", _pin))
|
||||
return bit;
|
||||
|
||||
if (mV != 1800 && mV != 3300)
|
||||
lower_voltage = (pin->configs & SH_PFC_PIN_VOLTAGE_25_33) ?
|
||||
2500 : 1800;
|
||||
|
||||
if (mV != lower_voltage && mV != 3300)
|
||||
return -EINVAL;
|
||||
|
||||
spin_lock_irqsave(&pfc->lock, flags);
|
||||
|
@ -31,6 +31,15 @@ enum {
|
||||
SH_PFC_PIN_CFG_PULL_DOWN)
|
||||
#define SH_PFC_PIN_CFG_IO_VOLTAGE (1 << 4)
|
||||
#define SH_PFC_PIN_CFG_DRIVE_STRENGTH (1 << 5)
|
||||
|
||||
#define SH_PFC_PIN_VOLTAGE_18_33 (0 << 6)
|
||||
#define SH_PFC_PIN_VOLTAGE_25_33 (1 << 6)
|
||||
|
||||
#define SH_PFC_PIN_CFG_IO_VOLTAGE_18_33 (SH_PFC_PIN_CFG_IO_VOLTAGE | \
|
||||
SH_PFC_PIN_VOLTAGE_18_33)
|
||||
#define SH_PFC_PIN_CFG_IO_VOLTAGE_25_33 (SH_PFC_PIN_CFG_IO_VOLTAGE | \
|
||||
SH_PFC_PIN_VOLTAGE_25_33)
|
||||
|
||||
#define SH_PFC_PIN_CFG_NO_GPIO (1 << 31)
|
||||
|
||||
struct sh_pfc_pin {
|
||||
@ -300,7 +309,7 @@ struct sh_pfc_soc_info {
|
||||
const u16 *pinmux_data;
|
||||
unsigned int pinmux_data_size;
|
||||
|
||||
u32 unlock_reg;
|
||||
u32 unlock_reg; /* can be literal address or mask */
|
||||
};
|
||||
|
||||
extern const struct sh_pfc_soc_info emev2_pinmux_info;
|
||||
@ -331,6 +340,7 @@ extern const struct sh_pfc_soc_info r8a77970_pinmux_info;
|
||||
extern const struct sh_pfc_soc_info r8a77980_pinmux_info;
|
||||
extern const struct sh_pfc_soc_info r8a77990_pinmux_info;
|
||||
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 sh7203_pinmux_info;
|
||||
extern const struct sh_pfc_soc_info sh7264_pinmux_info;
|
||||
extern const struct sh_pfc_soc_info sh7269_pinmux_info;
|
||||
@ -451,9 +461,13 @@ extern const struct sh_pfc_soc_info shx3_pinmux_info;
|
||||
fn(bank, pin, GP_##bank##_##pin, sfx, cfg)
|
||||
#define PORT_GP_1(bank, pin, fn, sfx) PORT_GP_CFG_1(bank, pin, fn, sfx, 0)
|
||||
|
||||
#define PORT_GP_CFG_4(bank, fn, sfx, cfg) \
|
||||
#define PORT_GP_CFG_2(bank, fn, sfx, cfg) \
|
||||
PORT_GP_CFG_1(bank, 0, fn, sfx, cfg), \
|
||||
PORT_GP_CFG_1(bank, 1, fn, sfx, cfg), \
|
||||
PORT_GP_CFG_1(bank, 1, fn, sfx, cfg)
|
||||
#define PORT_GP_2(bank, fn, sfx) PORT_GP_CFG_2(bank, fn, sfx, 0)
|
||||
|
||||
#define PORT_GP_CFG_4(bank, fn, sfx, cfg) \
|
||||
PORT_GP_CFG_2(bank, fn, sfx, cfg), \
|
||||
PORT_GP_CFG_1(bank, 2, fn, sfx, cfg), \
|
||||
PORT_GP_CFG_1(bank, 3, fn, sfx, cfg)
|
||||
#define PORT_GP_4(bank, fn, sfx) PORT_GP_CFG_4(bank, fn, sfx, 0)
|
||||
@ -572,9 +586,13 @@ extern const struct sh_pfc_soc_info shx3_pinmux_info;
|
||||
PORT_GP_CFG_1(bank, 29, fn, sfx, cfg)
|
||||
#define PORT_GP_30(bank, fn, sfx) PORT_GP_CFG_30(bank, fn, sfx, 0)
|
||||
|
||||
#define PORT_GP_CFG_32(bank, fn, sfx, cfg) \
|
||||
#define PORT_GP_CFG_31(bank, fn, sfx, cfg) \
|
||||
PORT_GP_CFG_30(bank, fn, sfx, cfg), \
|
||||
PORT_GP_CFG_1(bank, 30, fn, sfx, cfg), \
|
||||
PORT_GP_CFG_1(bank, 30, fn, sfx, cfg)
|
||||
#define PORT_GP_31(bank, fn, sfx) PORT_GP_CFG_31(bank, fn, sfx, 0)
|
||||
|
||||
#define PORT_GP_CFG_32(bank, fn, sfx, cfg) \
|
||||
PORT_GP_CFG_31(bank, fn, sfx, cfg), \
|
||||
PORT_GP_CFG_1(bank, 31, fn, sfx, cfg)
|
||||
#define PORT_GP_32(bank, fn, sfx) PORT_GP_CFG_32(bank, fn, sfx, 0)
|
||||
|
||||
|
@ -58,13 +58,13 @@ static void exynos_irq_mask(struct irq_data *irqd)
|
||||
unsigned long mask;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&bank->slock, flags);
|
||||
raw_spin_lock_irqsave(&bank->slock, flags);
|
||||
|
||||
mask = readl(bank->eint_base + reg_mask);
|
||||
mask |= 1 << irqd->hwirq;
|
||||
writel(mask, bank->eint_base + reg_mask);
|
||||
|
||||
spin_unlock_irqrestore(&bank->slock, flags);
|
||||
raw_spin_unlock_irqrestore(&bank->slock, flags);
|
||||
}
|
||||
|
||||
static void exynos_irq_ack(struct irq_data *irqd)
|
||||
@ -97,13 +97,13 @@ static void exynos_irq_unmask(struct irq_data *irqd)
|
||||
if (irqd_get_trigger_type(irqd) & IRQ_TYPE_LEVEL_MASK)
|
||||
exynos_irq_ack(irqd);
|
||||
|
||||
spin_lock_irqsave(&bank->slock, flags);
|
||||
raw_spin_lock_irqsave(&bank->slock, flags);
|
||||
|
||||
mask = readl(bank->eint_base + reg_mask);
|
||||
mask &= ~(1 << irqd->hwirq);
|
||||
writel(mask, bank->eint_base + reg_mask);
|
||||
|
||||
spin_unlock_irqrestore(&bank->slock, flags);
|
||||
raw_spin_unlock_irqrestore(&bank->slock, flags);
|
||||
}
|
||||
|
||||
static int exynos_irq_set_type(struct irq_data *irqd, unsigned int type)
|
||||
@ -169,14 +169,14 @@ static int exynos_irq_request_resources(struct irq_data *irqd)
|
||||
shift = irqd->hwirq * bank_type->fld_width[PINCFG_TYPE_FUNC];
|
||||
mask = (1 << bank_type->fld_width[PINCFG_TYPE_FUNC]) - 1;
|
||||
|
||||
spin_lock_irqsave(&bank->slock, flags);
|
||||
raw_spin_lock_irqsave(&bank->slock, flags);
|
||||
|
||||
con = readl(bank->pctl_base + reg_con);
|
||||
con &= ~(mask << shift);
|
||||
con |= EXYNOS_PIN_FUNC_EINT << shift;
|
||||
writel(con, bank->pctl_base + reg_con);
|
||||
|
||||
spin_unlock_irqrestore(&bank->slock, flags);
|
||||
raw_spin_unlock_irqrestore(&bank->slock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -192,14 +192,14 @@ static void exynos_irq_release_resources(struct irq_data *irqd)
|
||||
shift = irqd->hwirq * bank_type->fld_width[PINCFG_TYPE_FUNC];
|
||||
mask = (1 << bank_type->fld_width[PINCFG_TYPE_FUNC]) - 1;
|
||||
|
||||
spin_lock_irqsave(&bank->slock, flags);
|
||||
raw_spin_lock_irqsave(&bank->slock, flags);
|
||||
|
||||
con = readl(bank->pctl_base + reg_con);
|
||||
con &= ~(mask << shift);
|
||||
con |= EXYNOS_PIN_FUNC_INPUT << shift;
|
||||
writel(con, bank->pctl_base + reg_con);
|
||||
|
||||
spin_unlock_irqrestore(&bank->slock, flags);
|
||||
raw_spin_unlock_irqrestore(&bank->slock, flags);
|
||||
|
||||
gpiochip_unlock_as_irq(&bank->gpio_chip, irqd->hwirq);
|
||||
}
|
||||
|
@ -145,14 +145,14 @@ static void s3c24xx_eint_set_function(struct samsung_pinctrl_drv_data *d,
|
||||
shift = pin * bank_type->fld_width[PINCFG_TYPE_FUNC];
|
||||
mask = (1 << bank_type->fld_width[PINCFG_TYPE_FUNC]) - 1;
|
||||
|
||||
spin_lock_irqsave(&bank->slock, flags);
|
||||
raw_spin_lock_irqsave(&bank->slock, flags);
|
||||
|
||||
val = readl(reg);
|
||||
val &= ~(mask << shift);
|
||||
val |= bank->eint_func << shift;
|
||||
writel(val, reg);
|
||||
|
||||
spin_unlock_irqrestore(&bank->slock, flags);
|
||||
raw_spin_unlock_irqrestore(&bank->slock, flags);
|
||||
}
|
||||
|
||||
static int s3c24xx_eint_type(struct irq_data *data, unsigned int type)
|
||||
|
@ -286,14 +286,14 @@ static void s3c64xx_irq_set_function(struct samsung_pinctrl_drv_data *d,
|
||||
shift = shift * bank_type->fld_width[PINCFG_TYPE_FUNC];
|
||||
mask = (1 << bank_type->fld_width[PINCFG_TYPE_FUNC]) - 1;
|
||||
|
||||
spin_lock_irqsave(&bank->slock, flags);
|
||||
raw_spin_lock_irqsave(&bank->slock, flags);
|
||||
|
||||
val = readl(reg);
|
||||
val &= ~(mask << shift);
|
||||
val |= bank->eint_func << shift;
|
||||
writel(val, reg);
|
||||
|
||||
spin_unlock_irqrestore(&bank->slock, flags);
|
||||
raw_spin_unlock_irqrestore(&bank->slock, flags);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -400,14 +400,14 @@ static void samsung_pinmux_setup(struct pinctrl_dev *pctldev, unsigned selector,
|
||||
reg += 4;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&bank->slock, flags);
|
||||
raw_spin_lock_irqsave(&bank->slock, flags);
|
||||
|
||||
data = readl(reg + type->reg_offset[PINCFG_TYPE_FUNC]);
|
||||
data &= ~(mask << shift);
|
||||
data |= func->val << shift;
|
||||
writel(data, reg + type->reg_offset[PINCFG_TYPE_FUNC]);
|
||||
|
||||
spin_unlock_irqrestore(&bank->slock, flags);
|
||||
raw_spin_unlock_irqrestore(&bank->slock, flags);
|
||||
}
|
||||
|
||||
/* enable a specified pinmux by writing to registers */
|
||||
@ -451,7 +451,7 @@ static int samsung_pinconf_rw(struct pinctrl_dev *pctldev, unsigned int pin,
|
||||
width = type->fld_width[cfg_type];
|
||||
cfg_reg = type->reg_offset[cfg_type];
|
||||
|
||||
spin_lock_irqsave(&bank->slock, flags);
|
||||
raw_spin_lock_irqsave(&bank->slock, flags);
|
||||
|
||||
mask = (1 << width) - 1;
|
||||
shift = pin_offset * width;
|
||||
@ -468,7 +468,7 @@ static int samsung_pinconf_rw(struct pinctrl_dev *pctldev, unsigned int pin,
|
||||
*config = PINCFG_PACK(cfg_type, data);
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&bank->slock, flags);
|
||||
raw_spin_unlock_irqrestore(&bank->slock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -561,9 +561,9 @@ static void samsung_gpio_set(struct gpio_chip *gc, unsigned offset, int value)
|
||||
struct samsung_pin_bank *bank = gpiochip_get_data(gc);
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&bank->slock, flags);
|
||||
raw_spin_lock_irqsave(&bank->slock, flags);
|
||||
samsung_gpio_set_value(gc, offset, value);
|
||||
spin_unlock_irqrestore(&bank->slock, flags);
|
||||
raw_spin_unlock_irqrestore(&bank->slock, flags);
|
||||
}
|
||||
|
||||
/* gpiolib gpio_get callback function */
|
||||
@ -626,9 +626,9 @@ static int samsung_gpio_direction_input(struct gpio_chip *gc, unsigned offset)
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
|
||||
spin_lock_irqsave(&bank->slock, flags);
|
||||
raw_spin_lock_irqsave(&bank->slock, flags);
|
||||
ret = samsung_gpio_set_direction(gc, offset, true);
|
||||
spin_unlock_irqrestore(&bank->slock, flags);
|
||||
raw_spin_unlock_irqrestore(&bank->slock, flags);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -640,10 +640,10 @@ static int samsung_gpio_direction_output(struct gpio_chip *gc, unsigned offset,
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
|
||||
spin_lock_irqsave(&bank->slock, flags);
|
||||
raw_spin_lock_irqsave(&bank->slock, flags);
|
||||
samsung_gpio_set_value(gc, offset, value);
|
||||
ret = samsung_gpio_set_direction(gc, offset, false);
|
||||
spin_unlock_irqrestore(&bank->slock, flags);
|
||||
raw_spin_unlock_irqrestore(&bank->slock, flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -1057,7 +1057,7 @@ samsung_pinctrl_get_soc_data(struct samsung_pinctrl_drv_data *d,
|
||||
bank->eint_offset = bdata->eint_offset;
|
||||
bank->name = bdata->name;
|
||||
|
||||
spin_lock_init(&bank->slock);
|
||||
raw_spin_lock_init(&bank->slock);
|
||||
bank->drvdata = d;
|
||||
bank->pin_base = d->nr_pins;
|
||||
d->nr_pins += bank->nr_pins;
|
||||
|
@ -171,7 +171,7 @@ struct samsung_pin_bank {
|
||||
struct gpio_chip gpio_chip;
|
||||
struct pinctrl_gpio_range grange;
|
||||
struct exynos_irq_chip *irq_chip;
|
||||
spinlock_t slock;
|
||||
raw_spinlock_t slock;
|
||||
|
||||
u32 pm_save[PINCFG_TYPE_NUM + 1]; /* +1 to handle double CON registers*/
|
||||
};
|
||||
|
@ -1,7 +0,0 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
# CSR SiRFsoc pinmux support
|
||||
|
||||
obj-y += pinctrl-sirf.o
|
||||
obj-y += pinctrl-prima2.o
|
||||
obj-y += pinctrl-atlas6.o
|
||||
obj-y += pinctrl-atlas7.o
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,894 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* pinmux driver for CSR SiRFprimaII
|
||||
*
|
||||
* Authors:
|
||||
* Rongjun Ying <rongjun.ying@csr.com>
|
||||
* Yuping Luo <yuping.luo@csr.com>
|
||||
* Barry Song <baohua.song@csr.com>
|
||||
*
|
||||
* Copyright (c) 2011 - 2014 Cambridge Silicon Radio Limited, a CSR plc group
|
||||
* company.
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/pinctrl/pinctrl.h>
|
||||
#include <linux/pinctrl/pinmux.h>
|
||||
#include <linux/pinctrl/consumer.h>
|
||||
#include <linux/pinctrl/machine.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/gpio/driver.h>
|
||||
#include <linux/of_gpio.h>
|
||||
|
||||
#include "pinctrl-sirf.h"
|
||||
|
||||
#define DRIVER_NAME "pinmux-sirf"
|
||||
|
||||
struct sirfsoc_gpio_bank {
|
||||
int id;
|
||||
int parent_irq;
|
||||
spinlock_t lock;
|
||||
};
|
||||
|
||||
struct sirfsoc_gpio_chip {
|
||||
struct of_mm_gpio_chip chip;
|
||||
struct sirfsoc_gpio_bank sgpio_bank[SIRFSOC_GPIO_NO_OF_BANKS];
|
||||
spinlock_t lock;
|
||||
};
|
||||
|
||||
static struct sirfsoc_pin_group *sirfsoc_pin_groups;
|
||||
static int sirfsoc_pingrp_cnt;
|
||||
|
||||
static int sirfsoc_get_groups_count(struct pinctrl_dev *pctldev)
|
||||
{
|
||||
return sirfsoc_pingrp_cnt;
|
||||
}
|
||||
|
||||
static const char *sirfsoc_get_group_name(struct pinctrl_dev *pctldev,
|
||||
unsigned selector)
|
||||
{
|
||||
return sirfsoc_pin_groups[selector].name;
|
||||
}
|
||||
|
||||
static int sirfsoc_get_group_pins(struct pinctrl_dev *pctldev,
|
||||
unsigned selector,
|
||||
const unsigned **pins,
|
||||
unsigned *num_pins)
|
||||
{
|
||||
*pins = sirfsoc_pin_groups[selector].pins;
|
||||
*num_pins = sirfsoc_pin_groups[selector].num_pins;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void sirfsoc_pin_dbg_show(struct pinctrl_dev *pctldev,
|
||||
struct seq_file *s, unsigned offset)
|
||||
{
|
||||
seq_printf(s, " " DRIVER_NAME);
|
||||
}
|
||||
|
||||
static int sirfsoc_dt_node_to_map(struct pinctrl_dev *pctldev,
|
||||
struct device_node *np_config,
|
||||
struct pinctrl_map **map, unsigned *num_maps)
|
||||
{
|
||||
struct sirfsoc_pmx *spmx = pinctrl_dev_get_drvdata(pctldev);
|
||||
struct device_node *np;
|
||||
struct property *prop;
|
||||
const char *function, *group;
|
||||
int ret, index = 0, count = 0;
|
||||
|
||||
/* calculate number of maps required */
|
||||
for_each_child_of_node(np_config, np) {
|
||||
ret = of_property_read_string(np, "sirf,function", &function);
|
||||
if (ret < 0) {
|
||||
of_node_put(np);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = of_property_count_strings(np, "sirf,pins");
|
||||
if (ret < 0) {
|
||||
of_node_put(np);
|
||||
return ret;
|
||||
}
|
||||
|
||||
count += ret;
|
||||
}
|
||||
|
||||
if (!count) {
|
||||
dev_err(spmx->dev, "No child nodes passed via DT\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
*map = kcalloc(count, sizeof(**map), GFP_KERNEL);
|
||||
if (!*map)
|
||||
return -ENOMEM;
|
||||
|
||||
for_each_child_of_node(np_config, np) {
|
||||
of_property_read_string(np, "sirf,function", &function);
|
||||
of_property_for_each_string(np, "sirf,pins", prop, group) {
|
||||
(*map)[index].type = PIN_MAP_TYPE_MUX_GROUP;
|
||||
(*map)[index].data.mux.group = group;
|
||||
(*map)[index].data.mux.function = function;
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
*num_maps = count;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void sirfsoc_dt_free_map(struct pinctrl_dev *pctldev,
|
||||
struct pinctrl_map *map, unsigned num_maps)
|
||||
{
|
||||
kfree(map);
|
||||
}
|
||||
|
||||
static const struct pinctrl_ops sirfsoc_pctrl_ops = {
|
||||
.get_groups_count = sirfsoc_get_groups_count,
|
||||
.get_group_name = sirfsoc_get_group_name,
|
||||
.get_group_pins = sirfsoc_get_group_pins,
|
||||
.pin_dbg_show = sirfsoc_pin_dbg_show,
|
||||
.dt_node_to_map = sirfsoc_dt_node_to_map,
|
||||
.dt_free_map = sirfsoc_dt_free_map,
|
||||
};
|
||||
|
||||
static struct sirfsoc_pmx_func *sirfsoc_pmx_functions;
|
||||
static int sirfsoc_pmxfunc_cnt;
|
||||
|
||||
static void sirfsoc_pinmux_endisable(struct sirfsoc_pmx *spmx,
|
||||
unsigned selector, bool enable)
|
||||
{
|
||||
int i;
|
||||
const struct sirfsoc_padmux *mux =
|
||||
sirfsoc_pmx_functions[selector].padmux;
|
||||
const struct sirfsoc_muxmask *mask = mux->muxmask;
|
||||
|
||||
for (i = 0; i < mux->muxmask_counts; i++) {
|
||||
u32 muxval;
|
||||
muxval = readl(spmx->gpio_virtbase +
|
||||
SIRFSOC_GPIO_PAD_EN(mask[i].group));
|
||||
if (enable)
|
||||
muxval = muxval & ~mask[i].mask;
|
||||
else
|
||||
muxval = muxval | mask[i].mask;
|
||||
writel(muxval, spmx->gpio_virtbase +
|
||||
SIRFSOC_GPIO_PAD_EN(mask[i].group));
|
||||
}
|
||||
|
||||
if (mux->funcmask && enable) {
|
||||
u32 func_en_val;
|
||||
|
||||
func_en_val =
|
||||
readl(spmx->rsc_virtbase + mux->ctrlreg);
|
||||
func_en_val =
|
||||
(func_en_val & ~mux->funcmask) | (mux->funcval);
|
||||
writel(func_en_val, spmx->rsc_virtbase + mux->ctrlreg);
|
||||
}
|
||||
}
|
||||
|
||||
static int sirfsoc_pinmux_set_mux(struct pinctrl_dev *pmxdev,
|
||||
unsigned selector,
|
||||
unsigned group)
|
||||
{
|
||||
struct sirfsoc_pmx *spmx;
|
||||
|
||||
spmx = pinctrl_dev_get_drvdata(pmxdev);
|
||||
sirfsoc_pinmux_endisable(spmx, selector, true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sirfsoc_pinmux_get_funcs_count(struct pinctrl_dev *pmxdev)
|
||||
{
|
||||
return sirfsoc_pmxfunc_cnt;
|
||||
}
|
||||
|
||||
static const char *sirfsoc_pinmux_get_func_name(struct pinctrl_dev *pctldev,
|
||||
unsigned selector)
|
||||
{
|
||||
return sirfsoc_pmx_functions[selector].name;
|
||||
}
|
||||
|
||||
static int sirfsoc_pinmux_get_groups(struct pinctrl_dev *pctldev,
|
||||
unsigned selector,
|
||||
const char * const **groups,
|
||||
unsigned * const num_groups)
|
||||
{
|
||||
*groups = sirfsoc_pmx_functions[selector].groups;
|
||||
*num_groups = sirfsoc_pmx_functions[selector].num_groups;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sirfsoc_pinmux_request_gpio(struct pinctrl_dev *pmxdev,
|
||||
struct pinctrl_gpio_range *range, unsigned offset)
|
||||
{
|
||||
struct sirfsoc_pmx *spmx;
|
||||
|
||||
int group = range->id;
|
||||
|
||||
u32 muxval;
|
||||
|
||||
spmx = pinctrl_dev_get_drvdata(pmxdev);
|
||||
|
||||
muxval = readl(spmx->gpio_virtbase +
|
||||
SIRFSOC_GPIO_PAD_EN(group));
|
||||
muxval = muxval | (1 << (offset - range->pin_base));
|
||||
writel(muxval, spmx->gpio_virtbase +
|
||||
SIRFSOC_GPIO_PAD_EN(group));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct pinmux_ops sirfsoc_pinmux_ops = {
|
||||
.set_mux = sirfsoc_pinmux_set_mux,
|
||||
.get_functions_count = sirfsoc_pinmux_get_funcs_count,
|
||||
.get_function_name = sirfsoc_pinmux_get_func_name,
|
||||
.get_function_groups = sirfsoc_pinmux_get_groups,
|
||||
.gpio_request_enable = sirfsoc_pinmux_request_gpio,
|
||||
};
|
||||
|
||||
static struct pinctrl_desc sirfsoc_pinmux_desc = {
|
||||
.name = DRIVER_NAME,
|
||||
.pctlops = &sirfsoc_pctrl_ops,
|
||||
.pmxops = &sirfsoc_pinmux_ops,
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
static void __iomem *sirfsoc_rsc_of_iomap(void)
|
||||
{
|
||||
const struct of_device_id rsc_ids[] = {
|
||||
{ .compatible = "sirf,prima2-rsc" },
|
||||
{}
|
||||
};
|
||||
struct device_node *np;
|
||||
|
||||
np = of_find_matching_node(NULL, rsc_ids);
|
||||
if (!np)
|
||||
panic("unable to find compatible rsc node in dtb\n");
|
||||
|
||||
return of_iomap(np, 0);
|
||||
}
|
||||
|
||||
static int sirfsoc_gpio_of_xlate(struct gpio_chip *gc,
|
||||
const struct of_phandle_args *gpiospec,
|
||||
u32 *flags)
|
||||
{
|
||||
if (gpiospec->args[0] > SIRFSOC_GPIO_NO_OF_BANKS * SIRFSOC_GPIO_BANK_SIZE)
|
||||
return -EINVAL;
|
||||
|
||||
if (flags)
|
||||
*flags = gpiospec->args[1];
|
||||
|
||||
return gpiospec->args[0];
|
||||
}
|
||||
|
||||
static const struct of_device_id pinmux_ids[] = {
|
||||
{ .compatible = "sirf,prima2-pinctrl", .data = &prima2_pinctrl_data, },
|
||||
{ .compatible = "sirf,atlas6-pinctrl", .data = &atlas6_pinctrl_data, },
|
||||
{}
|
||||
};
|
||||
|
||||
static int sirfsoc_pinmux_probe(struct platform_device *pdev)
|
||||
{
|
||||
int ret;
|
||||
struct sirfsoc_pmx *spmx;
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
const struct sirfsoc_pinctrl_data *pdata;
|
||||
|
||||
/* Create state holders etc for this driver */
|
||||
spmx = devm_kzalloc(&pdev->dev, sizeof(*spmx), GFP_KERNEL);
|
||||
if (!spmx)
|
||||
return -ENOMEM;
|
||||
|
||||
spmx->dev = &pdev->dev;
|
||||
|
||||
platform_set_drvdata(pdev, spmx);
|
||||
|
||||
spmx->gpio_virtbase = of_iomap(np, 0);
|
||||
if (!spmx->gpio_virtbase) {
|
||||
dev_err(&pdev->dev, "can't map gpio registers\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
spmx->rsc_virtbase = sirfsoc_rsc_of_iomap();
|
||||
if (!spmx->rsc_virtbase) {
|
||||
ret = -ENOMEM;
|
||||
dev_err(&pdev->dev, "can't map rsc registers\n");
|
||||
goto out_no_rsc_remap;
|
||||
}
|
||||
|
||||
pdata = of_match_node(pinmux_ids, np)->data;
|
||||
sirfsoc_pin_groups = pdata->grps;
|
||||
sirfsoc_pingrp_cnt = pdata->grps_cnt;
|
||||
sirfsoc_pmx_functions = pdata->funcs;
|
||||
sirfsoc_pmxfunc_cnt = pdata->funcs_cnt;
|
||||
sirfsoc_pinmux_desc.pins = pdata->pads;
|
||||
sirfsoc_pinmux_desc.npins = pdata->pads_cnt;
|
||||
|
||||
|
||||
/* Now register the pin controller and all pins it handles */
|
||||
spmx->pmx = pinctrl_register(&sirfsoc_pinmux_desc, &pdev->dev, spmx);
|
||||
if (IS_ERR(spmx->pmx)) {
|
||||
dev_err(&pdev->dev, "could not register SIRFSOC pinmux driver\n");
|
||||
ret = PTR_ERR(spmx->pmx);
|
||||
goto out_no_pmx;
|
||||
}
|
||||
|
||||
dev_info(&pdev->dev, "initialized SIRFSOC pinmux driver\n");
|
||||
|
||||
return 0;
|
||||
|
||||
out_no_pmx:
|
||||
iounmap(spmx->rsc_virtbase);
|
||||
out_no_rsc_remap:
|
||||
iounmap(spmx->gpio_virtbase);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int sirfsoc_pinmux_suspend_noirq(struct device *dev)
|
||||
{
|
||||
int i, j;
|
||||
struct sirfsoc_pmx *spmx = dev_get_drvdata(dev);
|
||||
|
||||
for (i = 0; i < SIRFSOC_GPIO_NO_OF_BANKS; i++) {
|
||||
for (j = 0; j < SIRFSOC_GPIO_BANK_SIZE; j++) {
|
||||
spmx->gpio_regs[i][j] = readl(spmx->gpio_virtbase +
|
||||
SIRFSOC_GPIO_CTRL(i, j));
|
||||
}
|
||||
spmx->ints_regs[i] = readl(spmx->gpio_virtbase +
|
||||
SIRFSOC_GPIO_INT_STATUS(i));
|
||||
spmx->paden_regs[i] = readl(spmx->gpio_virtbase +
|
||||
SIRFSOC_GPIO_PAD_EN(i));
|
||||
}
|
||||
spmx->dspen_regs = readl(spmx->gpio_virtbase + SIRFSOC_GPIO_DSP_EN0);
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
spmx->rsc_regs[i] = readl(spmx->rsc_virtbase + 4 * i);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sirfsoc_pinmux_resume_noirq(struct device *dev)
|
||||
{
|
||||
int i, j;
|
||||
struct sirfsoc_pmx *spmx = dev_get_drvdata(dev);
|
||||
|
||||
for (i = 0; i < SIRFSOC_GPIO_NO_OF_BANKS; i++) {
|
||||
for (j = 0; j < SIRFSOC_GPIO_BANK_SIZE; j++) {
|
||||
writel(spmx->gpio_regs[i][j], spmx->gpio_virtbase +
|
||||
SIRFSOC_GPIO_CTRL(i, j));
|
||||
}
|
||||
writel(spmx->ints_regs[i], spmx->gpio_virtbase +
|
||||
SIRFSOC_GPIO_INT_STATUS(i));
|
||||
writel(spmx->paden_regs[i], spmx->gpio_virtbase +
|
||||
SIRFSOC_GPIO_PAD_EN(i));
|
||||
}
|
||||
writel(spmx->dspen_regs, spmx->gpio_virtbase + SIRFSOC_GPIO_DSP_EN0);
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
writel(spmx->rsc_regs[i], spmx->rsc_virtbase + 4 * i);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops sirfsoc_pinmux_pm_ops = {
|
||||
.suspend_noirq = sirfsoc_pinmux_suspend_noirq,
|
||||
.resume_noirq = sirfsoc_pinmux_resume_noirq,
|
||||
.freeze_noirq = sirfsoc_pinmux_suspend_noirq,
|
||||
.restore_noirq = sirfsoc_pinmux_resume_noirq,
|
||||
};
|
||||
#endif
|
||||
|
||||
static struct platform_driver sirfsoc_pinmux_driver = {
|
||||
.driver = {
|
||||
.name = DRIVER_NAME,
|
||||
.of_match_table = pinmux_ids,
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
.pm = &sirfsoc_pinmux_pm_ops,
|
||||
#endif
|
||||
},
|
||||
.probe = sirfsoc_pinmux_probe,
|
||||
};
|
||||
|
||||
static int __init sirfsoc_pinmux_init(void)
|
||||
{
|
||||
return platform_driver_register(&sirfsoc_pinmux_driver);
|
||||
}
|
||||
arch_initcall(sirfsoc_pinmux_init);
|
||||
|
||||
static inline struct sirfsoc_gpio_bank *
|
||||
sirfsoc_gpio_to_bank(struct sirfsoc_gpio_chip *sgpio, unsigned int offset)
|
||||
{
|
||||
return &sgpio->sgpio_bank[offset / SIRFSOC_GPIO_BANK_SIZE];
|
||||
}
|
||||
|
||||
static inline int sirfsoc_gpio_to_bankoff(unsigned int offset)
|
||||
{
|
||||
return offset % SIRFSOC_GPIO_BANK_SIZE;
|
||||
}
|
||||
|
||||
static void sirfsoc_gpio_irq_ack(struct irq_data *d)
|
||||
{
|
||||
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
|
||||
struct sirfsoc_gpio_chip *sgpio = gpiochip_get_data(gc);
|
||||
struct sirfsoc_gpio_bank *bank = sirfsoc_gpio_to_bank(sgpio, d->hwirq);
|
||||
int idx = sirfsoc_gpio_to_bankoff(d->hwirq);
|
||||
u32 val, offset;
|
||||
unsigned long flags;
|
||||
|
||||
offset = SIRFSOC_GPIO_CTRL(bank->id, idx);
|
||||
|
||||
spin_lock_irqsave(&sgpio->lock, flags);
|
||||
|
||||
val = readl(sgpio->chip.regs + offset);
|
||||
|
||||
writel(val, sgpio->chip.regs + offset);
|
||||
|
||||
spin_unlock_irqrestore(&sgpio->lock, flags);
|
||||
}
|
||||
|
||||
static void __sirfsoc_gpio_irq_mask(struct sirfsoc_gpio_chip *sgpio,
|
||||
struct sirfsoc_gpio_bank *bank,
|
||||
int idx)
|
||||
{
|
||||
u32 val, offset;
|
||||
unsigned long flags;
|
||||
|
||||
offset = SIRFSOC_GPIO_CTRL(bank->id, idx);
|
||||
|
||||
spin_lock_irqsave(&sgpio->lock, flags);
|
||||
|
||||
val = readl(sgpio->chip.regs + offset);
|
||||
val &= ~SIRFSOC_GPIO_CTL_INTR_EN_MASK;
|
||||
val &= ~SIRFSOC_GPIO_CTL_INTR_STS_MASK;
|
||||
writel(val, sgpio->chip.regs + offset);
|
||||
|
||||
spin_unlock_irqrestore(&sgpio->lock, flags);
|
||||
}
|
||||
|
||||
static void sirfsoc_gpio_irq_mask(struct irq_data *d)
|
||||
{
|
||||
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
|
||||
struct sirfsoc_gpio_chip *sgpio = gpiochip_get_data(gc);
|
||||
struct sirfsoc_gpio_bank *bank = sirfsoc_gpio_to_bank(sgpio, d->hwirq);
|
||||
|
||||
__sirfsoc_gpio_irq_mask(sgpio, bank, d->hwirq % SIRFSOC_GPIO_BANK_SIZE);
|
||||
}
|
||||
|
||||
static void sirfsoc_gpio_irq_unmask(struct irq_data *d)
|
||||
{
|
||||
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
|
||||
struct sirfsoc_gpio_chip *sgpio = gpiochip_get_data(gc);
|
||||
struct sirfsoc_gpio_bank *bank = sirfsoc_gpio_to_bank(sgpio, d->hwirq);
|
||||
int idx = sirfsoc_gpio_to_bankoff(d->hwirq);
|
||||
u32 val, offset;
|
||||
unsigned long flags;
|
||||
|
||||
offset = SIRFSOC_GPIO_CTRL(bank->id, idx);
|
||||
|
||||
spin_lock_irqsave(&sgpio->lock, flags);
|
||||
|
||||
val = readl(sgpio->chip.regs + offset);
|
||||
val &= ~SIRFSOC_GPIO_CTL_INTR_STS_MASK;
|
||||
val |= SIRFSOC_GPIO_CTL_INTR_EN_MASK;
|
||||
writel(val, sgpio->chip.regs + offset);
|
||||
|
||||
spin_unlock_irqrestore(&sgpio->lock, flags);
|
||||
}
|
||||
|
||||
static int sirfsoc_gpio_irq_type(struct irq_data *d, unsigned type)
|
||||
{
|
||||
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
|
||||
struct sirfsoc_gpio_chip *sgpio = gpiochip_get_data(gc);
|
||||
struct sirfsoc_gpio_bank *bank = sirfsoc_gpio_to_bank(sgpio, d->hwirq);
|
||||
int idx = sirfsoc_gpio_to_bankoff(d->hwirq);
|
||||
u32 val, offset;
|
||||
unsigned long flags;
|
||||
|
||||
offset = SIRFSOC_GPIO_CTRL(bank->id, idx);
|
||||
|
||||
spin_lock_irqsave(&sgpio->lock, flags);
|
||||
|
||||
val = readl(sgpio->chip.regs + offset);
|
||||
val &= ~(SIRFSOC_GPIO_CTL_INTR_STS_MASK | SIRFSOC_GPIO_CTL_OUT_EN_MASK);
|
||||
|
||||
switch (type) {
|
||||
case IRQ_TYPE_NONE:
|
||||
break;
|
||||
case IRQ_TYPE_EDGE_RISING:
|
||||
val |= SIRFSOC_GPIO_CTL_INTR_HIGH_MASK |
|
||||
SIRFSOC_GPIO_CTL_INTR_TYPE_MASK;
|
||||
val &= ~SIRFSOC_GPIO_CTL_INTR_LOW_MASK;
|
||||
break;
|
||||
case IRQ_TYPE_EDGE_FALLING:
|
||||
val &= ~SIRFSOC_GPIO_CTL_INTR_HIGH_MASK;
|
||||
val |= SIRFSOC_GPIO_CTL_INTR_LOW_MASK |
|
||||
SIRFSOC_GPIO_CTL_INTR_TYPE_MASK;
|
||||
break;
|
||||
case IRQ_TYPE_EDGE_BOTH:
|
||||
val |= SIRFSOC_GPIO_CTL_INTR_HIGH_MASK |
|
||||
SIRFSOC_GPIO_CTL_INTR_LOW_MASK |
|
||||
SIRFSOC_GPIO_CTL_INTR_TYPE_MASK;
|
||||
break;
|
||||
case IRQ_TYPE_LEVEL_LOW:
|
||||
val &= ~(SIRFSOC_GPIO_CTL_INTR_HIGH_MASK |
|
||||
SIRFSOC_GPIO_CTL_INTR_TYPE_MASK);
|
||||
val |= SIRFSOC_GPIO_CTL_INTR_LOW_MASK;
|
||||
break;
|
||||
case IRQ_TYPE_LEVEL_HIGH:
|
||||
val |= SIRFSOC_GPIO_CTL_INTR_HIGH_MASK;
|
||||
val &= ~(SIRFSOC_GPIO_CTL_INTR_LOW_MASK |
|
||||
SIRFSOC_GPIO_CTL_INTR_TYPE_MASK);
|
||||
break;
|
||||
}
|
||||
|
||||
writel(val, sgpio->chip.regs + offset);
|
||||
|
||||
spin_unlock_irqrestore(&sgpio->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct irq_chip sirfsoc_irq_chip = {
|
||||
.name = "sirf-gpio-irq",
|
||||
.irq_ack = sirfsoc_gpio_irq_ack,
|
||||
.irq_mask = sirfsoc_gpio_irq_mask,
|
||||
.irq_unmask = sirfsoc_gpio_irq_unmask,
|
||||
.irq_set_type = sirfsoc_gpio_irq_type,
|
||||
};
|
||||
|
||||
static void sirfsoc_gpio_handle_irq(struct irq_desc *desc)
|
||||
{
|
||||
unsigned int irq = irq_desc_get_irq(desc);
|
||||
struct gpio_chip *gc = irq_desc_get_handler_data(desc);
|
||||
struct sirfsoc_gpio_chip *sgpio = gpiochip_get_data(gc);
|
||||
struct sirfsoc_gpio_bank *bank;
|
||||
u32 status, ctrl;
|
||||
int idx = 0;
|
||||
struct irq_chip *chip = irq_desc_get_chip(desc);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < SIRFSOC_GPIO_NO_OF_BANKS; i++) {
|
||||
bank = &sgpio->sgpio_bank[i];
|
||||
if (bank->parent_irq == irq)
|
||||
break;
|
||||
}
|
||||
BUG_ON(i == SIRFSOC_GPIO_NO_OF_BANKS);
|
||||
|
||||
chained_irq_enter(chip, desc);
|
||||
|
||||
status = readl(sgpio->chip.regs + SIRFSOC_GPIO_INT_STATUS(bank->id));
|
||||
if (!status) {
|
||||
printk(KERN_WARNING
|
||||
"%s: gpio id %d status %#x no interrupt is flagged\n",
|
||||
__func__, bank->id, status);
|
||||
handle_bad_irq(desc);
|
||||
return;
|
||||
}
|
||||
|
||||
while (status) {
|
||||
ctrl = readl(sgpio->chip.regs + SIRFSOC_GPIO_CTRL(bank->id, idx));
|
||||
|
||||
/*
|
||||
* Here we must check whether the corresponding GPIO's interrupt
|
||||
* has been enabled, otherwise just skip it
|
||||
*/
|
||||
if ((status & 0x1) && (ctrl & SIRFSOC_GPIO_CTL_INTR_EN_MASK)) {
|
||||
pr_debug("%s: gpio id %d idx %d happens\n",
|
||||
__func__, bank->id, idx);
|
||||
generic_handle_irq(irq_find_mapping(gc->irq.domain, idx +
|
||||
bank->id * SIRFSOC_GPIO_BANK_SIZE));
|
||||
}
|
||||
|
||||
idx++;
|
||||
status = status >> 1;
|
||||
}
|
||||
|
||||
chained_irq_exit(chip, desc);
|
||||
}
|
||||
|
||||
static inline void sirfsoc_gpio_set_input(struct sirfsoc_gpio_chip *sgpio,
|
||||
unsigned ctrl_offset)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
val = readl(sgpio->chip.regs + ctrl_offset);
|
||||
val &= ~SIRFSOC_GPIO_CTL_OUT_EN_MASK;
|
||||
writel(val, sgpio->chip.regs + ctrl_offset);
|
||||
}
|
||||
|
||||
static int sirfsoc_gpio_request(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
struct sirfsoc_gpio_chip *sgpio = gpiochip_get_data(chip);
|
||||
struct sirfsoc_gpio_bank *bank = sirfsoc_gpio_to_bank(sgpio, offset);
|
||||
unsigned long flags;
|
||||
|
||||
if (pinctrl_gpio_request(chip->base + offset))
|
||||
return -ENODEV;
|
||||
|
||||
spin_lock_irqsave(&bank->lock, flags);
|
||||
|
||||
/*
|
||||
* default status:
|
||||
* set direction as input and mask irq
|
||||
*/
|
||||
sirfsoc_gpio_set_input(sgpio, SIRFSOC_GPIO_CTRL(bank->id, offset));
|
||||
__sirfsoc_gpio_irq_mask(sgpio, bank, offset);
|
||||
|
||||
spin_unlock_irqrestore(&bank->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void sirfsoc_gpio_free(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
struct sirfsoc_gpio_chip *sgpio = gpiochip_get_data(chip);
|
||||
struct sirfsoc_gpio_bank *bank = sirfsoc_gpio_to_bank(sgpio, offset);
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&bank->lock, flags);
|
||||
|
||||
__sirfsoc_gpio_irq_mask(sgpio, bank, offset);
|
||||
sirfsoc_gpio_set_input(sgpio, SIRFSOC_GPIO_CTRL(bank->id, offset));
|
||||
|
||||
spin_unlock_irqrestore(&bank->lock, flags);
|
||||
|
||||
pinctrl_gpio_free(chip->base + offset);
|
||||
}
|
||||
|
||||
static int sirfsoc_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
|
||||
{
|
||||
struct sirfsoc_gpio_chip *sgpio = gpiochip_get_data(chip);
|
||||
struct sirfsoc_gpio_bank *bank = sirfsoc_gpio_to_bank(sgpio, gpio);
|
||||
int idx = sirfsoc_gpio_to_bankoff(gpio);
|
||||
unsigned long flags;
|
||||
unsigned offset;
|
||||
|
||||
offset = SIRFSOC_GPIO_CTRL(bank->id, idx);
|
||||
|
||||
spin_lock_irqsave(&bank->lock, flags);
|
||||
|
||||
sirfsoc_gpio_set_input(sgpio, offset);
|
||||
|
||||
spin_unlock_irqrestore(&bank->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void sirfsoc_gpio_set_output(struct sirfsoc_gpio_chip *sgpio,
|
||||
struct sirfsoc_gpio_bank *bank,
|
||||
unsigned offset,
|
||||
int value)
|
||||
{
|
||||
u32 out_ctrl;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&bank->lock, flags);
|
||||
|
||||
out_ctrl = readl(sgpio->chip.regs + offset);
|
||||
if (value)
|
||||
out_ctrl |= SIRFSOC_GPIO_CTL_DATAOUT_MASK;
|
||||
else
|
||||
out_ctrl &= ~SIRFSOC_GPIO_CTL_DATAOUT_MASK;
|
||||
|
||||
out_ctrl &= ~SIRFSOC_GPIO_CTL_INTR_EN_MASK;
|
||||
out_ctrl |= SIRFSOC_GPIO_CTL_OUT_EN_MASK;
|
||||
writel(out_ctrl, sgpio->chip.regs + offset);
|
||||
|
||||
spin_unlock_irqrestore(&bank->lock, flags);
|
||||
}
|
||||
|
||||
static int sirfsoc_gpio_direction_output(struct gpio_chip *chip,
|
||||
unsigned gpio, int value)
|
||||
{
|
||||
struct sirfsoc_gpio_chip *sgpio = gpiochip_get_data(chip);
|
||||
struct sirfsoc_gpio_bank *bank = sirfsoc_gpio_to_bank(sgpio, gpio);
|
||||
int idx = sirfsoc_gpio_to_bankoff(gpio);
|
||||
u32 offset;
|
||||
unsigned long flags;
|
||||
|
||||
offset = SIRFSOC_GPIO_CTRL(bank->id, idx);
|
||||
|
||||
spin_lock_irqsave(&sgpio->lock, flags);
|
||||
|
||||
sirfsoc_gpio_set_output(sgpio, bank, offset, value);
|
||||
|
||||
spin_unlock_irqrestore(&sgpio->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sirfsoc_gpio_get_value(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
struct sirfsoc_gpio_chip *sgpio = gpiochip_get_data(chip);
|
||||
struct sirfsoc_gpio_bank *bank = sirfsoc_gpio_to_bank(sgpio, offset);
|
||||
u32 val;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&bank->lock, flags);
|
||||
|
||||
val = readl(sgpio->chip.regs + SIRFSOC_GPIO_CTRL(bank->id, offset));
|
||||
|
||||
spin_unlock_irqrestore(&bank->lock, flags);
|
||||
|
||||
return !!(val & SIRFSOC_GPIO_CTL_DATAIN_MASK);
|
||||
}
|
||||
|
||||
static void sirfsoc_gpio_set_value(struct gpio_chip *chip, unsigned offset,
|
||||
int value)
|
||||
{
|
||||
struct sirfsoc_gpio_chip *sgpio = gpiochip_get_data(chip);
|
||||
struct sirfsoc_gpio_bank *bank = sirfsoc_gpio_to_bank(sgpio, offset);
|
||||
u32 ctrl;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&bank->lock, flags);
|
||||
|
||||
ctrl = readl(sgpio->chip.regs + SIRFSOC_GPIO_CTRL(bank->id, offset));
|
||||
if (value)
|
||||
ctrl |= SIRFSOC_GPIO_CTL_DATAOUT_MASK;
|
||||
else
|
||||
ctrl &= ~SIRFSOC_GPIO_CTL_DATAOUT_MASK;
|
||||
writel(ctrl, sgpio->chip.regs + SIRFSOC_GPIO_CTRL(bank->id, offset));
|
||||
|
||||
spin_unlock_irqrestore(&bank->lock, flags);
|
||||
}
|
||||
|
||||
static void sirfsoc_gpio_set_pullup(struct sirfsoc_gpio_chip *sgpio,
|
||||
const u32 *pullups)
|
||||
{
|
||||
int i, n;
|
||||
const unsigned long *p = (const unsigned long *)pullups;
|
||||
|
||||
for (i = 0; i < SIRFSOC_GPIO_NO_OF_BANKS; i++) {
|
||||
for_each_set_bit(n, p + i, BITS_PER_LONG) {
|
||||
u32 offset = SIRFSOC_GPIO_CTRL(i, n);
|
||||
u32 val = readl(sgpio->chip.regs + offset);
|
||||
val |= SIRFSOC_GPIO_CTL_PULL_MASK;
|
||||
val |= SIRFSOC_GPIO_CTL_PULL_HIGH;
|
||||
writel(val, sgpio->chip.regs + offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void sirfsoc_gpio_set_pulldown(struct sirfsoc_gpio_chip *sgpio,
|
||||
const u32 *pulldowns)
|
||||
{
|
||||
int i, n;
|
||||
const unsigned long *p = (const unsigned long *)pulldowns;
|
||||
|
||||
for (i = 0; i < SIRFSOC_GPIO_NO_OF_BANKS; i++) {
|
||||
for_each_set_bit(n, p + i, BITS_PER_LONG) {
|
||||
u32 offset = SIRFSOC_GPIO_CTRL(i, n);
|
||||
u32 val = readl(sgpio->chip.regs + offset);
|
||||
val |= SIRFSOC_GPIO_CTL_PULL_MASK;
|
||||
val &= ~SIRFSOC_GPIO_CTL_PULL_HIGH;
|
||||
writel(val, sgpio->chip.regs + offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int sirfsoc_gpio_probe(struct device_node *np)
|
||||
{
|
||||
int i, err = 0;
|
||||
struct sirfsoc_gpio_chip *sgpio;
|
||||
struct sirfsoc_gpio_bank *bank;
|
||||
void __iomem *regs;
|
||||
struct platform_device *pdev;
|
||||
struct gpio_irq_chip *girq;
|
||||
|
||||
u32 pullups[SIRFSOC_GPIO_NO_OF_BANKS], pulldowns[SIRFSOC_GPIO_NO_OF_BANKS];
|
||||
|
||||
pdev = of_find_device_by_node(np);
|
||||
if (!pdev)
|
||||
return -ENODEV;
|
||||
|
||||
sgpio = devm_kzalloc(&pdev->dev, sizeof(*sgpio), GFP_KERNEL);
|
||||
if (!sgpio) {
|
||||
err = -ENOMEM;
|
||||
goto out_put_device;
|
||||
}
|
||||
spin_lock_init(&sgpio->lock);
|
||||
|
||||
regs = of_iomap(np, 0);
|
||||
if (!regs) {
|
||||
err = -ENOMEM;
|
||||
goto out_put_device;
|
||||
}
|
||||
|
||||
sgpio->chip.gc.request = sirfsoc_gpio_request;
|
||||
sgpio->chip.gc.free = sirfsoc_gpio_free;
|
||||
sgpio->chip.gc.direction_input = sirfsoc_gpio_direction_input;
|
||||
sgpio->chip.gc.get = sirfsoc_gpio_get_value;
|
||||
sgpio->chip.gc.direction_output = sirfsoc_gpio_direction_output;
|
||||
sgpio->chip.gc.set = sirfsoc_gpio_set_value;
|
||||
sgpio->chip.gc.base = 0;
|
||||
sgpio->chip.gc.ngpio = SIRFSOC_GPIO_BANK_SIZE * SIRFSOC_GPIO_NO_OF_BANKS;
|
||||
sgpio->chip.gc.label = kasprintf(GFP_KERNEL, "%pOF", np);
|
||||
sgpio->chip.gc.of_node = np;
|
||||
sgpio->chip.gc.of_xlate = sirfsoc_gpio_of_xlate;
|
||||
sgpio->chip.gc.of_gpio_n_cells = 2;
|
||||
sgpio->chip.gc.parent = &pdev->dev;
|
||||
sgpio->chip.regs = regs;
|
||||
|
||||
girq = &sgpio->chip.gc.irq;
|
||||
girq->chip = &sirfsoc_irq_chip;
|
||||
girq->parent_handler = sirfsoc_gpio_handle_irq;
|
||||
girq->num_parents = SIRFSOC_GPIO_NO_OF_BANKS;
|
||||
girq->parents = devm_kcalloc(&pdev->dev, SIRFSOC_GPIO_NO_OF_BANKS,
|
||||
sizeof(*girq->parents),
|
||||
GFP_KERNEL);
|
||||
if (!girq->parents) {
|
||||
err = -ENOMEM;
|
||||
goto out_put_device;
|
||||
}
|
||||
for (i = 0; i < SIRFSOC_GPIO_NO_OF_BANKS; i++) {
|
||||
bank = &sgpio->sgpio_bank[i];
|
||||
spin_lock_init(&bank->lock);
|
||||
bank->parent_irq = platform_get_irq(pdev, i);
|
||||
if (bank->parent_irq < 0) {
|
||||
err = bank->parent_irq;
|
||||
goto out;
|
||||
}
|
||||
girq->parents[i] = bank->parent_irq;
|
||||
}
|
||||
girq->default_type = IRQ_TYPE_NONE;
|
||||
girq->handler = handle_level_irq;
|
||||
|
||||
err = gpiochip_add_data(&sgpio->chip.gc, sgpio);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "%pOF: error in probe function with status %d\n",
|
||||
np, err);
|
||||
goto out;
|
||||
}
|
||||
|
||||
err = gpiochip_add_pin_range(&sgpio->chip.gc, dev_name(&pdev->dev),
|
||||
0, 0, SIRFSOC_GPIO_BANK_SIZE * SIRFSOC_GPIO_NO_OF_BANKS);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev,
|
||||
"could not add gpiochip pin range\n");
|
||||
goto out_no_range;
|
||||
}
|
||||
|
||||
if (!of_property_read_u32_array(np, "sirf,pullups", pullups,
|
||||
SIRFSOC_GPIO_NO_OF_BANKS))
|
||||
sirfsoc_gpio_set_pullup(sgpio, pullups);
|
||||
|
||||
if (!of_property_read_u32_array(np, "sirf,pulldowns", pulldowns,
|
||||
SIRFSOC_GPIO_NO_OF_BANKS))
|
||||
sirfsoc_gpio_set_pulldown(sgpio, pulldowns);
|
||||
|
||||
return 0;
|
||||
|
||||
out_no_range:
|
||||
gpiochip_remove(&sgpio->chip.gc);
|
||||
out:
|
||||
iounmap(regs);
|
||||
out_put_device:
|
||||
put_device(&pdev->dev);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int __init sirfsoc_gpio_init(void)
|
||||
{
|
||||
|
||||
struct device_node *np;
|
||||
|
||||
np = of_find_matching_node(NULL, pinmux_ids);
|
||||
|
||||
if (!np)
|
||||
return -ENODEV;
|
||||
|
||||
return sirfsoc_gpio_probe(np);
|
||||
}
|
||||
subsys_initcall(sirfsoc_gpio_init);
|
@ -1,116 +0,0 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* pinmux driver shared headfile for CSR SiRFsoc
|
||||
*
|
||||
* Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
|
||||
*/
|
||||
|
||||
#ifndef __PINMUX_SIRF_H__
|
||||
#define __PINMUX_SIRF_H__
|
||||
|
||||
#define SIRFSOC_NUM_PADS 622
|
||||
#define SIRFSOC_RSC_USB_UART_SHARE 0
|
||||
#define SIRFSOC_RSC_PIN_MUX 0x4
|
||||
|
||||
#define SIRFSOC_GPIO_PAD_EN(g) ((g)*0x100 + 0x84)
|
||||
#define SIRFSOC_GPIO_PAD_EN_CLR(g) ((g)*0x100 + 0x90)
|
||||
#define SIRFSOC_GPIO_CTRL(g, i) ((g)*0x100 + (i)*4)
|
||||
#define SIRFSOC_GPIO_DSP_EN0 (0x80)
|
||||
#define SIRFSOC_GPIO_INT_STATUS(g) ((g)*0x100 + 0x8C)
|
||||
|
||||
#define SIRFSOC_GPIO_CTL_INTR_LOW_MASK 0x1
|
||||
#define SIRFSOC_GPIO_CTL_INTR_HIGH_MASK 0x2
|
||||
#define SIRFSOC_GPIO_CTL_INTR_TYPE_MASK 0x4
|
||||
#define SIRFSOC_GPIO_CTL_INTR_EN_MASK 0x8
|
||||
#define SIRFSOC_GPIO_CTL_INTR_STS_MASK 0x10
|
||||
#define SIRFSOC_GPIO_CTL_OUT_EN_MASK 0x20
|
||||
#define SIRFSOC_GPIO_CTL_DATAOUT_MASK 0x40
|
||||
#define SIRFSOC_GPIO_CTL_DATAIN_MASK 0x80
|
||||
#define SIRFSOC_GPIO_CTL_PULL_MASK 0x100
|
||||
#define SIRFSOC_GPIO_CTL_PULL_HIGH 0x200
|
||||
#define SIRFSOC_GPIO_CTL_DSP_INT 0x400
|
||||
|
||||
#define SIRFSOC_GPIO_NO_OF_BANKS 5
|
||||
#define SIRFSOC_GPIO_BANK_SIZE 32
|
||||
#define SIRFSOC_GPIO_NUM(bank, index) (((bank)*(32)) + (index))
|
||||
|
||||
/**
|
||||
* @dev: a pointer back to containing device
|
||||
* @virtbase: the offset to the controller in virtual memory
|
||||
*/
|
||||
struct sirfsoc_pmx {
|
||||
struct device *dev;
|
||||
struct pinctrl_dev *pmx;
|
||||
void __iomem *gpio_virtbase;
|
||||
void __iomem *rsc_virtbase;
|
||||
u32 gpio_regs[SIRFSOC_GPIO_NO_OF_BANKS][SIRFSOC_GPIO_BANK_SIZE];
|
||||
u32 ints_regs[SIRFSOC_GPIO_NO_OF_BANKS];
|
||||
u32 paden_regs[SIRFSOC_GPIO_NO_OF_BANKS];
|
||||
u32 dspen_regs;
|
||||
u32 rsc_regs[3];
|
||||
};
|
||||
|
||||
/* SIRFSOC_GPIO_PAD_EN set */
|
||||
struct sirfsoc_muxmask {
|
||||
unsigned long group;
|
||||
unsigned long mask;
|
||||
};
|
||||
|
||||
struct sirfsoc_padmux {
|
||||
unsigned long muxmask_counts;
|
||||
const struct sirfsoc_muxmask *muxmask;
|
||||
/* RSC_PIN_MUX set */
|
||||
unsigned long ctrlreg;
|
||||
unsigned long funcmask;
|
||||
unsigned long funcval;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct sirfsoc_pin_group - describes a SiRFprimaII pin group
|
||||
* @name: the name of this specific pin group
|
||||
* @pins: an array of discrete physical pins used in this group, taken
|
||||
* from the driver-local pin enumeration space
|
||||
* @num_pins: the number of pins in this group array, i.e. the number of
|
||||
* elements in .pins so we can iterate over that array
|
||||
*/
|
||||
struct sirfsoc_pin_group {
|
||||
const char *name;
|
||||
const unsigned int *pins;
|
||||
const unsigned num_pins;
|
||||
};
|
||||
|
||||
#define SIRFSOC_PIN_GROUP(n, p) \
|
||||
{ \
|
||||
.name = n, \
|
||||
.pins = p, \
|
||||
.num_pins = ARRAY_SIZE(p), \
|
||||
}
|
||||
|
||||
struct sirfsoc_pmx_func {
|
||||
const char *name;
|
||||
const char * const *groups;
|
||||
const unsigned num_groups;
|
||||
const struct sirfsoc_padmux *padmux;
|
||||
};
|
||||
|
||||
#define SIRFSOC_PMX_FUNCTION(n, g, m) \
|
||||
{ \
|
||||
.name = n, \
|
||||
.groups = g, \
|
||||
.num_groups = ARRAY_SIZE(g), \
|
||||
.padmux = &m, \
|
||||
}
|
||||
|
||||
struct sirfsoc_pinctrl_data {
|
||||
struct pinctrl_pin_desc *pads;
|
||||
int pads_cnt;
|
||||
struct sirfsoc_pin_group *grps;
|
||||
int grps_cnt;
|
||||
struct sirfsoc_pmx_func *funcs;
|
||||
int funcs_cnt;
|
||||
};
|
||||
|
||||
extern struct sirfsoc_pinctrl_data prima2_pinctrl_data;
|
||||
extern struct sirfsoc_pinctrl_data atlas6_pinctrl_data;
|
||||
|
||||
#endif
|
@ -687,7 +687,7 @@ static int sprd_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin_id,
|
||||
shift = INPUT_SCHMITT_SHIFT;
|
||||
break;
|
||||
case PIN_CONFIG_BIAS_PULL_UP:
|
||||
if (is_sleep_config == true) {
|
||||
if (is_sleep_config) {
|
||||
val |= SLEEP_PULL_UP;
|
||||
mask = SLEEP_PULL_UP_MASK;
|
||||
shift = SLEEP_PULL_UP_SHIFT;
|
||||
|
@ -119,4 +119,14 @@ config PINCTRL_SUN50I_H6_R
|
||||
default ARM64 && ARCH_SUNXI
|
||||
select PINCTRL_SUNXI
|
||||
|
||||
config PINCTRL_SUN50I_H616
|
||||
bool "Support for the Allwinner H616 PIO"
|
||||
default ARM64 && ARCH_SUNXI
|
||||
select PINCTRL_SUNXI
|
||||
|
||||
config PINCTRL_SUN50I_H616_R
|
||||
bool "Support for the Allwinner H616 R-PIO"
|
||||
default ARM64 && ARCH_SUNXI
|
||||
select PINCTRL_SUNXI
|
||||
|
||||
endif
|
||||
|
@ -23,5 +23,7 @@ obj-$(CONFIG_PINCTRL_SUN8I_V3S) += pinctrl-sun8i-v3s.o
|
||||
obj-$(CONFIG_PINCTRL_SUN50I_H5) += pinctrl-sun50i-h5.o
|
||||
obj-$(CONFIG_PINCTRL_SUN50I_H6) += pinctrl-sun50i-h6.o
|
||||
obj-$(CONFIG_PINCTRL_SUN50I_H6_R) += pinctrl-sun50i-h6-r.o
|
||||
obj-$(CONFIG_PINCTRL_SUN50I_H616) += pinctrl-sun50i-h616.o
|
||||
obj-$(CONFIG_PINCTRL_SUN50I_H616_R) += pinctrl-sun50i-h616-r.o
|
||||
obj-$(CONFIG_PINCTRL_SUN9I_A80) += pinctrl-sun9i-a80.o
|
||||
obj-$(CONFIG_PINCTRL_SUN9I_A80_R) += pinctrl-sun9i-a80-r.o
|
||||
|
@ -24,11 +24,13 @@ static const struct sunxi_desc_pin sun50i_h6_r_pins[] = {
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 0),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION(0x2, "s_rsb"), /* SCK */
|
||||
SUNXI_FUNCTION(0x3, "s_i2c"), /* SCK */
|
||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 0)), /* PL_EINT0 */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 1),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION(0x2, "s_rsb"), /* SDA */
|
||||
SUNXI_FUNCTION(0x3, "s_i2c"), /* SDA */
|
||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 1)), /* PL_EINT1 */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 2),
|
||||
|
56
drivers/pinctrl/sunxi/pinctrl-sun50i-h616-r.c
Normal file
56
drivers/pinctrl/sunxi/pinctrl-sun50i-h616-r.c
Normal file
@ -0,0 +1,56 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Allwinner H616 R_PIO pin controller driver
|
||||
*
|
||||
* Copyright (C) 2020 Arm Ltd.
|
||||
* Based on former work, which is:
|
||||
* Copyright (C) 2017 Icenowy Zheng <icenowy@aosc.io>
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/pinctrl/pinctrl.h>
|
||||
#include <linux/reset.h>
|
||||
|
||||
#include "pinctrl-sunxi.h"
|
||||
|
||||
static const struct sunxi_desc_pin sun50i_h616_r_pins[] = {
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 0),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION(0x2, "s_rsb"), /* SCK */
|
||||
SUNXI_FUNCTION(0x3, "s_i2c")), /* SCK */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 1),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION(0x2, "s_rsb"), /* SDA */
|
||||
SUNXI_FUNCTION(0x3, "s_i2c")), /* SDA */
|
||||
};
|
||||
|
||||
static const struct sunxi_pinctrl_desc sun50i_h616_r_pinctrl_data = {
|
||||
.pins = sun50i_h616_r_pins,
|
||||
.npins = ARRAY_SIZE(sun50i_h616_r_pins),
|
||||
.pin_base = PL_BASE,
|
||||
};
|
||||
|
||||
static int sun50i_h616_r_pinctrl_probe(struct platform_device *pdev)
|
||||
{
|
||||
return sunxi_pinctrl_init(pdev,
|
||||
&sun50i_h616_r_pinctrl_data);
|
||||
}
|
||||
|
||||
static const struct of_device_id sun50i_h616_r_pinctrl_match[] = {
|
||||
{ .compatible = "allwinner,sun50i-h616-r-pinctrl", },
|
||||
{}
|
||||
};
|
||||
|
||||
static struct platform_driver sun50i_h616_r_pinctrl_driver = {
|
||||
.probe = sun50i_h616_r_pinctrl_probe,
|
||||
.driver = {
|
||||
.name = "sun50i-h616-r-pinctrl",
|
||||
.of_match_table = sun50i_h616_r_pinctrl_match,
|
||||
},
|
||||
};
|
||||
builtin_platform_driver(sun50i_h616_r_pinctrl_driver);
|
548
drivers/pinctrl/sunxi/pinctrl-sun50i-h616.c
Normal file
548
drivers/pinctrl/sunxi/pinctrl-sun50i-h616.c
Normal file
@ -0,0 +1,548 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Allwinner H616 SoC pinctrl driver.
|
||||
*
|
||||
* Copyright (C) 2020 Arm Ltd.
|
||||
* based on the H6 pinctrl driver
|
||||
* Copyright (C) 2017 Icenowy Zheng <icenowy@aosc.io>
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/pinctrl/pinctrl.h>
|
||||
|
||||
#include "pinctrl-sunxi.h"
|
||||
|
||||
static const struct sunxi_desc_pin h616_pins[] = {
|
||||
/* Internal connection to the AC200 part */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 0),
|
||||
SUNXI_FUNCTION(0x2, "emac1")), /* ERXD1 */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 1),
|
||||
SUNXI_FUNCTION(0x2, "emac1")), /* ERXD0 */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 2),
|
||||
SUNXI_FUNCTION(0x2, "emac1")), /* ECRS_DV */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 3),
|
||||
SUNXI_FUNCTION(0x2, "emac1")), /* ERXERR */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 4),
|
||||
SUNXI_FUNCTION(0x2, "emac1")), /* ETXD1 */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 5),
|
||||
SUNXI_FUNCTION(0x2, "emac1")), /* ETXD0 */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 6),
|
||||
SUNXI_FUNCTION(0x2, "emac1")), /* ETXCK */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 7),
|
||||
SUNXI_FUNCTION(0x2, "emac1")), /* ETXEN */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 8),
|
||||
SUNXI_FUNCTION(0x2, "emac1")), /* EMDC */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 9),
|
||||
SUNXI_FUNCTION(0x2, "emac1")), /* EMDIO */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 10),
|
||||
SUNXI_FUNCTION(0x2, "i2c3")), /* SCK */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 11),
|
||||
SUNXI_FUNCTION(0x2, "i2c3")), /* SDA */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 12),
|
||||
SUNXI_FUNCTION(0x2, "pwm5")),
|
||||
/* Hole */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 0),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION(0x2, "nand0"), /* WE */
|
||||
SUNXI_FUNCTION(0x3, "mmc2"), /* DS */
|
||||
SUNXI_FUNCTION(0x4, "spi0"), /* CLK */
|
||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 0)), /* PC_EINT0 */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 1),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION(0x2, "nand0"), /* ALE */
|
||||
SUNXI_FUNCTION(0x3, "mmc2"), /* RST */
|
||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 1)), /* PC_EINT1 */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 2),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION(0x2, "nand0"), /* CLE */
|
||||
SUNXI_FUNCTION(0x4, "spi0"), /* MOSI */
|
||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 2)), /* PC_EINT2 */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 3),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION(0x2, "nand0"), /* CE1 */
|
||||
SUNXI_FUNCTION(0x4, "spi0"), /* CS0 */
|
||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 3)), /* PC_EINT3 */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 4),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION(0x2, "nand0"), /* CE0 */
|
||||
SUNXI_FUNCTION(0x4, "spi0"), /* MISO */
|
||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 4)), /* PC_EINT4 */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 5),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION(0x2, "nand0"), /* RE */
|
||||
SUNXI_FUNCTION(0x3, "mmc2"), /* CLK */
|
||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 5)), /* PC_EINT5 */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 6),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION(0x2, "nand0"), /* RB0 */
|
||||
SUNXI_FUNCTION(0x3, "mmc2"), /* CMD */
|
||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 6)), /* PC_EINT6 */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 7),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION(0x2, "nand0"), /* RB1 */
|
||||
SUNXI_FUNCTION(0x4, "spi0"), /* CS1 */
|
||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 7)), /* PC_EINT7 */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 8),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION(0x2, "nand0"), /* DQ7 */
|
||||
SUNXI_FUNCTION(0x3, "mmc2"), /* D3 */
|
||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 8)), /* PC_EINT8 */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 9),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION(0x2, "nand0"), /* DQ6 */
|
||||
SUNXI_FUNCTION(0x3, "mmc2"), /* D4 */
|
||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 9)), /* PC_EINT9 */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 10),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION(0x2, "nand0"), /* DQ5 */
|
||||
SUNXI_FUNCTION(0x3, "mmc2"), /* D0 */
|
||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 10)), /* PC_EINT10 */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 11),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION(0x2, "nand0"), /* DQ4 */
|
||||
SUNXI_FUNCTION(0x3, "mmc2"), /* D5 */
|
||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 11)), /* PC_EINT11 */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 12),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION(0x2, "nand0"), /* DQS */
|
||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 12)), /* PC_EINT12 */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 13),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION(0x2, "nand0"), /* DQ3 */
|
||||
SUNXI_FUNCTION(0x3, "mmc2"), /* D1 */
|
||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 13)), /* PC_EINT13 */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 14),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION(0x2, "nand0"), /* DQ2 */
|
||||
SUNXI_FUNCTION(0x3, "mmc2"), /* D6 */
|
||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 14)), /* PC_EINT14 */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 15),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION(0x2, "nand0"), /* DQ1 */
|
||||
SUNXI_FUNCTION(0x3, "mmc2"), /* D2 */
|
||||
SUNXI_FUNCTION(0x4, "spi0"), /* WP */
|
||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 15)), /* PC_EINT15 */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 16),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION(0x2, "nand0"), /* DQ0 */
|
||||
SUNXI_FUNCTION(0x3, "mmc2"), /* D7 */
|
||||
SUNXI_FUNCTION(0x4, "spi0"), /* HOLD */
|
||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 16)), /* PC_EINT16 */
|
||||
/* Hole */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 0),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION(0x2, "mmc0"), /* D1 */
|
||||
SUNXI_FUNCTION(0x3, "jtag"), /* MS */
|
||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 4, 0)), /* PF_EINT0 */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 1),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION(0x2, "mmc0"), /* D0 */
|
||||
SUNXI_FUNCTION(0x3, "jtag"), /* DI */
|
||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 4, 1)), /* PF_EINT1 */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 2),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION(0x2, "mmc0"), /* CLK */
|
||||
SUNXI_FUNCTION(0x3, "uart0"), /* TX */
|
||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 4, 2)), /* PF_EINT2 */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 3),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION(0x2, "mmc0"), /* CMD */
|
||||
SUNXI_FUNCTION(0x3, "jtag"), /* DO */
|
||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 4, 3)), /* PF_EINT3 */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 4),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION(0x2, "mmc0"), /* D3 */
|
||||
SUNXI_FUNCTION(0x3, "uart0"), /* RX */
|
||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 4, 4)), /* PF_EINT4 */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 5),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION(0x2, "mmc0"), /* D2 */
|
||||
SUNXI_FUNCTION(0x3, "jtag"), /* CK */
|
||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 4, 5)), /* PF_EINT5 */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 6),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 4, 6)), /* PF_EINT6 */
|
||||
/* Hole */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 0),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION(0x2, "mmc1"), /* CLK */
|
||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 5, 0)), /* PG_EINT0 */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 1),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION(0x2, "mmc1"), /* CMD */
|
||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 5, 1)), /* PG_EINT1 */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 2),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION(0x2, "mmc1"), /* D0 */
|
||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 5, 2)), /* PG_EINT2 */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 3),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION(0x2, "mmc1"), /* D1 */
|
||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 5, 3)), /* PG_EINT3 */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 4),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION(0x2, "mmc1"), /* D2 */
|
||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 5, 4)), /* PG_EINT4 */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 5),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION(0x2, "mmc1"), /* D3 */
|
||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 5, 5)), /* PG_EINT5 */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 6),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION(0x2, "uart1"), /* TX */
|
||||
SUNXI_FUNCTION(0x4, "jtag"), /* MS */
|
||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 5, 6)), /* PG_EINT6 */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 7),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION(0x2, "uart1"), /* RX */
|
||||
SUNXI_FUNCTION(0x4, "jtag"), /* CK */
|
||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 5, 7)), /* PG_EINT7 */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 8),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION(0x2, "uart1"), /* RTS */
|
||||
SUNXI_FUNCTION(0x3, "clock"), /* PLL_LOCK_DEBUG */
|
||||
SUNXI_FUNCTION(0x4, "jtag"), /* DO */
|
||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 5, 8)), /* PG_EINT8 */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 9),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION(0x2, "uart1"), /* CTS */
|
||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 5, 9)), /* PG_EINT9 */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 10),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION(0x2, "i2s2"), /* MCLK */
|
||||
SUNXI_FUNCTION(0x3, "clock"), /* X32KFOUT */
|
||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 5, 10)), /* PG_EINT10 */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 11),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION(0x2, "i2s2"), /* BCLK */
|
||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 5, 11)), /* PG_EINT11 */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 12),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION(0x2, "i2s2"), /* SYNC */
|
||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 5, 12)), /* PG_EINT12 */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 13),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION(0x2, "i2s2"), /* DOUT */
|
||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 5, 13)), /* PG_EINT13 */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 14),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION(0x2, "i2s2"), /* DIN */
|
||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 5, 14)), /* PG_EINT14 */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 15),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION(0x2, "uart2"), /* TX */
|
||||
SUNXI_FUNCTION(0x5, "i2c4"), /* SCK */
|
||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 5, 15)), /* PG_EINT15 */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 16),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION(0x2, "uart2"), /* RX */
|
||||
SUNXI_FUNCTION(0x5, "i2c4"), /* SDA */
|
||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 5, 16)), /* PG_EINT16 */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 17),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION(0x2, "uart2"), /* RTS */
|
||||
SUNXI_FUNCTION(0x5, "i2c3"), /* SCK */
|
||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 5, 17)), /* PG_EINT17 */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 18),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION(0x2, "uart2"), /* CTS */
|
||||
SUNXI_FUNCTION(0x5, "i2c3"), /* SDA */
|
||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 5, 18)), /* PG_EINT18 */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 19),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION(0x4, "pwm1"),
|
||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 5, 19)), /* PG_EINT19 */
|
||||
/* Hole */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 0),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION(0x2, "uart0"), /* TX */
|
||||
SUNXI_FUNCTION(0x4, "pwm3"),
|
||||
SUNXI_FUNCTION(0x5, "i2c1"), /* SCK */
|
||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 6, 0)), /* PH_EINT0 */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 1),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION(0x2, "uart0"), /* RX */
|
||||
SUNXI_FUNCTION(0x4, "pwm4"),
|
||||
SUNXI_FUNCTION(0x5, "i2c1"), /* SDA */
|
||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 6, 1)), /* PH_EINT1 */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 2),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION(0x2, "uart5"), /* TX */
|
||||
SUNXI_FUNCTION(0x3, "spdif"), /* MCLK */
|
||||
SUNXI_FUNCTION(0x4, "pwm2"),
|
||||
SUNXI_FUNCTION(0x5, "i2c2"), /* SCK */
|
||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 6, 2)), /* PH_EINT2 */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 3),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION(0x2, "uart5"), /* RX */
|
||||
SUNXI_FUNCTION(0x4, "pwm1"),
|
||||
SUNXI_FUNCTION(0x5, "i2c2"), /* SDA */
|
||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 6, 3)), /* PH_EINT3 */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 4),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION(0x3, "spdif"), /* OUT */
|
||||
SUNXI_FUNCTION(0x5, "i2c3"), /* SCK */
|
||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 6, 4)), /* PH_EINT4 */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 5),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION(0x2, "uart2"), /* TX */
|
||||
SUNXI_FUNCTION(0x3, "i2s3"), /* MCLK */
|
||||
SUNXI_FUNCTION(0x4, "spi1"), /* CS0 */
|
||||
SUNXI_FUNCTION(0x5, "i2c3"), /* SDA */
|
||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 6, 5)), /* PH_EINT5 */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 6),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION(0x2, "uart2"), /* RX */
|
||||
SUNXI_FUNCTION(0x3, "i2s3"), /* BCLK */
|
||||
SUNXI_FUNCTION(0x4, "spi1"), /* CLK */
|
||||
SUNXI_FUNCTION(0x5, "i2c4"), /* SCK */
|
||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 6, 6)), /* PH_EINT6 */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 7),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION(0x2, "uart2"), /* RTS */
|
||||
SUNXI_FUNCTION(0x3, "i2s3"), /* SYNC */
|
||||
SUNXI_FUNCTION(0x4, "spi1"), /* MOSI */
|
||||
SUNXI_FUNCTION(0x5, "i2c4"), /* SDA */
|
||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 6, 7)), /* PH_EINT7 */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 8),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION(0x2, "uart2"), /* CTS */
|
||||
SUNXI_FUNCTION(0x3, "i2s3"), /* DO0 */
|
||||
SUNXI_FUNCTION(0x4, "spi1"), /* MISO */
|
||||
SUNXI_FUNCTION(0x5, "i2s3"), /* DI1 */
|
||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 6, 8)), /* PH_EINT8 */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 9),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION(0x3, "i2s3"), /* DI0 */
|
||||
SUNXI_FUNCTION(0x4, "spi1"), /* CS1 */
|
||||
SUNXI_FUNCTION(0x3, "i2s3"), /* DO1 */
|
||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 6, 9)), /* PH_EINT9 */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 10),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION(0x3, "ir_rx"),
|
||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 6, 10)), /* PH_EINT10 */
|
||||
/* Hole */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 0),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION(0x2, "emac0"), /* ERXD3 */
|
||||
SUNXI_FUNCTION(0x3, "dmic"), /* CLK */
|
||||
SUNXI_FUNCTION(0x4, "i2s0"), /* MCLK */
|
||||
SUNXI_FUNCTION(0x5, "hdmi"), /* HSCL */
|
||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 7, 0)), /* PI_EINT0 */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 1),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION(0x2, "emac0"), /* ERXD2 */
|
||||
SUNXI_FUNCTION(0x3, "dmic"), /* DATA0 */
|
||||
SUNXI_FUNCTION(0x4, "i2s0"), /* BCLK */
|
||||
SUNXI_FUNCTION(0x5, "hdmi"), /* HSDA */
|
||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 7, 1)), /* PI_EINT1 */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 2),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION(0x2, "emac0"), /* ERXD1 */
|
||||
SUNXI_FUNCTION(0x3, "dmic"), /* DATA1 */
|
||||
SUNXI_FUNCTION(0x4, "i2s0"), /* SYNC */
|
||||
SUNXI_FUNCTION(0x5, "hdmi"), /* HCEC */
|
||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 7, 2)), /* PI_EINT2 */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 3),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION(0x2, "emac0"), /* ERXD0 */
|
||||
SUNXI_FUNCTION(0x3, "dmic"), /* DATA2 */
|
||||
SUNXI_FUNCTION(0x4, "i2s0_dout0"), /* DO0 */
|
||||
SUNXI_FUNCTION(0x5, "i2s0_din1"), /* DI1 */
|
||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 7, 3)), /* PI_EINT3 */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 4),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION(0x2, "emac0"), /* ERXCK */
|
||||
SUNXI_FUNCTION(0x3, "dmic"), /* DATA3 */
|
||||
SUNXI_FUNCTION(0x4, "i2s0_din0"), /* DI0 */
|
||||
SUNXI_FUNCTION(0x5, "i2s0_dout1"), /* DO1 */
|
||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 7, 4)), /* PI_EINT4 */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 5),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION(0x2, "emac0"), /* ERXCTL */
|
||||
SUNXI_FUNCTION(0x3, "uart2"), /* TX */
|
||||
SUNXI_FUNCTION(0x4, "ts0"), /* CLK */
|
||||
SUNXI_FUNCTION(0x5, "i2c0"), /* SCK */
|
||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 7, 5)), /* PI_EINT5 */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 6),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION(0x2, "emac0"), /* ENULL */
|
||||
SUNXI_FUNCTION(0x3, "uart2"), /* RX */
|
||||
SUNXI_FUNCTION(0x4, "ts0"), /* ERR */
|
||||
SUNXI_FUNCTION(0x5, "i2c0"), /* SDA */
|
||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 7, 6)), /* PI_EINT6 */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 7),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION(0x2, "emac0"), /* ETXD3 */
|
||||
SUNXI_FUNCTION(0x3, "uart2"), /* RTS */
|
||||
SUNXI_FUNCTION(0x4, "ts0"), /* SYNC */
|
||||
SUNXI_FUNCTION(0x5, "i2c1"), /* SCK */
|
||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 7, 7)), /* PI_EINT7 */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 8),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION(0x2, "emac0"), /* ETXD2 */
|
||||
SUNXI_FUNCTION(0x3, "uart2"), /* CTS */
|
||||
SUNXI_FUNCTION(0x4, "ts0"), /* DVLD */
|
||||
SUNXI_FUNCTION(0x5, "i2c1"), /* SDA */
|
||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 7, 8)), /* PI_EINT8 */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 9),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION(0x2, "emac0"), /* ETXD1 */
|
||||
SUNXI_FUNCTION(0x3, "uart3"), /* TX */
|
||||
SUNXI_FUNCTION(0x4, "ts0"), /* D0 */
|
||||
SUNXI_FUNCTION(0x5, "i2c2"), /* SCK */
|
||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 7, 9)), /* PI_EINT9 */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 10),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION(0x2, "emac0"), /* ETXD0 */
|
||||
SUNXI_FUNCTION(0x3, "uart3"), /* RX */
|
||||
SUNXI_FUNCTION(0x4, "ts0"), /* D1 */
|
||||
SUNXI_FUNCTION(0x5, "i2c2"), /* SDA */
|
||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 7, 10)), /* PI_EINT10 */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 11),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION(0x2, "emac0"), /* ETXCK */
|
||||
SUNXI_FUNCTION(0x3, "uart3"), /* RTS */
|
||||
SUNXI_FUNCTION(0x4, "ts0"), /* D2 */
|
||||
SUNXI_FUNCTION(0x5, "pwm1"),
|
||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 7, 11)), /* PI_EINT11 */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 12),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION(0x2, "emac0"), /* ETXCTL */
|
||||
SUNXI_FUNCTION(0x3, "uart3"), /* CTS */
|
||||
SUNXI_FUNCTION(0x4, "ts0"), /* D3 */
|
||||
SUNXI_FUNCTION(0x5, "pwm2"),
|
||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 7, 12)), /* PI_EINT12 */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 13),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION(0x2, "emac0"), /* ECLKIN */
|
||||
SUNXI_FUNCTION(0x3, "uart4"), /* TX */
|
||||
SUNXI_FUNCTION(0x4, "ts0"), /* D4 */
|
||||
SUNXI_FUNCTION(0x5, "pwm3"),
|
||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 7, 13)), /* PI_EINT13 */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 14),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION(0x2, "emac0"), /* MDC */
|
||||
SUNXI_FUNCTION(0x3, "uart4"), /* RX */
|
||||
SUNXI_FUNCTION(0x4, "ts0"), /* D5 */
|
||||
SUNXI_FUNCTION(0x5, "pwm4"),
|
||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 7, 14)), /* PI_EINT14 */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 15),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION(0x2, "emac0"), /* MDIO */
|
||||
SUNXI_FUNCTION(0x3, "uart4"), /* RTS */
|
||||
SUNXI_FUNCTION(0x4, "ts0"), /* D6 */
|
||||
SUNXI_FUNCTION(0x5, "clock"), /* CLK_FANOUT0 */
|
||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 7, 15)), /* PI_EINT15 */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 16),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION(0x2, "emac0"), /* EPHY_CLK */
|
||||
SUNXI_FUNCTION(0x3, "uart4"), /* CTS */
|
||||
SUNXI_FUNCTION(0x4, "ts0"), /* D7 */
|
||||
SUNXI_FUNCTION(0x5, "clock"), /* CLK_FANOUT1 */
|
||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 7, 16)), /* PI_EINT16 */
|
||||
};
|
||||
static const unsigned int h616_irq_bank_map[] = { 0, 2, 3, 4, 5, 6, 7, 8 };
|
||||
|
||||
static const struct sunxi_pinctrl_desc h616_pinctrl_data = {
|
||||
.pins = h616_pins,
|
||||
.npins = ARRAY_SIZE(h616_pins),
|
||||
.irq_banks = ARRAY_SIZE(h616_irq_bank_map),
|
||||
.irq_bank_map = h616_irq_bank_map,
|
||||
.irq_read_needs_mux = true,
|
||||
.io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_SEL,
|
||||
};
|
||||
|
||||
static int h616_pinctrl_probe(struct platform_device *pdev)
|
||||
{
|
||||
return sunxi_pinctrl_init(pdev, &h616_pinctrl_data);
|
||||
}
|
||||
|
||||
static const struct of_device_id h616_pinctrl_match[] = {
|
||||
{ .compatible = "allwinner,sun50i-h616-pinctrl", },
|
||||
{}
|
||||
};
|
||||
|
||||
static struct platform_driver h616_pinctrl_driver = {
|
||||
.probe = h616_pinctrl_probe,
|
||||
.driver = {
|
||||
.name = "sun50i-h616-pinctrl",
|
||||
.of_match_table = h616_pinctrl_match,
|
||||
},
|
||||
};
|
||||
builtin_platform_driver(h616_pinctrl_driver);
|
@ -704,10 +704,9 @@ static void ti_iodelay_pinconf_group_dbg_show(struct pinctrl_dev *pctldev,
|
||||
u32 reg = 0;
|
||||
|
||||
cfg = &group->cfg[i];
|
||||
regmap_read(iod->regmap, cfg->offset, ®),
|
||||
seq_printf(s, "\n\t0x%08x = 0x%08x (%3d, %3d)",
|
||||
cfg->offset, reg, cfg->a_delay,
|
||||
cfg->g_delay);
|
||||
regmap_read(iod->regmap, cfg->offset, ®);
|
||||
seq_printf(s, "\n\t0x%08x = 0x%08x (%3d, %3d)",
|
||||
cfg->offset, reg, cfg->a_delay, cfg->g_delay);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -1,14 +0,0 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
config PINCTRL_ZX
|
||||
bool
|
||||
select PINMUX
|
||||
select GENERIC_PINCONF
|
||||
select GENERIC_PINCTRL_GROUPS
|
||||
select GENERIC_PINMUX_FUNCTIONS
|
||||
|
||||
config PINCTRL_ZX296718
|
||||
bool "ZTE ZX296718 pinctrl driver"
|
||||
depends on OF && ARCH_ZX
|
||||
select PINCTRL_ZX
|
||||
help
|
||||
Say Y here to enable the ZX296718 pinctrl driver
|
@ -1,3 +0,0 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
obj-$(CONFIG_PINCTRL_ZX) += pinctrl-zx.o
|
||||
obj-$(CONFIG_PINCTRL_ZX296718) += pinctrl-zx296718.o
|
@ -1,445 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (C) 2017 Sanechips Technology Co., Ltd.
|
||||
* Copyright 2017 Linaro Ltd.
|
||||
*/
|
||||
|
||||
#include <linux/io.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/pinctrl/pinctrl.h>
|
||||
#include <linux/pinctrl/pinconf-generic.h>
|
||||
#include <linux/pinctrl/pinmux.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include "../core.h"
|
||||
#include "../pinctrl-utils.h"
|
||||
#include "../pinmux.h"
|
||||
#include "pinctrl-zx.h"
|
||||
|
||||
#define ZX_PULL_DOWN BIT(0)
|
||||
#define ZX_PULL_UP BIT(1)
|
||||
#define ZX_INPUT_ENABLE BIT(3)
|
||||
#define ZX_DS_SHIFT 4
|
||||
#define ZX_DS_MASK (0x7 << ZX_DS_SHIFT)
|
||||
#define ZX_DS_VALUE(x) (((x) << ZX_DS_SHIFT) & ZX_DS_MASK)
|
||||
#define ZX_SLEW BIT(8)
|
||||
|
||||
struct zx_pinctrl {
|
||||
struct pinctrl_dev *pctldev;
|
||||
struct device *dev;
|
||||
void __iomem *base;
|
||||
void __iomem *aux_base;
|
||||
spinlock_t lock;
|
||||
struct zx_pinctrl_soc_info *info;
|
||||
};
|
||||
|
||||
static int zx_dt_node_to_map(struct pinctrl_dev *pctldev,
|
||||
struct device_node *np_config,
|
||||
struct pinctrl_map **map, u32 *num_maps)
|
||||
{
|
||||
return pinconf_generic_dt_node_to_map(pctldev, np_config, map,
|
||||
num_maps, PIN_MAP_TYPE_INVALID);
|
||||
}
|
||||
|
||||
static const struct pinctrl_ops zx_pinctrl_ops = {
|
||||
.dt_node_to_map = zx_dt_node_to_map,
|
||||
.dt_free_map = pinctrl_utils_free_map,
|
||||
.get_groups_count = pinctrl_generic_get_group_count,
|
||||
.get_group_name = pinctrl_generic_get_group_name,
|
||||
.get_group_pins = pinctrl_generic_get_group_pins,
|
||||
};
|
||||
|
||||
#define NONAON_MVAL 2
|
||||
|
||||
static int zx_set_mux(struct pinctrl_dev *pctldev, unsigned int func_selector,
|
||||
unsigned int group_selector)
|
||||
{
|
||||
struct zx_pinctrl *zpctl = pinctrl_dev_get_drvdata(pctldev);
|
||||
struct zx_pinctrl_soc_info *info = zpctl->info;
|
||||
const struct pinctrl_pin_desc *pindesc = info->pins + group_selector;
|
||||
struct zx_pin_data *data = pindesc->drv_data;
|
||||
struct zx_mux_desc *mux;
|
||||
u32 mask, offset, bitpos;
|
||||
struct function_desc *func;
|
||||
unsigned long flags;
|
||||
u32 val, mval;
|
||||
|
||||
/* Skip reserved pin */
|
||||
if (!data)
|
||||
return -EINVAL;
|
||||
|
||||
mux = data->muxes;
|
||||
mask = (1 << data->width) - 1;
|
||||
offset = data->offset;
|
||||
bitpos = data->bitpos;
|
||||
|
||||
func = pinmux_generic_get_function(pctldev, func_selector);
|
||||
if (!func)
|
||||
return -EINVAL;
|
||||
|
||||
while (mux->name) {
|
||||
if (strcmp(mux->name, func->name) == 0)
|
||||
break;
|
||||
mux++;
|
||||
}
|
||||
|
||||
/* Found mux value to be written */
|
||||
mval = mux->muxval;
|
||||
|
||||
spin_lock_irqsave(&zpctl->lock, flags);
|
||||
|
||||
if (data->aon_pin) {
|
||||
/*
|
||||
* It's an AON pin, whose mux register offset and bit position
|
||||
* can be calculated from pin number. Each register covers 16
|
||||
* pins, and each pin occupies 2 bits.
|
||||
*/
|
||||
u16 aoffset = pindesc->number / 16 * 4;
|
||||
u16 abitpos = (pindesc->number % 16) * 2;
|
||||
|
||||
if (mval & AON_MUX_FLAG) {
|
||||
/*
|
||||
* This is a mux value that needs to be written into
|
||||
* AON pinmux register. Write it and then we're done.
|
||||
*/
|
||||
val = readl(zpctl->aux_base + aoffset);
|
||||
val &= ~(0x3 << abitpos);
|
||||
val |= (mval & 0x3) << abitpos;
|
||||
writel(val, zpctl->aux_base + aoffset);
|
||||
} else {
|
||||
/*
|
||||
* It's a mux value that needs to be written into TOP
|
||||
* pinmux register.
|
||||
*/
|
||||
val = readl(zpctl->base + offset);
|
||||
val &= ~(mask << bitpos);
|
||||
val |= (mval & mask) << bitpos;
|
||||
writel(val, zpctl->base + offset);
|
||||
|
||||
/*
|
||||
* In this case, the AON pinmux register needs to be
|
||||
* set up to select non-AON function.
|
||||
*/
|
||||
val = readl(zpctl->aux_base + aoffset);
|
||||
val &= ~(0x3 << abitpos);
|
||||
val |= NONAON_MVAL << abitpos;
|
||||
writel(val, zpctl->aux_base + aoffset);
|
||||
}
|
||||
|
||||
} else {
|
||||
/*
|
||||
* This is a TOP pin, and we only need to set up TOP pinmux
|
||||
* register and then we're done with it.
|
||||
*/
|
||||
val = readl(zpctl->base + offset);
|
||||
val &= ~(mask << bitpos);
|
||||
val |= (mval & mask) << bitpos;
|
||||
writel(val, zpctl->base + offset);
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&zpctl->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct pinmux_ops zx_pinmux_ops = {
|
||||
.get_functions_count = pinmux_generic_get_function_count,
|
||||
.get_function_name = pinmux_generic_get_function_name,
|
||||
.get_function_groups = pinmux_generic_get_function_groups,
|
||||
.set_mux = zx_set_mux,
|
||||
};
|
||||
|
||||
static int zx_pin_config_get(struct pinctrl_dev *pctldev, unsigned int pin,
|
||||
unsigned long *config)
|
||||
{
|
||||
struct zx_pinctrl *zpctl = pinctrl_dev_get_drvdata(pctldev);
|
||||
struct zx_pinctrl_soc_info *info = zpctl->info;
|
||||
const struct pinctrl_pin_desc *pindesc = info->pins + pin;
|
||||
struct zx_pin_data *data = pindesc->drv_data;
|
||||
enum pin_config_param param = pinconf_to_config_param(*config);
|
||||
u32 val;
|
||||
|
||||
/* Skip reserved pin */
|
||||
if (!data)
|
||||
return -EINVAL;
|
||||
|
||||
val = readl(zpctl->aux_base + data->coffset);
|
||||
val = val >> data->cbitpos;
|
||||
|
||||
switch (param) {
|
||||
case PIN_CONFIG_BIAS_PULL_DOWN:
|
||||
val &= ZX_PULL_DOWN;
|
||||
val = !!val;
|
||||
if (val == 0)
|
||||
return -EINVAL;
|
||||
break;
|
||||
case PIN_CONFIG_BIAS_PULL_UP:
|
||||
val &= ZX_PULL_UP;
|
||||
val = !!val;
|
||||
if (val == 0)
|
||||
return -EINVAL;
|
||||
break;
|
||||
case PIN_CONFIG_INPUT_ENABLE:
|
||||
val &= ZX_INPUT_ENABLE;
|
||||
val = !!val;
|
||||
if (val == 0)
|
||||
return -EINVAL;
|
||||
break;
|
||||
case PIN_CONFIG_DRIVE_STRENGTH:
|
||||
val &= ZX_DS_MASK;
|
||||
val = val >> ZX_DS_SHIFT;
|
||||
break;
|
||||
case PIN_CONFIG_SLEW_RATE:
|
||||
val &= ZX_SLEW;
|
||||
val = !!val;
|
||||
break;
|
||||
default:
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
*config = pinconf_to_config_packed(param, val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int zx_pin_config_set(struct pinctrl_dev *pctldev, unsigned int pin,
|
||||
unsigned long *configs, unsigned int num_configs)
|
||||
{
|
||||
struct zx_pinctrl *zpctl = pinctrl_dev_get_drvdata(pctldev);
|
||||
struct zx_pinctrl_soc_info *info = zpctl->info;
|
||||
const struct pinctrl_pin_desc *pindesc = info->pins + pin;
|
||||
struct zx_pin_data *data = pindesc->drv_data;
|
||||
enum pin_config_param param;
|
||||
u32 val, arg;
|
||||
int i;
|
||||
|
||||
/* Skip reserved pin */
|
||||
if (!data)
|
||||
return -EINVAL;
|
||||
|
||||
val = readl(zpctl->aux_base + data->coffset);
|
||||
|
||||
for (i = 0; i < num_configs; i++) {
|
||||
param = pinconf_to_config_param(configs[i]);
|
||||
arg = pinconf_to_config_argument(configs[i]);
|
||||
|
||||
switch (param) {
|
||||
case PIN_CONFIG_BIAS_PULL_DOWN:
|
||||
val |= ZX_PULL_DOWN << data->cbitpos;
|
||||
break;
|
||||
case PIN_CONFIG_BIAS_PULL_UP:
|
||||
val |= ZX_PULL_UP << data->cbitpos;
|
||||
break;
|
||||
case PIN_CONFIG_INPUT_ENABLE:
|
||||
val |= ZX_INPUT_ENABLE << data->cbitpos;
|
||||
break;
|
||||
case PIN_CONFIG_DRIVE_STRENGTH:
|
||||
val &= ~(ZX_DS_MASK << data->cbitpos);
|
||||
val |= ZX_DS_VALUE(arg) << data->cbitpos;
|
||||
break;
|
||||
case PIN_CONFIG_SLEW_RATE:
|
||||
if (arg)
|
||||
val |= ZX_SLEW << data->cbitpos;
|
||||
else
|
||||
val &= ~ZX_SLEW << data->cbitpos;
|
||||
break;
|
||||
default:
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
}
|
||||
|
||||
writel(val, zpctl->aux_base + data->coffset);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct pinconf_ops zx_pinconf_ops = {
|
||||
.pin_config_set = zx_pin_config_set,
|
||||
.pin_config_get = zx_pin_config_get,
|
||||
.is_generic = true,
|
||||
};
|
||||
|
||||
static int zx_pinctrl_build_state(struct platform_device *pdev)
|
||||
{
|
||||
struct zx_pinctrl *zpctl = platform_get_drvdata(pdev);
|
||||
struct zx_pinctrl_soc_info *info = zpctl->info;
|
||||
struct pinctrl_dev *pctldev = zpctl->pctldev;
|
||||
struct function_desc *functions;
|
||||
int nfunctions;
|
||||
struct group_desc *groups;
|
||||
int ngroups;
|
||||
int i;
|
||||
|
||||
/* Every single pin composes a group */
|
||||
ngroups = info->npins;
|
||||
groups = devm_kcalloc(&pdev->dev, ngroups, sizeof(*groups),
|
||||
GFP_KERNEL);
|
||||
if (!groups)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < ngroups; i++) {
|
||||
const struct pinctrl_pin_desc *pindesc = info->pins + i;
|
||||
struct group_desc *group = groups + i;
|
||||
|
||||
group->name = pindesc->name;
|
||||
group->pins = (int *) &pindesc->number;
|
||||
group->num_pins = 1;
|
||||
radix_tree_insert(&pctldev->pin_group_tree, i, group);
|
||||
}
|
||||
|
||||
pctldev->num_groups = ngroups;
|
||||
|
||||
/* Build function list from pin mux functions */
|
||||
functions = kcalloc(info->npins, sizeof(*functions), GFP_KERNEL);
|
||||
if (!functions)
|
||||
return -ENOMEM;
|
||||
|
||||
nfunctions = 0;
|
||||
for (i = 0; i < info->npins; i++) {
|
||||
const struct pinctrl_pin_desc *pindesc = info->pins + i;
|
||||
struct zx_pin_data *data = pindesc->drv_data;
|
||||
struct zx_mux_desc *mux;
|
||||
|
||||
/* Reserved pins do not have a drv_data at all */
|
||||
if (!data)
|
||||
continue;
|
||||
|
||||
/* Loop over all muxes for the pin */
|
||||
mux = data->muxes;
|
||||
while (mux->name) {
|
||||
struct function_desc *func = functions;
|
||||
|
||||
/* Search function list for given mux */
|
||||
while (func->name) {
|
||||
if (strcmp(mux->name, func->name) == 0) {
|
||||
/* Function exists */
|
||||
func->num_group_names++;
|
||||
break;
|
||||
}
|
||||
func++;
|
||||
}
|
||||
|
||||
if (!func->name) {
|
||||
/* New function */
|
||||
func->name = mux->name;
|
||||
func->num_group_names = 1;
|
||||
radix_tree_insert(&pctldev->pin_function_tree,
|
||||
nfunctions++, func);
|
||||
}
|
||||
|
||||
mux++;
|
||||
}
|
||||
}
|
||||
|
||||
pctldev->num_functions = nfunctions;
|
||||
functions = krealloc(functions, nfunctions * sizeof(*functions),
|
||||
GFP_KERNEL);
|
||||
|
||||
/* Find pin groups for every single function */
|
||||
for (i = 0; i < info->npins; i++) {
|
||||
const struct pinctrl_pin_desc *pindesc = info->pins + i;
|
||||
struct zx_pin_data *data = pindesc->drv_data;
|
||||
struct zx_mux_desc *mux;
|
||||
|
||||
if (!data)
|
||||
continue;
|
||||
|
||||
mux = data->muxes;
|
||||
while (mux->name) {
|
||||
struct function_desc *func;
|
||||
const char **group;
|
||||
int j;
|
||||
|
||||
/* Find function for given mux */
|
||||
for (j = 0; j < nfunctions; j++)
|
||||
if (strcmp(functions[j].name, mux->name) == 0)
|
||||
break;
|
||||
|
||||
func = functions + j;
|
||||
if (!func->group_names) {
|
||||
func->group_names = devm_kcalloc(&pdev->dev,
|
||||
func->num_group_names,
|
||||
sizeof(*func->group_names),
|
||||
GFP_KERNEL);
|
||||
if (!func->group_names) {
|
||||
kfree(functions);
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
|
||||
group = func->group_names;
|
||||
while (*group)
|
||||
group++;
|
||||
*group = pindesc->name;
|
||||
|
||||
mux++;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int zx_pinctrl_init(struct platform_device *pdev,
|
||||
struct zx_pinctrl_soc_info *info)
|
||||
{
|
||||
struct pinctrl_desc *pctldesc;
|
||||
struct zx_pinctrl *zpctl;
|
||||
struct device_node *np;
|
||||
int ret;
|
||||
|
||||
zpctl = devm_kzalloc(&pdev->dev, sizeof(*zpctl), GFP_KERNEL);
|
||||
if (!zpctl)
|
||||
return -ENOMEM;
|
||||
|
||||
spin_lock_init(&zpctl->lock);
|
||||
|
||||
zpctl->base = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(zpctl->base))
|
||||
return PTR_ERR(zpctl->base);
|
||||
|
||||
np = of_parse_phandle(pdev->dev.of_node, "zte,auxiliary-controller", 0);
|
||||
if (!np) {
|
||||
dev_err(&pdev->dev, "failed to find auxiliary controller\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
zpctl->aux_base = of_iomap(np, 0);
|
||||
of_node_put(np);
|
||||
if (!zpctl->aux_base)
|
||||
return -ENOMEM;
|
||||
|
||||
zpctl->dev = &pdev->dev;
|
||||
zpctl->info = info;
|
||||
|
||||
pctldesc = devm_kzalloc(&pdev->dev, sizeof(*pctldesc), GFP_KERNEL);
|
||||
if (!pctldesc)
|
||||
return -ENOMEM;
|
||||
|
||||
pctldesc->name = dev_name(&pdev->dev);
|
||||
pctldesc->owner = THIS_MODULE;
|
||||
pctldesc->pins = info->pins;
|
||||
pctldesc->npins = info->npins;
|
||||
pctldesc->pctlops = &zx_pinctrl_ops;
|
||||
pctldesc->pmxops = &zx_pinmux_ops;
|
||||
pctldesc->confops = &zx_pinconf_ops;
|
||||
|
||||
zpctl->pctldev = devm_pinctrl_register(&pdev->dev, pctldesc, zpctl);
|
||||
if (IS_ERR(zpctl->pctldev)) {
|
||||
ret = PTR_ERR(zpctl->pctldev);
|
||||
dev_err(&pdev->dev, "failed to register pinctrl: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, zpctl);
|
||||
|
||||
ret = zx_pinctrl_build_state(pdev);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to build state: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
dev_info(&pdev->dev, "initialized pinctrl driver\n");
|
||||
return 0;
|
||||
}
|
@ -1,102 +0,0 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (C) 2017 Sanechips Technology Co., Ltd.
|
||||
* Copyright 2017 Linaro Ltd.
|
||||
*/
|
||||
|
||||
#ifndef __PINCTRL_ZX_H
|
||||
#define __PINCTRL_ZX_H
|
||||
|
||||
/**
|
||||
* struct zx_mux_desc - hardware mux descriptor
|
||||
* @name: mux function name
|
||||
* @muxval: mux register bit value
|
||||
*/
|
||||
struct zx_mux_desc {
|
||||
const char *name;
|
||||
u8 muxval;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct zx_pin_data - hardware per-pin data
|
||||
* @aon_pin: whether it's an AON pin
|
||||
* @offset: register offset within TOP pinmux controller
|
||||
* @bitpos: bit position within TOP pinmux register
|
||||
* @width: bit width within TOP pinmux register
|
||||
* @coffset: pinconf register offset within AON controller
|
||||
* @cbitpos: pinconf bit position within AON register
|
||||
* @muxes: available mux function names and corresponding register values
|
||||
*
|
||||
* Unlike TOP pinmux and AON pinconf registers which are arranged pretty
|
||||
* arbitrarily, AON pinmux register bits are well organized per pin id, and
|
||||
* each pin occupies two bits, so that we can calculate the AON register offset
|
||||
* and bit position from pin id. Thus, we only need to define TOP pinmux and
|
||||
* AON pinconf register data for the pin.
|
||||
*/
|
||||
struct zx_pin_data {
|
||||
bool aon_pin;
|
||||
u16 offset;
|
||||
u16 bitpos;
|
||||
u16 width;
|
||||
u16 coffset;
|
||||
u16 cbitpos;
|
||||
struct zx_mux_desc *muxes;
|
||||
};
|
||||
|
||||
struct zx_pinctrl_soc_info {
|
||||
const struct pinctrl_pin_desc *pins;
|
||||
unsigned int npins;
|
||||
};
|
||||
|
||||
#define TOP_PIN(pin, off, bp, wd, coff, cbp, ...) { \
|
||||
.number = pin, \
|
||||
.name = #pin, \
|
||||
.drv_data = &(struct zx_pin_data) { \
|
||||
.aon_pin = false, \
|
||||
.offset = off, \
|
||||
.bitpos = bp, \
|
||||
.width = wd, \
|
||||
.coffset = coff, \
|
||||
.cbitpos = cbp, \
|
||||
.muxes = (struct zx_mux_desc[]) { \
|
||||
__VA_ARGS__, { } }, \
|
||||
}, \
|
||||
}
|
||||
|
||||
#define AON_PIN(pin, off, bp, wd, coff, cbp, ...) { \
|
||||
.number = pin, \
|
||||
.name = #pin, \
|
||||
.drv_data = &(struct zx_pin_data) { \
|
||||
.aon_pin = true, \
|
||||
.offset = off, \
|
||||
.bitpos = bp, \
|
||||
.width = wd, \
|
||||
.coffset = coff, \
|
||||
.cbitpos = cbp, \
|
||||
.muxes = (struct zx_mux_desc[]) { \
|
||||
__VA_ARGS__, { } }, \
|
||||
}, \
|
||||
}
|
||||
|
||||
#define ZX_RESERVED(pin) PINCTRL_PIN(pin, #pin)
|
||||
|
||||
#define TOP_MUX(_val, _name) { \
|
||||
.name = _name, \
|
||||
.muxval = _val, \
|
||||
}
|
||||
|
||||
/*
|
||||
* When the flag is set, it's a mux configuration for an AON pin that sits in
|
||||
* AON register. Otherwise, it's one for AON pin but sitting in TOP register.
|
||||
*/
|
||||
#define AON_MUX_FLAG BIT(7)
|
||||
|
||||
#define AON_MUX(_val, _name) { \
|
||||
.name = _name, \
|
||||
.muxval = _val | AON_MUX_FLAG, \
|
||||
}
|
||||
|
||||
int zx_pinctrl_init(struct platform_device *pdev,
|
||||
struct zx_pinctrl_soc_info *info);
|
||||
|
||||
#endif /* __PINCTRL_ZX_H */
|
File diff suppressed because it is too large
Load Diff
@ -72,4 +72,10 @@
|
||||
*/
|
||||
#define IS_ENABLED(option) __or(IS_BUILTIN(option), IS_MODULE(option))
|
||||
|
||||
/*
|
||||
* IF_ENABLED(CONFIG_FOO, ptr) evaluates to (ptr) if CONFIG_FOO is set to 'y'
|
||||
* or 'm', NULL otherwise.
|
||||
*/
|
||||
#define IF_ENABLED(option, ptr) (IS_ENABLED(option) ? (ptr) : NULL)
|
||||
|
||||
#endif /* __LINUX_KCONFIG_H */
|
||||
|
Loading…
Reference in New Issue
Block a user