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 ...master
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-h5-pinctrl
|
||||||
- allwinner,sun50i-h6-pinctrl
|
- allwinner,sun50i-h6-pinctrl
|
||||||
- allwinner,sun50i-h6-r-pinctrl
|
- allwinner,sun50i-h6-r-pinctrl
|
||||||
|
- allwinner,sun50i-h616-pinctrl
|
||||||
|
- allwinner,sun50i-h616-r-pinctrl
|
||||||
- allwinner,suniv-f1c100s-pinctrl
|
- allwinner,suniv-f1c100s-pinctrl
|
||||||
- nextthing,gr8-pinctrl
|
- nextthing,gr8-pinctrl
|
||||||
|
|
||||||
|
@ -61,7 +63,7 @@ properties:
|
||||||
|
|
||||||
interrupts:
|
interrupts:
|
||||||
minItems: 1
|
minItems: 1
|
||||||
maxItems: 7
|
maxItems: 8
|
||||||
description:
|
description:
|
||||||
One interrupt per external interrupt bank supported on the
|
One interrupt per external interrupt bank supported on the
|
||||||
controller, sorted by bank number ascending order.
|
controller, sorted by bank number ascending order.
|
||||||
|
@ -91,7 +93,7 @@ properties:
|
||||||
bank found in the controller
|
bank found in the controller
|
||||||
$ref: /schemas/types.yaml#/definitions/uint32-array
|
$ref: /schemas/types.yaml#/definitions/uint32-array
|
||||||
minItems: 1
|
minItems: 1
|
||||||
maxItems: 5
|
maxItems: 8
|
||||||
|
|
||||||
patternProperties:
|
patternProperties:
|
||||||
# It's pretty scary, but the basic idea is that:
|
# 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
|
# boards are defining it at the moment so it would generate a lot of
|
||||||
# warnings.
|
# warnings.
|
||||||
|
|
||||||
|
- if:
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
enum:
|
||||||
|
- allwinner,sun50i-h616-pinctrl
|
||||||
|
|
||||||
|
then:
|
||||||
|
properties:
|
||||||
|
interrupts:
|
||||||
|
minItems: 8
|
||||||
|
|
||||||
- if:
|
- if:
|
||||||
properties:
|
properties:
|
||||||
compatible:
|
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.
|
right representation of the pin.
|
||||||
|
|
||||||
Optional properties:
|
Optional properties:
|
||||||
- GENERIC_PINCONFIG: generic pinconfig options to use, bias-disable,
|
- GENERIC_PINCONFIG: generic pinconfig options to use:
|
||||||
bias-pull-down, bias-pull-up, drive-open-drain, input-schmitt-enable,
|
- bias-disable, bias-pull-down, bias-pull-up, drive-open-drain,
|
||||||
input-debounce, output-low, output-high.
|
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
|
- atmel,drive-strength: 0 or 1 for low drive, 2 for medium drive and 3 for
|
||||||
high drive. The default value is low drive.
|
high drive. The default value is low drive.
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,7 @@ For example:
|
||||||
<0x660009b0 0x40>;
|
<0x660009b0 0x40>;
|
||||||
|
|
||||||
pinctrl-names = "default";
|
pinctrl-names = "default";
|
||||||
pinctrl-0 = <&nand_sel &uart3_rx &sdio0_d4>;
|
pinctrl-0 = <&nand_sel>, <&uart3_rx>, <&sdio0_d4>;
|
||||||
|
|
||||||
/* Select nand function */
|
/* Select nand function */
|
||||||
nand_sel: nand_sel {
|
nand_sel: nand_sel {
|
||||||
|
|
|
@ -30,7 +30,7 @@ For example:
|
||||||
<0x1803f408 0x04>;
|
<0x1803f408 0x04>;
|
||||||
|
|
||||||
pinctrl-names = "default";
|
pinctrl-names = "default";
|
||||||
pinctrl-0 = <&pwm &gpio_b &nand_sel>;
|
pinctrl-0 = <&pwm>, <&gpio_b>, <&nand_sel>;
|
||||||
|
|
||||||
pwm: pwm {
|
pwm: pwm {
|
||||||
function = "pwm";
|
function = "pwm";
|
||||||
|
|
|
@ -60,7 +60,7 @@ iomuxc-lpsr controller and SDA pad from iomuxc controller as:
|
||||||
|
|
||||||
i2c1: i2c@30a20000 {
|
i2c1: i2c@30a20000 {
|
||||||
pinctrl-names = "default";
|
pinctrl-names = "default";
|
||||||
pinctrl-0 = <&pinctrl_i2c1_1 &pinctrl_i2c1_2>;
|
pinctrl-0 = <&pinctrl_i2c1_1>, <&pinctrl_i2c1_2>;
|
||||||
};
|
};
|
||||||
|
|
||||||
iomuxc-lpsr@302c0000 {
|
iomuxc-lpsr@302c0000 {
|
||||||
|
|
|
@ -99,8 +99,8 @@ patternProperties:
|
||||||
|
|
||||||
'#interrupt-cells':
|
'#interrupt-cells':
|
||||||
description:
|
description:
|
||||||
Specifies the pin (port and bit) and flags, as defined in
|
Specifies the pin (port and bit) and flags, as defined in
|
||||||
defined in include/dt-bindings/interrupt-controller/irq.h
|
defined in include/dt-bindings/interrupt-controller/irq.h
|
||||||
const: 3
|
const: 3
|
||||||
|
|
||||||
ngpios:
|
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 {
|
device {
|
||||||
pinctrl-names = "active", "idle";
|
pinctrl-names = "active", "idle";
|
||||||
pinctrl-0 = <&state_0_node_a>;
|
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 */
|
/* For the same device if using state IDs */
|
||||||
device {
|
device {
|
||||||
pinctrl-0 = <&state_0_node_a>;
|
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>;
|
#interrupt-cells = <0x2>;
|
||||||
microchip,irq-mirror;
|
microchip,irq-mirror;
|
||||||
pinctrl-names = "default";
|
pinctrl-names = "default";
|
||||||
pinctrl-0 = <&i2cgpio0irq &gpio21pullups>;
|
pinctrl-0 = <&i2cgpio0irq>, <&gpio21pullups>;
|
||||||
|
|
||||||
gpio21pullups: pinmux {
|
gpio21pullups: pinmux {
|
||||||
pins = "gpio0", "gpio1", "gpio2", "gpio3",
|
pins = "gpio0", "gpio1", "gpio2", "gpio3",
|
||||||
|
|
|
@ -91,7 +91,7 @@ Examples:
|
||||||
pinctrl@1c20800 {
|
pinctrl@1c20800 {
|
||||||
compatible = "mediatek,mt8135-pinctrl";
|
compatible = "mediatek,mt8135-pinctrl";
|
||||||
reg = <0 0x1000B000 0 0x1000>;
|
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;
|
pins-are-numbered;
|
||||||
gpio-controller;
|
gpio-controller;
|
||||||
#gpio-cells = <2>;
|
#gpio-cells = <2>;
|
||||||
|
|
|
@ -8,7 +8,7 @@ Required properties:
|
||||||
- reg : offset and length of the register set for the mux registers
|
- 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
|
- #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
|
- pinctrl-single,register-width : pinmux register access width in bits
|
||||||
|
|
||||||
|
@ -80,7 +80,7 @@ Optional properties:
|
||||||
property.
|
property.
|
||||||
|
|
||||||
/* pin base, nr pins & gpio function */
|
/* 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
|
- interrupt-controller : standard interrupt controller binding if using
|
||||||
interrupts for wake-up events for example. In this case pinctrl-single
|
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>;
|
pinctrl-single,function-mask = <7>;
|
||||||
|
|
||||||
/* sparse GPIO range could be supported */
|
/* sparse GPIO range could be supported */
|
||||||
pinctrl-single,gpio-range = <&range 0 3 0 &range 3 9 1
|
pinctrl-single,gpio-range = <&range 0 3 0>, <&range 3 9 1>,
|
||||||
&range 12 1 0 &range 13 29 1
|
<&range 12 1 0>, <&range 13 29 1>,
|
||||||
&range 43 1 0 &range 44 49 1
|
<&range 43 1 0>, <&range 44 49 1>,
|
||||||
&range 94 1 1 &range 96 2 1>;
|
<&range 94 1 1>, <&range 96 2 1>;
|
||||||
|
|
||||||
range: gpio-range {
|
range: gpio-range {
|
||||||
#pinctrl-single,gpio-range-cells = <3>;
|
#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>
|
Value type: <string>
|
||||||
Definition: Should contain one of:
|
Definition: Should contain one of:
|
||||||
"qcom,pm8018-mpp",
|
"qcom,pm8018-mpp",
|
||||||
|
"qcom,pm8019-mpp",
|
||||||
"qcom,pm8038-mpp",
|
"qcom,pm8038-mpp",
|
||||||
"qcom,pm8058-mpp",
|
"qcom,pm8058-mpp",
|
||||||
"qcom,pm8821-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:
|
properties:
|
||||||
compatible:
|
compatible:
|
||||||
enum:
|
const: ralink,rt2880-pinmux
|
||||||
- ralink,rt2880-pinmux
|
|
||||||
|
|
||||||
pinctrl-0:
|
patternProperties:
|
||||||
description:
|
'-pins$':
|
||||||
A phandle to the node containing the subnodes containing default
|
type: object
|
||||||
configurations. This is for pinctrl hogs.
|
patternProperties:
|
||||||
|
'^(.*-)?pinmux$':
|
||||||
|
type: object
|
||||||
|
description: node for pinctrl.
|
||||||
|
$ref: pinmux-node.yaml#
|
||||||
|
|
||||||
pinctrl-names:
|
properties:
|
||||||
description:
|
groups:
|
||||||
A pinctrl state named "default" can be defined.
|
description: Name of the pin group to use for the functions.
|
||||||
const: default
|
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:
|
required:
|
||||||
- compatible
|
- 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
|
additionalProperties: false
|
||||||
|
|
||||||
examples:
|
examples:
|
||||||
|
@ -55,14 +54,9 @@ examples:
|
||||||
- |
|
- |
|
||||||
pinctrl {
|
pinctrl {
|
||||||
compatible = "ralink,rt2880-pinmux";
|
compatible = "ralink,rt2880-pinmux";
|
||||||
pinctrl-names = "default";
|
|
||||||
pinctrl-0 = <&state_default>;
|
|
||||||
|
|
||||||
state_default: pinctrl0 {
|
i2c_pins: i2c0-pins {
|
||||||
};
|
pinmux {
|
||||||
|
|
||||||
i2c_pins: i2c0 {
|
|
||||||
i2c0 {
|
|
||||||
groups = "i2c";
|
groups = "i2c";
|
||||||
function = "i2c";
|
function = "i2c";
|
||||||
};
|
};
|
||||||
|
|
|
@ -43,11 +43,12 @@ properties:
|
||||||
- renesas,pfc-r8a77980 # R-Car V3H
|
- renesas,pfc-r8a77980 # R-Car V3H
|
||||||
- renesas,pfc-r8a77990 # R-Car E3
|
- renesas,pfc-r8a77990 # R-Car E3
|
||||||
- renesas,pfc-r8a77995 # R-Car D3
|
- renesas,pfc-r8a77995 # R-Car D3
|
||||||
|
- renesas,pfc-r8a779a0 # R-Car V3U
|
||||||
- renesas,pfc-sh73a0 # SH-Mobile AG5
|
- renesas,pfc-sh73a0 # SH-Mobile AG5
|
||||||
|
|
||||||
reg:
|
reg:
|
||||||
minItems: 1
|
minItems: 1
|
||||||
maxItems: 2
|
maxItems: 10
|
||||||
|
|
||||||
gpio-controller: true
|
gpio-controller: true
|
||||||
|
|
||||||
|
|
|
@ -336,7 +336,7 @@ Example 3: A uart client node that supports 'default' and 'flow-control' states.
|
||||||
interrupts = <0 52 0>;
|
interrupts = <0 52 0>;
|
||||||
pinctrl-names = "default", "flow-control;
|
pinctrl-names = "default", "flow-control;
|
||||||
pinctrl-0 = <&uart0_data>;
|
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.
|
Example 4: Set up the default pin state for uart controller.
|
||||||
|
|
|
@ -226,14 +226,6 @@ config PINCTRL_SINGLE
|
||||||
help
|
help
|
||||||
This selects the device tree based generic pinctrl driver.
|
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
|
config PINCTRL_SX150X
|
||||||
bool "Semtech SX150x I2C GPIO expander pinctrl driver"
|
bool "Semtech SX150x I2C GPIO expander pinctrl driver"
|
||||||
depends on I2C=y
|
depends on I2C=y
|
||||||
|
@ -279,22 +271,6 @@ config PINCTRL_STMFX
|
||||||
and configuring push-pull, open-drain, and can also be used as
|
and configuring push-pull, open-drain, and can also be used as
|
||||||
interrupt-controller.
|
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
|
config PINCTRL_MAX77620
|
||||||
tristate "MAX77620/MAX20024 Pincontrol support"
|
tristate "MAX77620/MAX20024 Pincontrol support"
|
||||||
depends on MFD_MAX77620 && OF
|
depends on MFD_MAX77620 && OF
|
||||||
|
@ -417,7 +393,6 @@ source "drivers/pinctrl/ti/Kconfig"
|
||||||
source "drivers/pinctrl/uniphier/Kconfig"
|
source "drivers/pinctrl/uniphier/Kconfig"
|
||||||
source "drivers/pinctrl/vt8500/Kconfig"
|
source "drivers/pinctrl/vt8500/Kconfig"
|
||||||
source "drivers/pinctrl/mediatek/Kconfig"
|
source "drivers/pinctrl/mediatek/Kconfig"
|
||||||
source "drivers/pinctrl/zte/Kconfig"
|
|
||||||
source "drivers/pinctrl/meson/Kconfig"
|
source "drivers/pinctrl/meson/Kconfig"
|
||||||
source "drivers/pinctrl/cirrus/Kconfig"
|
source "drivers/pinctrl/cirrus/Kconfig"
|
||||||
source "drivers/pinctrl/visconti/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_PISTACHIO) += pinctrl-pistachio.o
|
||||||
obj-$(CONFIG_PINCTRL_ROCKCHIP) += pinctrl-rockchip.o
|
obj-$(CONFIG_PINCTRL_ROCKCHIP) += pinctrl-rockchip.o
|
||||||
obj-$(CONFIG_PINCTRL_SINGLE) += pinctrl-single.o
|
obj-$(CONFIG_PINCTRL_SINGLE) += pinctrl-single.o
|
||||||
obj-$(CONFIG_PINCTRL_SIRF) += sirf/
|
|
||||||
obj-$(CONFIG_PINCTRL_SX150X) += pinctrl-sx150x.o
|
obj-$(CONFIG_PINCTRL_SX150X) += pinctrl-sx150x.o
|
||||||
obj-$(CONFIG_ARCH_TEGRA) += tegra/
|
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_XWAY) += pinctrl-xway.o
|
||||||
obj-$(CONFIG_PINCTRL_LANTIQ) += pinctrl-lantiq.o
|
obj-$(CONFIG_PINCTRL_LANTIQ) += pinctrl-lantiq.o
|
||||||
obj-$(CONFIG_PINCTRL_LPC18XX) += pinctrl-lpc18xx.o
|
obj-$(CONFIG_PINCTRL_LPC18XX) += pinctrl-lpc18xx.o
|
||||||
|
@ -71,6 +68,5 @@ obj-y += ti/
|
||||||
obj-$(CONFIG_PINCTRL_UNIPHIER) += uniphier/
|
obj-$(CONFIG_PINCTRL_UNIPHIER) += uniphier/
|
||||||
obj-$(CONFIG_ARCH_VT8500) += vt8500/
|
obj-$(CONFIG_ARCH_VT8500) += vt8500/
|
||||||
obj-y += mediatek/
|
obj-y += mediatek/
|
||||||
obj-$(CONFIG_PINCTRL_ZX) += zte/
|
|
||||||
obj-y += cirrus/
|
obj-y += cirrus/
|
||||||
obj-$(CONFIG_PINCTRL_VISCONTI) += visconti/
|
obj-$(CONFIG_PINCTRL_VISCONTI) += visconti/
|
||||||
|
|
|
@ -12,18 +12,21 @@ config PINCTRL_OWL
|
||||||
|
|
||||||
config PINCTRL_S500
|
config PINCTRL_S500
|
||||||
bool "Actions Semi S500 pinctrl driver"
|
bool "Actions Semi S500 pinctrl driver"
|
||||||
|
depends on ARM || COMPILE_TEST
|
||||||
depends on PINCTRL_OWL
|
depends on PINCTRL_OWL
|
||||||
help
|
help
|
||||||
Say Y here to enable Actions Semi S500 pinctrl driver
|
Say Y here to enable Actions Semi S500 pinctrl driver
|
||||||
|
|
||||||
config PINCTRL_S700
|
config PINCTRL_S700
|
||||||
bool "Actions Semi S700 pinctrl driver"
|
bool "Actions Semi S700 pinctrl driver"
|
||||||
|
depends on ARM64 || COMPILE_TEST
|
||||||
depends on PINCTRL_OWL
|
depends on PINCTRL_OWL
|
||||||
help
|
help
|
||||||
Say Y here to enable Actions Semi S700 pinctrl driver
|
Say Y here to enable Actions Semi S700 pinctrl driver
|
||||||
|
|
||||||
config PINCTRL_S900
|
config PINCTRL_S900
|
||||||
bool "Actions Semi S900 pinctrl driver"
|
bool "Actions Semi S900 pinctrl driver"
|
||||||
|
depends on ARM64 || COMPILE_TEST
|
||||||
depends on PINCTRL_OWL
|
depends on PINCTRL_OWL
|
||||||
help
|
help
|
||||||
Say Y here to enable Actions Semi S900 pinctrl driver
|
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);
|
*config = pinconf_to_config_packed(param, arg);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int owl_group_config_set(struct pinctrl_dev *pctrldev,
|
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) {
|
switch (param) {
|
||||||
case PIN_CONFIG_BIAS_DISABLE:
|
case PIN_CONFIG_BIAS_DISABLE:
|
||||||
ns2_pin_get_pull(pctldev, pin, &pull_up, &pull_down);
|
ns2_pin_get_pull(pctldev, pin, &pull_up, &pull_down);
|
||||||
if ((pull_up == false) && (pull_down == false))
|
if (!pull_up && !pull_down)
|
||||||
return 0;
|
return 0;
|
||||||
else
|
else
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
|
@ -2117,7 +2117,6 @@ struct pinctrl_dev *pinctrl_register(struct pinctrl_desc *pctldesc,
|
||||||
return ERR_PTR(error);
|
return ERR_PTR(error);
|
||||||
|
|
||||||
return pctldev;
|
return pctldev;
|
||||||
|
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(pinctrl_register);
|
EXPORT_SYMBOL_GPL(pinctrl_register);
|
||||||
|
|
||||||
|
|
|
@ -290,7 +290,6 @@ static const struct pinctrl_ops imx1_pctrl_ops = {
|
||||||
.pin_dbg_show = imx1_pin_dbg_show,
|
.pin_dbg_show = imx1_pin_dbg_show,
|
||||||
.dt_node_to_map = imx1_dt_node_to_map,
|
.dt_node_to_map = imx1_dt_node_to_map,
|
||||||
.dt_free_map = imx1_dt_free_map,
|
.dt_free_map = imx1_dt_free_map,
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static int imx1_pmx_set(struct pinctrl_dev *pctldev, unsigned selector,
|
static int imx1_pmx_set(struct pinctrl_dev *pctldev, unsigned selector,
|
||||||
|
|
|
@ -29,6 +29,16 @@
|
||||||
#define REVID_SHIFT 16
|
#define REVID_SHIFT 16
|
||||||
#define REVID_MASK GENMASK(31, 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 PADBAR 0x00c
|
||||||
|
|
||||||
#define PADOWN_BITS 4
|
#define PADOWN_BITS 4
|
||||||
|
@ -1321,34 +1331,19 @@ static int intel_gpio_probe(struct intel_pinctrl *pctrl, int irq)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int intel_pinctrl_add_padgroups(struct intel_pinctrl *pctrl,
|
static int intel_pinctrl_add_padgroups_by_gpps(struct intel_pinctrl *pctrl,
|
||||||
struct intel_community *community)
|
struct intel_community *community)
|
||||||
{
|
{
|
||||||
struct intel_padgroup *gpps;
|
struct intel_padgroup *gpps;
|
||||||
unsigned int npins = community->npins;
|
|
||||||
unsigned int padown_num = 0;
|
unsigned int padown_num = 0;
|
||||||
size_t ngpps, i;
|
size_t i, ngpps = community->ngpps;
|
||||||
|
|
||||||
if (community->gpps)
|
|
||||||
ngpps = community->ngpps;
|
|
||||||
else
|
|
||||||
ngpps = DIV_ROUND_UP(community->npins, community->gpp_size);
|
|
||||||
|
|
||||||
gpps = devm_kcalloc(pctrl->dev, ngpps, sizeof(*gpps), GFP_KERNEL);
|
gpps = devm_kcalloc(pctrl->dev, ngpps, sizeof(*gpps), GFP_KERNEL);
|
||||||
if (!gpps)
|
if (!gpps)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
for (i = 0; i < ngpps; i++) {
|
for (i = 0; i < ngpps; i++) {
|
||||||
if (community->gpps) {
|
gpps[i] = community->gpps[i];
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (gpps[i].size > 32)
|
if (gpps[i].size > 32)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -1366,6 +1361,38 @@ static int intel_pinctrl_add_padgroups(struct intel_pinctrl *pctrl,
|
||||||
break;
|
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;
|
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++) {
|
for (i = 0; i < pctrl->ncommunities; i++) {
|
||||||
struct intel_community *community = &pctrl->communities[i];
|
struct intel_community *community = &pctrl->communities[i];
|
||||||
void __iomem *regs;
|
void __iomem *regs;
|
||||||
u32 padbar;
|
u32 offset;
|
||||||
|
u32 value;
|
||||||
|
|
||||||
*community = pctrl->soc->communities[i];
|
*community = pctrl->soc->communities[i];
|
||||||
|
|
||||||
|
@ -1463,27 +1491,48 @@ static int intel_pinctrl_probe(struct platform_device *pdev,
|
||||||
if (IS_ERR(regs))
|
if (IS_ERR(regs))
|
||||||
return PTR_ERR(regs);
|
return PTR_ERR(regs);
|
||||||
|
|
||||||
/*
|
/* Determine community features based on the revision */
|
||||||
* Determine community features based on the revision if
|
value = readl(regs + REVID);
|
||||||
* not specified already.
|
if (((value & REVID_MASK) >> REVID_SHIFT) >= 0x94) {
|
||||||
*/
|
community->features |= PINCTRL_FEATURE_DEBOUNCE;
|
||||||
if (!community->features) {
|
community->features |= PINCTRL_FEATURE_1K_PD;
|
||||||
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 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 */
|
/* Read offset of the pad configuration registers */
|
||||||
padbar = readl(regs + PADBAR);
|
offset = readl(regs + PADBAR);
|
||||||
|
|
||||||
community->regs = regs;
|
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)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -143,6 +143,10 @@ struct intel_community {
|
||||||
/* Additional features supported by the hardware */
|
/* Additional features supported by the hardware */
|
||||||
#define PINCTRL_FEATURE_DEBOUNCE BIT(0)
|
#define PINCTRL_FEATURE_DEBOUNCE BIT(0)
|
||||||
#define PINCTRL_FEATURE_1K_PD BIT(1)
|
#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
|
* 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[] = {
|
static const struct acpi_device_id tgl_pinctrl_acpi_match[] = {
|
||||||
{ "INT34C5", (kernel_ulong_t)&tgllp_soc_data },
|
{ "INT34C5", (kernel_ulong_t)&tgllp_soc_data },
|
||||||
{ "INT34C6", (kernel_ulong_t)&tglh_soc_data },
|
{ "INT34C6", (kernel_ulong_t)&tglh_soc_data },
|
||||||
|
{ "INTC1055", (kernel_ulong_t)&tgllp_soc_data },
|
||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(acpi, tgl_pinctrl_acpi_match);
|
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)
|
static int mtk_eint_set_type(struct irq_data *d, unsigned int type)
|
||||||
{
|
{
|
||||||
struct mtk_eint *eint = irq_data_get_irq_chip_data(d);
|
struct mtk_eint *eint = irq_data_get_irq_chip_data(d);
|
||||||
|
bool masked;
|
||||||
u32 mask = BIT(d->hwirq & 0x1f);
|
u32 mask = BIT(d->hwirq & 0x1f);
|
||||||
void __iomem *reg;
|
void __iomem *reg;
|
||||||
|
|
||||||
|
@ -173,6 +174,13 @@ static int mtk_eint_set_type(struct irq_data *d, unsigned int type)
|
||||||
else
|
else
|
||||||
eint->dual_edge[d->hwirq] = 0;
|
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)) {
|
if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_EDGE_FALLING)) {
|
||||||
reg = mtk_eint_get_offset(eint, d->hwirq, eint->regs->pol_clr);
|
reg = mtk_eint_get_offset(eint, d->hwirq, eint->regs->pol_clr);
|
||||||
writel(mask, reg);
|
writel(mask, reg);
|
||||||
|
@ -189,8 +197,9 @@ static int mtk_eint_set_type(struct irq_data *d, unsigned int type)
|
||||||
writel(mask, reg);
|
writel(mask, reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (eint->dual_edge[d->hwirq])
|
mtk_eint_ack(d);
|
||||||
mtk_eint_flip_edge(eint, d->hwirq);
|
if (!masked)
|
||||||
|
mtk_eint_unmask(d);
|
||||||
|
|
||||||
return 0;
|
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->direction_output = mtk_gpio_direction_output;
|
||||||
chip->get = mtk_gpio_get;
|
chip->get = mtk_gpio_get;
|
||||||
chip->set = mtk_gpio_set;
|
chip->set = mtk_gpio_set;
|
||||||
chip->to_irq = mtk_gpio_to_irq,
|
chip->to_irq = mtk_gpio_to_irq;
|
||||||
chip->set_config = mtk_gpio_set_config,
|
chip->set_config = mtk_gpio_set_config;
|
||||||
chip->base = -1;
|
chip->base = -1;
|
||||||
chip->ngpio = hw->soc->npins;
|
chip->ngpio = hw->soc->npins;
|
||||||
chip->of_node = np;
|
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->direction_output = mtk_gpio_direction_output;
|
||||||
chip->get = mtk_gpio_get;
|
chip->get = mtk_gpio_get;
|
||||||
chip->set = mtk_gpio_set;
|
chip->set = mtk_gpio_set;
|
||||||
chip->to_irq = mtk_gpio_to_irq,
|
chip->to_irq = mtk_gpio_to_irq;
|
||||||
chip->set_config = mtk_gpio_set_config,
|
chip->set_config = mtk_gpio_set_config;
|
||||||
chip->base = -1;
|
chip->base = -1;
|
||||||
chip->ngpio = hw->soc->npins;
|
chip->ngpio = hw->soc->npins;
|
||||||
chip->of_node = np;
|
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("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("led2_od", 13, 1, BIT(22), BIT(22), 0, "led"),
|
||||||
PIN_GRP_GPIO_2("led3_od", 14, 1, BIT(23), BIT(23), 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[] = {
|
static struct armada_37xx_pin_group armada_37xx_sb_groups[] = {
|
||||||
|
|
|
@ -923,7 +923,7 @@ struct npcm7xx_pincfg {
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct npcm7xx_pincfg 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(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(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)),
|
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_DIR_MASK BIT(8)
|
||||||
#define ATMEL_PIO_PUEN_MASK BIT(9)
|
#define ATMEL_PIO_PUEN_MASK BIT(9)
|
||||||
#define ATMEL_PIO_PDEN_MASK BIT(10)
|
#define ATMEL_PIO_PDEN_MASK BIT(10)
|
||||||
|
#define ATMEL_PIO_SR_MASK BIT(11)
|
||||||
#define ATMEL_PIO_IFEN_MASK BIT(12)
|
#define ATMEL_PIO_IFEN_MASK BIT(12)
|
||||||
#define ATMEL_PIO_IFSCEN_MASK BIT(13)
|
#define ATMEL_PIO_IFSCEN_MASK BIT(13)
|
||||||
#define ATMEL_PIO_OPD_MASK BIT(14)
|
#define ATMEL_PIO_OPD_MASK BIT(14)
|
||||||
|
@ -76,10 +77,12 @@
|
||||||
* @nbanks: number of PIO banks
|
* @nbanks: number of PIO banks
|
||||||
* @last_bank_count: number of lines in the last bank (can be less than
|
* @last_bank_count: number of lines in the last bank (can be less than
|
||||||
* the rest of the banks).
|
* the rest of the banks).
|
||||||
|
* @slew_rate_support: slew rate support
|
||||||
*/
|
*/
|
||||||
struct atmel_pioctrl_data {
|
struct atmel_pioctrl_data {
|
||||||
unsigned nbanks;
|
unsigned int nbanks;
|
||||||
unsigned last_bank_count;
|
unsigned int last_bank_count;
|
||||||
|
unsigned int slew_rate_support;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct atmel_group {
|
struct atmel_group {
|
||||||
|
@ -88,11 +91,11 @@ struct atmel_group {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct atmel_pin {
|
struct atmel_pin {
|
||||||
unsigned pin_id;
|
unsigned int pin_id;
|
||||||
unsigned mux;
|
unsigned int mux;
|
||||||
unsigned ioset;
|
unsigned int ioset;
|
||||||
unsigned bank;
|
unsigned int bank;
|
||||||
unsigned line;
|
unsigned int line;
|
||||||
const char *device;
|
const char *device;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -117,20 +120,21 @@ struct atmel_pin {
|
||||||
* @pm_suspend_backup: backup/restore register values on suspend/resume
|
* @pm_suspend_backup: backup/restore register values on suspend/resume
|
||||||
* @dev: device entry for the Atmel PIO controller.
|
* @dev: device entry for the Atmel PIO controller.
|
||||||
* @node: node of the Atmel PIO controller.
|
* @node: node of the Atmel PIO controller.
|
||||||
|
* @slew_rate_support: slew rate support
|
||||||
*/
|
*/
|
||||||
struct atmel_pioctrl {
|
struct atmel_pioctrl {
|
||||||
void __iomem *reg_base;
|
void __iomem *reg_base;
|
||||||
struct clk *clk;
|
struct clk *clk;
|
||||||
unsigned nbanks;
|
unsigned int nbanks;
|
||||||
struct pinctrl_dev *pinctrl_dev;
|
struct pinctrl_dev *pinctrl_dev;
|
||||||
struct atmel_group *groups;
|
struct atmel_group *groups;
|
||||||
const char * const *group_names;
|
const char * const *group_names;
|
||||||
struct atmel_pin **pins;
|
struct atmel_pin **pins;
|
||||||
unsigned npins;
|
unsigned int npins;
|
||||||
struct gpio_chip *gpio_chip;
|
struct gpio_chip *gpio_chip;
|
||||||
struct irq_domain *irq_domain;
|
struct irq_domain *irq_domain;
|
||||||
int *irqs;
|
int *irqs;
|
||||||
unsigned *pm_wakeup_sources;
|
unsigned int *pm_wakeup_sources;
|
||||||
struct {
|
struct {
|
||||||
u32 imr;
|
u32 imr;
|
||||||
u32 odsr;
|
u32 odsr;
|
||||||
|
@ -138,6 +142,7 @@ struct atmel_pioctrl {
|
||||||
} *pm_suspend_backup;
|
} *pm_suspend_backup;
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
struct device_node *node;
|
struct device_node *node;
|
||||||
|
unsigned int slew_rate_support;
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char * const atmel_functions[] = {
|
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_pioctrl *atmel_pioctrl = irq_data_get_irq_chip_data(d);
|
||||||
struct atmel_pin *pin = atmel_pioctrl->pins[d->hwirq];
|
struct atmel_pin *pin = atmel_pioctrl->pins[d->hwirq];
|
||||||
unsigned reg;
|
unsigned int reg;
|
||||||
|
|
||||||
atmel_gpio_write(atmel_pioctrl, pin->bank, ATMEL_PIO_MSKR,
|
atmel_gpio_write(atmel_pioctrl, pin->bank, ATMEL_PIO_MSKR,
|
||||||
BIT(pin->line));
|
BIT(pin->line));
|
||||||
|
@ -263,7 +268,7 @@ static struct irq_chip atmel_gpio_irq_chip = {
|
||||||
.irq_set_wake = atmel_gpio_irq_set_wake,
|
.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);
|
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);
|
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_pioctrl *atmel_pioctrl = gpiochip_get_data(chip);
|
||||||
struct atmel_pin *pin = atmel_pioctrl->pins[offset];
|
struct atmel_pin *pin = atmel_pioctrl->pins[offset];
|
||||||
unsigned reg;
|
unsigned int reg;
|
||||||
|
|
||||||
atmel_gpio_write(atmel_pioctrl, pin->bank, ATMEL_PIO_MSKR,
|
atmel_gpio_write(atmel_pioctrl, pin->bank, ATMEL_PIO_MSKR,
|
||||||
BIT(pin->line));
|
BIT(pin->line));
|
||||||
|
@ -326,11 +332,11 @@ static int atmel_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
|
||||||
return 0;
|
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_pioctrl *atmel_pioctrl = gpiochip_get_data(chip);
|
||||||
struct atmel_pin *pin = atmel_pioctrl->pins[offset];
|
struct atmel_pin *pin = atmel_pioctrl->pins[offset];
|
||||||
unsigned reg;
|
unsigned int reg;
|
||||||
|
|
||||||
reg = atmel_gpio_read(atmel_pioctrl, pin->bank, ATMEL_PIO_PDSR);
|
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;
|
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)
|
int value)
|
||||||
{
|
{
|
||||||
struct atmel_pioctrl *atmel_pioctrl = gpiochip_get_data(chip);
|
struct atmel_pioctrl *atmel_pioctrl = gpiochip_get_data(chip);
|
||||||
struct atmel_pin *pin = atmel_pioctrl->pins[offset];
|
struct atmel_pin *pin = atmel_pioctrl->pins[offset];
|
||||||
unsigned reg;
|
unsigned int reg;
|
||||||
|
|
||||||
atmel_gpio_write(atmel_pioctrl, pin->bank,
|
atmel_gpio_write(atmel_pioctrl, pin->bank,
|
||||||
value ? ATMEL_PIO_SODR : ATMEL_PIO_CODR,
|
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;
|
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_pioctrl *atmel_pioctrl = gpiochip_get_data(chip);
|
||||||
struct atmel_pin *pin = atmel_pioctrl->pins[offset];
|
struct atmel_pin *pin = atmel_pioctrl->pins[offset];
|
||||||
|
@ -440,11 +447,11 @@ static struct gpio_chip atmel_gpio_chip = {
|
||||||
|
|
||||||
/* --- PINCTRL --- */
|
/* --- PINCTRL --- */
|
||||||
static unsigned int atmel_pin_config_read(struct pinctrl_dev *pctldev,
|
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);
|
struct atmel_pioctrl *atmel_pioctrl = pinctrl_dev_get_drvdata(pctldev);
|
||||||
unsigned bank = atmel_pioctrl->pins[pin_id]->bank;
|
unsigned int bank = atmel_pioctrl->pins[pin_id]->bank;
|
||||||
unsigned line = atmel_pioctrl->pins[pin_id]->line;
|
unsigned int line = atmel_pioctrl->pins[pin_id]->line;
|
||||||
void __iomem *addr = atmel_pioctrl->reg_base
|
void __iomem *addr = atmel_pioctrl->reg_base
|
||||||
+ bank * ATMEL_PIO_BANK_OFFSET;
|
+ 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,
|
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);
|
struct atmel_pioctrl *atmel_pioctrl = pinctrl_dev_get_drvdata(pctldev);
|
||||||
unsigned bank = atmel_pioctrl->pins[pin_id]->bank;
|
unsigned int bank = atmel_pioctrl->pins[pin_id]->bank;
|
||||||
unsigned line = atmel_pioctrl->pins[pin_id]->line;
|
unsigned int line = atmel_pioctrl->pins[pin_id]->line;
|
||||||
void __iomem *addr = atmel_pioctrl->reg_base
|
void __iomem *addr = atmel_pioctrl->reg_base
|
||||||
+ bank * ATMEL_PIO_BANK_OFFSET;
|
+ 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,
|
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);
|
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,
|
static int atmel_pctl_get_group_pins(struct pinctrl_dev *pctldev,
|
||||||
unsigned selector, const unsigned **pins,
|
unsigned int selector,
|
||||||
unsigned *num_pins)
|
const unsigned int **pins,
|
||||||
|
unsigned int *num_pins)
|
||||||
{
|
{
|
||||||
struct atmel_pioctrl *atmel_pioctrl = pinctrl_dev_get_drvdata(pctldev);
|
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;
|
*num_pins = 1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct atmel_group *
|
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);
|
struct atmel_pioctrl *atmel_pioctrl = pinctrl_dev_get_drvdata(pctldev);
|
||||||
int i;
|
int i;
|
||||||
|
@ -519,7 +527,7 @@ static int atmel_pctl_xlate_pinfunc(struct pinctrl_dev *pctldev,
|
||||||
const char **func_name)
|
const char **func_name)
|
||||||
{
|
{
|
||||||
struct atmel_pioctrl *atmel_pioctrl = pinctrl_dev_get_drvdata(pctldev);
|
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;
|
struct atmel_group *grp;
|
||||||
|
|
||||||
pin_id = ATMEL_GET_PIN_NO(pinfunc);
|
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,
|
static int atmel_pctl_dt_subnode_to_map(struct pinctrl_dev *pctldev,
|
||||||
struct device_node *np,
|
struct device_node *np,
|
||||||
struct pinctrl_map **map,
|
struct pinctrl_map **map,
|
||||||
unsigned *reserved_maps,
|
unsigned int *reserved_maps,
|
||||||
unsigned *num_maps)
|
unsigned int *num_maps)
|
||||||
{
|
{
|
||||||
unsigned num_pins, num_configs, reserve;
|
unsigned int num_pins, num_configs, reserve;
|
||||||
unsigned long *configs;
|
unsigned long *configs;
|
||||||
struct property *pins;
|
struct property *pins;
|
||||||
u32 pinfunc;
|
u32 pinfunc;
|
||||||
|
@ -623,10 +631,10 @@ exit:
|
||||||
static int atmel_pctl_dt_node_to_map(struct pinctrl_dev *pctldev,
|
static int atmel_pctl_dt_node_to_map(struct pinctrl_dev *pctldev,
|
||||||
struct device_node *np_config,
|
struct device_node *np_config,
|
||||||
struct pinctrl_map **map,
|
struct pinctrl_map **map,
|
||||||
unsigned *num_maps)
|
unsigned int *num_maps)
|
||||||
{
|
{
|
||||||
struct device_node *np;
|
struct device_node *np;
|
||||||
unsigned reserved_maps;
|
unsigned int reserved_maps;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
*map = NULL;
|
*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,
|
static const char *atmel_pmx_get_function_name(struct pinctrl_dev *pctldev,
|
||||||
unsigned selector)
|
unsigned int selector)
|
||||||
{
|
{
|
||||||
return atmel_functions[selector];
|
return atmel_functions[selector];
|
||||||
}
|
}
|
||||||
|
|
||||||
static int atmel_pmx_get_function_groups(struct pinctrl_dev *pctldev,
|
static int atmel_pmx_get_function_groups(struct pinctrl_dev *pctldev,
|
||||||
unsigned selector,
|
unsigned int selector,
|
||||||
const char * const **groups,
|
const char * const **groups,
|
||||||
unsigned * const num_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,
|
static int atmel_pmx_set_mux(struct pinctrl_dev *pctldev,
|
||||||
unsigned function,
|
unsigned int function,
|
||||||
unsigned group)
|
unsigned int group)
|
||||||
{
|
{
|
||||||
struct atmel_pioctrl *atmel_pioctrl = pinctrl_dev_get_drvdata(pctldev);
|
struct atmel_pioctrl *atmel_pioctrl = pinctrl_dev_get_drvdata(pctldev);
|
||||||
unsigned pin;
|
unsigned int pin;
|
||||||
u32 conf;
|
u32 conf;
|
||||||
|
|
||||||
dev_dbg(pctldev->dev, "enable function %s group %s\n",
|
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,
|
static int atmel_conf_pin_config_group_get(struct pinctrl_dev *pctldev,
|
||||||
unsigned group,
|
unsigned int group,
|
||||||
unsigned long *config)
|
unsigned long *config)
|
||||||
{
|
{
|
||||||
struct atmel_pioctrl *atmel_pioctrl = pinctrl_dev_get_drvdata(pctldev);
|
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;
|
struct atmel_group *grp = atmel_pioctrl->groups + group;
|
||||||
unsigned pin_id = grp->pin;
|
unsigned int pin_id = grp->pin;
|
||||||
u32 res;
|
u32 res;
|
||||||
|
|
||||||
res = atmel_pin_config_read(pctldev, pin_id);
|
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;
|
return -EINVAL;
|
||||||
arg = 1;
|
arg = 1;
|
||||||
break;
|
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:
|
case ATMEL_PIN_CONFIG_DRIVE_STRENGTH:
|
||||||
if (!(res & ATMEL_PIO_DRVSTR_MASK))
|
if (!(res & ATMEL_PIO_DRVSTR_MASK))
|
||||||
return -EINVAL;
|
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,
|
static int atmel_conf_pin_config_group_set(struct pinctrl_dev *pctldev,
|
||||||
unsigned group,
|
unsigned int group,
|
||||||
unsigned long *configs,
|
unsigned long *configs,
|
||||||
unsigned num_configs)
|
unsigned int num_configs)
|
||||||
{
|
{
|
||||||
struct atmel_pioctrl *atmel_pioctrl = pinctrl_dev_get_drvdata(pctldev);
|
struct atmel_pioctrl *atmel_pioctrl = pinctrl_dev_get_drvdata(pctldev);
|
||||||
struct atmel_group *grp = atmel_pioctrl->groups + group;
|
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;
|
u32 mask, conf = 0;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
conf = atmel_pin_config_read(pctldev, pin_id);
|
conf = atmel_pin_config_read(pctldev, pin_id);
|
||||||
|
|
||||||
for (i = 0; i < num_configs; i++) {
|
for (i = 0; i < num_configs; i++) {
|
||||||
unsigned param = pinconf_to_config_param(configs[i]);
|
unsigned int param = pinconf_to_config_param(configs[i]);
|
||||||
unsigned arg = pinconf_to_config_argument(configs[i]);
|
unsigned int arg = pinconf_to_config_argument(configs[i]);
|
||||||
|
|
||||||
dev_dbg(pctldev->dev, "%s: pin=%u, config=0x%lx\n",
|
dev_dbg(pctldev->dev, "%s: pin=%u, config=0x%lx\n",
|
||||||
__func__, pin_id, configs[i]);
|
__func__, pin_id, configs[i]);
|
||||||
|
|
||||||
|
/* Keep slew rate enabled by default. */
|
||||||
|
if (atmel_pioctrl->slew_rate_support)
|
||||||
|
conf |= ATMEL_PIO_SR_MASK;
|
||||||
|
|
||||||
switch (param) {
|
switch (param) {
|
||||||
case PIN_CONFIG_BIAS_DISABLE:
|
case PIN_CONFIG_BIAS_DISABLE:
|
||||||
conf &= (~ATMEL_PIO_PUEN_MASK);
|
conf &= (~ATMEL_PIO_PUEN_MASK);
|
||||||
|
@ -850,6 +869,13 @@ static int atmel_conf_pin_config_group_set(struct pinctrl_dev *pctldev,
|
||||||
ATMEL_PIO_SODR);
|
ATMEL_PIO_SODR);
|
||||||
}
|
}
|
||||||
break;
|
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:
|
case ATMEL_PIN_CONFIG_DRIVE_STRENGTH:
|
||||||
switch (arg) {
|
switch (arg) {
|
||||||
case ATMEL_PIO_DRVSTR_LO:
|
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,
|
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);
|
struct atmel_pioctrl *atmel_pioctrl = pinctrl_dev_get_drvdata(pctldev);
|
||||||
u32 conf;
|
u32 conf;
|
||||||
|
@ -901,6 +928,8 @@ static void atmel_conf_pin_config_dbg_show(struct pinctrl_dev *pctldev,
|
||||||
seq_printf(s, "%s ", "open-drain");
|
seq_printf(s, "%s ", "open-drain");
|
||||||
if (conf & ATMEL_PIO_SCHMITT_MASK)
|
if (conf & ATMEL_PIO_SCHMITT_MASK)
|
||||||
seq_printf(s, "%s ", "schmitt");
|
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) {
|
if (conf & ATMEL_PIO_DRVSTR_MASK) {
|
||||||
switch ((conf & ATMEL_PIO_DRVSTR_MASK) >> ATMEL_PIO_DRVSTR_OFFSET) {
|
switch ((conf & ATMEL_PIO_DRVSTR_MASK) >> ATMEL_PIO_DRVSTR_OFFSET) {
|
||||||
case ATMEL_PIO_DRVSTR_ME:
|
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 = {
|
static const struct atmel_pioctrl_data microchip_sama7g5_pioctrl_data = {
|
||||||
.nbanks = 5,
|
.nbanks = 5,
|
||||||
.last_bank_count = 8, /* sama7g5 has only PE0 to PE7 */
|
.last_bank_count = 8, /* sama7g5 has only PE0 to PE7 */
|
||||||
|
.slew_rate_support = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct of_device_id atmel_pctrl_of_match[] = {
|
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_PIO_NPINS_PER_BANK;
|
||||||
atmel_pioctrl->npins += atmel_pioctrl_data->last_bank_count;
|
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);
|
atmel_pioctrl->reg_base = devm_platform_ioremap_resource(pdev, 0);
|
||||||
if (IS_ERR(atmel_pioctrl->reg_base))
|
if (IS_ERR(atmel_pioctrl->reg_base))
|
||||||
|
@ -1081,8 +1112,8 @@ static int atmel_pinctrl_probe(struct platform_device *pdev)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
for (i = 0 ; i < atmel_pioctrl->npins; i++) {
|
for (i = 0 ; i < atmel_pioctrl->npins; i++) {
|
||||||
struct atmel_group *group = atmel_pioctrl->groups + i;
|
struct atmel_group *group = atmel_pioctrl->groups + i;
|
||||||
unsigned bank = ATMEL_PIO_BANK(i);
|
unsigned int bank = ATMEL_PIO_BANK(i);
|
||||||
unsigned line = ATMEL_PIO_LINE(i);
|
unsigned int line = ATMEL_PIO_LINE(i);
|
||||||
|
|
||||||
atmel_pioctrl->pins[i] = devm_kzalloc(dev,
|
atmel_pioctrl->pins[i] = devm_kzalloc(dev,
|
||||||
sizeof(**atmel_pioctrl->pins), GFP_KERNEL);
|
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,
|
.get_slewrate = at91_mux_sam9x60_get_slewrate,
|
||||||
.set_slewrate = at91_mux_sam9x60_set_slewrate,
|
.set_slewrate = at91_mux_sam9x60_set_slewrate,
|
||||||
.irq_type = alt_gpio_irq_type,
|
.irq_type = alt_gpio_irq_type,
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct at91_pinctrl_mux_ops sama5d3_ops = {
|
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_disable = gpio_irq_mask;
|
||||||
gpio_irqchip->irq_mask = gpio_irq_mask;
|
gpio_irqchip->irq_mask = gpio_irq_mask;
|
||||||
gpio_irqchip->irq_unmask = gpio_irq_unmask;
|
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;
|
gpio_irqchip->irq_set_type = at91_gpio->ops->irq_type;
|
||||||
|
|
||||||
/* Disable irqs of this PIO controller */
|
/* 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,
|
0x26, 0x27, 0x28, 0x29,
|
||||||
0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31,
|
0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31,
|
||||||
};
|
};
|
||||||
static int jz4760_lcd_24bit_pins[] = {
|
static int jz4760_lcd_8bit_pins[] = {
|
||||||
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
|
0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x4c,
|
||||||
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
|
0x4d, 0x52, 0x53,
|
||||||
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
|
|
||||||
0x58, 0x59, 0x5a, 0x5b,
|
|
||||||
};
|
};
|
||||||
|
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_pwm0_pins[] = { 0x80, };
|
||||||
static int jz4760_pwm_pwm1_pins[] = { 0x81, };
|
static int jz4760_pwm_pwm1_pins[] = { 0x81, };
|
||||||
static int jz4760_pwm_pwm2_pins[] = { 0x82, };
|
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_pwm5_pins[] = { 0x85, };
|
||||||
static int jz4760_pwm_pwm6_pins[] = { 0x6a, };
|
static int jz4760_pwm_pwm6_pins[] = { 0x6a, };
|
||||||
static int jz4760_pwm_pwm7_pins[] = { 0x6b, };
|
static int jz4760_pwm_pwm7_pins[] = { 0x6b, };
|
||||||
|
static int jz4760_otg_pins[] = { 0x8a, };
|
||||||
|
|
||||||
static u8 jz4760_uart3_data_funcs[] = { 0, 1, };
|
static u8 jz4760_uart3_data_funcs[] = { 0, 1, };
|
||||||
static u8 jz4760_mmc0_1bit_a_funcs[] = { 1, 1, 0, };
|
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("i2c0-data", jz4760_i2c0, 0),
|
||||||
INGENIC_PIN_GROUP("i2c1-data", jz4760_i2c1, 0),
|
INGENIC_PIN_GROUP("i2c1-data", jz4760_i2c1, 0),
|
||||||
INGENIC_PIN_GROUP("cim-data", jz4760_cim, 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),
|
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("pwm0", jz4760_pwm_pwm0, 0),
|
||||||
INGENIC_PIN_GROUP("pwm1", jz4760_pwm_pwm1, 0),
|
INGENIC_PIN_GROUP("pwm1", jz4760_pwm_pwm1, 0),
|
||||||
INGENIC_PIN_GROUP("pwm2", jz4760_pwm_pwm2, 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("pwm5", jz4760_pwm_pwm5, 0),
|
||||||
INGENIC_PIN_GROUP("pwm6", jz4760_pwm_pwm6, 0),
|
INGENIC_PIN_GROUP("pwm6", jz4760_pwm_pwm6, 0),
|
||||||
INGENIC_PIN_GROUP("pwm7", jz4760_pwm_pwm7, 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", };
|
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_i2c0_groups[] = { "i2c0-data", };
|
||||||
static const char *jz4760_i2c1_groups[] = { "i2c1-data", };
|
static const char *jz4760_i2c1_groups[] = { "i2c1-data", };
|
||||||
static const char *jz4760_cim_groups[] = { "cim-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_pwm0_groups[] = { "pwm0", };
|
||||||
static const char *jz4760_pwm1_groups[] = { "pwm1", };
|
static const char *jz4760_pwm1_groups[] = { "pwm1", };
|
||||||
static const char *jz4760_pwm2_groups[] = { "pwm2", };
|
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_pwm5_groups[] = { "pwm5", };
|
||||||
static const char *jz4760_pwm6_groups[] = { "pwm6", };
|
static const char *jz4760_pwm6_groups[] = { "pwm6", };
|
||||||
static const char *jz4760_pwm7_groups[] = { "pwm7", };
|
static const char *jz4760_pwm7_groups[] = { "pwm7", };
|
||||||
|
static const char *jz4760_otg_groups[] = { "otg-vbus", };
|
||||||
|
|
||||||
static const struct function_desc jz4760_functions[] = {
|
static const struct function_desc jz4760_functions[] = {
|
||||||
{ "uart0", jz4760_uart0_groups, ARRAY_SIZE(jz4760_uart0_groups), },
|
{ "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), },
|
{ "pwm5", jz4760_pwm5_groups, ARRAY_SIZE(jz4760_pwm5_groups), },
|
||||||
{ "pwm6", jz4760_pwm6_groups, ARRAY_SIZE(jz4760_pwm6_groups), },
|
{ "pwm6", jz4760_pwm6_groups, ARRAY_SIZE(jz4760_pwm6_groups), },
|
||||||
{ "pwm7", jz4760_pwm7_groups, ARRAY_SIZE(jz4760_pwm7_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 = {
|
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,
|
0xa9, 0xab, 0xaa, 0xac, 0xa5, 0xa4, 0xad, 0xae, 0xa6, 0xa8,
|
||||||
};
|
};
|
||||||
static int jz4770_mac_mii_pins[] = { 0xa7, 0xaf, };
|
static int jz4770_mac_mii_pins[] = { 0xa7, 0xaf, };
|
||||||
static int jz4770_otg_pins[] = { 0x8a, };
|
|
||||||
|
|
||||||
static const struct group_desc jz4770_groups[] = {
|
static const struct group_desc jz4770_groups[] = {
|
||||||
INGENIC_PIN_GROUP("uart0-data", jz4770_uart0_data, 0),
|
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("pwm7", jz4770_pwm_pwm7, 0),
|
||||||
INGENIC_PIN_GROUP("mac-rmii", jz4770_mac_rmii, 0),
|
INGENIC_PIN_GROUP("mac-rmii", jz4770_mac_rmii, 0),
|
||||||
INGENIC_PIN_GROUP("mac-mii", jz4770_mac_mii, 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", };
|
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_pwm6_groups[] = { "pwm6", };
|
||||||
static const char *jz4770_pwm7_groups[] = { "pwm7", };
|
static const char *jz4770_pwm7_groups[] = { "pwm7", };
|
||||||
static const char *jz4770_mac_groups[] = { "mac-rmii", "mac-mii", };
|
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[] = {
|
static const struct function_desc jz4770_functions[] = {
|
||||||
{ "uart0", jz4770_uart0_groups, ARRAY_SIZE(jz4770_uart0_groups), },
|
{ "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), },
|
{ "pwm6", jz4770_pwm6_groups, ARRAY_SIZE(jz4770_pwm6_groups), },
|
||||||
{ "pwm7", jz4770_pwm7_groups, ARRAY_SIZE(jz4770_pwm7_groups), },
|
{ "pwm7", jz4770_pwm7_groups, ARRAY_SIZE(jz4770_pwm7_groups), },
|
||||||
{ "mac", jz4770_mac_groups, ARRAY_SIZE(jz4770_mac_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 = {
|
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;
|
unsigned int i;
|
||||||
int err;
|
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);
|
jzpc = devm_kzalloc(dev, sizeof(*jzpc), GFP_KERNEL);
|
||||||
if (!jzpc)
|
if (!jzpc)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
@ -2400,7 +2424,7 @@ static int __init ingenic_pinctrl_probe(struct platform_device *pdev)
|
||||||
}
|
}
|
||||||
|
|
||||||
jzpc->dev = dev;
|
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);
|
pctl_desc = devm_kzalloc(&pdev->dev, sizeof(*pctl_desc), GFP_KERNEL);
|
||||||
if (!pctl_desc)
|
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[] = {
|
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,jz4740-pinctrl",
|
||||||
{ .compatible = "ingenic,jz4760-pinctrl", .data = &jz4760_chip_info },
|
.data = IF_ENABLED(CONFIG_MACH_JZ4740, &jz4740_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,jz4725b-pinctrl",
|
||||||
{ .compatible = "ingenic,x1000-pinctrl", .data = &x1000_chip_info },
|
.data = IF_ENABLED(CONFIG_MACH_JZ4725B, &jz4725b_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,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 = {
|
static struct platform_driver ingenic_pinctrl_driver = {
|
||||||
|
|
|
@ -777,6 +777,7 @@ static int pcs_add_function(struct pcs_device *pcs,
|
||||||
|
|
||||||
function->vals = vals;
|
function->vals = vals;
|
||||||
function->nvals = nvals;
|
function->nvals = nvals;
|
||||||
|
function->name = name;
|
||||||
|
|
||||||
selector = pinmux_generic_add_function(pcs->pctl, name,
|
selector = pinmux_generic_add_function(pcs->pctl, name,
|
||||||
pgnames, npgnames,
|
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);
|
st_regmap_field_bit_set_clear_pin(rt_p->delay_0, delay & 0x1, pin);
|
||||||
/* 2 bit delay, msb */
|
/* 2 bit delay, msb */
|
||||||
st_regmap_field_bit_set_clear_pin(rt_p->delay_1, delay & 0x2, pin);
|
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,
|
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);
|
sx150x_gpio_oscio_set(pctl, value);
|
||||||
else
|
else
|
||||||
__sx150x_gpio_set(pctl, offset, value);
|
__sx150x_gpio_set(pctl, offset, value);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sx150x_gpio_set_multiple(struct gpio_chip *chip,
|
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;
|
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++)
|
for (i = 0; i < num_groups; i++)
|
||||||
seq_printf(s, "%s ", groups[i]);
|
seq_printf(s, "%s ", groups[i]);
|
||||||
seq_puts(s, "]\n");
|
seq_puts(s, "]\n");
|
||||||
|
|
|
@ -220,6 +220,15 @@ config PINCTRL_SC7280
|
||||||
Qualcomm Technologies Inc TLMM block found on the Qualcomm
|
Qualcomm Technologies Inc TLMM block found on the Qualcomm
|
||||||
Technologies Inc SC7280 platform.
|
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
|
config PINCTRL_SDM660
|
||||||
tristate "Qualcomm Technologies Inc SDM660 pin controller driver"
|
tristate "Qualcomm Technologies Inc SDM660 pin controller driver"
|
||||||
depends on GPIOLIB && OF
|
depends on GPIOLIB && OF
|
||||||
|
@ -265,6 +274,15 @@ config PINCTRL_SM8250
|
||||||
Qualcomm Technologies Inc TLMM block found on the Qualcomm
|
Qualcomm Technologies Inc TLMM block found on the Qualcomm
|
||||||
Technologies Inc SM8250 platform.
|
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
|
config PINCTRL_LPASS_LPI
|
||||||
tristate "Qualcomm Technologies Inc LPASS LPI pin controller driver"
|
tristate "Qualcomm Technologies Inc LPASS LPI pin controller driver"
|
||||||
select PINMUX
|
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_QCOM_SSBI_PMIC) += pinctrl-ssbi-mpp.o
|
||||||
obj-$(CONFIG_PINCTRL_SC7180) += pinctrl-sc7180.o
|
obj-$(CONFIG_PINCTRL_SC7180) += pinctrl-sc7180.o
|
||||||
obj-$(CONFIG_PINCTRL_SC7280) += pinctrl-sc7280.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_SDM660) += pinctrl-sdm660.o
|
||||||
obj-$(CONFIG_PINCTRL_SDM845) += pinctrl-sdm845.o
|
obj-$(CONFIG_PINCTRL_SDM845) += pinctrl-sdm845.o
|
||||||
obj-$(CONFIG_PINCTRL_SDX55) += pinctrl-sdx55.o
|
obj-$(CONFIG_PINCTRL_SDX55) += pinctrl-sdx55.o
|
||||||
obj-$(CONFIG_PINCTRL_SM8150) += pinctrl-sm8150.o
|
obj-$(CONFIG_PINCTRL_SM8150) += pinctrl-sm8150.o
|
||||||
obj-$(CONFIG_PINCTRL_SM8250) += pinctrl-sm8250.o
|
obj-$(CONFIG_PINCTRL_SM8250) += pinctrl-sm8250.o
|
||||||
|
obj-$(CONFIG_PINCTRL_SM8350) += pinctrl-sm8350.o
|
||||||
obj-$(CONFIG_PINCTRL_LPASS_LPI) += pinctrl-lpass-lpi.o
|
obj-$(CONFIG_PINCTRL_LPASS_LPI) += pinctrl-lpass-lpi.o
|
||||||
|
|
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,
|
.ngpios = 151,
|
||||||
.wakeirq_map = sdm845_pdc_map,
|
.wakeirq_map = sdm845_pdc_map,
|
||||||
.nwakeirq_map = ARRAY_SIZE(sdm845_pdc_map),
|
.nwakeirq_map = ARRAY_SIZE(sdm845_pdc_map),
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct msm_pinctrl_soc_data sdm845_acpi_pinctrl = {
|
static const struct msm_pinctrl_soc_data sdm845_acpi_pinctrl = {
|
||||||
|
|
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[] = {
|
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,pm8841-mpp" }, /* 4 MPP's */
|
||||||
{ .compatible = "qcom,pm8916-mpp" }, /* 4 MPP's */
|
{ .compatible = "qcom,pm8916-mpp" }, /* 4 MPP's */
|
||||||
{ .compatible = "qcom,pm8941-mpp" }, /* 8 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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pm8xxx_mpp_dbg_show(struct seq_file *s, struct gpio_chip *chip)
|
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)
|
static int rt2880_pinmux_index(struct rt2880_priv *p)
|
||||||
{
|
{
|
||||||
struct rt2880_pmx_func **f;
|
|
||||||
struct rt2880_pmx_group *mux = p->groups;
|
struct rt2880_pmx_group *mux = p->groups;
|
||||||
int i, j, c = 0;
|
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,
|
p->group_names = devm_kcalloc(p->dev, p->group_count,
|
||||||
sizeof(char *), GFP_KERNEL);
|
sizeof(char *), GFP_KERNEL);
|
||||||
if (!p->group_names)
|
if (!p->group_names)
|
||||||
return -1;
|
return -ENOMEM;
|
||||||
|
|
||||||
for (i = 0; i < p->group_count; i++) {
|
for (i = 0; i < p->group_count; i++) {
|
||||||
p->group_names[i] = p->groups[i].name;
|
p->group_names[i] = p->groups[i].name;
|
||||||
|
@ -218,31 +217,31 @@ static int rt2880_pinmux_index(struct rt2880_priv *p)
|
||||||
p->func_count++;
|
p->func_count++;
|
||||||
|
|
||||||
/* allocate our function and group mapping index buffers */
|
/* allocate our function and group mapping index buffers */
|
||||||
f = p->func = devm_kcalloc(p->dev,
|
p->func = devm_kcalloc(p->dev, p->func_count,
|
||||||
p->func_count,
|
sizeof(*p->func), GFP_KERNEL);
|
||||||
sizeof(*p->func),
|
|
||||||
GFP_KERNEL);
|
|
||||||
gpio_func.groups = devm_kcalloc(p->dev, p->group_count, sizeof(int),
|
gpio_func.groups = devm_kcalloc(p->dev, p->group_count, sizeof(int),
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
if (!f || !gpio_func.groups)
|
if (!p->func || !gpio_func.groups)
|
||||||
return -1;
|
return -ENOMEM;
|
||||||
|
|
||||||
/* add a backpointer to the function so it knows its group */
|
/* add a backpointer to the function so it knows its group */
|
||||||
gpio_func.group_count = p->group_count;
|
gpio_func.group_count = p->group_count;
|
||||||
for (i = 0; i < gpio_func.group_count; i++)
|
for (i = 0; i < gpio_func.group_count; i++)
|
||||||
gpio_func.groups[i] = i;
|
gpio_func.groups[i] = i;
|
||||||
|
|
||||||
f[c] = &gpio_func;
|
p->func[c] = &gpio_func;
|
||||||
c++;
|
c++;
|
||||||
|
|
||||||
/* add remaining functions */
|
/* add remaining functions */
|
||||||
for (i = 0; i < p->group_count; i++) {
|
for (i = 0; i < p->group_count; i++) {
|
||||||
for (j = 0; j < p->groups[i].func_count; j++) {
|
for (j = 0; j < p->groups[i].func_count; j++) {
|
||||||
f[c] = &p->groups[i].func[j];
|
p->func[c] = &p->groups[i].func[j];
|
||||||
f[c]->groups = devm_kzalloc(p->dev, sizeof(int),
|
p->func[c]->groups = devm_kzalloc(p->dev, sizeof(int),
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
f[c]->groups[0] = i;
|
if (!p->func[c]->groups)
|
||||||
f[c]->group_count = 1;
|
return -ENOMEM;
|
||||||
|
p->func[c]->groups[0] = i;
|
||||||
|
p->func[c]->group_count = 1;
|
||||||
c++;
|
c++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -280,10 +279,8 @@ static int rt2880_pinmux_pins(struct rt2880_priv *p)
|
||||||
/* the pads needed to tell pinctrl about our pins */
|
/* the pads needed to tell pinctrl about our pins */
|
||||||
p->pads = devm_kcalloc(p->dev, p->max_pins,
|
p->pads = devm_kcalloc(p->dev, p->max_pins,
|
||||||
sizeof(struct pinctrl_pin_desc), GFP_KERNEL);
|
sizeof(struct pinctrl_pin_desc), GFP_KERNEL);
|
||||||
if (!p->pads || !p->gpio) {
|
if (!p->pads || !p->gpio)
|
||||||
dev_err(p->dev, "Failed to allocate gpio data\n");
|
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
|
||||||
|
|
||||||
memset(p->gpio, 1, sizeof(u8) * p->max_pins);
|
memset(p->gpio, 1, sizeof(u8) * p->max_pins);
|
||||||
for (i = 0; i < p->func_count; i++) {
|
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 rt2880_priv *p;
|
||||||
struct pinctrl_dev *dev;
|
struct pinctrl_dev *dev;
|
||||||
|
int err;
|
||||||
|
|
||||||
if (!rt2880_pinmux_data)
|
if (!rt2880_pinmux_data)
|
||||||
return -ENOTSUPP;
|
return -ENOTSUPP;
|
||||||
|
@ -333,19 +331,20 @@ static int rt2880_pinmux_probe(struct platform_device *pdev)
|
||||||
platform_set_drvdata(pdev, p);
|
platform_set_drvdata(pdev, p);
|
||||||
|
|
||||||
/* init the device */
|
/* init the device */
|
||||||
if (rt2880_pinmux_index(p)) {
|
err = rt2880_pinmux_index(p);
|
||||||
|
if (err) {
|
||||||
dev_err(&pdev->dev, "failed to load index\n");
|
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");
|
dev_err(&pdev->dev, "failed to load pins\n");
|
||||||
return -EINVAL;
|
return err;
|
||||||
}
|
}
|
||||||
dev = pinctrl_register(p->desc, &pdev->dev, p);
|
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[] = {
|
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);
|
return platform_driver_register(&rt2880_pinmux_driver);
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,6 +36,7 @@ config PINCTRL_RENESAS
|
||||||
select PINCTRL_PFC_R8A77980 if ARCH_R8A77980
|
select PINCTRL_PFC_R8A77980 if ARCH_R8A77980
|
||||||
select PINCTRL_PFC_R8A77990 if ARCH_R8A77990
|
select PINCTRL_PFC_R8A77990 if ARCH_R8A77990
|
||||||
select PINCTRL_PFC_R8A77995 if ARCH_R8A77995
|
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_SH7203 if CPU_SUBTYPE_SH7203
|
||||||
select PINCTRL_PFC_SH7264 if CPU_SUBTYPE_SH7264
|
select PINCTRL_PFC_SH7264 if CPU_SUBTYPE_SH7264
|
||||||
select PINCTRL_PFC_SH7269 if CPU_SUBTYPE_SH7269
|
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
|
bool "pin control support for R-Car V3M" if COMPILE_TEST
|
||||||
select PINCTRL_SH_PFC
|
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
|
config PINCTRL_PFC_R8A7740
|
||||||
bool "pin control support for R-Mobile A1" if COMPILE_TEST
|
bool "pin control support for R-Mobile A1" if COMPILE_TEST
|
||||||
select PINCTRL_SH_PFC_GPIO
|
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_R8A77980) += pfc-r8a77980.o
|
||||||
obj-$(CONFIG_PINCTRL_PFC_R8A77990) += pfc-r8a77990.o
|
obj-$(CONFIG_PINCTRL_PFC_R8A77990) += pfc-r8a77990.o
|
||||||
obj-$(CONFIG_PINCTRL_PFC_R8A77995) += pfc-r8a77995.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_SH7203) += pfc-sh7203.o
|
||||||
obj-$(CONFIG_PINCTRL_PFC_SH7264) += pfc-sh7264.o
|
obj-$(CONFIG_PINCTRL_PFC_SH7264) += pfc-sh7264.o
|
||||||
obj-$(CONFIG_PINCTRL_PFC_SH7269) += pfc-sh7269.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);
|
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)
|
void sh_pfc_write(struct sh_pfc *pfc, u32 reg, u32 data)
|
||||||
{
|
{
|
||||||
if (pfc->info->unlock_reg)
|
sh_pfc_unlock_reg(pfc, reg, data);
|
||||||
sh_pfc_write_raw_reg(
|
|
||||||
sh_pfc_phys_to_virt(pfc, pfc->info->unlock_reg), 32,
|
|
||||||
~data);
|
|
||||||
|
|
||||||
sh_pfc_write_raw_reg(sh_pfc_phys_to_virt(pfc, reg), 32, 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 &= mask;
|
||||||
data |= value;
|
data |= value;
|
||||||
|
|
||||||
if (pfc->info->unlock_reg)
|
sh_pfc_unlock_reg(pfc, crp->reg, data);
|
||||||
sh_pfc_write_raw_reg(
|
|
||||||
sh_pfc_phys_to_virt(pfc, pfc->info->unlock_reg), 32,
|
|
||||||
~data);
|
|
||||||
|
|
||||||
sh_pfc_write_raw_reg(mapped_reg, crp->reg_width, 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,
|
.data = &r8a77995_pinmux_info,
|
||||||
},
|
},
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef CONFIG_PINCTRL_PFC_R8A779A0
|
||||||
|
{
|
||||||
|
.compatible = "renesas,pfc-r8a779a0",
|
||||||
|
.data = &r8a779a0_pinmux_info,
|
||||||
|
},
|
||||||
|
#endif
|
||||||
#ifdef CONFIG_PINCTRL_PFC_SH73A0
|
#ifdef CONFIG_PINCTRL_PFC_SH73A0
|
||||||
{
|
{
|
||||||
.compatible = "renesas,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;
|
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),
|
sh_pfc_regs = kcalloc(SH_PFC_MAX_REGS, sizeof(*sh_pfc_regs),
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
if (!sh_pfc_regs)
|
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_RX_CTL, PIN_AVB_RXC, PIN_AVB_RD0,
|
||||||
PIN_AVB_RD1, PIN_AVB_RD2, PIN_AVB_RD3,
|
PIN_AVB_RD1, PIN_AVB_RD2, PIN_AVB_RD3,
|
||||||
PIN_AVB_TXCREFCLK,
|
PIN_AVB_TXCREFCLK,
|
||||||
|
|
||||||
};
|
};
|
||||||
static const unsigned int avb_mii_mux[] = {
|
static const unsigned int avb_mii_mux[] = {
|
||||||
AVB_TX_CTL_MARK, AVB_TXC_MARK, AVB_TD0_MARK,
|
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_RX_CTL, PIN_AVB_RXC, PIN_AVB_RD0,
|
||||||
PIN_AVB_RD1, PIN_AVB_RD2, PIN_AVB_RD3,
|
PIN_AVB_RD1, PIN_AVB_RD2, PIN_AVB_RD3,
|
||||||
PIN_AVB_TXCREFCLK,
|
PIN_AVB_TXCREFCLK,
|
||||||
|
|
||||||
};
|
};
|
||||||
static const unsigned int avb_mii_mux[] = {
|
static const unsigned int avb_mii_mux[] = {
|
||||||
AVB_TX_CTL_MARK, AVB_TXC_MARK, AVB_TD0_MARK,
|
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_RX_CTL, PIN_AVB_RXC, PIN_AVB_RD0,
|
||||||
PIN_AVB_RD1, PIN_AVB_RD2, PIN_AVB_RD3,
|
PIN_AVB_RD1, PIN_AVB_RD2, PIN_AVB_RD3,
|
||||||
PIN_AVB_TXCREFCLK,
|
PIN_AVB_TXCREFCLK,
|
||||||
|
|
||||||
};
|
};
|
||||||
static const unsigned int avb_mii_mux[] = {
|
static const unsigned int avb_mii_mux[] = {
|
||||||
AVB_TX_CTL_MARK, AVB_TXC_MARK, AVB_TD0_MARK,
|
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_RX_CTL, PIN_AVB_RXC, PIN_AVB_RD0,
|
||||||
PIN_AVB_RD1, PIN_AVB_RD2, PIN_AVB_RD3,
|
PIN_AVB_RD1, PIN_AVB_RD2, PIN_AVB_RD3,
|
||||||
PIN_AVB_TXCREFCLK,
|
PIN_AVB_TXCREFCLK,
|
||||||
|
|
||||||
};
|
};
|
||||||
static const unsigned int avb_mii_mux[] = {
|
static const unsigned int avb_mii_mux[] = {
|
||||||
AVB_TX_CTL_MARK, AVB_TXC_MARK, AVB_TD0_MARK,
|
AVB_TX_CTL_MARK, AVB_TXC_MARK, AVB_TD0_MARK,
|
||||||
|
|
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: {
|
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;
|
u32 pocctrl, val;
|
||||||
int bit;
|
int bit;
|
||||||
|
|
||||||
|
@ -648,7 +651,10 @@ static int sh_pfc_pinconf_get(struct pinctrl_dev *pctldev, unsigned _pin,
|
||||||
val = sh_pfc_read(pfc, pocctrl);
|
val = sh_pfc_read(pfc, pocctrl);
|
||||||
spin_unlock_irqrestore(&pfc->lock, flags);
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -702,6 +708,9 @@ static int sh_pfc_pinconf_set(struct pinctrl_dev *pctldev, unsigned _pin,
|
||||||
|
|
||||||
case PIN_CONFIG_POWER_SOURCE: {
|
case PIN_CONFIG_POWER_SOURCE: {
|
||||||
unsigned int mV = pinconf_to_config_argument(configs[i]);
|
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;
|
u32 pocctrl, val;
|
||||||
int bit;
|
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))
|
if (WARN(bit < 0, "invalid pin %#x", _pin))
|
||||||
return bit;
|
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;
|
return -EINVAL;
|
||||||
|
|
||||||
spin_lock_irqsave(&pfc->lock, flags);
|
spin_lock_irqsave(&pfc->lock, flags);
|
||||||
|
|
|
@ -31,6 +31,15 @@ enum {
|
||||||
SH_PFC_PIN_CFG_PULL_DOWN)
|
SH_PFC_PIN_CFG_PULL_DOWN)
|
||||||
#define SH_PFC_PIN_CFG_IO_VOLTAGE (1 << 4)
|
#define SH_PFC_PIN_CFG_IO_VOLTAGE (1 << 4)
|
||||||
#define SH_PFC_PIN_CFG_DRIVE_STRENGTH (1 << 5)
|
#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)
|
#define SH_PFC_PIN_CFG_NO_GPIO (1 << 31)
|
||||||
|
|
||||||
struct sh_pfc_pin {
|
struct sh_pfc_pin {
|
||||||
|
@ -300,7 +309,7 @@ struct sh_pfc_soc_info {
|
||||||
const u16 *pinmux_data;
|
const u16 *pinmux_data;
|
||||||
unsigned int pinmux_data_size;
|
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;
|
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 r8a77980_pinmux_info;
|
||||||
extern const struct sh_pfc_soc_info r8a77990_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 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 sh7203_pinmux_info;
|
||||||
extern const struct sh_pfc_soc_info sh7264_pinmux_info;
|
extern const struct sh_pfc_soc_info sh7264_pinmux_info;
|
||||||
extern const struct sh_pfc_soc_info sh7269_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)
|
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_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, 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, 2, fn, sfx, cfg), \
|
||||||
PORT_GP_CFG_1(bank, 3, 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)
|
#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)
|
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_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_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)
|
PORT_GP_CFG_1(bank, 31, fn, sfx, cfg)
|
||||||
#define PORT_GP_32(bank, fn, sfx) PORT_GP_CFG_32(bank, fn, sfx, 0)
|
#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 mask;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
spin_lock_irqsave(&bank->slock, flags);
|
raw_spin_lock_irqsave(&bank->slock, flags);
|
||||||
|
|
||||||
mask = readl(bank->eint_base + reg_mask);
|
mask = readl(bank->eint_base + reg_mask);
|
||||||
mask |= 1 << irqd->hwirq;
|
mask |= 1 << irqd->hwirq;
|
||||||
writel(mask, bank->eint_base + reg_mask);
|
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)
|
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)
|
if (irqd_get_trigger_type(irqd) & IRQ_TYPE_LEVEL_MASK)
|
||||||
exynos_irq_ack(irqd);
|
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 = readl(bank->eint_base + reg_mask);
|
||||||
mask &= ~(1 << irqd->hwirq);
|
mask &= ~(1 << irqd->hwirq);
|
||||||
writel(mask, bank->eint_base + reg_mask);
|
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)
|
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];
|
shift = irqd->hwirq * bank_type->fld_width[PINCFG_TYPE_FUNC];
|
||||||
mask = (1 << bank_type->fld_width[PINCFG_TYPE_FUNC]) - 1;
|
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 = readl(bank->pctl_base + reg_con);
|
||||||
con &= ~(mask << shift);
|
con &= ~(mask << shift);
|
||||||
con |= EXYNOS_PIN_FUNC_EINT << shift;
|
con |= EXYNOS_PIN_FUNC_EINT << shift;
|
||||||
writel(con, bank->pctl_base + reg_con);
|
writel(con, bank->pctl_base + reg_con);
|
||||||
|
|
||||||
spin_unlock_irqrestore(&bank->slock, flags);
|
raw_spin_unlock_irqrestore(&bank->slock, flags);
|
||||||
|
|
||||||
return 0;
|
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];
|
shift = irqd->hwirq * bank_type->fld_width[PINCFG_TYPE_FUNC];
|
||||||
mask = (1 << bank_type->fld_width[PINCFG_TYPE_FUNC]) - 1;
|
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 = readl(bank->pctl_base + reg_con);
|
||||||
con &= ~(mask << shift);
|
con &= ~(mask << shift);
|
||||||
con |= EXYNOS_PIN_FUNC_INPUT << shift;
|
con |= EXYNOS_PIN_FUNC_INPUT << shift;
|
||||||
writel(con, bank->pctl_base + reg_con);
|
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);
|
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];
|
shift = pin * bank_type->fld_width[PINCFG_TYPE_FUNC];
|
||||||
mask = (1 << bank_type->fld_width[PINCFG_TYPE_FUNC]) - 1;
|
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 = readl(reg);
|
||||||
val &= ~(mask << shift);
|
val &= ~(mask << shift);
|
||||||
val |= bank->eint_func << shift;
|
val |= bank->eint_func << shift;
|
||||||
writel(val, reg);
|
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)
|
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];
|
shift = shift * bank_type->fld_width[PINCFG_TYPE_FUNC];
|
||||||
mask = (1 << bank_type->fld_width[PINCFG_TYPE_FUNC]) - 1;
|
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 = readl(reg);
|
||||||
val &= ~(mask << shift);
|
val &= ~(mask << shift);
|
||||||
val |= bank->eint_func << shift;
|
val |= bank->eint_func << shift;
|
||||||
writel(val, reg);
|
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;
|
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 = readl(reg + type->reg_offset[PINCFG_TYPE_FUNC]);
|
||||||
data &= ~(mask << shift);
|
data &= ~(mask << shift);
|
||||||
data |= func->val << shift;
|
data |= func->val << shift;
|
||||||
writel(data, reg + type->reg_offset[PINCFG_TYPE_FUNC]);
|
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 */
|
/* 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];
|
width = type->fld_width[cfg_type];
|
||||||
cfg_reg = type->reg_offset[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;
|
mask = (1 << width) - 1;
|
||||||
shift = pin_offset * width;
|
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);
|
*config = PINCFG_PACK(cfg_type, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_unlock_irqrestore(&bank->slock, flags);
|
raw_spin_unlock_irqrestore(&bank->slock, flags);
|
||||||
|
|
||||||
return 0;
|
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);
|
struct samsung_pin_bank *bank = gpiochip_get_data(gc);
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
spin_lock_irqsave(&bank->slock, flags);
|
raw_spin_lock_irqsave(&bank->slock, flags);
|
||||||
samsung_gpio_set_value(gc, offset, value);
|
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 */
|
/* gpiolib gpio_get callback function */
|
||||||
|
@ -626,9 +626,9 @@ static int samsung_gpio_direction_input(struct gpio_chip *gc, unsigned offset)
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
spin_lock_irqsave(&bank->slock, flags);
|
raw_spin_lock_irqsave(&bank->slock, flags);
|
||||||
ret = samsung_gpio_set_direction(gc, offset, true);
|
ret = samsung_gpio_set_direction(gc, offset, true);
|
||||||
spin_unlock_irqrestore(&bank->slock, flags);
|
raw_spin_unlock_irqrestore(&bank->slock, flags);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -640,10 +640,10 @@ static int samsung_gpio_direction_output(struct gpio_chip *gc, unsigned offset,
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
spin_lock_irqsave(&bank->slock, flags);
|
raw_spin_lock_irqsave(&bank->slock, flags);
|
||||||
samsung_gpio_set_value(gc, offset, value);
|
samsung_gpio_set_value(gc, offset, value);
|
||||||
ret = samsung_gpio_set_direction(gc, offset, false);
|
ret = samsung_gpio_set_direction(gc, offset, false);
|
||||||
spin_unlock_irqrestore(&bank->slock, flags);
|
raw_spin_unlock_irqrestore(&bank->slock, flags);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -1057,7 +1057,7 @@ samsung_pinctrl_get_soc_data(struct samsung_pinctrl_drv_data *d,
|
||||||
bank->eint_offset = bdata->eint_offset;
|
bank->eint_offset = bdata->eint_offset;
|
||||||
bank->name = bdata->name;
|
bank->name = bdata->name;
|
||||||
|
|
||||||
spin_lock_init(&bank->slock);
|
raw_spin_lock_init(&bank->slock);
|
||||||
bank->drvdata = d;
|
bank->drvdata = d;
|
||||||
bank->pin_base = d->nr_pins;
|
bank->pin_base = d->nr_pins;
|
||||||
d->nr_pins += bank->nr_pins;
|
d->nr_pins += bank->nr_pins;
|
||||||
|
|
|
@ -171,7 +171,7 @@ struct samsung_pin_bank {
|
||||||
struct gpio_chip gpio_chip;
|
struct gpio_chip gpio_chip;
|
||||||
struct pinctrl_gpio_range grange;
|
struct pinctrl_gpio_range grange;
|
||||||
struct exynos_irq_chip *irq_chip;
|
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*/
|
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;
|
shift = INPUT_SCHMITT_SHIFT;
|
||||||
break;
|
break;
|
||||||
case PIN_CONFIG_BIAS_PULL_UP:
|
case PIN_CONFIG_BIAS_PULL_UP:
|
||||||
if (is_sleep_config == true) {
|
if (is_sleep_config) {
|
||||||
val |= SLEEP_PULL_UP;
|
val |= SLEEP_PULL_UP;
|
||||||
mask = SLEEP_PULL_UP_MASK;
|
mask = SLEEP_PULL_UP_MASK;
|
||||||
shift = SLEEP_PULL_UP_SHIFT;
|
shift = SLEEP_PULL_UP_SHIFT;
|
||||||
|
|
|
@ -119,4 +119,14 @@ config PINCTRL_SUN50I_H6_R
|
||||||
default ARM64 && ARCH_SUNXI
|
default ARM64 && ARCH_SUNXI
|
||||||
select PINCTRL_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
|
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_H5) += pinctrl-sun50i-h5.o
|
||||||
obj-$(CONFIG_PINCTRL_SUN50I_H6) += pinctrl-sun50i-h6.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_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) += pinctrl-sun9i-a80.o
|
||||||
obj-$(CONFIG_PINCTRL_SUN9I_A80_R) += pinctrl-sun9i-a80-r.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_PIN(SUNXI_PINCTRL_PIN(L, 0),
|
||||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||||
|
SUNXI_FUNCTION(0x2, "s_rsb"), /* SCK */
|
||||||
SUNXI_FUNCTION(0x3, "s_i2c"), /* SCK */
|
SUNXI_FUNCTION(0x3, "s_i2c"), /* SCK */
|
||||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 0)), /* PL_EINT0 */
|
SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 0)), /* PL_EINT0 */
|
||||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 1),
|
SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 1),
|
||||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||||
|
SUNXI_FUNCTION(0x2, "s_rsb"), /* SDA */
|
||||||
SUNXI_FUNCTION(0x3, "s_i2c"), /* SDA */
|
SUNXI_FUNCTION(0x3, "s_i2c"), /* SDA */
|
||||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 1)), /* PL_EINT1 */
|
SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 1)), /* PL_EINT1 */
|
||||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 2),
|
SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 2),
|
||||||
|
|
|
@ -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);
|
|
@ -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;
|
u32 reg = 0;
|
||||||
|
|
||||||
cfg = &group->cfg[i];
|
cfg = &group->cfg[i];
|
||||||
regmap_read(iod->regmap, cfg->offset, ®),
|
regmap_read(iod->regmap, cfg->offset, ®);
|
||||||
seq_printf(s, "\n\t0x%08x = 0x%08x (%3d, %3d)",
|
seq_printf(s, "\n\t0x%08x = 0x%08x (%3d, %3d)",
|
||||||
cfg->offset, reg, cfg->a_delay,
|
cfg->offset, reg, cfg->a_delay, cfg->g_delay);
|
||||||
cfg->g_delay);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#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))
|
#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 */
|
#endif /* __LINUX_KCONFIG_H */
|
||||||
|
|
Loading…
Reference in New Issue