This is the bulk of pin control changes for the v5.12 kernel.

This time a calm set with no core changes.
 
 New drivers/subdrivers:
 
 - Renesas R8A7790A0 pin controller.
 
 - Allwinner H616 and H616-R pin controllers.
 
 - Qualcomm SM8350 and SC8180x pin controllers.
 
 Improvements:
 
 - Redo the DT bindings for Ralink RT2880.
 
 - A common Qualcomm TLMM DT binding in YAML.
 
 - Delete the unused drivers for U300, COH901, Sirf Atlas, and ZTE ZX.
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEElDRnuGcz/wPCXQWMQRCzN7AZXXMFAmAy848ACgkQQRCzN7AZ
 XXPR0BAArpuUx8elp/+y+gDzL/5Lsv3aJ3AQ9yLfBda380YFwGWZSqjAEovVbhKx
 6Xm4g+MzQQ+sxcIHZY7tVWnrI1sbp6MaljVFLqPWWHeY4h4trsw6d+u2bMOFkJTl
 z0++Ybck+NTscTBvaN0wHqfao3IOU8FG5rL8y9azn9glfQg+xgKCbgAecUgjPXBI
 9YLCGMl8mnzH1sl+aImKDszYEuc29NGJrstmkVWcYGVR/XYfxEqNhtT4FlO2P9X1
 FNhQYgS0zJsu7UgOOgBsg0xRK5X9pWimwupxEH8MwqANivV3VGweQpcyqIlnA5Qe
 aXQEa+ZIndOoAsr5UvaHgDXucos7x1odm5AHuIb4V2aGOF5IYyj+iyR3Av4ODdpM
 +mYI+w9Nydlu1o1JiOb1hAxWNSb2NOBcrOcuiSAIJC7/rO/rqaAPpWmzxSYvGNFO
 xJTbMN3DtLokE/u9BxCVsXiEFXMy3IA5vu5o+Xks6HRLclWOAqeZJO3uhnlBc8Me
 qsijZxlugCUIvI7pdKblzOfO+PnB0rLX/7m05/ESTqh6vDcwrZjXLSH0bRWWZBvD
 CEtBtkIJGjdWsqMk0bqTXJkoqScaKdi0nLSFPK0qOCeqa0ShbxjqU4Vq/f4cQSu+
 DzUhF5qBdIaJhDY7V5V7vWygp48+AKVvFtHHmTD+Wb9AJL0MZiY=
 =WKZ8
 -----END PGP SIGNATURE-----

Merge tag 'pinctrl-v5.12-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl

Pull pin control updates from Linus Walleij:
 "This is the bulk of pin control changes for the v5.12 kernel.

  This time a calm set with no core changes.

  New drivers/subdrivers:

   - Renesas R8A7790A0 pin controller.

   - Allwinner H616 and H616-R pin controllers.

   - Qualcomm SM8350 and SC8180x pin controllers.

  Improvements:

   - Redo the DT bindings for Ralink RT2880.

   - A common Qualcomm TLMM DT binding in YAML.

   - Delete the unused drivers for U300, COH901, Sirf Atlas, and ZTE ZX"

* tag 'pinctrl-v5.12-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl: (71 commits)
  pinctrl: mediatek: Fix trigger type setting follow for unexpected interrupt
  dt-bindings: pinctrl: Group tuples in pin control properties
  pinctrl: nuvoton: npcm7xx: Fix alignment of table header comment
  pinctrl: at91-pio4: fix "Prefer 'unsigned int' to bare use of 'unsigned'"
  pinctrl: at91-pio4: add support for slew-rate
  dt-bindings: pinctrl: at91-pio4: add slew-rate
  pinctrl: actions: Add depends on || COMPILE_TEST
  pinctrl: single: set function name when adding function
  pinctrl: qcom: Add sc8180x TLMM driver
  dt-bindings: pinctrl: qcom: Add sc8180x binding
  dt-bindings: pinctrl: qcom: Define common TLMM binding
  pinctrl: qcom: Add SM8350 pinctrl driver
  dt-bindings: pinctrl: qcom: Add SM8350 pinctrl bindings
  pinctrl: samsung: use raw_spinlock for s3c64xx
  dt-bindings: mediatek: mt8192: Fix dt_binding_check warning
  pinctrl: qcom: spmi-mpp: Add PM8019 compatible
  pinctrl: pinmux: add function selector to pinmux-functions
  pinctrl: samsung: use raw_spinlock for locking
  pinctrl: clarify #pinctrl-cells for pinctrl-single,pins
  pinctrl: actions: Add the platform dependency to drivers
  ...
This commit is contained in:
Linus Torvalds 2021-02-22 18:39:11 -08:00
commit 3b9cdafb53
88 changed files with 9222 additions and 13460 deletions

View File

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

View File

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

View File

@ -53,6 +53,8 @@ properties:
- allwinner,sun50i-h5-pinctrl
- allwinner,sun50i-h6-pinctrl
- allwinner,sun50i-h6-r-pinctrl
- allwinner,sun50i-h616-pinctrl
- allwinner,sun50i-h616-r-pinctrl
- allwinner,suniv-f1c100s-pinctrl
- nextthing,gr8-pinctrl
@ -61,7 +63,7 @@ properties:
interrupts:
minItems: 1
maxItems: 7
maxItems: 8
description:
One interrupt per external interrupt bank supported on the
controller, sorted by bank number ascending order.
@ -91,7 +93,7 @@ properties:
bank found in the controller
$ref: /schemas/types.yaml#/definitions/uint32-array
minItems: 1
maxItems: 5
maxItems: 8
patternProperties:
# It's pretty scary, but the basic idea is that:
@ -145,6 +147,17 @@ allOf:
# boards are defining it at the moment so it would generate a lot of
# warnings.
- if:
properties:
compatible:
enum:
- allwinner,sun50i-h616-pinctrl
then:
properties:
interrupts:
minItems: 8
- if:
properties:
compatible:

View File

@ -35,9 +35,11 @@ ioset settings. Use the macros from boot/dts/<soc>-pinfunc.h file to get the
right representation of the pin.
Optional properties:
- GENERIC_PINCONFIG: generic pinconfig options to use, bias-disable,
bias-pull-down, bias-pull-up, drive-open-drain, input-schmitt-enable,
input-debounce, output-low, output-high.
- GENERIC_PINCONFIG: generic pinconfig options to use:
- bias-disable, bias-pull-down, bias-pull-up, drive-open-drain,
input-schmitt-enable, input-debounce, output-low, output-high.
- for microchip,sama7g5-pinctrl only:
- slew-rate: 0 - disabled, 1 - enabled (default)
- atmel,drive-strength: 0 or 1 for low drive, 2 for medium drive and 3 for
high drive. The default value is low drive.

View File

@ -39,7 +39,7 @@ For example:
<0x660009b0 0x40>;
pinctrl-names = "default";
pinctrl-0 = <&nand_sel &uart3_rx &sdio0_d4>;
pinctrl-0 = <&nand_sel>, <&uart3_rx>, <&sdio0_d4>;
/* Select nand function */
nand_sel: nand_sel {

View File

@ -30,7 +30,7 @@ For example:
<0x1803f408 0x04>;
pinctrl-names = "default";
pinctrl-0 = <&pwm &gpio_b &nand_sel>;
pinctrl-0 = <&pwm>, <&gpio_b>, <&nand_sel>;
pwm: pwm {
function = "pwm";

View File

@ -60,7 +60,7 @@ iomuxc-lpsr controller and SDA pad from iomuxc controller as:
i2c1: i2c@30a20000 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_i2c1_1 &pinctrl_i2c1_2>;
pinctrl-0 = <&pinctrl_i2c1_1>, <&pinctrl_i2c1_2>;
};
iomuxc-lpsr@302c0000 {

View File

@ -99,8 +99,8 @@ patternProperties:
'#interrupt-cells':
description:
Specifies the pin (port and bit) and flags, as defined in
defined in include/dt-bindings/interrupt-controller/irq.h
Specifies the pin (port and bit) and flags, as defined in
defined in include/dt-bindings/interrupt-controller/irq.h
const: 3
ngpios:

View File

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

View File

@ -77,13 +77,13 @@ For example:
device {
pinctrl-names = "active", "idle";
pinctrl-0 = <&state_0_node_a>;
pinctrl-1 = <&state_1_node_a &state_1_node_b>;
pinctrl-1 = <&state_1_node_a>, <&state_1_node_b>;
};
/* For the same device if using state IDs */
device {
pinctrl-0 = <&state_0_node_a>;
pinctrl-1 = <&state_1_node_a &state_1_node_b>;
pinctrl-1 = <&state_1_node_a>, <&state_1_node_b>;
};
/*

View File

@ -134,7 +134,7 @@ gpio21: gpio@21 {
#interrupt-cells = <0x2>;
microchip,irq-mirror;
pinctrl-names = "default";
pinctrl-0 = <&i2cgpio0irq &gpio21pullups>;
pinctrl-0 = <&i2cgpio0irq>, <&gpio21pullups>;
gpio21pullups: pinmux {
pins = "gpio0", "gpio1", "gpio2", "gpio3",

View File

@ -91,7 +91,7 @@ Examples:
pinctrl@1c20800 {
compatible = "mediatek,mt8135-pinctrl";
reg = <0 0x1000B000 0 0x1000>;
mediatek,pctl-regmap = <&syscfg_pctl_a &syscfg_pctl_b>;
mediatek,pctl-regmap = <&syscfg_pctl_a>, <&syscfg_pctl_b>;
pins-are-numbered;
gpio-controller;
#gpio-cells = <2>;

View File

@ -8,7 +8,7 @@ Required properties:
- reg : offset and length of the register set for the mux registers
- #pinctrl-cells : number of cells in addition to the index, set to 1
for pinctrl-single,pins and 2 for pinctrl-single,bits
or 2 for pinctrl-single,pins and set to 2 for pinctrl-single,bits
- pinctrl-single,register-width : pinmux register access width in bits
@ -80,7 +80,7 @@ Optional properties:
property.
/* pin base, nr pins & gpio function */
pinctrl-single,gpio-range = <&range 0 3 0 &range 3 9 1>;
pinctrl-single,gpio-range = <&range 0 3 0>, <&range 3 9 1>;
- interrupt-controller : standard interrupt controller binding if using
interrupts for wake-up events for example. In this case pinctrl-single
@ -185,10 +185,10 @@ pmx_gpio: pinmux@d401e000 {
pinctrl-single,function-mask = <7>;
/* sparse GPIO range could be supported */
pinctrl-single,gpio-range = <&range 0 3 0 &range 3 9 1
&range 12 1 0 &range 13 29 1
&range 43 1 0 &range 44 49 1
&range 94 1 1 &range 96 2 1>;
pinctrl-single,gpio-range = <&range 0 3 0>, <&range 3 9 1>,
<&range 12 1 0>, <&range 13 29 1>,
<&range 43 1 0>, <&range 44 49 1>,
<&range 94 1 1>, <&range 96 2 1>;
range: gpio-range {
#pinctrl-single,gpio-range-cells = <3>;

View File

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

View File

@ -8,6 +8,7 @@ of PMIC's from Qualcomm.
Value type: <string>
Definition: Should contain one of:
"qcom,pm8018-mpp",
"qcom,pm8019-mpp",
"qcom,pm8038-mpp",
"qcom,pm8058-mpp",
"qcom,pm8821-mpp",

View File

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

View File

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

View File

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

View File

@ -15,39 +15,38 @@ description:
properties:
compatible:
enum:
- ralink,rt2880-pinmux
const: ralink,rt2880-pinmux
pinctrl-0:
description:
A phandle to the node containing the subnodes containing default
configurations. This is for pinctrl hogs.
patternProperties:
'-pins$':
type: object
patternProperties:
'^(.*-)?pinmux$':
type: object
description: node for pinctrl.
$ref: pinmux-node.yaml#
pinctrl-names:
description:
A pinctrl state named "default" can be defined.
const: default
properties:
groups:
description: Name of the pin group to use for the functions.
enum: [i2c, spi, uart1, uart2, uart3, rgmii1, rgmii2, mdio,
pcie, sdhci]
function:
description: The mux function to select
enum: [gpio, i2c, spi, uart1, uart2, uart3, rgmii1, rgmii2,
mdio, nand1, nand2, sdhci]
required:
- groups
- function
additionalProperties: false
additionalProperties: false
required:
- compatible
patternProperties:
'[a-z0-9_-]+':
if:
type: object
description: node for pinctrl.
$ref: "pinmux-node.yaml"
then:
properties:
groups:
description: Name of the pin group to use for the functions.
enum: [i2c, spi, uart1, uart2, uart3, rgmii1, rgmii2, mdio,
pcie, sdhci]
function:
description: The mux function to select
enum: [gpio, i2c, spi, uart1, uart2, uart3, rgmii1, rgmii2,
mdio, nand1, nand2, sdhci]
additionalProperties: false
examples:
@ -55,14 +54,9 @@ examples:
- |
pinctrl {
compatible = "ralink,rt2880-pinmux";
pinctrl-names = "default";
pinctrl-0 = <&state_default>;
state_default: pinctrl0 {
};
i2c_pins: i2c0 {
i2c0 {
i2c_pins: i2c0-pins {
pinmux {
groups = "i2c";
function = "i2c";
};

View File

@ -43,11 +43,12 @@ properties:
- renesas,pfc-r8a77980 # R-Car V3H
- renesas,pfc-r8a77990 # R-Car E3
- renesas,pfc-r8a77995 # R-Car D3
- renesas,pfc-r8a779a0 # R-Car V3U
- renesas,pfc-sh73a0 # SH-Mobile AG5
reg:
minItems: 1
maxItems: 2
maxItems: 10
gpio-controller: true

View File

@ -336,7 +336,7 @@ Example 3: A uart client node that supports 'default' and 'flow-control' states.
interrupts = <0 52 0>;
pinctrl-names = "default", "flow-control;
pinctrl-0 = <&uart0_data>;
pinctrl-1 = <&uart0_data &uart0_fctl>;
pinctrl-1 = <&uart0_data>, <&uart0_fctl>;
};
Example 4: Set up the default pin state for uart controller.

View File

@ -226,14 +226,6 @@ config PINCTRL_SINGLE
help
This selects the device tree based generic pinctrl driver.
config PINCTRL_SIRF
bool "CSR SiRFprimaII pin controller driver"
depends on ARCH_SIRF
select PINMUX
select PINCONF
select GENERIC_PINCONF
select GPIOLIB_IRQCHIP
config PINCTRL_SX150X
bool "Semtech SX150x I2C GPIO expander pinctrl driver"
depends on I2C=y
@ -279,22 +271,6 @@ config PINCTRL_STMFX
and configuring push-pull, open-drain, and can also be used as
interrupt-controller.
config PINCTRL_U300
bool "U300 pin controller driver"
depends on ARCH_U300
select PINMUX
select GENERIC_PINCONF
config PINCTRL_COH901
bool "ST-Ericsson U300 COH 901 335/571 GPIO"
depends on GPIOLIB && ARCH_U300 && PINCTRL_U300
select GPIOLIB_IRQCHIP
help
Say yes here to support GPIO interface on ST-Ericsson U300.
The names of the two IP block variants supported are
COH 901 335 and COH 901 571/3. They contain 3, 5 or 7
ports of 8 GPIO pins each.
config PINCTRL_MAX77620
tristate "MAX77620/MAX20024 Pincontrol support"
depends on MFD_MAX77620 && OF
@ -417,7 +393,6 @@ source "drivers/pinctrl/ti/Kconfig"
source "drivers/pinctrl/uniphier/Kconfig"
source "drivers/pinctrl/vt8500/Kconfig"
source "drivers/pinctrl/mediatek/Kconfig"
source "drivers/pinctrl/zte/Kconfig"
source "drivers/pinctrl/meson/Kconfig"
source "drivers/pinctrl/cirrus/Kconfig"
source "drivers/pinctrl/visconti/Kconfig"

View File

@ -31,11 +31,8 @@ obj-$(CONFIG_PINCTRL_PIC32) += pinctrl-pic32.o
obj-$(CONFIG_PINCTRL_PISTACHIO) += pinctrl-pistachio.o
obj-$(CONFIG_PINCTRL_ROCKCHIP) += pinctrl-rockchip.o
obj-$(CONFIG_PINCTRL_SINGLE) += pinctrl-single.o
obj-$(CONFIG_PINCTRL_SIRF) += sirf/
obj-$(CONFIG_PINCTRL_SX150X) += pinctrl-sx150x.o
obj-$(CONFIG_ARCH_TEGRA) += tegra/
obj-$(CONFIG_PINCTRL_U300) += pinctrl-u300.o
obj-$(CONFIG_PINCTRL_COH901) += pinctrl-coh901.o
obj-$(CONFIG_PINCTRL_XWAY) += pinctrl-xway.o
obj-$(CONFIG_PINCTRL_LANTIQ) += pinctrl-lantiq.o
obj-$(CONFIG_PINCTRL_LPC18XX) += pinctrl-lpc18xx.o
@ -71,6 +68,5 @@ obj-y += ti/
obj-$(CONFIG_PINCTRL_UNIPHIER) += uniphier/
obj-$(CONFIG_ARCH_VT8500) += vt8500/
obj-y += mediatek/
obj-$(CONFIG_PINCTRL_ZX) += zte/
obj-y += cirrus/
obj-$(CONFIG_PINCTRL_VISCONTI) += visconti/

View File

@ -12,18 +12,21 @@ config PINCTRL_OWL
config PINCTRL_S500
bool "Actions Semi S500 pinctrl driver"
depends on ARM || COMPILE_TEST
depends on PINCTRL_OWL
help
Say Y here to enable Actions Semi S500 pinctrl driver
config PINCTRL_S700
bool "Actions Semi S700 pinctrl driver"
depends on ARM64 || COMPILE_TEST
depends on PINCTRL_OWL
help
Say Y here to enable Actions Semi S700 pinctrl driver
config PINCTRL_S900
bool "Actions Semi S900 pinctrl driver"
depends on ARM64 || COMPILE_TEST
depends on PINCTRL_OWL
help
Say Y here to enable Actions Semi S900 pinctrl driver

View File

@ -444,7 +444,6 @@ static int owl_group_config_get(struct pinctrl_dev *pctrldev,
*config = pinconf_to_config_packed(param, arg);
return ret;
}
static int owl_group_config_set(struct pinctrl_dev *pctrldev,

View File

@ -853,7 +853,7 @@ static int ns2_pin_config_get(struct pinctrl_dev *pctldev, unsigned int pin,
switch (param) {
case PIN_CONFIG_BIAS_DISABLE:
ns2_pin_get_pull(pctldev, pin, &pull_up, &pull_down);
if ((pull_up == false) && (pull_down == false))
if (!pull_up && !pull_down)
return 0;
else
return -EINVAL;

View File

@ -2117,7 +2117,6 @@ struct pinctrl_dev *pinctrl_register(struct pinctrl_desc *pctldesc,
return ERR_PTR(error);
return pctldev;
}
EXPORT_SYMBOL_GPL(pinctrl_register);

View File

@ -290,7 +290,6 @@ static const struct pinctrl_ops imx1_pctrl_ops = {
.pin_dbg_show = imx1_pin_dbg_show,
.dt_node_to_map = imx1_dt_node_to_map,
.dt_free_map = imx1_dt_free_map,
};
static int imx1_pmx_set(struct pinctrl_dev *pctldev, unsigned selector,

View File

@ -29,6 +29,16 @@
#define REVID_SHIFT 16
#define REVID_MASK GENMASK(31, 16)
#define CAPLIST 0x004
#define CAPLIST_ID_SHIFT 16
#define CAPLIST_ID_MASK GENMASK(23, 16)
#define CAPLIST_ID_GPIO_HW_INFO 1
#define CAPLIST_ID_PWM 2
#define CAPLIST_ID_BLINK 3
#define CAPLIST_ID_EXP 4
#define CAPLIST_NEXT_SHIFT 0
#define CAPLIST_NEXT_MASK GENMASK(15, 0)
#define PADBAR 0x00c
#define PADOWN_BITS 4
@ -1321,34 +1331,19 @@ static int intel_gpio_probe(struct intel_pinctrl *pctrl, int irq)
return 0;
}
static int intel_pinctrl_add_padgroups(struct intel_pinctrl *pctrl,
struct intel_community *community)
static int intel_pinctrl_add_padgroups_by_gpps(struct intel_pinctrl *pctrl,
struct intel_community *community)
{
struct intel_padgroup *gpps;
unsigned int npins = community->npins;
unsigned int padown_num = 0;
size_t ngpps, i;
if (community->gpps)
ngpps = community->ngpps;
else
ngpps = DIV_ROUND_UP(community->npins, community->gpp_size);
size_t i, ngpps = community->ngpps;
gpps = devm_kcalloc(pctrl->dev, ngpps, sizeof(*gpps), GFP_KERNEL);
if (!gpps)
return -ENOMEM;
for (i = 0; i < ngpps; i++) {
if (community->gpps) {
gpps[i] = community->gpps[i];
} else {
unsigned int gpp_size = community->gpp_size;
gpps[i].reg_num = i;
gpps[i].base = community->pin_base + i * gpp_size;
gpps[i].size = min(gpp_size, npins);
npins -= gpps[i].size;
}
gpps[i] = community->gpps[i];
if (gpps[i].size > 32)
return -EINVAL;
@ -1366,6 +1361,38 @@ static int intel_pinctrl_add_padgroups(struct intel_pinctrl *pctrl,
break;
}
gpps[i].padown_num = padown_num;
padown_num += DIV_ROUND_UP(gpps[i].size * 4, 32);
}
community->gpps = gpps;
return 0;
}
static int intel_pinctrl_add_padgroups_by_size(struct intel_pinctrl *pctrl,
struct intel_community *community)
{
struct intel_padgroup *gpps;
unsigned int npins = community->npins;
unsigned int padown_num = 0;
size_t i, ngpps = DIV_ROUND_UP(npins, community->gpp_size);
if (community->gpp_size > 32)
return -EINVAL;
gpps = devm_kcalloc(pctrl->dev, ngpps, sizeof(*gpps), GFP_KERNEL);
if (!gpps)
return -ENOMEM;
for (i = 0; i < ngpps; i++) {
unsigned int gpp_size = community->gpp_size;
gpps[i].reg_num = i;
gpps[i].base = community->pin_base + i * gpp_size;
gpps[i].size = min(gpp_size, npins);
npins -= gpps[i].size;
gpps[i].padown_num = padown_num;
/*
@ -1455,7 +1482,8 @@ static int intel_pinctrl_probe(struct platform_device *pdev,
for (i = 0; i < pctrl->ncommunities; i++) {
struct intel_community *community = &pctrl->communities[i];
void __iomem *regs;
u32 padbar;
u32 offset;
u32 value;
*community = pctrl->soc->communities[i];
@ -1463,27 +1491,48 @@ static int intel_pinctrl_probe(struct platform_device *pdev,
if (IS_ERR(regs))
return PTR_ERR(regs);
/*
* Determine community features based on the revision if
* not specified already.
*/
if (!community->features) {
u32 rev;
rev = (readl(regs + REVID) & REVID_MASK) >> REVID_SHIFT;
if (rev >= 0x94) {
community->features |= PINCTRL_FEATURE_DEBOUNCE;
community->features |= PINCTRL_FEATURE_1K_PD;
}
/* Determine community features based on the revision */
value = readl(regs + REVID);
if (((value & REVID_MASK) >> REVID_SHIFT) >= 0x94) {
community->features |= PINCTRL_FEATURE_DEBOUNCE;
community->features |= PINCTRL_FEATURE_1K_PD;
}
/* Determine community features based on the capabilities */
offset = CAPLIST;
do {
value = readl(regs + offset);
switch ((value & CAPLIST_ID_MASK) >> CAPLIST_ID_SHIFT) {
case CAPLIST_ID_GPIO_HW_INFO:
community->features |= PINCTRL_FEATURE_GPIO_HW_INFO;
break;
case CAPLIST_ID_PWM:
community->features |= PINCTRL_FEATURE_PWM;
break;
case CAPLIST_ID_BLINK:
community->features |= PINCTRL_FEATURE_BLINK;
break;
case CAPLIST_ID_EXP:
community->features |= PINCTRL_FEATURE_EXP;
break;
default:
break;
}
offset = (value & CAPLIST_NEXT_MASK) >> CAPLIST_NEXT_SHIFT;
} while (offset);
dev_dbg(&pdev->dev, "Community%d features: %#08x\n", i, community->features);
/* Read offset of the pad configuration registers */
padbar = readl(regs + PADBAR);
offset = readl(regs + PADBAR);
community->regs = regs;
community->pad_regs = regs + padbar;
community->pad_regs = regs + offset;
ret = intel_pinctrl_add_padgroups(pctrl, community);
if (community->gpps)
ret = intel_pinctrl_add_padgroups_by_gpps(pctrl, community);
else
ret = intel_pinctrl_add_padgroups_by_size(pctrl, community);
if (ret)
return ret;
}

View File

@ -143,6 +143,10 @@ struct intel_community {
/* Additional features supported by the hardware */
#define PINCTRL_FEATURE_DEBOUNCE BIT(0)
#define PINCTRL_FEATURE_1K_PD BIT(1)
#define PINCTRL_FEATURE_GPIO_HW_INFO BIT(2)
#define PINCTRL_FEATURE_PWM BIT(3)
#define PINCTRL_FEATURE_BLINK BIT(4)
#define PINCTRL_FEATURE_EXP BIT(5)
/**
* PIN_GROUP - Declare a pin group

View File

@ -748,6 +748,7 @@ static const struct intel_pinctrl_soc_data tglh_soc_data = {
static const struct acpi_device_id tgl_pinctrl_acpi_match[] = {
{ "INT34C5", (kernel_ulong_t)&tgllp_soc_data },
{ "INT34C6", (kernel_ulong_t)&tglh_soc_data },
{ "INTC1055", (kernel_ulong_t)&tgllp_soc_data },
{ }
};
MODULE_DEVICE_TABLE(acpi, tgl_pinctrl_acpi_match);

View File

@ -157,6 +157,7 @@ static void mtk_eint_ack(struct irq_data *d)
static int mtk_eint_set_type(struct irq_data *d, unsigned int type)
{
struct mtk_eint *eint = irq_data_get_irq_chip_data(d);
bool masked;
u32 mask = BIT(d->hwirq & 0x1f);
void __iomem *reg;
@ -173,6 +174,13 @@ static int mtk_eint_set_type(struct irq_data *d, unsigned int type)
else
eint->dual_edge[d->hwirq] = 0;
if (!mtk_eint_get_mask(eint, d->hwirq)) {
mtk_eint_mask(d);
masked = false;
} else {
masked = true;
}
if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_EDGE_FALLING)) {
reg = mtk_eint_get_offset(eint, d->hwirq, eint->regs->pol_clr);
writel(mask, reg);
@ -189,8 +197,9 @@ static int mtk_eint_set_type(struct irq_data *d, unsigned int type)
writel(mask, reg);
}
if (eint->dual_edge[d->hwirq])
mtk_eint_flip_edge(eint, d->hwirq);
mtk_eint_ack(d);
if (!masked)
mtk_eint_unmask(d);
return 0;
}

View File

@ -514,8 +514,8 @@ static int mtk_build_gpiochip(struct mtk_pinctrl *hw, struct device_node *np)
chip->direction_output = mtk_gpio_direction_output;
chip->get = mtk_gpio_get;
chip->set = mtk_gpio_set;
chip->to_irq = mtk_gpio_to_irq,
chip->set_config = mtk_gpio_set_config,
chip->to_irq = mtk_gpio_to_irq;
chip->set_config = mtk_gpio_set_config;
chip->base = -1;
chip->ngpio = hw->soc->npins;
chip->of_node = np;

View File

@ -891,8 +891,8 @@ static int mtk_build_gpiochip(struct mtk_pinctrl *hw, struct device_node *np)
chip->direction_output = mtk_gpio_direction_output;
chip->get = mtk_gpio_get;
chip->set = mtk_gpio_set;
chip->to_irq = mtk_gpio_to_irq,
chip->set_config = mtk_gpio_set_config,
chip->to_irq = mtk_gpio_to_irq;
chip->set_config = mtk_gpio_set_config;
chip->base = -1;
chip->ngpio = hw->soc->npins;
chip->of_node = np;

View File

@ -188,7 +188,6 @@ static struct armada_37xx_pin_group armada_37xx_nb_groups[] = {
PIN_GRP_GPIO_2("led1_od", 12, 1, BIT(21), BIT(21), 0, "led"),
PIN_GRP_GPIO_2("led2_od", 13, 1, BIT(22), BIT(22), 0, "led"),
PIN_GRP_GPIO_2("led3_od", 14, 1, BIT(23), BIT(23), 0, "led"),
};
static struct armada_37xx_pin_group armada_37xx_sb_groups[] = {

View File

@ -923,7 +923,7 @@ struct npcm7xx_pincfg {
};
static const struct npcm7xx_pincfg pincfg[] = {
/* PIN FUNCTION 1 FUNCTION 2 FUNCTION 3 FLAGS */
/* PIN FUNCTION 1 FUNCTION 2 FUNCTION 3 FLAGS */
NPCM7XX_PINCFG(0, iox1, MFSEL1, 30, none, NONE, 0, none, NONE, 0, 0),
NPCM7XX_PINCFG(1, iox1, MFSEL1, 30, none, NONE, 0, none, NONE, 0, DS(8, 12)),
NPCM7XX_PINCFG(2, iox1, MFSEL1, 30, none, NONE, 0, none, NONE, 0, DS(8, 12)),

View File

@ -36,6 +36,7 @@
#define ATMEL_PIO_DIR_MASK BIT(8)
#define ATMEL_PIO_PUEN_MASK BIT(9)
#define ATMEL_PIO_PDEN_MASK BIT(10)
#define ATMEL_PIO_SR_MASK BIT(11)
#define ATMEL_PIO_IFEN_MASK BIT(12)
#define ATMEL_PIO_IFSCEN_MASK BIT(13)
#define ATMEL_PIO_OPD_MASK BIT(14)
@ -76,10 +77,12 @@
* @nbanks: number of PIO banks
* @last_bank_count: number of lines in the last bank (can be less than
* the rest of the banks).
* @slew_rate_support: slew rate support
*/
struct atmel_pioctrl_data {
unsigned nbanks;
unsigned last_bank_count;
unsigned int nbanks;
unsigned int last_bank_count;
unsigned int slew_rate_support;
};
struct atmel_group {
@ -88,11 +91,11 @@ struct atmel_group {
};
struct atmel_pin {
unsigned pin_id;
unsigned mux;
unsigned ioset;
unsigned bank;
unsigned line;
unsigned int pin_id;
unsigned int mux;
unsigned int ioset;
unsigned int bank;
unsigned int line;
const char *device;
};
@ -117,20 +120,21 @@ struct atmel_pin {
* @pm_suspend_backup: backup/restore register values on suspend/resume
* @dev: device entry for the Atmel PIO controller.
* @node: node of the Atmel PIO controller.
* @slew_rate_support: slew rate support
*/
struct atmel_pioctrl {
void __iomem *reg_base;
struct clk *clk;
unsigned nbanks;
unsigned int nbanks;
struct pinctrl_dev *pinctrl_dev;
struct atmel_group *groups;
const char * const *group_names;
struct atmel_pin **pins;
unsigned npins;
unsigned int npins;
struct gpio_chip *gpio_chip;
struct irq_domain *irq_domain;
int *irqs;
unsigned *pm_wakeup_sources;
unsigned int *pm_wakeup_sources;
struct {
u32 imr;
u32 odsr;
@ -138,6 +142,7 @@ struct atmel_pioctrl {
} *pm_suspend_backup;
struct device *dev;
struct device_node *node;
unsigned int slew_rate_support;
};
static const char * const atmel_functions[] = {
@ -172,11 +177,11 @@ static void atmel_gpio_irq_ack(struct irq_data *d)
*/
}
static int atmel_gpio_irq_set_type(struct irq_data *d, unsigned type)
static int atmel_gpio_irq_set_type(struct irq_data *d, unsigned int type)
{
struct atmel_pioctrl *atmel_pioctrl = irq_data_get_irq_chip_data(d);
struct atmel_pin *pin = atmel_pioctrl->pins[d->hwirq];
unsigned reg;
unsigned int reg;
atmel_gpio_write(atmel_pioctrl, pin->bank, ATMEL_PIO_MSKR,
BIT(pin->line));
@ -263,7 +268,7 @@ static struct irq_chip atmel_gpio_irq_chip = {
.irq_set_wake = atmel_gpio_irq_set_wake,
};
static int atmel_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
static int atmel_gpio_to_irq(struct gpio_chip *chip, unsigned int offset)
{
struct atmel_pioctrl *atmel_pioctrl = gpiochip_get_data(chip);
@ -311,11 +316,12 @@ static void atmel_gpio_irq_handler(struct irq_desc *desc)
chained_irq_exit(chip, desc);
}
static int atmel_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
static int atmel_gpio_direction_input(struct gpio_chip *chip,
unsigned int offset)
{
struct atmel_pioctrl *atmel_pioctrl = gpiochip_get_data(chip);
struct atmel_pin *pin = atmel_pioctrl->pins[offset];
unsigned reg;
unsigned int reg;
atmel_gpio_write(atmel_pioctrl, pin->bank, ATMEL_PIO_MSKR,
BIT(pin->line));
@ -326,11 +332,11 @@ static int atmel_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
return 0;
}
static int atmel_gpio_get(struct gpio_chip *chip, unsigned offset)
static int atmel_gpio_get(struct gpio_chip *chip, unsigned int offset)
{
struct atmel_pioctrl *atmel_pioctrl = gpiochip_get_data(chip);
struct atmel_pin *pin = atmel_pioctrl->pins[offset];
unsigned reg;
unsigned int reg;
reg = atmel_gpio_read(atmel_pioctrl, pin->bank, ATMEL_PIO_PDSR);
@ -364,12 +370,13 @@ static int atmel_gpio_get_multiple(struct gpio_chip *chip, unsigned long *mask,
return 0;
}
static int atmel_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
static int atmel_gpio_direction_output(struct gpio_chip *chip,
unsigned int offset,
int value)
{
struct atmel_pioctrl *atmel_pioctrl = gpiochip_get_data(chip);
struct atmel_pin *pin = atmel_pioctrl->pins[offset];
unsigned reg;
unsigned int reg;
atmel_gpio_write(atmel_pioctrl, pin->bank,
value ? ATMEL_PIO_SODR : ATMEL_PIO_CODR,
@ -384,7 +391,7 @@ static int atmel_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
return 0;
}
static void atmel_gpio_set(struct gpio_chip *chip, unsigned offset, int val)
static void atmel_gpio_set(struct gpio_chip *chip, unsigned int offset, int val)
{
struct atmel_pioctrl *atmel_pioctrl = gpiochip_get_data(chip);
struct atmel_pin *pin = atmel_pioctrl->pins[offset];
@ -440,11 +447,11 @@ static struct gpio_chip atmel_gpio_chip = {
/* --- PINCTRL --- */
static unsigned int atmel_pin_config_read(struct pinctrl_dev *pctldev,
unsigned pin_id)
unsigned int pin_id)
{
struct atmel_pioctrl *atmel_pioctrl = pinctrl_dev_get_drvdata(pctldev);
unsigned bank = atmel_pioctrl->pins[pin_id]->bank;
unsigned line = atmel_pioctrl->pins[pin_id]->line;
unsigned int bank = atmel_pioctrl->pins[pin_id]->bank;
unsigned int line = atmel_pioctrl->pins[pin_id]->line;
void __iomem *addr = atmel_pioctrl->reg_base
+ bank * ATMEL_PIO_BANK_OFFSET;
@ -456,11 +463,11 @@ static unsigned int atmel_pin_config_read(struct pinctrl_dev *pctldev,
}
static void atmel_pin_config_write(struct pinctrl_dev *pctldev,
unsigned pin_id, u32 conf)
unsigned int pin_id, u32 conf)
{
struct atmel_pioctrl *atmel_pioctrl = pinctrl_dev_get_drvdata(pctldev);
unsigned bank = atmel_pioctrl->pins[pin_id]->bank;
unsigned line = atmel_pioctrl->pins[pin_id]->line;
unsigned int bank = atmel_pioctrl->pins[pin_id]->bank;
unsigned int line = atmel_pioctrl->pins[pin_id]->line;
void __iomem *addr = atmel_pioctrl->reg_base
+ bank * ATMEL_PIO_BANK_OFFSET;
@ -478,7 +485,7 @@ static int atmel_pctl_get_groups_count(struct pinctrl_dev *pctldev)
}
static const char *atmel_pctl_get_group_name(struct pinctrl_dev *pctldev,
unsigned selector)
unsigned int selector)
{
struct atmel_pioctrl *atmel_pioctrl = pinctrl_dev_get_drvdata(pctldev);
@ -486,19 +493,20 @@ static const char *atmel_pctl_get_group_name(struct pinctrl_dev *pctldev,
}
static int atmel_pctl_get_group_pins(struct pinctrl_dev *pctldev,
unsigned selector, const unsigned **pins,
unsigned *num_pins)
unsigned int selector,
const unsigned int **pins,
unsigned int *num_pins)
{
struct atmel_pioctrl *atmel_pioctrl = pinctrl_dev_get_drvdata(pctldev);
*pins = (unsigned *)&atmel_pioctrl->groups[selector].pin;
*pins = (unsigned int *)&atmel_pioctrl->groups[selector].pin;
*num_pins = 1;
return 0;
}
static struct atmel_group *
atmel_pctl_find_group_by_pin(struct pinctrl_dev *pctldev, unsigned pin)
atmel_pctl_find_group_by_pin(struct pinctrl_dev *pctldev, unsigned int pin)
{
struct atmel_pioctrl *atmel_pioctrl = pinctrl_dev_get_drvdata(pctldev);
int i;
@ -519,7 +527,7 @@ static int atmel_pctl_xlate_pinfunc(struct pinctrl_dev *pctldev,
const char **func_name)
{
struct atmel_pioctrl *atmel_pioctrl = pinctrl_dev_get_drvdata(pctldev);
unsigned pin_id, func_id;
unsigned int pin_id, func_id;
struct atmel_group *grp;
pin_id = ATMEL_GET_PIN_NO(pinfunc);
@ -549,10 +557,10 @@ static int atmel_pctl_xlate_pinfunc(struct pinctrl_dev *pctldev,
static int atmel_pctl_dt_subnode_to_map(struct pinctrl_dev *pctldev,
struct device_node *np,
struct pinctrl_map **map,
unsigned *reserved_maps,
unsigned *num_maps)
unsigned int *reserved_maps,
unsigned int *num_maps)
{
unsigned num_pins, num_configs, reserve;
unsigned int num_pins, num_configs, reserve;
unsigned long *configs;
struct property *pins;
u32 pinfunc;
@ -623,10 +631,10 @@ static int atmel_pctl_dt_subnode_to_map(struct pinctrl_dev *pctldev,
static int atmel_pctl_dt_node_to_map(struct pinctrl_dev *pctldev,
struct device_node *np_config,
struct pinctrl_map **map,
unsigned *num_maps)
unsigned int *num_maps)
{
struct device_node *np;
unsigned reserved_maps;
unsigned int reserved_maps;
int ret;
*map = NULL;
@ -674,13 +682,13 @@ static int atmel_pmx_get_functions_count(struct pinctrl_dev *pctldev)
}
static const char *atmel_pmx_get_function_name(struct pinctrl_dev *pctldev,
unsigned selector)
unsigned int selector)
{
return atmel_functions[selector];
}
static int atmel_pmx_get_function_groups(struct pinctrl_dev *pctldev,
unsigned selector,
unsigned int selector,
const char * const **groups,
unsigned * const num_groups)
{
@ -693,11 +701,11 @@ static int atmel_pmx_get_function_groups(struct pinctrl_dev *pctldev,
}
static int atmel_pmx_set_mux(struct pinctrl_dev *pctldev,
unsigned function,
unsigned group)
unsigned int function,
unsigned int group)
{
struct atmel_pioctrl *atmel_pioctrl = pinctrl_dev_get_drvdata(pctldev);
unsigned pin;
unsigned int pin;
u32 conf;
dev_dbg(pctldev->dev, "enable function %s group %s\n",
@ -721,13 +729,13 @@ static const struct pinmux_ops atmel_pmxops = {
};
static int atmel_conf_pin_config_group_get(struct pinctrl_dev *pctldev,
unsigned group,
unsigned int group,
unsigned long *config)
{
struct atmel_pioctrl *atmel_pioctrl = pinctrl_dev_get_drvdata(pctldev);
unsigned param = pinconf_to_config_param(*config), arg = 0;
unsigned int param = pinconf_to_config_param(*config), arg = 0;
struct atmel_group *grp = atmel_pioctrl->groups + group;
unsigned pin_id = grp->pin;
unsigned int pin_id = grp->pin;
u32 res;
res = atmel_pin_config_read(pctldev, pin_id);
@ -760,6 +768,13 @@ static int atmel_conf_pin_config_group_get(struct pinctrl_dev *pctldev,
return -EINVAL;
arg = 1;
break;
case PIN_CONFIG_SLEW_RATE:
if (!atmel_pioctrl->slew_rate_support)
return -EOPNOTSUPP;
if (!(res & ATMEL_PIO_SR_MASK))
return -EINVAL;
arg = 1;
break;
case ATMEL_PIN_CONFIG_DRIVE_STRENGTH:
if (!(res & ATMEL_PIO_DRVSTR_MASK))
return -EINVAL;
@ -774,25 +789,29 @@ static int atmel_conf_pin_config_group_get(struct pinctrl_dev *pctldev,
}
static int atmel_conf_pin_config_group_set(struct pinctrl_dev *pctldev,
unsigned group,
unsigned int group,
unsigned long *configs,
unsigned num_configs)
unsigned int num_configs)
{
struct atmel_pioctrl *atmel_pioctrl = pinctrl_dev_get_drvdata(pctldev);
struct atmel_group *grp = atmel_pioctrl->groups + group;
unsigned bank, pin, pin_id = grp->pin;
unsigned int bank, pin, pin_id = grp->pin;
u32 mask, conf = 0;
int i;
conf = atmel_pin_config_read(pctldev, pin_id);
for (i = 0; i < num_configs; i++) {
unsigned param = pinconf_to_config_param(configs[i]);
unsigned arg = pinconf_to_config_argument(configs[i]);
unsigned int param = pinconf_to_config_param(configs[i]);
unsigned int arg = pinconf_to_config_argument(configs[i]);
dev_dbg(pctldev->dev, "%s: pin=%u, config=0x%lx\n",
__func__, pin_id, configs[i]);
/* Keep slew rate enabled by default. */
if (atmel_pioctrl->slew_rate_support)
conf |= ATMEL_PIO_SR_MASK;
switch (param) {
case PIN_CONFIG_BIAS_DISABLE:
conf &= (~ATMEL_PIO_PUEN_MASK);
@ -850,6 +869,13 @@ static int atmel_conf_pin_config_group_set(struct pinctrl_dev *pctldev,
ATMEL_PIO_SODR);
}
break;
case PIN_CONFIG_SLEW_RATE:
if (!atmel_pioctrl->slew_rate_support)
break;
/* And remove it if explicitly requested. */
if (arg == 0)
conf &= ~ATMEL_PIO_SR_MASK;
break;
case ATMEL_PIN_CONFIG_DRIVE_STRENGTH:
switch (arg) {
case ATMEL_PIO_DRVSTR_LO:
@ -877,7 +903,8 @@ static int atmel_conf_pin_config_group_set(struct pinctrl_dev *pctldev,
}
static void atmel_conf_pin_config_dbg_show(struct pinctrl_dev *pctldev,
struct seq_file *s, unsigned pin_id)
struct seq_file *s,
unsigned int pin_id)
{
struct atmel_pioctrl *atmel_pioctrl = pinctrl_dev_get_drvdata(pctldev);
u32 conf;
@ -901,6 +928,8 @@ static void atmel_conf_pin_config_dbg_show(struct pinctrl_dev *pctldev,
seq_printf(s, "%s ", "open-drain");
if (conf & ATMEL_PIO_SCHMITT_MASK)
seq_printf(s, "%s ", "schmitt");
if (atmel_pioctrl->slew_rate_support && (conf & ATMEL_PIO_SR_MASK))
seq_printf(s, "%s ", "slew-rate");
if (conf & ATMEL_PIO_DRVSTR_MASK) {
switch ((conf & ATMEL_PIO_DRVSTR_MASK) >> ATMEL_PIO_DRVSTR_OFFSET) {
case ATMEL_PIO_DRVSTR_ME:
@ -994,6 +1023,7 @@ static const struct atmel_pioctrl_data atmel_sama5d2_pioctrl_data = {
static const struct atmel_pioctrl_data microchip_sama7g5_pioctrl_data = {
.nbanks = 5,
.last_bank_count = 8, /* sama7g5 has only PE0 to PE7 */
.slew_rate_support = 1,
};
static const struct of_device_id atmel_pctrl_of_match[] = {
@ -1039,6 +1069,7 @@ static int atmel_pinctrl_probe(struct platform_device *pdev)
atmel_pioctrl->npins -= ATMEL_PIO_NPINS_PER_BANK;
atmel_pioctrl->npins += atmel_pioctrl_data->last_bank_count;
}
atmel_pioctrl->slew_rate_support = atmel_pioctrl_data->slew_rate_support;
atmel_pioctrl->reg_base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(atmel_pioctrl->reg_base))
@ -1081,8 +1112,8 @@ static int atmel_pinctrl_probe(struct platform_device *pdev)
return -ENOMEM;
for (i = 0 ; i < atmel_pioctrl->npins; i++) {
struct atmel_group *group = atmel_pioctrl->groups + i;
unsigned bank = ATMEL_PIO_BANK(i);
unsigned line = ATMEL_PIO_LINE(i);
unsigned int bank = ATMEL_PIO_BANK(i);
unsigned int line = ATMEL_PIO_LINE(i);
atmel_pioctrl->pins[i] = devm_kzalloc(dev,
sizeof(**atmel_pioctrl->pins), GFP_KERNEL);

View File

@ -733,7 +733,6 @@ static const struct at91_pinctrl_mux_ops sam9x60_ops = {
.get_slewrate = at91_mux_sam9x60_get_slewrate,
.set_slewrate = at91_mux_sam9x60_set_slewrate,
.irq_type = alt_gpio_irq_type,
};
static struct at91_pinctrl_mux_ops sama5d3_ops = {
@ -1742,7 +1741,7 @@ static int at91_gpio_of_irq_setup(struct platform_device *pdev,
gpio_irqchip->irq_disable = gpio_irq_mask;
gpio_irqchip->irq_mask = gpio_irq_mask;
gpio_irqchip->irq_unmask = gpio_irq_unmask;
gpio_irqchip->irq_set_wake = gpio_irq_set_wake,
gpio_irqchip->irq_set_wake = gpio_irq_set_wake;
gpio_irqchip->irq_set_type = at91_gpio->ops->irq_type;
/* Disable irqs of this PIO controller */

View File

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

View File

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

View File

@ -376,12 +376,21 @@ static int jz4760_cim_pins[] = {
0x26, 0x27, 0x28, 0x29,
0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31,
};
static int jz4760_lcd_24bit_pins[] = {
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
0x58, 0x59, 0x5a, 0x5b,
static int jz4760_lcd_8bit_pins[] = {
0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x4c,
0x4d, 0x52, 0x53,
};
static int jz4760_lcd_16bit_pins[] = {
0x4e, 0x4f, 0x50, 0x51, 0x56, 0x57, 0x58, 0x59,
};
static int jz4760_lcd_18bit_pins[] = {
0x5a, 0x5b,
};
static int jz4760_lcd_24bit_pins[] = {
0x40, 0x41, 0x4a, 0x4b, 0x54, 0x55,
};
static int jz4760_lcd_special_pins[] = { 0x40, 0x41, 0x4a, 0x54 };
static int jz4760_lcd_generic_pins[] = { 0x49, };
static int jz4760_pwm_pwm0_pins[] = { 0x80, };
static int jz4760_pwm_pwm1_pins[] = { 0x81, };
static int jz4760_pwm_pwm2_pins[] = { 0x82, };
@ -390,6 +399,7 @@ static int jz4760_pwm_pwm4_pins[] = { 0x84, };
static int jz4760_pwm_pwm5_pins[] = { 0x85, };
static int jz4760_pwm_pwm6_pins[] = { 0x6a, };
static int jz4760_pwm_pwm7_pins[] = { 0x6b, };
static int jz4760_otg_pins[] = { 0x8a, };
static u8 jz4760_uart3_data_funcs[] = { 0, 1, };
static u8 jz4760_mmc0_1bit_a_funcs[] = { 1, 1, 0, };
@ -436,8 +446,12 @@ static const struct group_desc jz4760_groups[] = {
INGENIC_PIN_GROUP("i2c0-data", jz4760_i2c0, 0),
INGENIC_PIN_GROUP("i2c1-data", jz4760_i2c1, 0),
INGENIC_PIN_GROUP("cim-data", jz4760_cim, 0),
INGENIC_PIN_GROUP("lcd-8bit", jz4760_lcd_8bit, 0),
INGENIC_PIN_GROUP("lcd-16bit", jz4760_lcd_16bit, 0),
INGENIC_PIN_GROUP("lcd-18bit", jz4760_lcd_18bit, 0),
INGENIC_PIN_GROUP("lcd-24bit", jz4760_lcd_24bit, 0),
{ "lcd-no-pins", },
INGENIC_PIN_GROUP("lcd-generic", jz4760_lcd_generic, 0),
INGENIC_PIN_GROUP("lcd-special", jz4760_lcd_special, 1),
INGENIC_PIN_GROUP("pwm0", jz4760_pwm_pwm0, 0),
INGENIC_PIN_GROUP("pwm1", jz4760_pwm_pwm1, 0),
INGENIC_PIN_GROUP("pwm2", jz4760_pwm_pwm2, 0),
@ -446,6 +460,7 @@ static const struct group_desc jz4760_groups[] = {
INGENIC_PIN_GROUP("pwm5", jz4760_pwm_pwm5, 0),
INGENIC_PIN_GROUP("pwm6", jz4760_pwm_pwm6, 0),
INGENIC_PIN_GROUP("pwm7", jz4760_pwm_pwm7, 0),
INGENIC_PIN_GROUP("otg-vbus", jz4760_otg, 0),
};
static const char *jz4760_uart0_groups[] = { "uart0-data", "uart0-hwflow", };
@ -477,7 +492,10 @@ static const char *jz4760_cs6_groups[] = { "nemc-cs6", };
static const char *jz4760_i2c0_groups[] = { "i2c0-data", };
static const char *jz4760_i2c1_groups[] = { "i2c1-data", };
static const char *jz4760_cim_groups[] = { "cim-data", };
static const char *jz4760_lcd_groups[] = { "lcd-24bit", "lcd-no-pins", };
static const char *jz4760_lcd_groups[] = {
"lcd-8bit", "lcd-16bit", "lcd-18bit", "lcd-24bit",
"lcd-special", "lcd-generic",
};
static const char *jz4760_pwm0_groups[] = { "pwm0", };
static const char *jz4760_pwm1_groups[] = { "pwm1", };
static const char *jz4760_pwm2_groups[] = { "pwm2", };
@ -486,6 +504,7 @@ static const char *jz4760_pwm4_groups[] = { "pwm4", };
static const char *jz4760_pwm5_groups[] = { "pwm5", };
static const char *jz4760_pwm6_groups[] = { "pwm6", };
static const char *jz4760_pwm7_groups[] = { "pwm7", };
static const char *jz4760_otg_groups[] = { "otg-vbus", };
static const struct function_desc jz4760_functions[] = {
{ "uart0", jz4760_uart0_groups, ARRAY_SIZE(jz4760_uart0_groups), },
@ -514,6 +533,7 @@ static const struct function_desc jz4760_functions[] = {
{ "pwm5", jz4760_pwm5_groups, ARRAY_SIZE(jz4760_pwm5_groups), },
{ "pwm6", jz4760_pwm6_groups, ARRAY_SIZE(jz4760_pwm6_groups), },
{ "pwm7", jz4760_pwm7_groups, ARRAY_SIZE(jz4760_pwm7_groups), },
{ "otg", jz4760_otg_groups, ARRAY_SIZE(jz4760_otg_groups), },
};
static const struct ingenic_chip_info jz4760_chip_info = {
@ -648,7 +668,6 @@ static int jz4770_mac_rmii_pins[] = {
0xa9, 0xab, 0xaa, 0xac, 0xa5, 0xa4, 0xad, 0xae, 0xa6, 0xa8,
};
static int jz4770_mac_mii_pins[] = { 0xa7, 0xaf, };
static int jz4770_otg_pins[] = { 0x8a, };
static const struct group_desc jz4770_groups[] = {
INGENIC_PIN_GROUP("uart0-data", jz4770_uart0_data, 0),
@ -747,7 +766,7 @@ static const struct group_desc jz4770_groups[] = {
INGENIC_PIN_GROUP("pwm7", jz4770_pwm_pwm7, 0),
INGENIC_PIN_GROUP("mac-rmii", jz4770_mac_rmii, 0),
INGENIC_PIN_GROUP("mac-mii", jz4770_mac_mii, 0),
INGENIC_PIN_GROUP("otg-vbus", jz4770_otg, 0),
INGENIC_PIN_GROUP("otg-vbus", jz4760_otg, 0),
};
static const char *jz4770_uart0_groups[] = { "uart0-data", "uart0-hwflow", };
@ -808,7 +827,6 @@ static const char *jz4770_pwm5_groups[] = { "pwm5", };
static const char *jz4770_pwm6_groups[] = { "pwm6", };
static const char *jz4770_pwm7_groups[] = { "pwm7", };
static const char *jz4770_mac_groups[] = { "mac-rmii", "mac-mii", };
static const char *jz4770_otg_groups[] = { "otg-vbus", };
static const struct function_desc jz4770_functions[] = {
{ "uart0", jz4770_uart0_groups, ARRAY_SIZE(jz4770_uart0_groups), },
@ -841,7 +859,7 @@ static const struct function_desc jz4770_functions[] = {
{ "pwm6", jz4770_pwm6_groups, ARRAY_SIZE(jz4770_pwm6_groups), },
{ "pwm7", jz4770_pwm7_groups, ARRAY_SIZE(jz4770_pwm7_groups), },
{ "mac", jz4770_mac_groups, ARRAY_SIZE(jz4770_mac_groups), },
{ "otg", jz4770_otg_groups, ARRAY_SIZE(jz4770_otg_groups), },
{ "otg", jz4760_otg_groups, ARRAY_SIZE(jz4760_otg_groups), },
};
static const struct ingenic_chip_info jz4770_chip_info = {
@ -2384,6 +2402,12 @@ static int __init ingenic_pinctrl_probe(struct platform_device *pdev)
unsigned int i;
int err;
chip_info = of_device_get_match_data(dev);
if (!chip_info) {
dev_err(dev, "Unsupported SoC\n");
return -EINVAL;
}
jzpc = devm_kzalloc(dev, sizeof(*jzpc), GFP_KERNEL);
if (!jzpc)
return -ENOMEM;
@ -2400,7 +2424,7 @@ static int __init ingenic_pinctrl_probe(struct platform_device *pdev)
}
jzpc->dev = dev;
jzpc->info = chip_info = of_device_get_match_data(dev);
jzpc->info = chip_info;
pctl_desc = devm_kzalloc(&pdev->dev, sizeof(*pctl_desc), GFP_KERNEL);
if (!pctl_desc)
@ -2470,17 +2494,47 @@ static int __init ingenic_pinctrl_probe(struct platform_device *pdev)
}
static const struct of_device_id ingenic_pinctrl_of_match[] = {
{ .compatible = "ingenic,jz4740-pinctrl", .data = &jz4740_chip_info },
{ .compatible = "ingenic,jz4725b-pinctrl", .data = &jz4725b_chip_info },
{ .compatible = "ingenic,jz4760-pinctrl", .data = &jz4760_chip_info },
{ .compatible = "ingenic,jz4760b-pinctrl", .data = &jz4760_chip_info },
{ .compatible = "ingenic,jz4770-pinctrl", .data = &jz4770_chip_info },
{ .compatible = "ingenic,jz4780-pinctrl", .data = &jz4780_chip_info },
{ .compatible = "ingenic,x1000-pinctrl", .data = &x1000_chip_info },
{ .compatible = "ingenic,x1000e-pinctrl", .data = &x1000_chip_info },
{ .compatible = "ingenic,x1500-pinctrl", .data = &x1500_chip_info },
{ .compatible = "ingenic,x1830-pinctrl", .data = &x1830_chip_info },
{},
{
.compatible = "ingenic,jz4740-pinctrl",
.data = IF_ENABLED(CONFIG_MACH_JZ4740, &jz4740_chip_info)
},
{
.compatible = "ingenic,jz4725b-pinctrl",
.data = IF_ENABLED(CONFIG_MACH_JZ4725B, &jz4725b_chip_info)
},
{
.compatible = "ingenic,jz4760-pinctrl",
.data = IF_ENABLED(CONFIG_MACH_JZ4760, &jz4760_chip_info)
},
{
.compatible = "ingenic,jz4760b-pinctrl",
.data = IF_ENABLED(CONFIG_MACH_JZ4760, &jz4760_chip_info)
},
{
.compatible = "ingenic,jz4770-pinctrl",
.data = IF_ENABLED(CONFIG_MACH_JZ4770, &jz4770_chip_info)
},
{
.compatible = "ingenic,jz4780-pinctrl",
.data = IF_ENABLED(CONFIG_MACH_JZ4780, &jz4780_chip_info)
},
{
.compatible = "ingenic,x1000-pinctrl",
.data = IF_ENABLED(CONFIG_MACH_X1000, &x1000_chip_info)
},
{
.compatible = "ingenic,x1000e-pinctrl",
.data = IF_ENABLED(CONFIG_MACH_X1000, &x1000_chip_info)
},
{
.compatible = "ingenic,x1500-pinctrl",
.data = IF_ENABLED(CONFIG_MACH_X1500, &x1500_chip_info)
},
{
.compatible = "ingenic,x1830-pinctrl",
.data = IF_ENABLED(CONFIG_MACH_X1830, &x1830_chip_info)
},
{ /* sentinel */ },
};
static struct platform_driver ingenic_pinctrl_driver = {

View File

@ -777,6 +777,7 @@ static int pcs_add_function(struct pcs_device *pcs,
function->vals = vals;
function->nvals = nvals;
function->name = name;
selector = pinmux_generic_add_function(pcs->pctl, name,
pgnames, npgnames,

View File

@ -541,7 +541,6 @@ static void st_pinconf_set_retime_packed(struct st_pinctrl *info,
st_regmap_field_bit_set_clear_pin(rt_p->delay_0, delay & 0x1, pin);
/* 2 bit delay, msb */
st_regmap_field_bit_set_clear_pin(rt_p->delay_1, delay & 0x2, pin);
}
static void st_pinconf_set_retime_dedicated(struct st_pinctrl *info,

View File

@ -443,7 +443,6 @@ static void sx150x_gpio_set(struct gpio_chip *chip, unsigned int offset,
sx150x_gpio_oscio_set(pctl, value);
else
__sx150x_gpio_set(pctl, offset, value);
}
static void sx150x_gpio_set_multiple(struct gpio_chip *chip,

File diff suppressed because it is too large Load Diff

View File

@ -564,7 +564,7 @@ static int pinmux_functions_show(struct seq_file *s, void *what)
continue;
}
seq_printf(s, "function: %s, groups = [ ", func);
seq_printf(s, "function %d: %s, groups = [ ", func_selector, func);
for (i = 0; i < num_groups; i++)
seq_printf(s, "%s ", groups[i]);
seq_puts(s, "]\n");

View File

@ -220,6 +220,15 @@ config PINCTRL_SC7280
Qualcomm Technologies Inc TLMM block found on the Qualcomm
Technologies Inc SC7280 platform.
config PINCTRL_SC8180X
tristate "Qualcomm Technologies Inc SC8180x pin controller driver"
depends on GPIOLIB && OF
select PINCTRL_MSM
help
This is the pinctrl, pinmux, pinconf and gpiolib driver for the
Qualcomm Technologies Inc TLMM block found on the Qualcomm
Technologies Inc SC8180x platform.
config PINCTRL_SDM660
tristate "Qualcomm Technologies Inc SDM660 pin controller driver"
depends on GPIOLIB && OF
@ -265,6 +274,15 @@ config PINCTRL_SM8250
Qualcomm Technologies Inc TLMM block found on the Qualcomm
Technologies Inc SM8250 platform.
config PINCTRL_SM8350
tristate "Qualcomm Technologies Inc SM8350 pin controller driver"
depends on GPIOLIB && OF
select PINCTRL_MSM
help
This is the pinctrl, pinmux, pinconf and gpiolib driver for the
Qualcomm Technologies Inc TLMM block found on the Qualcomm
Technologies Inc SM8350 platform.
config PINCTRL_LPASS_LPI
tristate "Qualcomm Technologies Inc LPASS LPI pin controller driver"
select PINMUX

View File

@ -26,9 +26,11 @@ obj-$(CONFIG_PINCTRL_QCOM_SSBI_PMIC) += pinctrl-ssbi-gpio.o
obj-$(CONFIG_PINCTRL_QCOM_SSBI_PMIC) += pinctrl-ssbi-mpp.o
obj-$(CONFIG_PINCTRL_SC7180) += pinctrl-sc7180.o
obj-$(CONFIG_PINCTRL_SC7280) += pinctrl-sc7280.o
obj-$(CONFIG_PINCTRL_SC8180X) += pinctrl-sc8180x.o
obj-$(CONFIG_PINCTRL_SDM660) += pinctrl-sdm660.o
obj-$(CONFIG_PINCTRL_SDM845) += pinctrl-sdm845.o
obj-$(CONFIG_PINCTRL_SDX55) += pinctrl-sdx55.o
obj-$(CONFIG_PINCTRL_SM8150) += pinctrl-sm8150.o
obj-$(CONFIG_PINCTRL_SM8250) += pinctrl-sm8250.o
obj-$(CONFIG_PINCTRL_SM8350) += pinctrl-sm8350.o
obj-$(CONFIG_PINCTRL_LPASS_LPI) += pinctrl-lpass-lpi.o

File diff suppressed because it is too large Load Diff

View File

@ -1310,7 +1310,6 @@ static const struct msm_pinctrl_soc_data sdm845_pinctrl = {
.ngpios = 151,
.wakeirq_map = sdm845_pdc_map,
.nwakeirq_map = ARRAY_SIZE(sdm845_pdc_map),
};
static const struct msm_pinctrl_soc_data sdm845_acpi_pinctrl = {

File diff suppressed because it is too large Load Diff

View File

@ -912,6 +912,7 @@ static int pmic_mpp_remove(struct platform_device *pdev)
}
static const struct of_device_id pmic_mpp_of_match[] = {
{ .compatible = "qcom,pm8019-mpp" }, /* 6 MPP's */
{ .compatible = "qcom,pm8841-mpp" }, /* 4 MPP's */
{ .compatible = "qcom,pm8916-mpp" }, /* 4 MPP's */
{ .compatible = "qcom,pm8941-mpp" }, /* 8 MPP's */

View File

@ -617,7 +617,6 @@ static void pm8xxx_mpp_dbg_show_one(struct seq_file *s,
}
break;
}
}
static void pm8xxx_mpp_dbg_show(struct seq_file *s, struct gpio_chip *chip)

View File

@ -193,7 +193,6 @@ static struct rt2880_pmx_func gpio_func = {
static int rt2880_pinmux_index(struct rt2880_priv *p)
{
struct rt2880_pmx_func **f;
struct rt2880_pmx_group *mux = p->groups;
int i, j, c = 0;
@ -207,7 +206,7 @@ static int rt2880_pinmux_index(struct rt2880_priv *p)
p->group_names = devm_kcalloc(p->dev, p->group_count,
sizeof(char *), GFP_KERNEL);
if (!p->group_names)
return -1;
return -ENOMEM;
for (i = 0; i < p->group_count; i++) {
p->group_names[i] = p->groups[i].name;
@ -218,31 +217,31 @@ static int rt2880_pinmux_index(struct rt2880_priv *p)
p->func_count++;
/* allocate our function and group mapping index buffers */
f = p->func = devm_kcalloc(p->dev,
p->func_count,
sizeof(*p->func),
GFP_KERNEL);
p->func = devm_kcalloc(p->dev, p->func_count,
sizeof(*p->func), GFP_KERNEL);
gpio_func.groups = devm_kcalloc(p->dev, p->group_count, sizeof(int),
GFP_KERNEL);
if (!f || !gpio_func.groups)
return -1;
if (!p->func || !gpio_func.groups)
return -ENOMEM;
/* add a backpointer to the function so it knows its group */
gpio_func.group_count = p->group_count;
for (i = 0; i < gpio_func.group_count; i++)
gpio_func.groups[i] = i;
f[c] = &gpio_func;
p->func[c] = &gpio_func;
c++;
/* add remaining functions */
for (i = 0; i < p->group_count; i++) {
for (j = 0; j < p->groups[i].func_count; j++) {
f[c] = &p->groups[i].func[j];
f[c]->groups = devm_kzalloc(p->dev, sizeof(int),
p->func[c] = &p->groups[i].func[j];
p->func[c]->groups = devm_kzalloc(p->dev, sizeof(int),
GFP_KERNEL);
f[c]->groups[0] = i;
f[c]->group_count = 1;
if (!p->func[c]->groups)
return -ENOMEM;
p->func[c]->groups[0] = i;
p->func[c]->group_count = 1;
c++;
}
}
@ -280,10 +279,8 @@ static int rt2880_pinmux_pins(struct rt2880_priv *p)
/* the pads needed to tell pinctrl about our pins */
p->pads = devm_kcalloc(p->dev, p->max_pins,
sizeof(struct pinctrl_pin_desc), GFP_KERNEL);
if (!p->pads || !p->gpio) {
dev_err(p->dev, "Failed to allocate gpio data\n");
if (!p->pads || !p->gpio)
return -ENOMEM;
}
memset(p->gpio, 1, sizeof(u8) * p->max_pins);
for (i = 0; i < p->func_count; i++) {
@ -318,6 +315,7 @@ static int rt2880_pinmux_probe(struct platform_device *pdev)
{
struct rt2880_priv *p;
struct pinctrl_dev *dev;
int err;
if (!rt2880_pinmux_data)
return -ENOTSUPP;
@ -333,19 +331,20 @@ static int rt2880_pinmux_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, p);
/* init the device */
if (rt2880_pinmux_index(p)) {
err = rt2880_pinmux_index(p);
if (err) {
dev_err(&pdev->dev, "failed to load index\n");
return -EINVAL;
return err;
}
if (rt2880_pinmux_pins(p)) {
err = rt2880_pinmux_pins(p);
if (err) {
dev_err(&pdev->dev, "failed to load pins\n");
return -EINVAL;
return err;
}
dev = pinctrl_register(p->desc, &pdev->dev, p);
if (IS_ERR(dev))
return PTR_ERR(dev);
return 0;
return PTR_ERR_OR_ZERO(dev);
}
static const struct of_device_id rt2880_pinmux_match[] = {
@ -362,7 +361,7 @@ static struct platform_driver rt2880_pinmux_driver = {
},
};
int __init rt2880_pinmux_init(void)
static int __init rt2880_pinmux_init(void)
{
return platform_driver_register(&rt2880_pinmux_driver);
}

View File

@ -36,6 +36,7 @@ config PINCTRL_RENESAS
select PINCTRL_PFC_R8A77980 if ARCH_R8A77980
select PINCTRL_PFC_R8A77990 if ARCH_R8A77990
select PINCTRL_PFC_R8A77995 if ARCH_R8A77995
select PINCTRL_PFC_R8A779A0 if ARCH_R8A779A0
select PINCTRL_PFC_SH7203 if CPU_SUBTYPE_SH7203
select PINCTRL_PFC_SH7264 if CPU_SUBTYPE_SH7264
select PINCTRL_PFC_SH7269 if CPU_SUBTYPE_SH7269
@ -142,6 +143,10 @@ config PINCTRL_PFC_R8A77970
bool "pin control support for R-Car V3M" if COMPILE_TEST
select PINCTRL_SH_PFC
config PINCTRL_PFC_R8A779A0
bool "pin control support for R-Car V3U" if COMPILE_TEST
select PINCTRL_SH_PFC
config PINCTRL_PFC_R8A7740
bool "pin control support for R-Mobile A1" if COMPILE_TEST
select PINCTRL_SH_PFC_GPIO

View File

@ -29,6 +29,7 @@ obj-$(CONFIG_PINCTRL_PFC_R8A77970) += pfc-r8a77970.o
obj-$(CONFIG_PINCTRL_PFC_R8A77980) += pfc-r8a77980.o
obj-$(CONFIG_PINCTRL_PFC_R8A77990) += pfc-r8a77990.o
obj-$(CONFIG_PINCTRL_PFC_R8A77995) += pfc-r8a77995.o
obj-$(CONFIG_PINCTRL_PFC_R8A779A0) += pfc-r8a779a0.o
obj-$(CONFIG_PINCTRL_PFC_SH7203) += pfc-sh7203.o
obj-$(CONFIG_PINCTRL_PFC_SH7264) += pfc-sh7264.o
obj-$(CONFIG_PINCTRL_PFC_SH7269) += pfc-sh7269.o

View File

@ -175,13 +175,25 @@ u32 sh_pfc_read(struct sh_pfc *pfc, u32 reg)
return sh_pfc_read_raw_reg(sh_pfc_phys_to_virt(pfc, reg), 32);
}
static void sh_pfc_unlock_reg(struct sh_pfc *pfc, u32 reg, u32 data)
{
u32 unlock;
if (!pfc->info->unlock_reg)
return;
if (pfc->info->unlock_reg >= 0x80000000UL)
unlock = pfc->info->unlock_reg;
else
/* unlock_reg is a mask */
unlock = reg & ~pfc->info->unlock_reg;
sh_pfc_write_raw_reg(sh_pfc_phys_to_virt(pfc, unlock), 32, ~data);
}
void sh_pfc_write(struct sh_pfc *pfc, u32 reg, u32 data)
{
if (pfc->info->unlock_reg)
sh_pfc_write_raw_reg(
sh_pfc_phys_to_virt(pfc, pfc->info->unlock_reg), 32,
~data);
sh_pfc_unlock_reg(pfc, reg, data);
sh_pfc_write_raw_reg(sh_pfc_phys_to_virt(pfc, reg), 32, data);
}
@ -227,11 +239,7 @@ static void sh_pfc_write_config_reg(struct sh_pfc *pfc,
data &= mask;
data |= value;
if (pfc->info->unlock_reg)
sh_pfc_write_raw_reg(
sh_pfc_phys_to_virt(pfc, pfc->info->unlock_reg), 32,
~data);
sh_pfc_unlock_reg(pfc, crp->reg, data);
sh_pfc_write_raw_reg(mapped_reg, crp->reg_width, data);
}
@ -638,6 +646,12 @@ static const struct of_device_id sh_pfc_of_table[] = {
.data = &r8a77995_pinmux_info,
},
#endif
#ifdef CONFIG_PINCTRL_PFC_R8A779A0
{
.compatible = "renesas,pfc-r8a779a0",
.data = &r8a779a0_pinmux_info,
},
#endif
#ifdef CONFIG_PINCTRL_PFC_SH73A0
{
.compatible = "renesas,pfc-sh73a0",
@ -1052,6 +1066,10 @@ static void __init sh_pfc_check_driver(const struct platform_driver *pdrv)
{
unsigned int i;
if (!IS_ENABLED(CONFIG_SUPERH) &&
!of_find_matching_node(NULL, pdrv->driver.of_match_table))
return;
sh_pfc_regs = kcalloc(SH_PFC_MAX_REGS, sizeof(*sh_pfc_regs),
GFP_KERNEL);
if (!sh_pfc_regs)

View File

@ -1668,7 +1668,6 @@ static const unsigned int avb_mii_pins[] = {
PIN_AVB_RX_CTL, PIN_AVB_RXC, PIN_AVB_RD0,
PIN_AVB_RD1, PIN_AVB_RD2, PIN_AVB_RD3,
PIN_AVB_TXCREFCLK,
};
static const unsigned int avb_mii_mux[] = {
AVB_TX_CTL_MARK, AVB_TXC_MARK, AVB_TD0_MARK,

View File

@ -1727,7 +1727,6 @@ static const unsigned int avb_mii_pins[] = {
PIN_AVB_RX_CTL, PIN_AVB_RXC, PIN_AVB_RD0,
PIN_AVB_RD1, PIN_AVB_RD2, PIN_AVB_RD3,
PIN_AVB_TXCREFCLK,
};
static const unsigned int avb_mii_mux[] = {
AVB_TX_CTL_MARK, AVB_TXC_MARK, AVB_TD0_MARK,

View File

@ -1731,7 +1731,6 @@ static const unsigned int avb_mii_pins[] = {
PIN_AVB_RX_CTL, PIN_AVB_RXC, PIN_AVB_RD0,
PIN_AVB_RD1, PIN_AVB_RD2, PIN_AVB_RD3,
PIN_AVB_TXCREFCLK,
};
static const unsigned int avb_mii_mux[] = {
AVB_TX_CTL_MARK, AVB_TXC_MARK, AVB_TD0_MARK,

View File

@ -1736,7 +1736,6 @@ static const unsigned int avb_mii_pins[] = {
PIN_AVB_RX_CTL, PIN_AVB_RXC, PIN_AVB_RD0,
PIN_AVB_RD1, PIN_AVB_RD2, PIN_AVB_RD3,
PIN_AVB_TXCREFCLK,
};
static const unsigned int avb_mii_mux[] = {
AVB_TX_CTL_MARK, AVB_TXC_MARK, AVB_TD0_MARK,

File diff suppressed because it is too large Load Diff

View File

@ -634,6 +634,9 @@ static int sh_pfc_pinconf_get(struct pinctrl_dev *pctldev, unsigned _pin,
}
case PIN_CONFIG_POWER_SOURCE: {
int idx = sh_pfc_get_pin_index(pfc, _pin);
const struct sh_pfc_pin *pin = &pfc->info->pins[idx];
unsigned int lower_voltage;
u32 pocctrl, val;
int bit;
@ -648,7 +651,10 @@ static int sh_pfc_pinconf_get(struct pinctrl_dev *pctldev, unsigned _pin,
val = sh_pfc_read(pfc, pocctrl);
spin_unlock_irqrestore(&pfc->lock, flags);
arg = (val & BIT(bit)) ? 3300 : 1800;
lower_voltage = (pin->configs & SH_PFC_PIN_VOLTAGE_25_33) ?
2500 : 1800;
arg = (val & BIT(bit)) ? 3300 : lower_voltage;
break;
}
@ -702,6 +708,9 @@ static int sh_pfc_pinconf_set(struct pinctrl_dev *pctldev, unsigned _pin,
case PIN_CONFIG_POWER_SOURCE: {
unsigned int mV = pinconf_to_config_argument(configs[i]);
int idx = sh_pfc_get_pin_index(pfc, _pin);
const struct sh_pfc_pin *pin = &pfc->info->pins[idx];
unsigned int lower_voltage;
u32 pocctrl, val;
int bit;
@ -712,7 +721,10 @@ static int sh_pfc_pinconf_set(struct pinctrl_dev *pctldev, unsigned _pin,
if (WARN(bit < 0, "invalid pin %#x", _pin))
return bit;
if (mV != 1800 && mV != 3300)
lower_voltage = (pin->configs & SH_PFC_PIN_VOLTAGE_25_33) ?
2500 : 1800;
if (mV != lower_voltage && mV != 3300)
return -EINVAL;
spin_lock_irqsave(&pfc->lock, flags);

View File

@ -31,6 +31,15 @@ enum {
SH_PFC_PIN_CFG_PULL_DOWN)
#define SH_PFC_PIN_CFG_IO_VOLTAGE (1 << 4)
#define SH_PFC_PIN_CFG_DRIVE_STRENGTH (1 << 5)
#define SH_PFC_PIN_VOLTAGE_18_33 (0 << 6)
#define SH_PFC_PIN_VOLTAGE_25_33 (1 << 6)
#define SH_PFC_PIN_CFG_IO_VOLTAGE_18_33 (SH_PFC_PIN_CFG_IO_VOLTAGE | \
SH_PFC_PIN_VOLTAGE_18_33)
#define SH_PFC_PIN_CFG_IO_VOLTAGE_25_33 (SH_PFC_PIN_CFG_IO_VOLTAGE | \
SH_PFC_PIN_VOLTAGE_25_33)
#define SH_PFC_PIN_CFG_NO_GPIO (1 << 31)
struct sh_pfc_pin {
@ -300,7 +309,7 @@ struct sh_pfc_soc_info {
const u16 *pinmux_data;
unsigned int pinmux_data_size;
u32 unlock_reg;
u32 unlock_reg; /* can be literal address or mask */
};
extern const struct sh_pfc_soc_info emev2_pinmux_info;
@ -331,6 +340,7 @@ extern const struct sh_pfc_soc_info r8a77970_pinmux_info;
extern const struct sh_pfc_soc_info r8a77980_pinmux_info;
extern const struct sh_pfc_soc_info r8a77990_pinmux_info;
extern const struct sh_pfc_soc_info r8a77995_pinmux_info;
extern const struct sh_pfc_soc_info r8a779a0_pinmux_info;
extern const struct sh_pfc_soc_info sh7203_pinmux_info;
extern const struct sh_pfc_soc_info sh7264_pinmux_info;
extern const struct sh_pfc_soc_info sh7269_pinmux_info;
@ -451,9 +461,13 @@ extern const struct sh_pfc_soc_info shx3_pinmux_info;
fn(bank, pin, GP_##bank##_##pin, sfx, cfg)
#define PORT_GP_1(bank, pin, fn, sfx) PORT_GP_CFG_1(bank, pin, fn, sfx, 0)
#define PORT_GP_CFG_4(bank, fn, sfx, cfg) \
#define PORT_GP_CFG_2(bank, fn, sfx, cfg) \
PORT_GP_CFG_1(bank, 0, fn, sfx, cfg), \
PORT_GP_CFG_1(bank, 1, fn, sfx, cfg), \
PORT_GP_CFG_1(bank, 1, fn, sfx, cfg)
#define PORT_GP_2(bank, fn, sfx) PORT_GP_CFG_2(bank, fn, sfx, 0)
#define PORT_GP_CFG_4(bank, fn, sfx, cfg) \
PORT_GP_CFG_2(bank, fn, sfx, cfg), \
PORT_GP_CFG_1(bank, 2, fn, sfx, cfg), \
PORT_GP_CFG_1(bank, 3, fn, sfx, cfg)
#define PORT_GP_4(bank, fn, sfx) PORT_GP_CFG_4(bank, fn, sfx, 0)
@ -572,9 +586,13 @@ extern const struct sh_pfc_soc_info shx3_pinmux_info;
PORT_GP_CFG_1(bank, 29, fn, sfx, cfg)
#define PORT_GP_30(bank, fn, sfx) PORT_GP_CFG_30(bank, fn, sfx, 0)
#define PORT_GP_CFG_32(bank, fn, sfx, cfg) \
#define PORT_GP_CFG_31(bank, fn, sfx, cfg) \
PORT_GP_CFG_30(bank, fn, sfx, cfg), \
PORT_GP_CFG_1(bank, 30, fn, sfx, cfg), \
PORT_GP_CFG_1(bank, 30, fn, sfx, cfg)
#define PORT_GP_31(bank, fn, sfx) PORT_GP_CFG_31(bank, fn, sfx, 0)
#define PORT_GP_CFG_32(bank, fn, sfx, cfg) \
PORT_GP_CFG_31(bank, fn, sfx, cfg), \
PORT_GP_CFG_1(bank, 31, fn, sfx, cfg)
#define PORT_GP_32(bank, fn, sfx) PORT_GP_CFG_32(bank, fn, sfx, 0)

View File

@ -58,13 +58,13 @@ static void exynos_irq_mask(struct irq_data *irqd)
unsigned long mask;
unsigned long flags;
spin_lock_irqsave(&bank->slock, flags);
raw_spin_lock_irqsave(&bank->slock, flags);
mask = readl(bank->eint_base + reg_mask);
mask |= 1 << irqd->hwirq;
writel(mask, bank->eint_base + reg_mask);
spin_unlock_irqrestore(&bank->slock, flags);
raw_spin_unlock_irqrestore(&bank->slock, flags);
}
static void exynos_irq_ack(struct irq_data *irqd)
@ -97,13 +97,13 @@ static void exynos_irq_unmask(struct irq_data *irqd)
if (irqd_get_trigger_type(irqd) & IRQ_TYPE_LEVEL_MASK)
exynos_irq_ack(irqd);
spin_lock_irqsave(&bank->slock, flags);
raw_spin_lock_irqsave(&bank->slock, flags);
mask = readl(bank->eint_base + reg_mask);
mask &= ~(1 << irqd->hwirq);
writel(mask, bank->eint_base + reg_mask);
spin_unlock_irqrestore(&bank->slock, flags);
raw_spin_unlock_irqrestore(&bank->slock, flags);
}
static int exynos_irq_set_type(struct irq_data *irqd, unsigned int type)
@ -169,14 +169,14 @@ static int exynos_irq_request_resources(struct irq_data *irqd)
shift = irqd->hwirq * bank_type->fld_width[PINCFG_TYPE_FUNC];
mask = (1 << bank_type->fld_width[PINCFG_TYPE_FUNC]) - 1;
spin_lock_irqsave(&bank->slock, flags);
raw_spin_lock_irqsave(&bank->slock, flags);
con = readl(bank->pctl_base + reg_con);
con &= ~(mask << shift);
con |= EXYNOS_PIN_FUNC_EINT << shift;
writel(con, bank->pctl_base + reg_con);
spin_unlock_irqrestore(&bank->slock, flags);
raw_spin_unlock_irqrestore(&bank->slock, flags);
return 0;
}
@ -192,14 +192,14 @@ static void exynos_irq_release_resources(struct irq_data *irqd)
shift = irqd->hwirq * bank_type->fld_width[PINCFG_TYPE_FUNC];
mask = (1 << bank_type->fld_width[PINCFG_TYPE_FUNC]) - 1;
spin_lock_irqsave(&bank->slock, flags);
raw_spin_lock_irqsave(&bank->slock, flags);
con = readl(bank->pctl_base + reg_con);
con &= ~(mask << shift);
con |= EXYNOS_PIN_FUNC_INPUT << shift;
writel(con, bank->pctl_base + reg_con);
spin_unlock_irqrestore(&bank->slock, flags);
raw_spin_unlock_irqrestore(&bank->slock, flags);
gpiochip_unlock_as_irq(&bank->gpio_chip, irqd->hwirq);
}

View File

@ -145,14 +145,14 @@ static void s3c24xx_eint_set_function(struct samsung_pinctrl_drv_data *d,
shift = pin * bank_type->fld_width[PINCFG_TYPE_FUNC];
mask = (1 << bank_type->fld_width[PINCFG_TYPE_FUNC]) - 1;
spin_lock_irqsave(&bank->slock, flags);
raw_spin_lock_irqsave(&bank->slock, flags);
val = readl(reg);
val &= ~(mask << shift);
val |= bank->eint_func << shift;
writel(val, reg);
spin_unlock_irqrestore(&bank->slock, flags);
raw_spin_unlock_irqrestore(&bank->slock, flags);
}
static int s3c24xx_eint_type(struct irq_data *data, unsigned int type)

View File

@ -286,14 +286,14 @@ static void s3c64xx_irq_set_function(struct samsung_pinctrl_drv_data *d,
shift = shift * bank_type->fld_width[PINCFG_TYPE_FUNC];
mask = (1 << bank_type->fld_width[PINCFG_TYPE_FUNC]) - 1;
spin_lock_irqsave(&bank->slock, flags);
raw_spin_lock_irqsave(&bank->slock, flags);
val = readl(reg);
val &= ~(mask << shift);
val |= bank->eint_func << shift;
writel(val, reg);
spin_unlock_irqrestore(&bank->slock, flags);
raw_spin_unlock_irqrestore(&bank->slock, flags);
}
/*

View File

@ -400,14 +400,14 @@ static void samsung_pinmux_setup(struct pinctrl_dev *pctldev, unsigned selector,
reg += 4;
}
spin_lock_irqsave(&bank->slock, flags);
raw_spin_lock_irqsave(&bank->slock, flags);
data = readl(reg + type->reg_offset[PINCFG_TYPE_FUNC]);
data &= ~(mask << shift);
data |= func->val << shift;
writel(data, reg + type->reg_offset[PINCFG_TYPE_FUNC]);
spin_unlock_irqrestore(&bank->slock, flags);
raw_spin_unlock_irqrestore(&bank->slock, flags);
}
/* enable a specified pinmux by writing to registers */
@ -451,7 +451,7 @@ static int samsung_pinconf_rw(struct pinctrl_dev *pctldev, unsigned int pin,
width = type->fld_width[cfg_type];
cfg_reg = type->reg_offset[cfg_type];
spin_lock_irqsave(&bank->slock, flags);
raw_spin_lock_irqsave(&bank->slock, flags);
mask = (1 << width) - 1;
shift = pin_offset * width;
@ -468,7 +468,7 @@ static int samsung_pinconf_rw(struct pinctrl_dev *pctldev, unsigned int pin,
*config = PINCFG_PACK(cfg_type, data);
}
spin_unlock_irqrestore(&bank->slock, flags);
raw_spin_unlock_irqrestore(&bank->slock, flags);
return 0;
}
@ -561,9 +561,9 @@ static void samsung_gpio_set(struct gpio_chip *gc, unsigned offset, int value)
struct samsung_pin_bank *bank = gpiochip_get_data(gc);
unsigned long flags;
spin_lock_irqsave(&bank->slock, flags);
raw_spin_lock_irqsave(&bank->slock, flags);
samsung_gpio_set_value(gc, offset, value);
spin_unlock_irqrestore(&bank->slock, flags);
raw_spin_unlock_irqrestore(&bank->slock, flags);
}
/* gpiolib gpio_get callback function */
@ -626,9 +626,9 @@ static int samsung_gpio_direction_input(struct gpio_chip *gc, unsigned offset)
unsigned long flags;
int ret;
spin_lock_irqsave(&bank->slock, flags);
raw_spin_lock_irqsave(&bank->slock, flags);
ret = samsung_gpio_set_direction(gc, offset, true);
spin_unlock_irqrestore(&bank->slock, flags);
raw_spin_unlock_irqrestore(&bank->slock, flags);
return ret;
}
@ -640,10 +640,10 @@ static int samsung_gpio_direction_output(struct gpio_chip *gc, unsigned offset,
unsigned long flags;
int ret;
spin_lock_irqsave(&bank->slock, flags);
raw_spin_lock_irqsave(&bank->slock, flags);
samsung_gpio_set_value(gc, offset, value);
ret = samsung_gpio_set_direction(gc, offset, false);
spin_unlock_irqrestore(&bank->slock, flags);
raw_spin_unlock_irqrestore(&bank->slock, flags);
return ret;
}
@ -1057,7 +1057,7 @@ samsung_pinctrl_get_soc_data(struct samsung_pinctrl_drv_data *d,
bank->eint_offset = bdata->eint_offset;
bank->name = bdata->name;
spin_lock_init(&bank->slock);
raw_spin_lock_init(&bank->slock);
bank->drvdata = d;
bank->pin_base = d->nr_pins;
d->nr_pins += bank->nr_pins;

View File

@ -171,7 +171,7 @@ struct samsung_pin_bank {
struct gpio_chip gpio_chip;
struct pinctrl_gpio_range grange;
struct exynos_irq_chip *irq_chip;
spinlock_t slock;
raw_spinlock_t slock;
u32 pm_save[PINCFG_TYPE_NUM + 1]; /* +1 to handle double CON registers*/
};

View File

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

View File

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

View File

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

View File

@ -687,7 +687,7 @@ static int sprd_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin_id,
shift = INPUT_SCHMITT_SHIFT;
break;
case PIN_CONFIG_BIAS_PULL_UP:
if (is_sleep_config == true) {
if (is_sleep_config) {
val |= SLEEP_PULL_UP;
mask = SLEEP_PULL_UP_MASK;
shift = SLEEP_PULL_UP_SHIFT;

View File

@ -119,4 +119,14 @@ config PINCTRL_SUN50I_H6_R
default ARM64 && ARCH_SUNXI
select PINCTRL_SUNXI
config PINCTRL_SUN50I_H616
bool "Support for the Allwinner H616 PIO"
default ARM64 && ARCH_SUNXI
select PINCTRL_SUNXI
config PINCTRL_SUN50I_H616_R
bool "Support for the Allwinner H616 R-PIO"
default ARM64 && ARCH_SUNXI
select PINCTRL_SUNXI
endif

View File

@ -23,5 +23,7 @@ obj-$(CONFIG_PINCTRL_SUN8I_V3S) += pinctrl-sun8i-v3s.o
obj-$(CONFIG_PINCTRL_SUN50I_H5) += pinctrl-sun50i-h5.o
obj-$(CONFIG_PINCTRL_SUN50I_H6) += pinctrl-sun50i-h6.o
obj-$(CONFIG_PINCTRL_SUN50I_H6_R) += pinctrl-sun50i-h6-r.o
obj-$(CONFIG_PINCTRL_SUN50I_H616) += pinctrl-sun50i-h616.o
obj-$(CONFIG_PINCTRL_SUN50I_H616_R) += pinctrl-sun50i-h616-r.o
obj-$(CONFIG_PINCTRL_SUN9I_A80) += pinctrl-sun9i-a80.o
obj-$(CONFIG_PINCTRL_SUN9I_A80_R) += pinctrl-sun9i-a80-r.o

View File

@ -24,11 +24,13 @@ static const struct sunxi_desc_pin sun50i_h6_r_pins[] = {
SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 0),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "s_rsb"), /* SCK */
SUNXI_FUNCTION(0x3, "s_i2c"), /* SCK */
SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 0)), /* PL_EINT0 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 1),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "s_rsb"), /* SDA */
SUNXI_FUNCTION(0x3, "s_i2c"), /* SDA */
SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 1)), /* PL_EINT1 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 2),

View File

@ -0,0 +1,56 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Allwinner H616 R_PIO pin controller driver
*
* Copyright (C) 2020 Arm Ltd.
* Based on former work, which is:
* Copyright (C) 2017 Icenowy Zheng <icenowy@aosc.io>
*/
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/pinctrl/pinctrl.h>
#include <linux/reset.h>
#include "pinctrl-sunxi.h"
static const struct sunxi_desc_pin sun50i_h616_r_pins[] = {
SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 0),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "s_rsb"), /* SCK */
SUNXI_FUNCTION(0x3, "s_i2c")), /* SCK */
SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 1),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "s_rsb"), /* SDA */
SUNXI_FUNCTION(0x3, "s_i2c")), /* SDA */
};
static const struct sunxi_pinctrl_desc sun50i_h616_r_pinctrl_data = {
.pins = sun50i_h616_r_pins,
.npins = ARRAY_SIZE(sun50i_h616_r_pins),
.pin_base = PL_BASE,
};
static int sun50i_h616_r_pinctrl_probe(struct platform_device *pdev)
{
return sunxi_pinctrl_init(pdev,
&sun50i_h616_r_pinctrl_data);
}
static const struct of_device_id sun50i_h616_r_pinctrl_match[] = {
{ .compatible = "allwinner,sun50i-h616-r-pinctrl", },
{}
};
static struct platform_driver sun50i_h616_r_pinctrl_driver = {
.probe = sun50i_h616_r_pinctrl_probe,
.driver = {
.name = "sun50i-h616-r-pinctrl",
.of_match_table = sun50i_h616_r_pinctrl_match,
},
};
builtin_platform_driver(sun50i_h616_r_pinctrl_driver);

View File

@ -0,0 +1,548 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Allwinner H616 SoC pinctrl driver.
*
* Copyright (C) 2020 Arm Ltd.
* based on the H6 pinctrl driver
* Copyright (C) 2017 Icenowy Zheng <icenowy@aosc.io>
*/
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/pinctrl/pinctrl.h>
#include "pinctrl-sunxi.h"
static const struct sunxi_desc_pin h616_pins[] = {
/* Internal connection to the AC200 part */
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 0),
SUNXI_FUNCTION(0x2, "emac1")), /* ERXD1 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 1),
SUNXI_FUNCTION(0x2, "emac1")), /* ERXD0 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 2),
SUNXI_FUNCTION(0x2, "emac1")), /* ECRS_DV */
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 3),
SUNXI_FUNCTION(0x2, "emac1")), /* ERXERR */
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 4),
SUNXI_FUNCTION(0x2, "emac1")), /* ETXD1 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 5),
SUNXI_FUNCTION(0x2, "emac1")), /* ETXD0 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 6),
SUNXI_FUNCTION(0x2, "emac1")), /* ETXCK */
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 7),
SUNXI_FUNCTION(0x2, "emac1")), /* ETXEN */
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 8),
SUNXI_FUNCTION(0x2, "emac1")), /* EMDC */
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 9),
SUNXI_FUNCTION(0x2, "emac1")), /* EMDIO */
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 10),
SUNXI_FUNCTION(0x2, "i2c3")), /* SCK */
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 11),
SUNXI_FUNCTION(0x2, "i2c3")), /* SDA */
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 12),
SUNXI_FUNCTION(0x2, "pwm5")),
/* Hole */
SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 0),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "nand0"), /* WE */
SUNXI_FUNCTION(0x3, "mmc2"), /* DS */
SUNXI_FUNCTION(0x4, "spi0"), /* CLK */
SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 0)), /* PC_EINT0 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 1),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "nand0"), /* ALE */
SUNXI_FUNCTION(0x3, "mmc2"), /* RST */
SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 1)), /* PC_EINT1 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 2),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "nand0"), /* CLE */
SUNXI_FUNCTION(0x4, "spi0"), /* MOSI */
SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 2)), /* PC_EINT2 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 3),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "nand0"), /* CE1 */
SUNXI_FUNCTION(0x4, "spi0"), /* CS0 */
SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 3)), /* PC_EINT3 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 4),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "nand0"), /* CE0 */
SUNXI_FUNCTION(0x4, "spi0"), /* MISO */
SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 4)), /* PC_EINT4 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 5),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "nand0"), /* RE */
SUNXI_FUNCTION(0x3, "mmc2"), /* CLK */
SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 5)), /* PC_EINT5 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 6),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "nand0"), /* RB0 */
SUNXI_FUNCTION(0x3, "mmc2"), /* CMD */
SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 6)), /* PC_EINT6 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 7),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "nand0"), /* RB1 */
SUNXI_FUNCTION(0x4, "spi0"), /* CS1 */
SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 7)), /* PC_EINT7 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 8),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "nand0"), /* DQ7 */
SUNXI_FUNCTION(0x3, "mmc2"), /* D3 */
SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 8)), /* PC_EINT8 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 9),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "nand0"), /* DQ6 */
SUNXI_FUNCTION(0x3, "mmc2"), /* D4 */
SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 9)), /* PC_EINT9 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 10),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "nand0"), /* DQ5 */
SUNXI_FUNCTION(0x3, "mmc2"), /* D0 */
SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 10)), /* PC_EINT10 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 11),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "nand0"), /* DQ4 */
SUNXI_FUNCTION(0x3, "mmc2"), /* D5 */
SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 11)), /* PC_EINT11 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 12),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "nand0"), /* DQS */
SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 12)), /* PC_EINT12 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 13),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "nand0"), /* DQ3 */
SUNXI_FUNCTION(0x3, "mmc2"), /* D1 */
SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 13)), /* PC_EINT13 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 14),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "nand0"), /* DQ2 */
SUNXI_FUNCTION(0x3, "mmc2"), /* D6 */
SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 14)), /* PC_EINT14 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 15),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "nand0"), /* DQ1 */
SUNXI_FUNCTION(0x3, "mmc2"), /* D2 */
SUNXI_FUNCTION(0x4, "spi0"), /* WP */
SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 15)), /* PC_EINT15 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 16),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "nand0"), /* DQ0 */
SUNXI_FUNCTION(0x3, "mmc2"), /* D7 */
SUNXI_FUNCTION(0x4, "spi0"), /* HOLD */
SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 16)), /* PC_EINT16 */
/* Hole */
SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 0),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "mmc0"), /* D1 */
SUNXI_FUNCTION(0x3, "jtag"), /* MS */
SUNXI_FUNCTION_IRQ_BANK(0x6, 4, 0)), /* PF_EINT0 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 1),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "mmc0"), /* D0 */
SUNXI_FUNCTION(0x3, "jtag"), /* DI */
SUNXI_FUNCTION_IRQ_BANK(0x6, 4, 1)), /* PF_EINT1 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 2),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "mmc0"), /* CLK */
SUNXI_FUNCTION(0x3, "uart0"), /* TX */
SUNXI_FUNCTION_IRQ_BANK(0x6, 4, 2)), /* PF_EINT2 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 3),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "mmc0"), /* CMD */
SUNXI_FUNCTION(0x3, "jtag"), /* DO */
SUNXI_FUNCTION_IRQ_BANK(0x6, 4, 3)), /* PF_EINT3 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 4),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "mmc0"), /* D3 */
SUNXI_FUNCTION(0x3, "uart0"), /* RX */
SUNXI_FUNCTION_IRQ_BANK(0x6, 4, 4)), /* PF_EINT4 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 5),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "mmc0"), /* D2 */
SUNXI_FUNCTION(0x3, "jtag"), /* CK */
SUNXI_FUNCTION_IRQ_BANK(0x6, 4, 5)), /* PF_EINT5 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 6),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION_IRQ_BANK(0x6, 4, 6)), /* PF_EINT6 */
/* Hole */
SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 0),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "mmc1"), /* CLK */
SUNXI_FUNCTION_IRQ_BANK(0x6, 5, 0)), /* PG_EINT0 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 1),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "mmc1"), /* CMD */
SUNXI_FUNCTION_IRQ_BANK(0x6, 5, 1)), /* PG_EINT1 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 2),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "mmc1"), /* D0 */
SUNXI_FUNCTION_IRQ_BANK(0x6, 5, 2)), /* PG_EINT2 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 3),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "mmc1"), /* D1 */
SUNXI_FUNCTION_IRQ_BANK(0x6, 5, 3)), /* PG_EINT3 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 4),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "mmc1"), /* D2 */
SUNXI_FUNCTION_IRQ_BANK(0x6, 5, 4)), /* PG_EINT4 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 5),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "mmc1"), /* D3 */
SUNXI_FUNCTION_IRQ_BANK(0x6, 5, 5)), /* PG_EINT5 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 6),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "uart1"), /* TX */
SUNXI_FUNCTION(0x4, "jtag"), /* MS */
SUNXI_FUNCTION_IRQ_BANK(0x6, 5, 6)), /* PG_EINT6 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 7),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "uart1"), /* RX */
SUNXI_FUNCTION(0x4, "jtag"), /* CK */
SUNXI_FUNCTION_IRQ_BANK(0x6, 5, 7)), /* PG_EINT7 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 8),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "uart1"), /* RTS */
SUNXI_FUNCTION(0x3, "clock"), /* PLL_LOCK_DEBUG */
SUNXI_FUNCTION(0x4, "jtag"), /* DO */
SUNXI_FUNCTION_IRQ_BANK(0x6, 5, 8)), /* PG_EINT8 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 9),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "uart1"), /* CTS */
SUNXI_FUNCTION_IRQ_BANK(0x6, 5, 9)), /* PG_EINT9 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 10),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "i2s2"), /* MCLK */
SUNXI_FUNCTION(0x3, "clock"), /* X32KFOUT */
SUNXI_FUNCTION_IRQ_BANK(0x6, 5, 10)), /* PG_EINT10 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 11),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "i2s2"), /* BCLK */
SUNXI_FUNCTION_IRQ_BANK(0x6, 5, 11)), /* PG_EINT11 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 12),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "i2s2"), /* SYNC */
SUNXI_FUNCTION_IRQ_BANK(0x6, 5, 12)), /* PG_EINT12 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 13),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "i2s2"), /* DOUT */
SUNXI_FUNCTION_IRQ_BANK(0x6, 5, 13)), /* PG_EINT13 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 14),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "i2s2"), /* DIN */
SUNXI_FUNCTION_IRQ_BANK(0x6, 5, 14)), /* PG_EINT14 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 15),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "uart2"), /* TX */
SUNXI_FUNCTION(0x5, "i2c4"), /* SCK */
SUNXI_FUNCTION_IRQ_BANK(0x6, 5, 15)), /* PG_EINT15 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 16),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "uart2"), /* RX */
SUNXI_FUNCTION(0x5, "i2c4"), /* SDA */
SUNXI_FUNCTION_IRQ_BANK(0x6, 5, 16)), /* PG_EINT16 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 17),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "uart2"), /* RTS */
SUNXI_FUNCTION(0x5, "i2c3"), /* SCK */
SUNXI_FUNCTION_IRQ_BANK(0x6, 5, 17)), /* PG_EINT17 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 18),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "uart2"), /* CTS */
SUNXI_FUNCTION(0x5, "i2c3"), /* SDA */
SUNXI_FUNCTION_IRQ_BANK(0x6, 5, 18)), /* PG_EINT18 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 19),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x4, "pwm1"),
SUNXI_FUNCTION_IRQ_BANK(0x6, 5, 19)), /* PG_EINT19 */
/* Hole */
SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 0),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "uart0"), /* TX */
SUNXI_FUNCTION(0x4, "pwm3"),
SUNXI_FUNCTION(0x5, "i2c1"), /* SCK */
SUNXI_FUNCTION_IRQ_BANK(0x6, 6, 0)), /* PH_EINT0 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 1),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "uart0"), /* RX */
SUNXI_FUNCTION(0x4, "pwm4"),
SUNXI_FUNCTION(0x5, "i2c1"), /* SDA */
SUNXI_FUNCTION_IRQ_BANK(0x6, 6, 1)), /* PH_EINT1 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 2),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "uart5"), /* TX */
SUNXI_FUNCTION(0x3, "spdif"), /* MCLK */
SUNXI_FUNCTION(0x4, "pwm2"),
SUNXI_FUNCTION(0x5, "i2c2"), /* SCK */
SUNXI_FUNCTION_IRQ_BANK(0x6, 6, 2)), /* PH_EINT2 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 3),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "uart5"), /* RX */
SUNXI_FUNCTION(0x4, "pwm1"),
SUNXI_FUNCTION(0x5, "i2c2"), /* SDA */
SUNXI_FUNCTION_IRQ_BANK(0x6, 6, 3)), /* PH_EINT3 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 4),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x3, "spdif"), /* OUT */
SUNXI_FUNCTION(0x5, "i2c3"), /* SCK */
SUNXI_FUNCTION_IRQ_BANK(0x6, 6, 4)), /* PH_EINT4 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 5),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "uart2"), /* TX */
SUNXI_FUNCTION(0x3, "i2s3"), /* MCLK */
SUNXI_FUNCTION(0x4, "spi1"), /* CS0 */
SUNXI_FUNCTION(0x5, "i2c3"), /* SDA */
SUNXI_FUNCTION_IRQ_BANK(0x6, 6, 5)), /* PH_EINT5 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 6),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "uart2"), /* RX */
SUNXI_FUNCTION(0x3, "i2s3"), /* BCLK */
SUNXI_FUNCTION(0x4, "spi1"), /* CLK */
SUNXI_FUNCTION(0x5, "i2c4"), /* SCK */
SUNXI_FUNCTION_IRQ_BANK(0x6, 6, 6)), /* PH_EINT6 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 7),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "uart2"), /* RTS */
SUNXI_FUNCTION(0x3, "i2s3"), /* SYNC */
SUNXI_FUNCTION(0x4, "spi1"), /* MOSI */
SUNXI_FUNCTION(0x5, "i2c4"), /* SDA */
SUNXI_FUNCTION_IRQ_BANK(0x6, 6, 7)), /* PH_EINT7 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 8),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "uart2"), /* CTS */
SUNXI_FUNCTION(0x3, "i2s3"), /* DO0 */
SUNXI_FUNCTION(0x4, "spi1"), /* MISO */
SUNXI_FUNCTION(0x5, "i2s3"), /* DI1 */
SUNXI_FUNCTION_IRQ_BANK(0x6, 6, 8)), /* PH_EINT8 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 9),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x3, "i2s3"), /* DI0 */
SUNXI_FUNCTION(0x4, "spi1"), /* CS1 */
SUNXI_FUNCTION(0x3, "i2s3"), /* DO1 */
SUNXI_FUNCTION_IRQ_BANK(0x6, 6, 9)), /* PH_EINT9 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 10),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x3, "ir_rx"),
SUNXI_FUNCTION_IRQ_BANK(0x6, 6, 10)), /* PH_EINT10 */
/* Hole */
SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 0),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "emac0"), /* ERXD3 */
SUNXI_FUNCTION(0x3, "dmic"), /* CLK */
SUNXI_FUNCTION(0x4, "i2s0"), /* MCLK */
SUNXI_FUNCTION(0x5, "hdmi"), /* HSCL */
SUNXI_FUNCTION_IRQ_BANK(0x6, 7, 0)), /* PI_EINT0 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 1),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "emac0"), /* ERXD2 */
SUNXI_FUNCTION(0x3, "dmic"), /* DATA0 */
SUNXI_FUNCTION(0x4, "i2s0"), /* BCLK */
SUNXI_FUNCTION(0x5, "hdmi"), /* HSDA */
SUNXI_FUNCTION_IRQ_BANK(0x6, 7, 1)), /* PI_EINT1 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 2),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "emac0"), /* ERXD1 */
SUNXI_FUNCTION(0x3, "dmic"), /* DATA1 */
SUNXI_FUNCTION(0x4, "i2s0"), /* SYNC */
SUNXI_FUNCTION(0x5, "hdmi"), /* HCEC */
SUNXI_FUNCTION_IRQ_BANK(0x6, 7, 2)), /* PI_EINT2 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 3),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "emac0"), /* ERXD0 */
SUNXI_FUNCTION(0x3, "dmic"), /* DATA2 */
SUNXI_FUNCTION(0x4, "i2s0_dout0"), /* DO0 */
SUNXI_FUNCTION(0x5, "i2s0_din1"), /* DI1 */
SUNXI_FUNCTION_IRQ_BANK(0x6, 7, 3)), /* PI_EINT3 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 4),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "emac0"), /* ERXCK */
SUNXI_FUNCTION(0x3, "dmic"), /* DATA3 */
SUNXI_FUNCTION(0x4, "i2s0_din0"), /* DI0 */
SUNXI_FUNCTION(0x5, "i2s0_dout1"), /* DO1 */
SUNXI_FUNCTION_IRQ_BANK(0x6, 7, 4)), /* PI_EINT4 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 5),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "emac0"), /* ERXCTL */
SUNXI_FUNCTION(0x3, "uart2"), /* TX */
SUNXI_FUNCTION(0x4, "ts0"), /* CLK */
SUNXI_FUNCTION(0x5, "i2c0"), /* SCK */
SUNXI_FUNCTION_IRQ_BANK(0x6, 7, 5)), /* PI_EINT5 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 6),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "emac0"), /* ENULL */
SUNXI_FUNCTION(0x3, "uart2"), /* RX */
SUNXI_FUNCTION(0x4, "ts0"), /* ERR */
SUNXI_FUNCTION(0x5, "i2c0"), /* SDA */
SUNXI_FUNCTION_IRQ_BANK(0x6, 7, 6)), /* PI_EINT6 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 7),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "emac0"), /* ETXD3 */
SUNXI_FUNCTION(0x3, "uart2"), /* RTS */
SUNXI_FUNCTION(0x4, "ts0"), /* SYNC */
SUNXI_FUNCTION(0x5, "i2c1"), /* SCK */
SUNXI_FUNCTION_IRQ_BANK(0x6, 7, 7)), /* PI_EINT7 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 8),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "emac0"), /* ETXD2 */
SUNXI_FUNCTION(0x3, "uart2"), /* CTS */
SUNXI_FUNCTION(0x4, "ts0"), /* DVLD */
SUNXI_FUNCTION(0x5, "i2c1"), /* SDA */
SUNXI_FUNCTION_IRQ_BANK(0x6, 7, 8)), /* PI_EINT8 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 9),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "emac0"), /* ETXD1 */
SUNXI_FUNCTION(0x3, "uart3"), /* TX */
SUNXI_FUNCTION(0x4, "ts0"), /* D0 */
SUNXI_FUNCTION(0x5, "i2c2"), /* SCK */
SUNXI_FUNCTION_IRQ_BANK(0x6, 7, 9)), /* PI_EINT9 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 10),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "emac0"), /* ETXD0 */
SUNXI_FUNCTION(0x3, "uart3"), /* RX */
SUNXI_FUNCTION(0x4, "ts0"), /* D1 */
SUNXI_FUNCTION(0x5, "i2c2"), /* SDA */
SUNXI_FUNCTION_IRQ_BANK(0x6, 7, 10)), /* PI_EINT10 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 11),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "emac0"), /* ETXCK */
SUNXI_FUNCTION(0x3, "uart3"), /* RTS */
SUNXI_FUNCTION(0x4, "ts0"), /* D2 */
SUNXI_FUNCTION(0x5, "pwm1"),
SUNXI_FUNCTION_IRQ_BANK(0x6, 7, 11)), /* PI_EINT11 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 12),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "emac0"), /* ETXCTL */
SUNXI_FUNCTION(0x3, "uart3"), /* CTS */
SUNXI_FUNCTION(0x4, "ts0"), /* D3 */
SUNXI_FUNCTION(0x5, "pwm2"),
SUNXI_FUNCTION_IRQ_BANK(0x6, 7, 12)), /* PI_EINT12 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 13),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "emac0"), /* ECLKIN */
SUNXI_FUNCTION(0x3, "uart4"), /* TX */
SUNXI_FUNCTION(0x4, "ts0"), /* D4 */
SUNXI_FUNCTION(0x5, "pwm3"),
SUNXI_FUNCTION_IRQ_BANK(0x6, 7, 13)), /* PI_EINT13 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 14),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "emac0"), /* MDC */
SUNXI_FUNCTION(0x3, "uart4"), /* RX */
SUNXI_FUNCTION(0x4, "ts0"), /* D5 */
SUNXI_FUNCTION(0x5, "pwm4"),
SUNXI_FUNCTION_IRQ_BANK(0x6, 7, 14)), /* PI_EINT14 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 15),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "emac0"), /* MDIO */
SUNXI_FUNCTION(0x3, "uart4"), /* RTS */
SUNXI_FUNCTION(0x4, "ts0"), /* D6 */
SUNXI_FUNCTION(0x5, "clock"), /* CLK_FANOUT0 */
SUNXI_FUNCTION_IRQ_BANK(0x6, 7, 15)), /* PI_EINT15 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 16),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "emac0"), /* EPHY_CLK */
SUNXI_FUNCTION(0x3, "uart4"), /* CTS */
SUNXI_FUNCTION(0x4, "ts0"), /* D7 */
SUNXI_FUNCTION(0x5, "clock"), /* CLK_FANOUT1 */
SUNXI_FUNCTION_IRQ_BANK(0x6, 7, 16)), /* PI_EINT16 */
};
static const unsigned int h616_irq_bank_map[] = { 0, 2, 3, 4, 5, 6, 7, 8 };
static const struct sunxi_pinctrl_desc h616_pinctrl_data = {
.pins = h616_pins,
.npins = ARRAY_SIZE(h616_pins),
.irq_banks = ARRAY_SIZE(h616_irq_bank_map),
.irq_bank_map = h616_irq_bank_map,
.irq_read_needs_mux = true,
.io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_SEL,
};
static int h616_pinctrl_probe(struct platform_device *pdev)
{
return sunxi_pinctrl_init(pdev, &h616_pinctrl_data);
}
static const struct of_device_id h616_pinctrl_match[] = {
{ .compatible = "allwinner,sun50i-h616-pinctrl", },
{}
};
static struct platform_driver h616_pinctrl_driver = {
.probe = h616_pinctrl_probe,
.driver = {
.name = "sun50i-h616-pinctrl",
.of_match_table = h616_pinctrl_match,
},
};
builtin_platform_driver(h616_pinctrl_driver);

View File

@ -704,10 +704,9 @@ static void ti_iodelay_pinconf_group_dbg_show(struct pinctrl_dev *pctldev,
u32 reg = 0;
cfg = &group->cfg[i];
regmap_read(iod->regmap, cfg->offset, &reg),
seq_printf(s, "\n\t0x%08x = 0x%08x (%3d, %3d)",
cfg->offset, reg, cfg->a_delay,
cfg->g_delay);
regmap_read(iod->regmap, cfg->offset, &reg);
seq_printf(s, "\n\t0x%08x = 0x%08x (%3d, %3d)",
cfg->offset, reg, cfg->a_delay, cfg->g_delay);
}
}
#endif

View File

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

View File

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

View File

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

View File

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

View File

@ -72,4 +72,10 @@
*/
#define IS_ENABLED(option) __or(IS_BUILTIN(option), IS_MODULE(option))
/*
* IF_ENABLED(CONFIG_FOO, ptr) evaluates to (ptr) if CONFIG_FOO is set to 'y'
* or 'm', NULL otherwise.
*/
#define IF_ENABLED(option, ptr) (IS_ENABLED(option) ? (ptr) : NULL)
#endif /* __LINUX_KCONFIG_H */