This is the bulk of pin control changes for the v3.20 cycle:

- Framework changes and enhancements:
   - Passing -DDEBUG recursively to subdir drivers so we get
     debug messages properly turned on.
   - Infer map type from DT property in the groups parsing code
     in the generic pinconfig code.
   - Support for custom parameter passing in generic pin config.
     This is used when you are using the generic pin config, but
     want to add a few custom properties that no other driver
     will use.
 
 - New drivers:
   - Driver for the Xilinx Zynq
   - Driver for the AmLogic Meson SoCs
 
 - New features in drivers:
   - Sleep support (suspend/resume) for the Cherryview driver
   - mvebeu a38x can now mux a UART on pins MPP19 and MPP20
   - Migrated the qualcomm driver to generic pin config handling
     of extended config options in the core code.
   - Support BUS1 and AUDIO in the Exynos pin controller.
   - Add some missing functions in the sun6i driver.
   - Add support for the A31S variant in the sun6i driver.
   - EMEv2 support in the Renesas PFC driver.
   - Ass support for Qualcomm MSM8916 in the qcom driver.
 
 - Deleted features
   - Drop support for the SiRF Marco that was never released to
     the market.
   - Drop SH7372 support as the support for this platform is
     removed from the kernel.
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQIcBAABAgAGBQJU2w2GAAoJEEEQszewGV1z7kYQAKw4Y4SY9Mq9O97GBq0JWvzv
 uLK4P8NvegHkgX0IDc/etAtHzBN6L+4axh7rDAsaDhug+42CbZxVZjXCfLGFClZP
 kJ/gz4II28AGWiP7TZPNHspIJYgKUdWcVfg0cTZwpM22/AEdBAo9HQ2a/FltvrCn
 eYwzFlAOKUUygmDdbfXHk5Z+ndrJw0ahLjXn8zjBe1HkD2QVaigM9ecA2aQHiG9a
 QvABUJ2qVVs9rqTIxoVzSIGTLeLzrv8cezDLQhZ4KaEasAkxtWKM4kYQSMx/PoTB
 mg+FZ5B8IXqlksnSljT+wOcSP1nmtRdjnED/MpsSLbo9RfJgHkA4Lu4Q8iqt7rZL
 +k/kKi3+p9pTE2pIi56nSpHnfgF8JHgdRAYIXBea5Ug0YnBp83/5jLrU7Fmcjr7s
 l0PH0Fk0iRFRdfn6crcs+SLrhQKtuP+Douwg+3ujVOQiKIW6m+b161GwEVYkvWlq
 1JRWPSjncpsmyg5O8dEwZDwgtzPU65UMEsLgRk9wMNJYw0TqGPugEy4+2rBdJWLy
 CYzJo2At9OcHbB2rT8UKwtErQF85IcWmfnMyfo2PANTLGaj5EFruhmSc2J0m7kOe
 ExPXtWOWxGCtWG53ZDeJUYBg9ySMyleY10LYBP9fPQnotvNB3vfyAkBwV74fnBXs
 ijxO6/Uamd4Rrs5LDRBL
 =Nbzh
 -----END PGP SIGNATURE-----

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

Pull pincontrol updates from Linus Walleij:
 :This is the bulk of pin control changes for the v3.20 cycle:

  Framework changes and enhancements:
   - Passing -DDEBUG recursively to subdir drivers so we get debug
     messages properly turned on.
   - Infer map type from DT property in the groups parsing code in the
     generic pinconfig code.
   - Support for custom parameter passing in generic pin config.  This
     is used when you are using the generic pin config, but want to add
     a few custom properties that no other driver will use.

  New drivers:
   - Driver for the Xilinx Zynq
   - Driver for the AmLogic Meson SoCs

  New features in drivers:
   - Sleep support (suspend/resume) for the Cherryview driver
   - mvebeu a38x can now mux a UART on pins MPP19 and MPP20
   - Migrated the qualcomm driver to generic pin config handling of
     extended config options in the core code.
   - Support BUS1 and AUDIO in the Exynos pin controller.
   - Add some missing functions in the sun6i driver.
   - Add support for the A31S variant in the sun6i driver.
   - EMEv2 support in the Renesas PFC driver.
   - Add support for Qualcomm MSM8916 in the qcom driver.

  Deleted features
   - Drop support for the SiRF Marco that was never released to the
     market.
   - Drop SH7372 support as the support for this platform is removed
     from the kernel"

* tag 'pinctrl-v3.20-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl: (40 commits)
  sh-pfc: emev2 - Fix mangled author name
  pinctrl: cherryview: Configure HiZ pins to be input when requested as GPIOs
  pinctrl: imx25: fix numbering for pins
  pinctrl: pinctrl-imx: don't use invalid value of conf_reg
  pinctrl: qcom: delete pin_config_get/set pinconf operations
  pinctrl: qcom: Add msm8916 pinctrl driver
  DT: pinctrl: Document Qualcomm MSM8916 pinctrl binding
  pinctrl: qcom: increase variable size for register offsets
  pinctrl: hide PCONFDUMP in #ifdef
  pinctrl: rockchip: Only mask interrupts; never disable
  pinctrl: zynq: Fix usb0 pins
  pinctrl: sh-pfc: sh7372: Remove DT binding documentation
  pinctrl: sh-pfc: sh7372: Remove PFC support
  sh-pfc: Add emev2 pinmux support
  sh-pfc: add macro to define pinmux without function
  pinctrl: add driver for Amlogic Meson SoCs
  staging: drivers: pinctrl: Fixed checkpatch.pl warnings
  pinctrl: exynos: Add AUDIO pin controller for exynos7
  sh-pfc: r8a7790: add MLB+ pin group
  sh-pfc: r8a7791: add MLB+ pin group
  ...
This commit is contained in:
Linus Torvalds 2015-02-11 11:23:13 -08:00
commit ce01e871a1
54 changed files with 7866 additions and 3161 deletions

View file

@ -11,6 +11,7 @@ Required properties:
"allwinner,sun5i-a10s-pinctrl"
"allwinner,sun5i-a13-pinctrl"
"allwinner,sun6i-a31-pinctrl"
"allwinner,sun6i-a31s-pinctrl"
"allwinner,sun6i-a31-r-pinctrl"
"allwinner,sun7i-a20-pinctrl"
"allwinner,sun8i-a23-pinctrl"

View file

@ -0,0 +1,186 @@
Qualcomm MSM8916 TLMM block
This binding describes the Top Level Mode Multiplexer block found in the
MSM8916 platform.
- compatible:
Usage: required
Value type: <string>
Definition: must be "qcom,msm8916-pinctrl"
- reg:
Usage: required
Value type: <prop-encoded-array>
Definition: the base address and size of the TLMM register space.
- interrupts:
Usage: required
Value type: <prop-encoded-array>
Definition: should specify the TLMM summary IRQ.
- interrupt-controller:
Usage: required
Value type: <none>
Definition: identifies this node as an interrupt controller
- #interrupt-cells:
Usage: required
Value type: <u32>
Definition: must be 2. Specifying the pin number and flags, as defined
in <dt-bindings/interrupt-controller/irq.h>
- gpio-controller:
Usage: required
Value type: <none>
Definition: identifies this node as a gpio controller
- #gpio-cells:
Usage: required
Value type: <u32>
Definition: must be 2. Specifying the pin number and flags, as defined
in <dt-bindings/gpio/gpio.h>
Please refer to ../gpio/gpio.txt and ../interrupt-controller/interrupts.txt for
a general description of GPIO and interrupt bindings.
Please refer to pinctrl-bindings.txt in this directory for details of the
common pinctrl bindings used by client devices, including the meaning of the
phrase "pin configuration node".
The pin configuration nodes act as a container for an arbitrary number of
subnodes. Each of these subnodes represents some desired configuration for a
pin, a group, or a list of pins or groups. This configuration can include the
mux function to select on those pin(s)/group(s), and various pin configuration
parameters, such as pull-up, drive strength, etc.
PIN CONFIGURATION NODES:
The name of each subnode is not important; all subnodes should be enumerated
and processed purely based on their content.
Each subnode only affects those parameters that are explicitly listed. In
other words, a subnode that lists a mux function but no pin configuration
parameters implies no information about any pin configuration parameters.
Similarly, a pin subnode that describes a pullup parameter implies no
information about e.g. the mux function.
The following generic properties as defined in pinctrl-bindings.txt are valid
to specify in a pin configuration subnode:
- pins:
Usage: required
Value type: <string-array>
Definition: List of gpio pins affected by the properties specified in
this subnode. Valid pins are:
gpio0-gpio121,
sdc1_clk,
sdc1_cmd,
sdc1_data
sdc2_clk,
sdc2_cmd,
sdc2_data,
qdsd_cmd,
qdsd_data0,
qdsd_data1,
qdsd_data2,
qdsd_data3
- function:
Usage: required
Value type: <string>
Definition: Specify the alternative function to be configured for the
specified pins. Functions are only valid for gpio pins.
Valid values are:
adsp_ext, alsp_int, atest_bbrx0, atest_bbrx1, atest_char, atest_char0,
atest_char1, atest_char2, atest_char3, atest_combodac, atest_gpsadc0,
atest_gpsadc1, atest_tsens, atest_wlan0, atest_wlan1, backlight_en,
bimc_dte0,bimc_dte1, blsp_i2c1, blsp_i2c2, blsp_i2c3, blsp_i2c4,
blsp_i2c5, blsp_i2c6, blsp_spi1, blsp_spi1_cs1, blsp_spi1_cs2,
blsp_spi1_cs3, blsp_spi2, blsp_spi2_cs1, blsp_spi2_cs2, blsp_spi2_cs3,
blsp_spi3, blsp_spi3_cs1, blsp_spi3_cs2, blsp_spi3_cs3, blsp_spi4,
blsp_spi5, blsp_spi6, blsp_uart1, blsp_uart2, blsp_uim1, blsp_uim2,
cam1_rst, cam1_standby, cam_mclk0, cam_mclk1, cci_async, cci_i2c,
cci_timer0, cci_timer1, cci_timer2, cdc_pdm0, codec_mad, dbg_out,
display_5v, dmic0_clk, dmic0_data, dsi_rst, ebi0_wrcdc, euro_us,
ext_lpass, flash_strobe, gcc_gp1_clk_a, gcc_gp1_clk_b, gcc_gp2_clk_a,
gcc_gp2_clk_b, gcc_gp3_clk_a, gcc_gp3_clk_b, gpio, gsm0_tx0, gsm0_tx1,
gsm1_tx0, gsm1_tx1, gyro_accl, kpsns0, kpsns1, kpsns2, ldo_en,
ldo_update, mag_int, mdp_vsync, modem_tsync, m_voc, nav_pps, nav_tsync,
pa_indicator, pbs0, pbs1, pbs2, pri_mi2s, pri_mi2s_ws, prng_rosc,
pwr_crypto_enabled_a, pwr_crypto_enabled_b, pwr_modem_enabled_a,
pwr_modem_enabled_b, pwr_nav_enabled_a, pwr_nav_enabled_b,
qdss_ctitrig_in_a0, qdss_ctitrig_in_a1, qdss_ctitrig_in_b0,
qdss_ctitrig_in_b1, qdss_ctitrig_out_a0, qdss_ctitrig_out_a1,
qdss_ctitrig_out_b0, qdss_ctitrig_out_b1, qdss_traceclk_a,
qdss_traceclk_b, qdss_tracectl_a, qdss_tracectl_b, qdss_tracedata_a,
qdss_tracedata_b, reset_n, sd_card, sd_write, sec_mi2s, smb_int,
ssbi_wtr0, ssbi_wtr1, uim1, uim2, uim3, uim_batt, wcss_bt, wcss_fm,
wcss_wlan, webcam1_rst
- bias-disable:
Usage: optional
Value type: <none>
Definition: The specified pins should be configued as no pull.
- bias-pull-down:
Usage: optional
Value type: <none>
Definition: The specified pins should be configued as pull down.
- bias-pull-up:
Usage: optional
Value type: <none>
Definition: The specified pins should be configued as pull up.
- output-high:
Usage: optional
Value type: <none>
Definition: The specified pins are configured in output mode, driven
high.
Not valid for sdc pins.
- output-low:
Usage: optional
Value type: <none>
Definition: The specified pins are configured in output mode, driven
low.
Not valid for sdc pins.
- drive-strength:
Usage: optional
Value type: <u32>
Definition: Selects the drive strength for the specified pins, in mA.
Valid values are: 2, 4, 6, 8, 10, 12, 14 and 16
Example:
tlmm: pinctrl@1000000 {
compatible = "qcom,msm8916-pinctrl";
reg = <0x1000000 0x300000>;
interrupts = <0 208 0>;
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
uart2: uart2-default {
mux {
pins = "gpio4", "gpio5";
function = "blsp_uart2";
};
tx {
pins = "gpio4";
drive-strength = <4>;
bias-disable;
};
rx {
pins = "gpio5";
drive-strength = <2>;
bias-pull-up;
};
};
};

View file

@ -1,7 +1,7 @@
* Renesas Pin Function Controller (GPIO and Pin Mux/Config)
The Pin Function Controller (PFC) is a Pin Mux/Config controller. On SH7372,
SH73A0, R8A73A4 and R8A7740 it also acts as a GPIO controller.
The Pin Function Controller (PFC) is a Pin Mux/Config controller. On SH73A0,
R8A73A4 and R8A7740 it also acts as a GPIO controller.
Pin Control
@ -10,13 +10,13 @@ Pin Control
Required Properties:
- compatible: should be one of the following.
- "renesas,pfc-emev2": for EMEV2 (EMMA Mobile EV2) compatible pin-controller.
- "renesas,pfc-r8a73a4": for R8A73A4 (R-Mobile APE6) compatible pin-controller.
- "renesas,pfc-r8a7740": for R8A7740 (R-Mobile A1) compatible pin-controller.
- "renesas,pfc-r8a7778": for R8A7778 (R-Mobile M1) compatible pin-controller.
- "renesas,pfc-r8a7779": for R8A7779 (R-Car H1) compatible pin-controller.
- "renesas,pfc-r8a7790": for R8A7790 (R-Car H2) compatible pin-controller.
- "renesas,pfc-r8a7791": for R8A7791 (R-Car M2) compatible pin-controller.
- "renesas,pfc-sh7372": for SH7372 (SH-Mobile AP4) compatible pin-controller.
- "renesas,pfc-sh73a0": for SH73A0 (SH-Mobile AG5) compatible pin-controller.
- reg: Base address and length of each memory resource used by the pin
@ -75,8 +75,7 @@ bias-disable, bias-pull-up and bias-pull-down.
GPIO
----
On SH7372, SH73A0, R8A73A4 and R8A7740 the PFC node is also a GPIO controller
node.
On SH73A0, R8A73A4 and R8A7740 the PFC node is also a GPIO controller node.
Required Properties:

View file

@ -171,6 +171,18 @@ Aliases:
All the pin controller nodes should be represented in the aliases node using
the following format 'pinctrl{n}' where n is a unique number for the alias.
Aliases for controllers compatible with "samsung,exynos7-pinctrl":
- pinctrl0: pin controller of ALIVE block,
- pinctrl1: pin controller of BUS0 block,
- pinctrl2: pin controller of NFC block,
- pinctrl3: pin controller of TOUCH block,
- pinctrl4: pin controller of FF block,
- pinctrl5: pin controller of ESE block,
- pinctrl6: pin controller of FSYS0 block,
- pinctrl7: pin controller of FSYS1 block,
- pinctrl8: pin controller of BUS1 block,
- pinctrl9: pin controller of AUDIO block,
Example: A pin-controller node with pin banks:
pinctrl_0: pinctrl@11400000 {

View file

@ -16,17 +16,22 @@ mux function to select on those pin(s)/group(s), and various pin configuration
parameters, such as input, output, pull up, pull down...
The name of each subnode is not important; all subnodes should be enumerated
and processed purely based on their content.
and processed purely based on their content. The subnodes use the generic
pin multiplexing node layout from the standard pin control bindings
(see pinctrl-bindings.txt):
Required subnode-properties:
- ste,pins : An array of strings. Each string contains the name of a pin or
group.
Optional subnode-properties:
- ste,function: A string containing the name of the function to mux to the
Required pin multiplexing subnode properties:
- function: A string containing the name of the function to mux to the
pin or group.
- groups : An array of strings. Each string contains the name of a pin
group that will be combined with the function to form a multiplexing
set-up.
- ste,config: Handle of pin configuration node (e.g. ste,config = <&slpm_in_wkup_pdis>)
Required pin configuration subnode properties:
- pins: A string array describing the pins affected by the configuration
in the node.
- ste,config: Handle of pin configuration node
(e.g. ste,config = <&slpm_in_wkup_pdis>)
- ste,input : <0/1/2>
0: input with no pull
@ -97,32 +102,32 @@ Example board file extract:
uart0 {
uart0_default_mux: uart0_mux {
u0_default_mux {
ste,function = "u0";
ste,pins = "u0_a_1";
function = "u0";
pins = "u0_a_1";
};
};
uart0_default_mode: uart0_default {
uart0_default_cfg1 {
ste,pins = "GPIO0", "GPIO2";
pins = "GPIO0", "GPIO2";
ste,input = <1>;
};
uart0_default_cfg2 {
ste,pins = "GPIO1", "GPIO3";
pins = "GPIO1", "GPIO3";
ste,output = <1>;
};
};
uart0_sleep_mode: uart0_sleep {
uart0_sleep_cfg1 {
ste,pins = "GPIO0", "GPIO2";
pins = "GPIO0", "GPIO2";
ste,config = <&slpm_in_wkup_pdis>;
};
uart0_sleep_cfg2 {
ste,pins = "GPIO1";
pins = "GPIO1";
ste,config = <&slpm_out_hi_wkup_pdis>;
};
uart0_sleep_cfg3 {
ste,pins = "GPIO3";
pins = "GPIO3";
ste,config = <&slpm_out_wkup_pdis>;
};
};

View file

@ -0,0 +1,104 @@
Binding for Xilinx Zynq Pinctrl
Required properties:
- compatible: "xlnx,zynq-pinctrl"
- syscon: phandle to SLCR
- reg: Offset and length of pinctrl space in SLCR
Please refer to pinctrl-bindings.txt in this directory for details of the
common pinctrl bindings used by client devices, including the meaning of the
phrase "pin configuration node".
Zynq's pin configuration nodes act as a container for an arbitrary number of
subnodes. Each of these subnodes represents some desired configuration for a
pin, a group, or a list of pins or groups. This configuration can include the
mux function to select on those pin(s)/group(s), and various pin configuration
parameters, such as pull-up, slew rate, etc.
Each configuration node can consist of multiple nodes describing the pinmux and
pinconf options. Those nodes can be pinmux nodes or pinconf nodes.
The name of each subnode is not important; all subnodes should be enumerated
and processed purely based on their content.
Required properties for pinmux nodes are:
- groups: A list of pinmux groups.
- function: The name of a pinmux function to activate for the specified set
of groups.
Required properties for configuration nodes:
One of:
- pins: a list of pin names
- groups: A list of pinmux groups.
The following generic properties as defined in pinctrl-bindings.txt are valid
to specify in a pinmux subnode:
groups, function
The following generic properties as defined in pinctrl-bindings.txt are valid
to specify in a pinconf subnode:
groups, pins, bias-disable, bias-high-impedance, bias-pull-up, slew-rate,
low-power-disable, low-power-enable
Valid arguments for 'slew-rate' are '0' and '1' to select between slow and fast
respectively.
Valid values for groups are:
ethernet0_0_grp, ethernet1_0_grp, mdio0_0_grp, mdio1_0_grp,
qspi0_0_grp, qspi1_0_grp, qspi_fbclk, qspi_cs1_grp, spi0_0_grp,
spi0_1_grp - spi0_2_grp, spi1_0_grp - spi1_3_grp, sdio0_0_grp - sdio0_2_grp,
sdio1_0_grp - sdio1_3_grp, sdio0_emio_wp, sdio0_emio_cd, sdio1_emio_wp,
sdio1_emio_cd, smc0_nor, smc0_nor_cs1_grp, smc0_nor_addr25_grp, smc0_nand,
can0_0_grp - can0_10_grp, can1_0_grp - can1_11_grp, uart0_0_grp - uart0_10_grp,
uart1_0_grp - uart1_11_grp, i2c0_0_grp - i2c0_10_grp, i2c1_0_grp - i2c1_10_grp,
ttc0_0_grp - ttc0_2_grp, ttc1_0_grp - ttc1_2_grp, swdt0_0_grp - swdt0_4_grp,
gpio0_0_grp - gpio0_53_grp, usb0_0_grp, usb1_0_grp
Valid values for pins are:
MIO0 - MIO53
Valid values for function are:
ethernet0, ethernet1, mdio0, mdio1, qspi0, qspi1, qspi_fbclk, qspi_cs1,
spi0, spi1, sdio0, sdio0_pc, sdio0_cd, sdio0_wp,
sdio1, sdio1_pc, sdio1_cd, sdio1_wp,
smc0_nor, smc0_nor_cs1, smc0_nor_addr25, smc0_nand, can0, can1, uart0, uart1,
i2c0, i2c1, ttc0, ttc1, swdt0, gpio0, usb0, usb1
The following driver-specific properties as defined here are valid to specify in
a pin configuration subnode:
- io-standard: Configure the pin to use the selected IO standard according to
this mapping:
1: LVCMOS18
2: LVCMOS25
3: LVCMOS33
4: HSTL
Example:
pinctrl0: pinctrl@700 {
compatible = "xlnx,pinctrl-zynq";
reg = <0x700 0x200>;
syscon = <&slcr>;
pinctrl_uart1_default: uart1-default {
mux {
groups = "uart1_10_grp";
function = "uart1";
};
conf {
groups = "uart1_10_grp";
slew-rate = <0>;
io-standard = <1>;
};
conf-rx {
pins = "MIO49";
bias-high-impedance;
};
conf-tx {
pins = "MIO48";
bias-disable;
};
};
};

View file

@ -96,6 +96,14 @@ config PINCTRL_FALCON
depends on SOC_FALCON
depends on PINCTRL_LANTIQ
config PINCTRL_MESON
bool
select PINMUX
select PINCONF
select GENERIC_PINCONF
select OF_GPIO
select REGMAP_MMIO
config PINCTRL_ROCKCHIP
bool
select PINMUX
@ -113,7 +121,7 @@ config PINCTRL_SINGLE
This selects the device tree based generic pinctrl driver.
config PINCTRL_SIRF
bool "CSR SiRFprimaII/SiRFmarco pin controller driver"
bool "CSR SiRFprimaII pin controller driver"
depends on ARCH_SIRF
select PINMUX
select GPIOLIB_IRQCHIP
@ -191,6 +199,14 @@ config PINCTRL_PALMAS
open drain configuration for the Palmas series devices like
TPS65913, TPS80036 etc.
config PINCTRL_ZYNQ
bool "Pinctrl driver for Xilinx Zynq"
depends on ARCH_ZYNQ
select PINMUX
select GENERIC_PINCONF
help
This selectes the pinctrl driver for Xilinx Zynq.
source "drivers/pinctrl/berlin/Kconfig"
source "drivers/pinctrl/freescale/Kconfig"
source "drivers/pinctrl/intel/Kconfig"

View file

@ -1,6 +1,6 @@
# generic pinmux support
ccflags-$(CONFIG_DEBUG_PINCTRL) += -DDEBUG
subdir-ccflags-$(CONFIG_DEBUG_PINCTRL) += -DDEBUG
obj-$(CONFIG_PINCTRL) += core.o pinctrl-utils.o
obj-$(CONFIG_PINMUX) += pinmux.o
@ -17,6 +17,7 @@ obj-$(CONFIG_PINCTRL_AT91) += pinctrl-at91.o
obj-$(CONFIG_PINCTRL_BCM2835) += pinctrl-bcm2835.o
obj-$(CONFIG_PINCTRL_BCM281XX) += pinctrl-bcm281xx.o
obj-$(CONFIG_PINCTRL_FALCON) += pinctrl-falcon.o
obj-$(CONFIG_PINCTRL_MESON) += meson/
obj-$(CONFIG_PINCTRL_PALMAS) += pinctrl-palmas.o
obj-$(CONFIG_PINCTRL_ROCKCHIP) += pinctrl-rockchip.o
obj-$(CONFIG_PINCTRL_SINGLE) += pinctrl-single.o
@ -35,6 +36,7 @@ obj-$(CONFIG_PINCTRL_XWAY) += pinctrl-xway.o
obj-$(CONFIG_PINCTRL_LANTIQ) += pinctrl-lantiq.o
obj-$(CONFIG_PINCTRL_TB10X) += pinctrl-tb10x.o
obj-$(CONFIG_PINCTRL_ST) += pinctrl-st.o
obj-$(CONFIG_PINCTRL_ZYNQ) += pinctrl-zynq.o
obj-$(CONFIG_ARCH_BERLIN) += berlin/
obj-y += freescale/

View file

@ -437,7 +437,7 @@ static void imx_pinconf_dbg_show(struct pinctrl_dev *pctldev,
const struct imx_pin_reg *pin_reg = &info->pin_regs[pin_id];
unsigned long config;
if (!pin_reg || !pin_reg->conf_reg) {
if (!pin_reg || pin_reg->conf_reg == -1) {
seq_printf(s, "N/A");
return;
}

View file

@ -27,150 +27,148 @@
enum imx25_pads {
MX25_PAD_RESERVE0 = 1,
MX25_PAD_RESERVE1 = 2,
MX25_PAD_A10 = 3,
MX25_PAD_A13 = 4,
MX25_PAD_A14 = 5,
MX25_PAD_A15 = 6,
MX25_PAD_A16 = 7,
MX25_PAD_A17 = 8,
MX25_PAD_A18 = 9,
MX25_PAD_A19 = 10,
MX25_PAD_A20 = 11,
MX25_PAD_A21 = 12,
MX25_PAD_A22 = 13,
MX25_PAD_A23 = 14,
MX25_PAD_A24 = 15,
MX25_PAD_A25 = 16,
MX25_PAD_EB0 = 17,
MX25_PAD_EB1 = 18,
MX25_PAD_OE = 19,
MX25_PAD_CS0 = 20,
MX25_PAD_CS1 = 21,
MX25_PAD_CS4 = 22,
MX25_PAD_CS5 = 23,
MX25_PAD_NF_CE0 = 24,
MX25_PAD_ECB = 25,
MX25_PAD_LBA = 26,
MX25_PAD_BCLK = 27,
MX25_PAD_RW = 28,
MX25_PAD_NFWE_B = 29,
MX25_PAD_NFRE_B = 30,
MX25_PAD_NFALE = 31,
MX25_PAD_NFCLE = 32,
MX25_PAD_NFWP_B = 33,
MX25_PAD_NFRB = 34,
MX25_PAD_D15 = 35,
MX25_PAD_D14 = 36,
MX25_PAD_D13 = 37,
MX25_PAD_D12 = 38,
MX25_PAD_D11 = 39,
MX25_PAD_D10 = 40,
MX25_PAD_D9 = 41,
MX25_PAD_D8 = 42,
MX25_PAD_D7 = 43,
MX25_PAD_D6 = 44,
MX25_PAD_D5 = 45,
MX25_PAD_D4 = 46,
MX25_PAD_D3 = 47,
MX25_PAD_D2 = 48,
MX25_PAD_D1 = 49,
MX25_PAD_D0 = 50,
MX25_PAD_LD0 = 51,
MX25_PAD_LD1 = 52,
MX25_PAD_LD2 = 53,
MX25_PAD_LD3 = 54,
MX25_PAD_LD4 = 55,
MX25_PAD_LD5 = 56,
MX25_PAD_LD6 = 57,
MX25_PAD_LD7 = 58,
MX25_PAD_LD8 = 59,
MX25_PAD_LD9 = 60,
MX25_PAD_LD10 = 61,
MX25_PAD_LD11 = 62,
MX25_PAD_LD12 = 63,
MX25_PAD_LD13 = 64,
MX25_PAD_LD14 = 65,
MX25_PAD_LD15 = 66,
MX25_PAD_HSYNC = 67,
MX25_PAD_VSYNC = 68,
MX25_PAD_LSCLK = 69,
MX25_PAD_OE_ACD = 70,
MX25_PAD_CONTRAST = 71,
MX25_PAD_PWM = 72,
MX25_PAD_CSI_D2 = 73,
MX25_PAD_CSI_D3 = 74,
MX25_PAD_CSI_D4 = 75,
MX25_PAD_CSI_D5 = 76,
MX25_PAD_CSI_D6 = 77,
MX25_PAD_CSI_D7 = 78,
MX25_PAD_CSI_D8 = 79,
MX25_PAD_CSI_D9 = 80,
MX25_PAD_CSI_MCLK = 81,
MX25_PAD_CSI_VSYNC = 82,
MX25_PAD_CSI_HSYNC = 83,
MX25_PAD_CSI_PIXCLK = 84,
MX25_PAD_I2C1_CLK = 85,
MX25_PAD_I2C1_DAT = 86,
MX25_PAD_CSPI1_MOSI = 87,
MX25_PAD_CSPI1_MISO = 88,
MX25_PAD_CSPI1_SS0 = 89,
MX25_PAD_CSPI1_SS1 = 90,
MX25_PAD_CSPI1_SCLK = 91,
MX25_PAD_CSPI1_RDY = 92,
MX25_PAD_UART1_RXD = 93,
MX25_PAD_UART1_TXD = 94,
MX25_PAD_UART1_RTS = 95,
MX25_PAD_UART1_CTS = 96,
MX25_PAD_UART2_RXD = 97,
MX25_PAD_UART2_TXD = 98,
MX25_PAD_UART2_RTS = 99,
MX25_PAD_UART2_CTS = 100,
MX25_PAD_SD1_CMD = 101,
MX25_PAD_SD1_CLK = 102,
MX25_PAD_SD1_DATA0 = 103,
MX25_PAD_SD1_DATA1 = 104,
MX25_PAD_SD1_DATA2 = 105,
MX25_PAD_SD1_DATA3 = 106,
MX25_PAD_KPP_ROW0 = 107,
MX25_PAD_KPP_ROW1 = 108,
MX25_PAD_KPP_ROW2 = 109,
MX25_PAD_KPP_ROW3 = 110,
MX25_PAD_KPP_COL0 = 111,
MX25_PAD_KPP_COL1 = 112,
MX25_PAD_KPP_COL2 = 113,
MX25_PAD_KPP_COL3 = 114,
MX25_PAD_FEC_MDC = 115,
MX25_PAD_FEC_MDIO = 116,
MX25_PAD_FEC_TDATA0 = 117,
MX25_PAD_FEC_TDATA1 = 118,
MX25_PAD_FEC_TX_EN = 119,
MX25_PAD_FEC_RDATA0 = 120,
MX25_PAD_FEC_RDATA1 = 121,
MX25_PAD_FEC_RX_DV = 122,
MX25_PAD_FEC_TX_CLK = 123,
MX25_PAD_RTCK = 124,
MX25_PAD_DE_B = 125,
MX25_PAD_GPIO_A = 126,
MX25_PAD_GPIO_B = 127,
MX25_PAD_GPIO_C = 128,
MX25_PAD_GPIO_D = 129,
MX25_PAD_GPIO_E = 130,
MX25_PAD_GPIO_F = 131,
MX25_PAD_EXT_ARMCLK = 132,
MX25_PAD_UPLL_BYPCLK = 133,
MX25_PAD_VSTBY_REQ = 134,
MX25_PAD_VSTBY_ACK = 135,
MX25_PAD_POWER_FAIL = 136,
MX25_PAD_CLKO = 137,
MX25_PAD_BOOT_MODE0 = 138,
MX25_PAD_BOOT_MODE1 = 139,
MX25_PAD_A10 = 2,
MX25_PAD_A13 = 3,
MX25_PAD_A14 = 4,
MX25_PAD_A15 = 5,
MX25_PAD_A16 = 6,
MX25_PAD_A17 = 7,
MX25_PAD_A18 = 8,
MX25_PAD_A19 = 9,
MX25_PAD_A20 = 10,
MX25_PAD_A21 = 11,
MX25_PAD_A22 = 12,
MX25_PAD_A23 = 13,
MX25_PAD_A24 = 14,
MX25_PAD_A25 = 15,
MX25_PAD_EB0 = 16,
MX25_PAD_EB1 = 17,
MX25_PAD_OE = 18,
MX25_PAD_CS0 = 19,
MX25_PAD_CS1 = 20,
MX25_PAD_CS4 = 21,
MX25_PAD_CS5 = 22,
MX25_PAD_NF_CE0 = 23,
MX25_PAD_ECB = 24,
MX25_PAD_LBA = 25,
MX25_PAD_BCLK = 26,
MX25_PAD_RW = 27,
MX25_PAD_NFWE_B = 28,
MX25_PAD_NFRE_B = 29,
MX25_PAD_NFALE = 30,
MX25_PAD_NFCLE = 31,
MX25_PAD_NFWP_B = 32,
MX25_PAD_NFRB = 33,
MX25_PAD_D15 = 34,
MX25_PAD_D14 = 35,
MX25_PAD_D13 = 36,
MX25_PAD_D12 = 37,
MX25_PAD_D11 = 38,
MX25_PAD_D10 = 39,
MX25_PAD_D9 = 40,
MX25_PAD_D8 = 41,
MX25_PAD_D7 = 42,
MX25_PAD_D6 = 43,
MX25_PAD_D5 = 44,
MX25_PAD_D4 = 45,
MX25_PAD_D3 = 46,
MX25_PAD_D2 = 47,
MX25_PAD_D1 = 48,
MX25_PAD_D0 = 49,
MX25_PAD_LD0 = 50,
MX25_PAD_LD1 = 51,
MX25_PAD_LD2 = 52,
MX25_PAD_LD3 = 53,
MX25_PAD_LD4 = 54,
MX25_PAD_LD5 = 55,
MX25_PAD_LD6 = 56,
MX25_PAD_LD7 = 57,
MX25_PAD_LD8 = 58,
MX25_PAD_LD9 = 59,
MX25_PAD_LD10 = 60,
MX25_PAD_LD11 = 61,
MX25_PAD_LD12 = 62,
MX25_PAD_LD13 = 63,
MX25_PAD_LD14 = 64,
MX25_PAD_LD15 = 65,
MX25_PAD_HSYNC = 66,
MX25_PAD_VSYNC = 67,
MX25_PAD_LSCLK = 68,
MX25_PAD_OE_ACD = 69,
MX25_PAD_CONTRAST = 70,
MX25_PAD_PWM = 71,
MX25_PAD_CSI_D2 = 72,
MX25_PAD_CSI_D3 = 73,
MX25_PAD_CSI_D4 = 74,
MX25_PAD_CSI_D5 = 75,
MX25_PAD_CSI_D6 = 76,
MX25_PAD_CSI_D7 = 77,
MX25_PAD_CSI_D8 = 78,
MX25_PAD_CSI_D9 = 79,
MX25_PAD_CSI_MCLK = 80,
MX25_PAD_CSI_VSYNC = 81,
MX25_PAD_CSI_HSYNC = 82,
MX25_PAD_CSI_PIXCLK = 83,
MX25_PAD_I2C1_CLK = 84,
MX25_PAD_I2C1_DAT = 85,
MX25_PAD_CSPI1_MOSI = 86,
MX25_PAD_CSPI1_MISO = 87,
MX25_PAD_CSPI1_SS0 = 88,
MX25_PAD_CSPI1_SS1 = 89,
MX25_PAD_CSPI1_SCLK = 90,
MX25_PAD_CSPI1_RDY = 91,
MX25_PAD_UART1_RXD = 92,
MX25_PAD_UART1_TXD = 93,
MX25_PAD_UART1_RTS = 94,
MX25_PAD_UART1_CTS = 95,
MX25_PAD_UART2_RXD = 96,
MX25_PAD_UART2_TXD = 97,
MX25_PAD_UART2_RTS = 98,
MX25_PAD_UART2_CTS = 99,
MX25_PAD_SD1_CMD = 100,
MX25_PAD_SD1_CLK = 101,
MX25_PAD_SD1_DATA0 = 102,
MX25_PAD_SD1_DATA1 = 103,
MX25_PAD_SD1_DATA2 = 104,
MX25_PAD_SD1_DATA3 = 105,
MX25_PAD_KPP_ROW0 = 106,
MX25_PAD_KPP_ROW1 = 107,
MX25_PAD_KPP_ROW2 = 108,
MX25_PAD_KPP_ROW3 = 109,
MX25_PAD_KPP_COL0 = 110,
MX25_PAD_KPP_COL1 = 111,
MX25_PAD_KPP_COL2 = 112,
MX25_PAD_KPP_COL3 = 113,
MX25_PAD_FEC_MDC = 114,
MX25_PAD_FEC_MDIO = 115,
MX25_PAD_FEC_TDATA0 = 116,
MX25_PAD_FEC_TDATA1 = 117,
MX25_PAD_FEC_TX_EN = 118,
MX25_PAD_FEC_RDATA0 = 119,
MX25_PAD_FEC_RDATA1 = 120,
MX25_PAD_FEC_RX_DV = 121,
MX25_PAD_FEC_TX_CLK = 122,
MX25_PAD_RTCK = 123,
MX25_PAD_DE_B = 124,
MX25_PAD_GPIO_A = 125,
MX25_PAD_GPIO_B = 126,
MX25_PAD_GPIO_C = 127,
MX25_PAD_GPIO_D = 128,
MX25_PAD_GPIO_E = 129,
MX25_PAD_GPIO_F = 130,
MX25_PAD_EXT_ARMCLK = 131,
MX25_PAD_UPLL_BYPCLK = 132,
MX25_PAD_VSTBY_REQ = 133,
MX25_PAD_VSTBY_ACK = 134,
MX25_PAD_POWER_FAIL = 135,
MX25_PAD_CLKO = 136,
MX25_PAD_BOOT_MODE0 = 137,
MX25_PAD_BOOT_MODE1 = 138,
};
/* Pad names for the pinmux subsystem */
static const struct pinctrl_pin_desc imx25_pinctrl_pads[] = {
IMX_PINCTRL_PIN(MX25_PAD_RESERVE0),
IMX_PINCTRL_PIN(MX25_PAD_RESERVE1),
IMX_PINCTRL_PIN(MX25_PAD_A10),
IMX_PINCTRL_PIN(MX25_PAD_A13),
IMX_PINCTRL_PIN(MX25_PAD_A14),

View file

@ -148,6 +148,11 @@ struct chv_community {
size_t ngpios;
};
struct chv_pin_context {
u32 padctrl0;
u32 padctrl1;
};
/**
* struct chv_pinctrl - CHV pinctrl private structure
* @dev: Pointer to the parent device
@ -172,6 +177,8 @@ struct chv_pinctrl {
spinlock_t lock;
unsigned intr_lines[16];
const struct chv_community *community;
u32 saved_intmask;
struct chv_pin_context *saved_pin_context;
};
#define gpiochip_to_pinctrl(c) container_of(c, struct chv_pinctrl, chip)
@ -873,9 +880,22 @@ static int chv_gpio_request_enable(struct pinctrl_dev *pctldev,
value &= ~CHV_PADCTRL1_INVRXTX_MASK;
chv_writel(value, reg);
/* Switch to a GPIO mode */
reg = chv_padreg(pctrl, offset, CHV_PADCTRL0);
value = readl(reg) | CHV_PADCTRL0_GPIOEN;
value = readl(reg);
/*
* If the pin is in HiZ mode (both TX and RX buffers are
* disabled) we turn it to be input now.
*/
if ((value & CHV_PADCTRL0_GPIOCFG_MASK) ==
(CHV_PADCTRL0_GPIOCFG_HIZ << CHV_PADCTRL0_GPIOCFG_SHIFT)) {
value &= ~CHV_PADCTRL0_GPIOCFG_MASK;
value |= CHV_PADCTRL0_GPIOCFG_GPI <<
CHV_PADCTRL0_GPIOCFG_SHIFT;
}
/* Switch to a GPIO mode */
value |= CHV_PADCTRL0_GPIOEN;
chv_writel(value, reg);
}
@ -1443,6 +1463,14 @@ static int chv_pinctrl_probe(struct platform_device *pdev)
spin_lock_init(&pctrl->lock);
pctrl->dev = &pdev->dev;
#ifdef CONFIG_PM_SLEEP
pctrl->saved_pin_context = devm_kcalloc(pctrl->dev,
pctrl->community->npins, sizeof(*pctrl->saved_pin_context),
GFP_KERNEL);
if (!pctrl->saved_pin_context)
return -ENOMEM;
#endif
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
pctrl->regs = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(pctrl->regs))
@ -1486,6 +1514,94 @@ static int chv_pinctrl_remove(struct platform_device *pdev)
return 0;
}
#ifdef CONFIG_PM_SLEEP
static int chv_pinctrl_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct chv_pinctrl *pctrl = platform_get_drvdata(pdev);
int i;
pctrl->saved_intmask = readl(pctrl->regs + CHV_INTMASK);
for (i = 0; i < pctrl->community->npins; i++) {
const struct pinctrl_pin_desc *desc;
struct chv_pin_context *ctx;
void __iomem *reg;
desc = &pctrl->community->pins[i];
if (chv_pad_locked(pctrl, desc->number))
continue;
ctx = &pctrl->saved_pin_context[i];
reg = chv_padreg(pctrl, desc->number, CHV_PADCTRL0);
ctx->padctrl0 = readl(reg) & ~CHV_PADCTRL0_GPIORXSTATE;
reg = chv_padreg(pctrl, desc->number, CHV_PADCTRL1);
ctx->padctrl1 = readl(reg);
}
return 0;
}
static int chv_pinctrl_resume(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct chv_pinctrl *pctrl = platform_get_drvdata(pdev);
int i;
/*
* Mask all interrupts before restoring per-pin configuration
* registers because we don't know in which state BIOS left them
* upon exiting suspend.
*/
chv_writel(0, pctrl->regs + CHV_INTMASK);
for (i = 0; i < pctrl->community->npins; i++) {
const struct pinctrl_pin_desc *desc;
const struct chv_pin_context *ctx;
void __iomem *reg;
u32 val;
desc = &pctrl->community->pins[i];
if (chv_pad_locked(pctrl, desc->number))
continue;
ctx = &pctrl->saved_pin_context[i];
/* Only restore if our saved state differs from the current */
reg = chv_padreg(pctrl, desc->number, CHV_PADCTRL0);
val = readl(reg) & ~CHV_PADCTRL0_GPIORXSTATE;
if (ctx->padctrl0 != val) {
chv_writel(ctx->padctrl0, reg);
dev_dbg(pctrl->dev, "restored pin %2u ctrl0 0x%08x\n",
desc->number, readl(reg));
}
reg = chv_padreg(pctrl, desc->number, CHV_PADCTRL1);
val = readl(reg);
if (ctx->padctrl1 != val) {
chv_writel(ctx->padctrl1, reg);
dev_dbg(pctrl->dev, "restored pin %2u ctrl1 0x%08x\n",
desc->number, readl(reg));
}
}
/*
* Now that all pins are restored to known state, we can restore
* the interrupt mask register as well.
*/
chv_writel(0xffff, pctrl->regs + CHV_INTSTAT);
chv_writel(pctrl->saved_intmask, pctrl->regs + CHV_INTMASK);
return 0;
}
#endif
static const struct dev_pm_ops chv_pinctrl_pm_ops = {
SET_LATE_SYSTEM_SLEEP_PM_OPS(chv_pinctrl_suspend, chv_pinctrl_resume)
};
static const struct acpi_device_id chv_pinctrl_acpi_match[] = {
{ "INT33FF" },
{ }
@ -1497,7 +1613,7 @@ static struct platform_driver chv_pinctrl_driver = {
.remove = chv_pinctrl_remove,
.driver = {
.name = "cherryview-pinctrl",
.owner = THIS_MODULE,
.pm = &chv_pinctrl_pm_ops,
.acpi_match_table = chv_pinctrl_acpi_match,
},
};

View file

@ -0,0 +1,2 @@
obj-y += pinctrl-meson8.o
obj-y += pinctrl-meson.o

View file

@ -0,0 +1,761 @@
/*
* Pin controller and GPIO driver for Amlogic Meson SoCs
*
* Copyright (C) 2014 Beniamino Galvani <b.galvani@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* The available pins are organized in banks (A,B,C,D,E,X,Y,Z,AO,
* BOOT,CARD for meson6 and X,Y,DV,H,Z,AO,BOOT,CARD for meson8) and
* each bank has a variable number of pins.
*
* The AO bank is special because it belongs to the Always-On power
* domain which can't be powered off; the bank also uses a set of
* registers different from the other banks.
*
* For each of the two power domains (regular and always-on) there are
* 4 different register ranges that control the following properties
* of the pins:
* 1) pin muxing
* 2) pull enable/disable
* 3) pull up/down
* 4) GPIO direction, output value, input value
*
* In some cases the register ranges for pull enable and pull
* direction are the same and thus there are only 3 register ranges.
*
* Every pinmux group can be enabled by a specific bit in the first
* register range of the domain; when all groups for a given pin are
* disabled the pin acts as a GPIO.
*
* For the pull and GPIO configuration every bank uses a contiguous
* set of bits in the register sets described above; the same register
* can be shared by more banks with different offsets.
*
* In addition to this there are some registers shared between all
* banks that control the IRQ functionality. This feature is not
* supported at the moment by the driver.
*/
#include <linux/device.h>
#include <linux/gpio.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/pinctrl/pinconf-generic.h>
#include <linux/pinctrl/pinconf.h>
#include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/pinmux.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/seq_file.h>
#include "../core.h"
#include "../pinctrl-utils.h"
#include "pinctrl-meson.h"
/**
* meson_get_bank() - find the bank containing a given pin
*
* @domain: the domain containing the pin
* @pin: the pin number
* @bank: the found bank
*
* Return: 0 on success, a negative value on error
*/
static int meson_get_bank(struct meson_domain *domain, unsigned int pin,
struct meson_bank **bank)
{
int i;
for (i = 0; i < domain->data->num_banks; i++) {
if (pin >= domain->data->banks[i].first &&
pin <= domain->data->banks[i].last) {
*bank = &domain->data->banks[i];
return 0;
}
}
return -EINVAL;
}
/**
* meson_get_domain_and_bank() - find domain and bank containing a given pin
*
* @pc: Meson pin controller device
* @pin: the pin number
* @domain: the found domain
* @bank: the found bank
*
* Return: 0 on success, a negative value on error
*/
static int meson_get_domain_and_bank(struct meson_pinctrl *pc, unsigned int pin,
struct meson_domain **domain,
struct meson_bank **bank)
{
struct meson_domain *d;
int i;
for (i = 0; i < pc->data->num_domains; i++) {
d = &pc->domains[i];
if (pin >= d->data->pin_base &&
pin < d->data->pin_base + d->data->num_pins) {
*domain = d;
return meson_get_bank(d, pin, bank);
}
}
return -EINVAL;
}
/**
* meson_calc_reg_and_bit() - calculate register and bit for a pin
*
* @bank: the bank containing the pin
* @pin: the pin number
* @reg_type: the type of register needed (pull-enable, pull, etc...)
* @reg: the computed register offset
* @bit: the computed bit
*/
static void meson_calc_reg_and_bit(struct meson_bank *bank, unsigned int pin,
enum meson_reg_type reg_type,
unsigned int *reg, unsigned int *bit)
{
struct meson_reg_desc *desc = &bank->regs[reg_type];
*reg = desc->reg * 4;
*bit = desc->bit + pin - bank->first;
}
static int meson_get_groups_count(struct pinctrl_dev *pcdev)
{
struct meson_pinctrl *pc = pinctrl_dev_get_drvdata(pcdev);
return pc->data->num_groups;
}
static const char *meson_get_group_name(struct pinctrl_dev *pcdev,
unsigned selector)
{
struct meson_pinctrl *pc = pinctrl_dev_get_drvdata(pcdev);
return pc->data->groups[selector].name;
}
static int meson_get_group_pins(struct pinctrl_dev *pcdev, unsigned selector,
const unsigned **pins, unsigned *num_pins)
{
struct meson_pinctrl *pc = pinctrl_dev_get_drvdata(pcdev);
*pins = pc->data->groups[selector].pins;
*num_pins = pc->data->groups[selector].num_pins;
return 0;
}
static void meson_pin_dbg_show(struct pinctrl_dev *pcdev, struct seq_file *s,
unsigned offset)
{
seq_printf(s, " %s", dev_name(pcdev->dev));
}
static const struct pinctrl_ops meson_pctrl_ops = {
.get_groups_count = meson_get_groups_count,
.get_group_name = meson_get_group_name,
.get_group_pins = meson_get_group_pins,
.dt_node_to_map = pinconf_generic_dt_node_to_map_all,
.dt_free_map = pinctrl_utils_dt_free_map,
.pin_dbg_show = meson_pin_dbg_show,
};
/**
* meson_pmx_disable_other_groups() - disable other groups using a given pin
*
* @pc: meson pin controller device
* @pin: number of the pin
* @sel_group: index of the selected group, or -1 if none
*
* The function disables all pinmux groups using a pin except the
* selected one. If @sel_group is -1 all groups are disabled, leaving
* the pin in GPIO mode.
*/
static void meson_pmx_disable_other_groups(struct meson_pinctrl *pc,
unsigned int pin, int sel_group)
{
struct meson_pmx_group *group;
struct meson_domain *domain;
int i, j;
for (i = 0; i < pc->data->num_groups; i++) {
group = &pc->data->groups[i];
if (group->is_gpio || i == sel_group)
continue;
for (j = 0; j < group->num_pins; j++) {
if (group->pins[j] == pin) {
/* We have found a group using the pin */
domain = &pc->domains[group->domain];
regmap_update_bits(domain->reg_mux,
group->reg * 4,
BIT(group->bit), 0);
}
}
}
}
static int meson_pmx_set_mux(struct pinctrl_dev *pcdev, unsigned func_num,
unsigned group_num)
{
struct meson_pinctrl *pc = pinctrl_dev_get_drvdata(pcdev);
struct meson_pmx_func *func = &pc->data->funcs[func_num];
struct meson_pmx_group *group = &pc->data->groups[group_num];
struct meson_domain *domain = &pc->domains[group->domain];
int i, ret = 0;
dev_dbg(pc->dev, "enable function %s, group %s\n", func->name,
group->name);
/*
* Disable groups using the same pin.
* The selected group is not disabled to avoid glitches.
*/
for (i = 0; i < group->num_pins; i++)
meson_pmx_disable_other_groups(pc, group->pins[i], group_num);
/* Function 0 (GPIO) doesn't need any additional setting */
if (func_num)
ret = regmap_update_bits(domain->reg_mux, group->reg * 4,
BIT(group->bit), BIT(group->bit));
return ret;
}
static int meson_pmx_request_gpio(struct pinctrl_dev *pcdev,
struct pinctrl_gpio_range *range,
unsigned offset)
{
struct meson_pinctrl *pc = pinctrl_dev_get_drvdata(pcdev);
meson_pmx_disable_other_groups(pc, range->pin_base + offset, -1);
return 0;
}
static int meson_pmx_get_funcs_count(struct pinctrl_dev *pcdev)
{
struct meson_pinctrl *pc = pinctrl_dev_get_drvdata(pcdev);
return pc->data->num_funcs;
}
static const char *meson_pmx_get_func_name(struct pinctrl_dev *pcdev,
unsigned selector)
{
struct meson_pinctrl *pc = pinctrl_dev_get_drvdata(pcdev);
return pc->data->funcs[selector].name;
}
static int meson_pmx_get_groups(struct pinctrl_dev *pcdev, unsigned selector,
const char * const **groups,
unsigned * const num_groups)
{
struct meson_pinctrl *pc = pinctrl_dev_get_drvdata(pcdev);
*groups = pc->data->funcs[selector].groups;
*num_groups = pc->data->funcs[selector].num_groups;
return 0;
}
static const struct pinmux_ops meson_pmx_ops = {
.set_mux = meson_pmx_set_mux,
.get_functions_count = meson_pmx_get_funcs_count,
.get_function_name = meson_pmx_get_func_name,
.get_function_groups = meson_pmx_get_groups,
.gpio_request_enable = meson_pmx_request_gpio,
};
static int meson_pinconf_set(struct pinctrl_dev *pcdev, unsigned int pin,
unsigned long *configs, unsigned num_configs)
{
struct meson_pinctrl *pc = pinctrl_dev_get_drvdata(pcdev);
struct meson_domain *domain;
struct meson_bank *bank;
enum pin_config_param param;
unsigned int reg, bit;
int i, ret;
u16 arg;
ret = meson_get_domain_and_bank(pc, pin, &domain, &bank);
if (ret)
return ret;
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_DISABLE:
dev_dbg(pc->dev, "pin %u: disable bias\n", pin);
meson_calc_reg_and_bit(bank, pin, REG_PULL, &reg, &bit);
ret = regmap_update_bits(domain->reg_pull, reg,
BIT(bit), 0);
if (ret)
return ret;
break;
case PIN_CONFIG_BIAS_PULL_UP:
dev_dbg(pc->dev, "pin %u: enable pull-up\n", pin);
meson_calc_reg_and_bit(bank, pin, REG_PULLEN,
&reg, &bit);
ret = regmap_update_bits(domain->reg_pullen, reg,
BIT(bit), BIT(bit));
if (ret)
return ret;
meson_calc_reg_and_bit(bank, pin, REG_PULL, &reg, &bit);
ret = regmap_update_bits(domain->reg_pull, reg,
BIT(bit), BIT(bit));
if (ret)
return ret;
break;
case PIN_CONFIG_BIAS_PULL_DOWN:
dev_dbg(pc->dev, "pin %u: enable pull-down\n", pin);
meson_calc_reg_and_bit(bank, pin, REG_PULLEN,
&reg, &bit);
ret = regmap_update_bits(domain->reg_pullen, reg,
BIT(bit), BIT(bit));
if (ret)
return ret;
meson_calc_reg_and_bit(bank, pin, REG_PULL, &reg, &bit);
ret = regmap_update_bits(domain->reg_pull, reg,
BIT(bit), 0);
if (ret)
return ret;
break;
default:
return -ENOTSUPP;
}
}
return 0;
}
static int meson_pinconf_get_pull(struct meson_pinctrl *pc, unsigned int pin)
{
struct meson_domain *domain;
struct meson_bank *bank;
unsigned int reg, bit, val;
int ret, conf;
ret = meson_get_domain_and_bank(pc, pin, &domain, &bank);
if (ret)
return ret;
meson_calc_reg_and_bit(bank, pin, REG_PULLEN, &reg, &bit);
ret = regmap_read(domain->reg_pullen, reg, &val);
if (ret)
return ret;
if (!(val & BIT(bit))) {
conf = PIN_CONFIG_BIAS_DISABLE;
} else {
meson_calc_reg_and_bit(bank, pin, REG_PULL, &reg, &bit);
ret = regmap_read(domain->reg_pull, reg, &val);
if (ret)
return ret;
if (val & BIT(bit))
conf = PIN_CONFIG_BIAS_PULL_UP;
else
conf = PIN_CONFIG_BIAS_PULL_DOWN;
}
return conf;
}
static int meson_pinconf_get(struct pinctrl_dev *pcdev, unsigned int pin,
unsigned long *config)
{
struct meson_pinctrl *pc = pinctrl_dev_get_drvdata(pcdev);
enum pin_config_param param = pinconf_to_config_param(*config);
u16 arg;
switch (param) {
case PIN_CONFIG_BIAS_DISABLE:
case PIN_CONFIG_BIAS_PULL_DOWN:
case PIN_CONFIG_BIAS_PULL_UP:
if (meson_pinconf_get_pull(pc, pin) == param)
arg = 1;
else
return -EINVAL;
break;
default:
return -ENOTSUPP;
}
*config = pinconf_to_config_packed(param, arg);
dev_dbg(pc->dev, "pinconf for pin %u is %lu\n", pin, *config);
return 0;
}
static int meson_pinconf_group_set(struct pinctrl_dev *pcdev,
unsigned int num_group,
unsigned long *configs, unsigned num_configs)
{
struct meson_pinctrl *pc = pinctrl_dev_get_drvdata(pcdev);
struct meson_pmx_group *group = &pc->data->groups[num_group];
int i;
dev_dbg(pc->dev, "set pinconf for group %s\n", group->name);
for (i = 0; i < group->num_pins; i++) {
meson_pinconf_set(pcdev, group->pins[i], configs,
num_configs);
}
return 0;
}
static int meson_pinconf_group_get(struct pinctrl_dev *pcdev,
unsigned int group, unsigned long *config)
{
return -ENOSYS;
}
static const struct pinconf_ops meson_pinconf_ops = {
.pin_config_get = meson_pinconf_get,
.pin_config_set = meson_pinconf_set,
.pin_config_group_get = meson_pinconf_group_get,
.pin_config_group_set = meson_pinconf_group_set,
.is_generic = true,
};
static inline struct meson_domain *to_meson_domain(struct gpio_chip *chip)
{
return container_of(chip, struct meson_domain, chip);
}
static int meson_gpio_request(struct gpio_chip *chip, unsigned gpio)
{
return pinctrl_request_gpio(chip->base + gpio);
}
static void meson_gpio_free(struct gpio_chip *chip, unsigned gpio)
{
struct meson_domain *domain = to_meson_domain(chip);
pinctrl_free_gpio(domain->data->pin_base + gpio);
}
static int meson_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
{
struct meson_domain *domain = to_meson_domain(chip);
unsigned int reg, bit, pin;
struct meson_bank *bank;
int ret;
pin = domain->data->pin_base + gpio;
ret = meson_get_bank(domain, pin, &bank);
if (ret)
return ret;
meson_calc_reg_and_bit(bank, pin, REG_DIR, &reg, &bit);
return regmap_update_bits(domain->reg_gpio, reg, BIT(bit), BIT(bit));
}
static int meson_gpio_direction_output(struct gpio_chip *chip, unsigned gpio,
int value)
{
struct meson_domain *domain = to_meson_domain(chip);
unsigned int reg, bit, pin;
struct meson_bank *bank;
int ret;
pin = domain->data->pin_base + gpio;
ret = meson_get_bank(domain, pin, &bank);
if (ret)
return ret;
meson_calc_reg_and_bit(bank, pin, REG_DIR, &reg, &bit);
ret = regmap_update_bits(domain->reg_gpio, reg, BIT(bit), 0);
if (ret)
return ret;
meson_calc_reg_and_bit(bank, pin, REG_OUT, &reg, &bit);
return regmap_update_bits(domain->reg_gpio, reg, BIT(bit),
value ? BIT(bit) : 0);
}
static void meson_gpio_set(struct gpio_chip *chip, unsigned gpio, int value)
{
struct meson_domain *domain = to_meson_domain(chip);
unsigned int reg, bit, pin;
struct meson_bank *bank;
int ret;
pin = domain->data->pin_base + gpio;
ret = meson_get_bank(domain, pin, &bank);
if (ret)
return;
meson_calc_reg_and_bit(bank, pin, REG_OUT, &reg, &bit);
regmap_update_bits(domain->reg_gpio, reg, BIT(bit),
value ? BIT(bit) : 0);
}
static int meson_gpio_get(struct gpio_chip *chip, unsigned gpio)
{
struct meson_domain *domain = to_meson_domain(chip);
unsigned int reg, bit, val, pin;
struct meson_bank *bank;
int ret;
pin = domain->data->pin_base + gpio;
ret = meson_get_bank(domain, pin, &bank);
if (ret)
return ret;
meson_calc_reg_and_bit(bank, pin, REG_IN, &reg, &bit);
regmap_read(domain->reg_gpio, reg, &val);
return !!(val & BIT(bit));
}
static const struct of_device_id meson_pinctrl_dt_match[] = {
{
.compatible = "amlogic,meson8-pinctrl",
.data = &meson8_pinctrl_data,
},
{ },
};
MODULE_DEVICE_TABLE(of, meson_pinctrl_dt_match);
static int meson_gpiolib_register(struct meson_pinctrl *pc)
{
struct meson_domain *domain;
int i, ret;
for (i = 0; i < pc->data->num_domains; i++) {
domain = &pc->domains[i];
domain->chip.label = domain->data->name;
domain->chip.dev = pc->dev;
domain->chip.request = meson_gpio_request;
domain->chip.free = meson_gpio_free;
domain->chip.direction_input = meson_gpio_direction_input;
domain->chip.direction_output = meson_gpio_direction_output;
domain->chip.get = meson_gpio_get;
domain->chip.set = meson_gpio_set;
domain->chip.base = -1;
domain->chip.ngpio = domain->data->num_pins;
domain->chip.can_sleep = false;
domain->chip.of_node = domain->of_node;
domain->chip.of_gpio_n_cells = 2;
ret = gpiochip_add(&domain->chip);
if (ret) {
dev_err(pc->dev, "can't add gpio chip %s\n",
domain->data->name);
goto fail;
}
ret = gpiochip_add_pin_range(&domain->chip, dev_name(pc->dev),
0, domain->data->pin_base,
domain->chip.ngpio);
if (ret) {
dev_err(pc->dev, "can't add pin range\n");
goto fail;
}
}
return 0;
fail:
for (i--; i >= 0; i--)
gpiochip_remove(&pc->domains[i].chip);
return ret;
}
static struct meson_domain_data *meson_get_domain_data(struct meson_pinctrl *pc,
struct device_node *np)
{
int i;
for (i = 0; i < pc->data->num_domains; i++) {
if (!strcmp(np->name, pc->data->domain_data[i].name))
return &pc->data->domain_data[i];
}
return NULL;
}
static struct regmap_config meson_regmap_config = {
.reg_bits = 32,
.val_bits = 32,
.reg_stride = 4,
};
static struct regmap *meson_map_resource(struct meson_pinctrl *pc,
struct device_node *node, char *name)
{
struct resource res;
void __iomem *base;
int i;
i = of_property_match_string(node, "reg-names", name);
if (of_address_to_resource(node, i, &res))
return ERR_PTR(-ENOENT);
base = devm_ioremap_resource(pc->dev, &res);
if (IS_ERR(base))
return ERR_CAST(base);
meson_regmap_config.max_register = resource_size(&res) - 4;
meson_regmap_config.name = devm_kasprintf(pc->dev, GFP_KERNEL,
"%s-%s", node->name,
name);
if (!meson_regmap_config.name)
return ERR_PTR(-ENOMEM);
return devm_regmap_init_mmio(pc->dev, base, &meson_regmap_config);
}
static int meson_pinctrl_parse_dt(struct meson_pinctrl *pc,
struct device_node *node)
{
struct device_node *np;
struct meson_domain *domain;
int i = 0, num_domains = 0;
for_each_child_of_node(node, np) {
if (!of_find_property(np, "gpio-controller", NULL))
continue;
num_domains++;
}
if (num_domains != pc->data->num_domains) {
dev_err(pc->dev, "wrong number of subnodes\n");
return -EINVAL;
}
pc->domains = devm_kzalloc(pc->dev, num_domains *
sizeof(struct meson_domain), GFP_KERNEL);
if (!pc->domains)
return -ENOMEM;
for_each_child_of_node(node, np) {
if (!of_find_property(np, "gpio-controller", NULL))
continue;
domain = &pc->domains[i];
domain->data = meson_get_domain_data(pc, np);
if (!domain->data) {
dev_err(pc->dev, "domain data not found for node %s\n",
np->name);
return -ENODEV;
}
domain->of_node = np;
domain->reg_mux = meson_map_resource(pc, np, "mux");
if (IS_ERR(domain->reg_mux)) {
dev_err(pc->dev, "mux registers not found\n");
return PTR_ERR(domain->reg_mux);
}
domain->reg_pull = meson_map_resource(pc, np, "pull");
if (IS_ERR(domain->reg_pull)) {
dev_err(pc->dev, "pull registers not found\n");
return PTR_ERR(domain->reg_pull);
}
domain->reg_pullen = meson_map_resource(pc, np, "pull-enable");
/* Use pull region if pull-enable one is not present */
if (IS_ERR(domain->reg_pullen))
domain->reg_pullen = domain->reg_pull;
domain->reg_gpio = meson_map_resource(pc, np, "gpio");
if (IS_ERR(domain->reg_gpio)) {
dev_err(pc->dev, "gpio registers not found\n");
return PTR_ERR(domain->reg_gpio);
}
i++;
}
return 0;
}
static int meson_pinctrl_probe(struct platform_device *pdev)
{
const struct of_device_id *match;
struct device *dev = &pdev->dev;
struct meson_pinctrl *pc;
int ret;
pc = devm_kzalloc(dev, sizeof(struct meson_pinctrl), GFP_KERNEL);
if (!pc)
return -ENOMEM;
pc->dev = dev;
match = of_match_node(meson_pinctrl_dt_match, pdev->dev.of_node);
pc->data = (struct meson_pinctrl_data *)match->data;
ret = meson_pinctrl_parse_dt(pc, pdev->dev.of_node);
if (ret)
return ret;
pc->desc.name = "pinctrl-meson";
pc->desc.owner = THIS_MODULE;
pc->desc.pctlops = &meson_pctrl_ops;
pc->desc.pmxops = &meson_pmx_ops;
pc->desc.confops = &meson_pinconf_ops;
pc->desc.pins = pc->data->pins;
pc->desc.npins = pc->data->num_pins;
pc->pcdev = pinctrl_register(&pc->desc, pc->dev, pc);
if (!pc->pcdev) {
dev_err(pc->dev, "can't register pinctrl device");
return -EINVAL;
}
ret = meson_gpiolib_register(pc);
if (ret) {
pinctrl_unregister(pc->pcdev);
return ret;
}
return 0;
}
static struct platform_driver meson_pinctrl_driver = {
.probe = meson_pinctrl_probe,
.driver = {
.name = "meson-pinctrl",
.of_match_table = meson_pinctrl_dt_match,
},
};
module_platform_driver(meson_pinctrl_driver);
MODULE_AUTHOR("Beniamino Galvani <b.galvani@gmail.com>");
MODULE_DESCRIPTION("Amlogic Meson pinctrl driver");
MODULE_LICENSE("GPL v2");

View file

@ -0,0 +1,209 @@
/*
* Pin controller and GPIO driver for Amlogic Meson SoCs
*
* Copyright (C) 2014 Beniamino Galvani <b.galvani@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <linux/gpio.h>
#include <linux/pinctrl/pinctrl.h>
#include <linux/regmap.h>
#include <linux/types.h>
/**
* struct meson_pmx_group - a pinmux group
*
* @name: group name
* @pins: pins in the group
* @num_pins: number of pins in the group
* @is_gpio: whether the group is a single GPIO group
* @reg: register offset for the group in the domain mux registers
* @bit bit index enabling the group
* @domain: index of the domain this group belongs to
*/
struct meson_pmx_group {
const char *name;
const unsigned int *pins;
unsigned int num_pins;
bool is_gpio;
unsigned int reg;
unsigned int bit;
unsigned int domain;
};
/**
* struct meson_pmx_func - a pinmux function
*
* @name: function name
* @groups: groups in the function
* @num_groups: number of groups in the function
*/
struct meson_pmx_func {
const char *name;
const char * const *groups;
unsigned int num_groups;
};
/**
* struct meson_reg_desc - a register descriptor
*
* @reg: register offset in the regmap
* @bit: bit index in register
*
* The structure describes the information needed to control pull,
* pull-enable, direction, etc. for a single pin
*/
struct meson_reg_desc {
unsigned int reg;
unsigned int bit;
};
/**
* enum meson_reg_type - type of registers encoded in @meson_reg_desc
*/
enum meson_reg_type {
REG_PULLEN,
REG_PULL,
REG_DIR,
REG_OUT,
REG_IN,
NUM_REG,
};
/**
* struct meson bank
*
* @name: bank name
* @first: first pin of the bank
* @last: last pin of the bank
* @regs: array of register descriptors
*
* A bank represents a set of pins controlled by a contiguous set of
* bits in the domain registers. The structure specifies which bits in
* the regmap control the different functionalities. Each member of
* the @regs array refers to the first pin of the bank.
*/
struct meson_bank {
const char *name;
unsigned int first;
unsigned int last;
struct meson_reg_desc regs[NUM_REG];
};
/**
* struct meson_domain_data - domain platform data
*
* @name: name of the domain
* @banks: set of banks belonging to the domain
* @num_banks: number of banks in the domain
*/
struct meson_domain_data {
const char *name;
struct meson_bank *banks;
unsigned int num_banks;
unsigned int pin_base;
unsigned int num_pins;
};
/**
* struct meson_domain
*
* @reg_mux: registers for mux settings
* @reg_pullen: registers for pull-enable settings
* @reg_pull: registers for pull settings
* @reg_gpio: registers for gpio settings
* @chip: gpio chip associated with the domain
* @data; platform data for the domain
* @node: device tree node for the domain
*
* A domain represents a set of banks controlled by the same set of
* registers.
*/
struct meson_domain {
struct regmap *reg_mux;
struct regmap *reg_pullen;
struct regmap *reg_pull;
struct regmap *reg_gpio;
struct gpio_chip chip;
struct meson_domain_data *data;
struct device_node *of_node;
};
struct meson_pinctrl_data {
const struct pinctrl_pin_desc *pins;
struct meson_pmx_group *groups;
struct meson_pmx_func *funcs;
struct meson_domain_data *domain_data;
unsigned int num_pins;
unsigned int num_groups;
unsigned int num_funcs;
unsigned int num_domains;
};
struct meson_pinctrl {
struct device *dev;
struct pinctrl_dev *pcdev;
struct pinctrl_desc desc;
struct meson_pinctrl_data *data;
struct meson_domain *domains;
};
#define GROUP(grp, r, b) \
{ \
.name = #grp, \
.pins = grp ## _pins, \
.num_pins = ARRAY_SIZE(grp ## _pins), \
.reg = r, \
.bit = b, \
.domain = 0, \
}
#define GPIO_GROUP(gpio) \
{ \
.name = #gpio, \
.pins = (const unsigned int[]){ PIN_ ## gpio}, \
.num_pins = 1, \
.is_gpio = true, \
}
#define GROUP_AO(grp, r, b) \
{ \
.name = #grp, \
.pins = grp ## _pins, \
.num_pins = ARRAY_SIZE(grp ## _pins), \
.reg = r, \
.bit = b, \
.domain = 1, \
}
#define FUNCTION(fn) \
{ \
.name = #fn, \
.groups = fn ## _groups, \
.num_groups = ARRAY_SIZE(fn ## _groups), \
}
#define BANK(n, f, l, per, peb, pr, pb, dr, db, or, ob, ir, ib) \
{ \
.name = n, \
.first = f, \
.last = l, \
.regs = { \
[REG_PULLEN] = { per, peb }, \
[REG_PULL] = { pr, pb }, \
[REG_DIR] = { dr, db }, \
[REG_OUT] = { or, ob }, \
[REG_IN] = { ir, ib }, \
}, \
}
#define MESON_PIN(x) PINCTRL_PIN(PIN_ ## x, #x)
extern struct meson_pinctrl_data meson8_pinctrl_data;

File diff suppressed because it is too large Load diff

View file

@ -145,14 +145,16 @@ static struct mvebu_mpp_mode armada_38x_mpp_modes[] = {
MPP_VAR_FUNCTION(2, "ptp", "event_req", V_88F6810_PLUS),
MPP_VAR_FUNCTION(3, "pcie0", "clkreq", V_88F6810_PLUS),
MPP_VAR_FUNCTION(4, "sata1", "prsnt", V_88F6810_PLUS),
MPP_VAR_FUNCTION(5, "ua0", "cts", V_88F6810_PLUS)),
MPP_VAR_FUNCTION(5, "ua0", "cts", V_88F6810_PLUS),
MPP_VAR_FUNCTION(6, "ua1", "rxd", V_88F6810_PLUS)),
MPP_MODE(20,
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
MPP_VAR_FUNCTION(1, "ge0", "txclk", V_88F6810_PLUS),
MPP_VAR_FUNCTION(2, "ptp", "clk", V_88F6810_PLUS),
MPP_VAR_FUNCTION(3, "pcie1", "rstout", V_88F6820_PLUS),
MPP_VAR_FUNCTION(4, "sata0", "prsnt", V_88F6810_PLUS),
MPP_VAR_FUNCTION(5, "ua0", "rts", V_88F6810_PLUS)),
MPP_VAR_FUNCTION(5, "ua0", "rts", V_88F6810_PLUS),
MPP_VAR_FUNCTION(6, "ua1", "txd", V_88F6810_PLUS)),
MPP_MODE(21,
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
MPP_VAR_FUNCTION(1, "spi0", "cs1", V_88F6810_PLUS),

View file

@ -751,12 +751,12 @@ static struct mvebu_pinctrl_soc_info dove_pinctrl_info = {
static struct clk *clk;
static struct of_device_id dove_pinctrl_of_match[] = {
static const struct of_device_id dove_pinctrl_of_match[] = {
{ .compatible = "marvell,dove-pinctrl", .data = &dove_pinctrl_info },
{ }
};
static struct regmap_config gc_regmap_config = {
static const struct regmap_config gc_regmap_config = {
.reg_bits = 32,
.val_bits = 32,
.reg_stride = 4,

View file

@ -914,7 +914,7 @@ static int abx500_dt_subnode_to_map(struct pinctrl_dev *pctldev,
}
}
ret = pinconf_generic_parse_dt_config(np, &configs, &nconfigs);
ret = pinconf_generic_parse_dt_config(np, pctldev, &configs, &nconfigs);
if (nconfigs) {
const char *gpio_name;
const char *pin;

View file

@ -27,17 +27,6 @@
#include "pinctrl-utils.h"
#ifdef CONFIG_DEBUG_FS
struct pin_config_item {
const enum pin_config_param param;
const char * const display;
const char * const format;
bool has_arg;
};
#define PCONFDUMP(a, b, c, d) { .param = a, .display = b, .format = c, \
.has_arg = d }
static const struct pin_config_item conf_items[] = {
PCONFDUMP(PIN_CONFIG_BIAS_DISABLE, "input bias disabled", NULL, false),
PCONFDUMP(PIN_CONFIG_BIAS_HIGH_IMPEDANCE, "input bias high impedance", NULL, false),
@ -60,22 +49,25 @@ static const struct pin_config_item conf_items[] = {
PCONFDUMP(PIN_CONFIG_OUTPUT, "pin output", "level", true),
};
void pinconf_generic_dump_pin(struct pinctrl_dev *pctldev,
struct seq_file *s, unsigned pin)
static void pinconf_generic_dump_one(struct pinctrl_dev *pctldev,
struct seq_file *s, const char *gname,
unsigned pin,
const struct pin_config_item *items,
int nitems)
{
const struct pinconf_ops *ops = pctldev->desc->confops;
int i;
if (!ops->is_generic)
return;
for (i = 0; i < ARRAY_SIZE(conf_items); i++) {
for (i = 0; i < nitems; i++) {
unsigned long config;
int ret;
/* We want to check out this parameter */
config = pinconf_to_config_packed(conf_items[i].param, 0);
ret = pin_config_get_for_pin(pctldev, pin, &config);
config = pinconf_to_config_packed(items[i].param, 0);
if (gname)
ret = pin_config_group_get(dev_name(pctldev->dev),
gname, &config);
else
ret = pin_config_get_for_pin(pctldev, pin, &config);
/* These are legal errors */
if (ret == -EINVAL || ret == -ENOTSUPP)
continue;
@ -85,56 +77,47 @@ void pinconf_generic_dump_pin(struct pinctrl_dev *pctldev,
}
/* Space between multiple configs */
seq_puts(s, " ");
seq_puts(s, conf_items[i].display);
seq_puts(s, items[i].display);
/* Print unit if available */
if (conf_items[i].has_arg) {
if (items[i].has_arg) {
seq_printf(s, " (%u",
pinconf_to_config_argument(config));
if (conf_items[i].format)
seq_printf(s, " %s)", conf_items[i].format);
if (items[i].format)
seq_printf(s, " %s)", items[i].format);
else
seq_puts(s, ")");
}
}
}
void pinconf_generic_dump_group(struct pinctrl_dev *pctldev,
struct seq_file *s, const char *gname)
/**
* pinconf_generic_dump_pins - Print information about pin or group of pins
* @pctldev: Pincontrol device
* @s: File to print to
* @gname: Group name specifying pins
* @pin: Pin number specyfying pin
*
* Print the pinconf configuration for the requested pin(s) to @s. Pins can be
* specified either by pin using @pin or by group using @gname. Only one needs
* to be specified the other can be NULL/0.
*/
void pinconf_generic_dump_pins(struct pinctrl_dev *pctldev, struct seq_file *s,
const char *gname, unsigned pin)
{
const struct pinconf_ops *ops = pctldev->desc->confops;
int i;
if (!ops->is_generic)
return;
for (i = 0; i < ARRAY_SIZE(conf_items); i++) {
unsigned long config;
int ret;
/* We want to check out this parameter */
config = pinconf_to_config_packed(conf_items[i].param, 0);
ret = pin_config_group_get(dev_name(pctldev->dev), gname,
&config);
/* These are legal errors */
if (ret == -EINVAL || ret == -ENOTSUPP)
continue;
if (ret) {
seq_printf(s, "ERROR READING CONFIG SETTING %d ", i);
continue;
}
/* Space between multiple configs */
seq_puts(s, " ");
seq_puts(s, conf_items[i].display);
/* Print unit if available */
if (conf_items[i].has_arg) {
seq_printf(s, " (%u",
pinconf_to_config_argument(config));
if (conf_items[i].format)
seq_printf(s, " %s)", conf_items[i].format);
else
seq_puts(s, ")");
}
}
/* generic parameters */
pinconf_generic_dump_one(pctldev, s, gname, pin, conf_items,
ARRAY_SIZE(conf_items));
/* driver-specific parameters */
if (pctldev->desc->num_custom_params &&
pctldev->desc->custom_conf_items)
pinconf_generic_dump_one(pctldev, s, gname, pin,
pctldev->desc->custom_conf_items,
pctldev->desc->num_custom_params);
}
void pinconf_generic_dump_config(struct pinctrl_dev *pctldev,
@ -148,18 +131,25 @@ void pinconf_generic_dump_config(struct pinctrl_dev *pctldev,
seq_printf(s, "%s: 0x%x", conf_items[i].display,
pinconf_to_config_argument(config));
}
if (!pctldev->desc->num_custom_params ||
!pctldev->desc->custom_conf_items)
return;
for (i = 0; i < pctldev->desc->num_custom_params; i++) {
if (pinconf_to_config_param(config) !=
pctldev->desc->custom_conf_items[i].param)
continue;
seq_printf(s, "%s: 0x%x",
pctldev->desc->custom_conf_items[i].display,
pinconf_to_config_argument(config));
}
}
EXPORT_SYMBOL_GPL(pinconf_generic_dump_config);
#endif
#ifdef CONFIG_OF
struct pinconf_generic_dt_params {
const char * const property;
enum pin_config_param param;
u32 default_value;
};
static const struct pinconf_generic_dt_params dt_params[] = {
static const struct pinconf_generic_params dt_params[] = {
{ "bias-disable", PIN_CONFIG_BIAS_DISABLE, 0 },
{ "bias-high-impedance", PIN_CONFIG_BIAS_HIGH_IMPEDANCE, 0 },
{ "bias-bus-hold", PIN_CONFIG_BIAS_BUS_HOLD, 0 },
@ -184,32 +174,30 @@ static const struct pinconf_generic_dt_params dt_params[] = {
};
/**
* pinconf_generic_parse_dt_config()
* parse the config properties into generic pinconfig values.
* @np: node containing the pinconfig properties
* @configs: array with nconfigs entries containing the generic pinconf values
* @nconfigs: umber of configurations
* parse_dt_cfg() - Parse DT pinconf parameters
* @np: DT node
* @params: Array of describing generic parameters
* @count: Number of entries in @params
* @cfg: Array of parsed config options
* @ncfg: Number of entries in @cfg
*
* Parse the config options described in @params from @np and puts the result
* in @cfg. @cfg does not need to be empty, entries are added beggining at
* @ncfg. @ncfg is updated to reflect the number of entries after parsing. @cfg
* needs to have enough memory allocated to hold all possible entries.
*/
int pinconf_generic_parse_dt_config(struct device_node *np,
unsigned long **configs,
unsigned int *nconfigs)
static void parse_dt_cfg(struct device_node *np,
const struct pinconf_generic_params *params,
unsigned int count, unsigned long *cfg,
unsigned int *ncfg)
{
unsigned long *cfg;
unsigned int ncfg = 0;
int ret;
int i;
u32 val;
if (!np)
return -EINVAL;
for (i = 0; i < count; i++) {
u32 val;
int ret;
const struct pinconf_generic_params *par = &params[i];
/* allocate a temporary array big enough to hold one of each option */
cfg = kzalloc(sizeof(*cfg) * ARRAY_SIZE(dt_params), GFP_KERNEL);
if (!cfg)
return -ENOMEM;
for (i = 0; i < ARRAY_SIZE(dt_params); i++) {
const struct pinconf_generic_dt_params *par = &dt_params[i];
ret = of_property_read_u32(np, par->property, &val);
/* property not found */
@ -221,9 +209,43 @@ int pinconf_generic_parse_dt_config(struct device_node *np,
val = par->default_value;
pr_debug("found %s with value %u\n", par->property, val);
cfg[ncfg] = pinconf_to_config_packed(par->param, val);
ncfg++;
cfg[*ncfg] = pinconf_to_config_packed(par->param, val);
(*ncfg)++;
}
}
/**
* pinconf_generic_parse_dt_config()
* parse the config properties into generic pinconfig values.
* @np: node containing the pinconfig properties
* @configs: array with nconfigs entries containing the generic pinconf values
* @nconfigs: umber of configurations
*/
int pinconf_generic_parse_dt_config(struct device_node *np,
struct pinctrl_dev *pctldev,
unsigned long **configs,
unsigned int *nconfigs)
{
unsigned long *cfg;
unsigned int max_cfg, ncfg = 0;
int ret;
if (!np)
return -EINVAL;
/* allocate a temporary array big enough to hold one of each option */
max_cfg = ARRAY_SIZE(dt_params);
if (pctldev)
max_cfg += pctldev->desc->num_custom_params;
cfg = kcalloc(max_cfg, sizeof(*cfg), GFP_KERNEL);
if (!cfg)
return -ENOMEM;
parse_dt_cfg(np, dt_params, ARRAY_SIZE(dt_params), cfg, &ncfg);
if (pctldev && pctldev->desc->num_custom_params &&
pctldev->desc->custom_params)
parse_dt_cfg(np, pctldev->desc->custom_params,
pctldev->desc->num_custom_params, cfg, &ncfg);
ret = 0;
@ -264,6 +286,7 @@ int pinconf_generic_dt_subnode_to_map(struct pinctrl_dev *pctldev,
unsigned reserve;
struct property *prop;
const char *group;
const char *subnode_target_type = "pins";
ret = of_property_read_string(np, "function", &function);
if (ret < 0) {
@ -273,7 +296,8 @@ int pinconf_generic_dt_subnode_to_map(struct pinctrl_dev *pctldev,
function = NULL;
}
ret = pinconf_generic_parse_dt_config(np, &configs, &num_configs);
ret = pinconf_generic_parse_dt_config(np, pctldev, &configs,
&num_configs);
if (ret < 0) {
dev_err(dev, "could not parse node property\n");
return ret;
@ -284,10 +308,20 @@ int pinconf_generic_dt_subnode_to_map(struct pinctrl_dev *pctldev,
reserve++;
if (num_configs)
reserve++;
ret = of_property_count_strings(np, "pins");
if (ret < 0) {
dev_err(dev, "could not parse property pins\n");
goto exit;
ret = of_property_count_strings(np, "groups");
if (ret < 0) {
dev_err(dev, "could not parse property pins/groups\n");
goto exit;
}
if (type == PIN_MAP_TYPE_INVALID)
type = PIN_MAP_TYPE_CONFIGS_GROUP;
subnode_target_type = "groups";
} else {
if (type == PIN_MAP_TYPE_INVALID)
type = PIN_MAP_TYPE_CONFIGS_PIN;
}
reserve *= ret;
@ -296,7 +330,7 @@ int pinconf_generic_dt_subnode_to_map(struct pinctrl_dev *pctldev,
if (ret < 0)
goto exit;
of_property_for_each_string(np, "pins", prop, group) {
of_property_for_each_string(np, subnode_target_type, prop, group) {
if (function) {
ret = pinctrl_utils_add_map_mux(pctldev, map,
reserved_maps, num_maps, group,

View file

@ -288,7 +288,7 @@ static void pinconf_dump_pin(struct pinctrl_dev *pctldev,
const struct pinconf_ops *ops = pctldev->desc->confops;
/* no-op when not using generic pin config */
pinconf_generic_dump_pin(pctldev, s, pin);
pinconf_generic_dump_pins(pctldev, s, NULL, pin);
if (ops && ops->pin_config_dbg_show)
ops->pin_config_dbg_show(pctldev, s, pin);
}
@ -333,7 +333,7 @@ static void pinconf_dump_group(struct pinctrl_dev *pctldev,
const struct pinconf_ops *ops = pctldev->desc->confops;
/* no-op when not using generic pin config */
pinconf_generic_dump_group(pctldev, s, gname);
pinconf_generic_dump_pins(pctldev, s, gname, 0);
if (ops && ops->pin_config_group_dbg_show)
ops->pin_config_group_dbg_show(pctldev, s, selector);
}

View file

@ -92,26 +92,17 @@ static inline void pinconf_init_device_debugfs(struct dentry *devroot,
#if defined(CONFIG_GENERIC_PINCONF) && defined(CONFIG_DEBUG_FS)
void pinconf_generic_dump_pin(struct pinctrl_dev *pctldev,
struct seq_file *s, unsigned pin);
void pinconf_generic_dump_group(struct pinctrl_dev *pctldev,
struct seq_file *s, const char *gname);
void pinconf_generic_dump_pins(struct pinctrl_dev *pctldev,
struct seq_file *s, const char *gname,
unsigned pin);
void pinconf_generic_dump_config(struct pinctrl_dev *pctldev,
struct seq_file *s, unsigned long config);
#else
static inline void pinconf_generic_dump_pin(struct pinctrl_dev *pctldev,
struct seq_file *s,
unsigned pin)
{
return;
}
static inline void pinconf_generic_dump_group(struct pinctrl_dev *pctldev,
struct seq_file *s,
const char *gname)
static inline void pinconf_generic_dump_pins(struct pinctrl_dev *pctldev,
struct seq_file *s,
const char *gname, unsigned pin)
{
return;
}
@ -126,6 +117,7 @@ static inline void pinconf_generic_dump_config(struct pinctrl_dev *pctldev,
#if defined(CONFIG_GENERIC_PINCONF) && defined(CONFIG_OF)
int pinconf_generic_parse_dt_config(struct device_node *np,
struct pinctrl_dev *pctldev,
unsigned long **configs,
unsigned int *nconfigs);
#endif

View file

@ -976,7 +976,7 @@ static inline void bcm281xx_pin_update(u32 *reg_val, u32 *reg_mask,
*reg_mask |= param_mask;
}
static struct regmap_config bcm281xx_pinctrl_regmap_config = {
static const struct regmap_config bcm281xx_pinctrl_regmap_config = {
.reg_bits = 32,
.reg_stride = 4,
.val_bits = 32,
@ -1435,7 +1435,7 @@ static int __init bcm281xx_pinctrl_probe(struct platform_device *pdev)
return 0;
}
static struct of_device_id bcm281xx_pinctrl_of_match[] = {
static const struct of_device_id bcm281xx_pinctrl_of_match[] = {
{ .compatible = "brcm,bcm11351-pinctrl", },
{ },
};

View file

@ -101,6 +101,7 @@ static void lantiq_load_pin_desc(struct pinctrl_pin_desc *d, int bank, int len)
for (i = 0; i < len; i++) {
/* strlen("ioXYZ") + 1 = 6 */
char *name = kzalloc(6, GFP_KERNEL);
snprintf(name, 6, "io%d", base + i);
d[i].number = base + i;
d[i].name = name;
@ -463,7 +464,7 @@ static int pinctrl_falcon_probe(struct platform_device *pdev)
&res);
if (IS_ERR(falcon_info.membase[*bank]))
return PTR_ERR(falcon_info.membase[*bank]);
avail = pad_r32(falcon_info.membase[*bank],
LTQ_PADC_AVAIL);
pins = fls(avail);

View file

@ -89,7 +89,7 @@ struct rockchip_iomux {
* @reg_pull: optional separate register for additional pull settings
* @clk: clock of the gpio bank
* @irq: interrupt of the gpio bank
* @saved_enables: Saved content of GPIO_INTEN at suspend time.
* @saved_masks: Saved content of GPIO_INTEN at suspend time.
* @pin_base: first pin number
* @nr_pins: number of pins in this bank
* @name: name of the bank
@ -108,7 +108,7 @@ struct rockchip_pin_bank {
struct regmap *regmap_pull;
struct clk *clk;
int irq;
u32 saved_enables;
u32 saved_masks;
u32 pin_base;
u8 nr_pins;
char *name;
@ -1142,7 +1142,7 @@ static int rockchip_pinctrl_parse_groups(struct device_node *np,
return -EINVAL;
np_config = of_find_node_by_phandle(be32_to_cpup(phandle));
ret = pinconf_generic_parse_dt_config(np_config,
ret = pinconf_generic_parse_dt_config(np_config, NULL,
&grp->data[j].configs, &grp->data[j].nconfigs);
if (ret)
return ret;
@ -1545,8 +1545,8 @@ static void rockchip_irq_suspend(struct irq_data *d)
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
struct rockchip_pin_bank *bank = gc->private;
bank->saved_enables = irq_reg_readl(gc, GPIO_INTEN);
irq_reg_writel(gc, gc->wake_active, GPIO_INTEN);
bank->saved_masks = irq_reg_readl(gc, GPIO_INTMASK);
irq_reg_writel(gc, ~gc->wake_active, GPIO_INTMASK);
}
static void rockchip_irq_resume(struct irq_data *d)
@ -1554,35 +1554,7 @@ static void rockchip_irq_resume(struct irq_data *d)
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
struct rockchip_pin_bank *bank = gc->private;
irq_reg_writel(gc, bank->saved_enables, GPIO_INTEN);
}
static void rockchip_irq_disable(struct irq_data *d)
{
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
u32 val;
irq_gc_lock(gc);
val = irq_reg_readl(gc, GPIO_INTEN);
val &= ~d->mask;
irq_reg_writel(gc, val, GPIO_INTEN);
irq_gc_unlock(gc);
}
static void rockchip_irq_enable(struct irq_data *d)
{
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
u32 val;
irq_gc_lock(gc);
val = irq_reg_readl(gc, GPIO_INTEN);
val |= d->mask;
irq_reg_writel(gc, val, GPIO_INTEN);
irq_gc_unlock(gc);
irq_reg_writel(gc, bank->saved_masks, GPIO_INTMASK);
}
static int rockchip_interrupts_register(struct platform_device *pdev,
@ -1620,6 +1592,14 @@ static int rockchip_interrupts_register(struct platform_device *pdev,
continue;
}
/*
* Linux assumes that all interrupts start out disabled/masked.
* Our driver only uses the concept of masked and always keeps
* things enabled, so for us that's all masked and all enabled.
*/
writel_relaxed(0xffffffff, bank->reg_base + GPIO_INTMASK);
writel_relaxed(0xffffffff, bank->reg_base + GPIO_INTEN);
gc = irq_get_domain_generic_chip(bank->domain, 0);
gc->reg_base = bank->reg_base;
gc->private = bank;
@ -1628,8 +1608,6 @@ static int rockchip_interrupts_register(struct platform_device *pdev,
gc->chip_types[0].chip.irq_ack = irq_gc_ack_set_bit;
gc->chip_types[0].chip.irq_mask = irq_gc_mask_set_bit;
gc->chip_types[0].chip.irq_unmask = irq_gc_mask_clr_bit;
gc->chip_types[0].chip.irq_enable = rockchip_irq_enable;
gc->chip_types[0].chip.irq_disable = rockchip_irq_disable;
gc->chip_types[0].chip.irq_set_wake = irq_gc_set_wake;
gc->chip_types[0].chip.irq_suspend = rockchip_irq_suspend;
gc->chip_types[0].chip.irq_resume = rockchip_irq_resume;

View file

@ -415,7 +415,7 @@ static int tz1090_pdc_pinctrl_dt_subnode_to_map(struct device *dev,
function = NULL;
}
ret = pinconf_generic_parse_dt_config(np, &configs, &num_configs);
ret = pinconf_generic_parse_dt_config(np, NULL, &configs, &num_configs);
if (ret)
return ret;

View file

@ -1131,7 +1131,7 @@ static int tz1090_pinctrl_dt_subnode_to_map(struct device *dev,
function = NULL;
}
ret = pinconf_generic_parse_dt_config(np, &configs, &num_configs);
ret = pinconf_generic_parse_dt_config(np, NULL, &configs, &num_configs);
if (ret)
return ret;

File diff suppressed because it is too large Load diff

View file

@ -47,6 +47,14 @@ config PINCTRL_MSM8X74
This is the pinctrl, pinmux, pinconf and gpiolib driver for the
Qualcomm TLMM block found in the Qualcomm 8974 platform.
config PINCTRL_MSM8916
tristate "Qualcomm 8916 pin controller driver"
depends on GPIOLIB && OF
select PINCTRL_MSM
help
This is the pinctrl, pinmux, pinconf and gpiolib driver for the
Qualcomm TLMM block found on the Qualcomm 8916 platform.
config PINCTRL_QCOM_SPMI_PMIC
tristate "Qualcomm SPMI PMIC pin controller driver"
depends on GPIOLIB && OF && SPMI

View file

@ -5,5 +5,6 @@ obj-$(CONFIG_PINCTRL_APQ8084) += pinctrl-apq8084.o
obj-$(CONFIG_PINCTRL_IPQ8064) += pinctrl-ipq8064.o
obj-$(CONFIG_PINCTRL_MSM8960) += pinctrl-msm8960.o
obj-$(CONFIG_PINCTRL_MSM8X74) += pinctrl-msm8x74.o
obj-$(CONFIG_PINCTRL_MSM8916) += pinctrl-msm8916.o
obj-$(CONFIG_PINCTRL_QCOM_SPMI_PMIC) += pinctrl-spmi-gpio.o
obj-$(CONFIG_PINCTRL_QCOM_SPMI_PMIC) += pinctrl-spmi-mpp.o

View file

@ -204,21 +204,6 @@ static int msm_config_reg(struct msm_pinctrl *pctrl,
return 0;
}
static int msm_config_get(struct pinctrl_dev *pctldev,
unsigned int pin,
unsigned long *config)
{
dev_err(pctldev->dev, "pin_config_set op not supported\n");
return -ENOTSUPP;
}
static int msm_config_set(struct pinctrl_dev *pctldev, unsigned int pin,
unsigned long *configs, unsigned num_configs)
{
dev_err(pctldev->dev, "pin_config_set op not supported\n");
return -ENOTSUPP;
}
#define MSM_NO_PULL 0
#define MSM_PULL_DOWN 1
#define MSM_KEEPER 2
@ -372,8 +357,6 @@ static int msm_config_group_set(struct pinctrl_dev *pctldev,
}
static const struct pinconf_ops msm_pinconf_ops = {
.pin_config_get = msm_config_get,
.pin_config_set = msm_config_set,
.pin_config_group_get = msm_config_group_get,
.pin_config_group_set = msm_config_group_set,
};

View file

@ -70,11 +70,11 @@ struct msm_pingroup {
unsigned *funcs;
unsigned nfuncs;
s16 ctl_reg;
s16 io_reg;
s16 intr_cfg_reg;
s16 intr_status_reg;
s16 intr_target_reg;
u32 ctl_reg;
u32 io_reg;
u32 intr_cfg_reg;
u32 intr_status_reg;
u32 intr_target_reg;
unsigned mux_bit:5;

File diff suppressed because it is too large Load diff

View file

@ -131,15 +131,17 @@ struct pmic_gpio_state {
struct gpio_chip chip;
};
struct pmic_gpio_bindings {
const char *property;
unsigned param;
static const struct pinconf_generic_params pmic_gpio_bindings[] = {
{"qcom,pull-up-strength", PMIC_GPIO_CONF_PULL_UP, 0},
{"qcom,drive-strength", PMIC_GPIO_CONF_STRENGTH, 0},
};
static struct pmic_gpio_bindings pmic_gpio_bindings[] = {
{"qcom,pull-up-strength", PMIC_GPIO_CONF_PULL_UP},
{"qcom,drive-strength", PMIC_GPIO_CONF_STRENGTH},
#ifdef CONFIG_DEBUG_FS
static const struct pin_config_item pmic_conf_items[ARRAY_SIZE(pmic_gpio_bindings)] = {
PCONFDUMP(PMIC_GPIO_CONF_PULL_UP, "pull up strength", NULL, true),
PCONFDUMP(PMIC_GPIO_CONF_STRENGTH, "drive-strength", NULL, true),
};
#endif
static const char *const pmic_gpio_groups[] = {
"gpio1", "gpio2", "gpio3", "gpio4", "gpio5", "gpio6", "gpio7", "gpio8",
@ -209,118 +211,11 @@ static int pmic_gpio_get_group_pins(struct pinctrl_dev *pctldev, unsigned pin,
return 0;
}
static int pmic_gpio_parse_dt_config(struct device_node *np,
struct pinctrl_dev *pctldev,
unsigned long **configs,
unsigned int *nconfs)
{
struct pmic_gpio_bindings *par;
unsigned long cfg;
int ret, i;
u32 val;
for (i = 0; i < ARRAY_SIZE(pmic_gpio_bindings); i++) {
par = &pmic_gpio_bindings[i];
ret = of_property_read_u32(np, par->property, &val);
/* property not found */
if (ret == -EINVAL)
continue;
/* use zero as default value */
if (ret)
val = 0;
dev_dbg(pctldev->dev, "found %s with value %u\n",
par->property, val);
cfg = pinconf_to_config_packed(par->param, val);
ret = pinctrl_utils_add_config(pctldev, configs, nconfs, cfg);
if (ret)
return ret;
}
return 0;
}
static int pmic_gpio_dt_subnode_to_map(struct pinctrl_dev *pctldev,
struct device_node *np,
struct pinctrl_map **map,
unsigned *reserv, unsigned *nmaps,
enum pinctrl_map_type type)
{
unsigned long *configs = NULL;
unsigned nconfs = 0;
struct property *prop;
const char *group;
int ret;
ret = pmic_gpio_parse_dt_config(np, pctldev, &configs, &nconfs);
if (ret < 0)
return ret;
if (!nconfs)
return 0;
ret = of_property_count_strings(np, "pins");
if (ret < 0)
goto exit;
ret = pinctrl_utils_reserve_map(pctldev, map, reserv, nmaps, ret);
if (ret < 0)
goto exit;
of_property_for_each_string(np, "pins", prop, group) {
ret = pinctrl_utils_add_map_configs(pctldev, map,
reserv, nmaps, group,
configs, nconfs, type);
if (ret < 0)
break;
}
exit:
kfree(configs);
return ret;
}
static int pmic_gpio_dt_node_to_map(struct pinctrl_dev *pctldev,
struct device_node *np_config,
struct pinctrl_map **map, unsigned *nmaps)
{
enum pinctrl_map_type type;
struct device_node *np;
unsigned reserv;
int ret;
ret = 0;
*map = NULL;
*nmaps = 0;
reserv = 0;
type = PIN_MAP_TYPE_CONFIGS_GROUP;
for_each_child_of_node(np_config, np) {
ret = pinconf_generic_dt_subnode_to_map(pctldev, np, map,
&reserv, nmaps, type);
if (ret)
break;
ret = pmic_gpio_dt_subnode_to_map(pctldev, np, map, &reserv,
nmaps, type);
if (ret)
break;
}
if (ret < 0)
pinctrl_utils_dt_free_map(pctldev, *map, *nmaps);
return ret;
}
static const struct pinctrl_ops pmic_gpio_pinctrl_ops = {
.get_groups_count = pmic_gpio_get_groups_count,
.get_group_name = pmic_gpio_get_group_name,
.get_group_pins = pmic_gpio_get_group_pins,
.dt_node_to_map = pmic_gpio_dt_node_to_map,
.dt_node_to_map = pinconf_generic_dt_node_to_map_group,
.dt_free_map = pinctrl_utils_dt_free_map,
};
@ -590,6 +485,7 @@ static void pmic_gpio_config_dbg_show(struct pinctrl_dev *pctldev,
}
static const struct pinconf_ops pmic_gpio_pinconf_ops = {
.is_generic = true,
.pin_config_group_get = pmic_gpio_config_get,
.pin_config_group_set = pmic_gpio_config_set,
.pin_config_group_dbg_show = pmic_gpio_config_dbg_show,
@ -848,6 +744,11 @@ static int pmic_gpio_probe(struct platform_device *pdev)
pctrldesc->name = dev_name(dev);
pctrldesc->pins = pindesc;
pctrldesc->npins = npins;
pctrldesc->num_custom_params = ARRAY_SIZE(pmic_gpio_bindings);
pctrldesc->custom_params = pmic_gpio_bindings;
#ifdef CONFIG_DEBUG_FS
pctrldesc->custom_conf_items = pmic_conf_items;
#endif
for (i = 0; i < npins; i++, pindesc++) {
pad = &pads[i];

View file

@ -1300,6 +1300,25 @@ static const struct samsung_pin_bank_data exynos7_pin_banks7[] __initconst = {
EXYNOS_PIN_BANK_EINTG(8, 0x060, "gpr3", 0x0c),
};
/* pin banks of exynos7 pin-controller - BUS1 */
static const struct samsung_pin_bank_data exynos7_pin_banks8[] __initconst = {
EXYNOS_PIN_BANK_EINTG(8, 0x020, "gpf0", 0x00),
EXYNOS_PIN_BANK_EINTG(8, 0x040, "gpf1", 0x04),
EXYNOS_PIN_BANK_EINTG(4, 0x060, "gpf2", 0x08),
EXYNOS_PIN_BANK_EINTG(5, 0x080, "gpf3", 0x0c),
EXYNOS_PIN_BANK_EINTG(8, 0x0a0, "gpf4", 0x10),
EXYNOS_PIN_BANK_EINTG(8, 0x0c0, "gpf5", 0x14),
EXYNOS_PIN_BANK_EINTG(5, 0x0e0, "gpg1", 0x18),
EXYNOS_PIN_BANK_EINTG(5, 0x100, "gpg2", 0x1c),
EXYNOS_PIN_BANK_EINTG(6, 0x120, "gph1", 0x20),
EXYNOS_PIN_BANK_EINTG(3, 0x140, "gpv6", 0x24),
};
static const struct samsung_pin_bank_data exynos7_pin_banks9[] __initconst = {
EXYNOS_PIN_BANK_EINTG(7, 0x000, "gpz0", 0x00),
EXYNOS_PIN_BANK_EINTG(4, 0x020, "gpz1", 0x04),
};
const struct samsung_pin_ctrl exynos7_pin_ctrl[] __initconst = {
{
/* pin-controller instance 0 Alive data */
@ -1342,5 +1361,15 @@ const struct samsung_pin_ctrl exynos7_pin_ctrl[] __initconst = {
.pin_banks = exynos7_pin_banks7,
.nr_banks = ARRAY_SIZE(exynos7_pin_banks7),
.eint_gpio_init = exynos_eint_gpio_init,
}, {
/* pin-controller instance 8 BUS1 data */
.pin_banks = exynos7_pin_banks8,
.nr_banks = ARRAY_SIZE(exynos7_pin_banks8),
.eint_gpio_init = exynos_eint_gpio_init,
}, {
/* pin-controller instance 9 AUD data */
.pin_banks = exynos7_pin_banks9,
.nr_banks = ARRAY_SIZE(exynos7_pin_banks9),
.eint_gpio_init = exynos_eint_gpio_init,
},
};

View file

@ -20,6 +20,11 @@ config GPIO_SH_PFC
This enables support for GPIOs within the SoC's pin function
controller.
config PINCTRL_PFC_EMEV2
def_bool y
depends on ARCH_EMEV2
select PINCTRL_SH_PFC
config PINCTRL_PFC_R8A73A4
def_bool y
depends on ARCH_R8A73A4
@ -68,11 +73,6 @@ config PINCTRL_PFC_SH7269
depends on GPIOLIB
select PINCTRL_SH_PFC
config PINCTRL_PFC_SH7372
def_bool y
depends on ARCH_SH7372
select PINCTRL_SH_PFC
config PINCTRL_PFC_SH73A0
def_bool y
depends on ARCH_SH73A0

View file

@ -3,6 +3,7 @@ ifeq ($(CONFIG_GPIO_SH_PFC),y)
sh-pfc-objs += gpio.o
endif
obj-$(CONFIG_PINCTRL_SH_PFC) += sh-pfc.o
obj-$(CONFIG_PINCTRL_PFC_EMEV2) += pfc-emev2.o
obj-$(CONFIG_PINCTRL_PFC_R8A73A4) += pfc-r8a73a4.o
obj-$(CONFIG_PINCTRL_PFC_R8A7740) += pfc-r8a7740.o
obj-$(CONFIG_PINCTRL_PFC_R8A7778) += pfc-r8a7778.o
@ -12,7 +13,6 @@ obj-$(CONFIG_PINCTRL_PFC_R8A7791) += pfc-r8a7791.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
obj-$(CONFIG_PINCTRL_PFC_SH7372) += pfc-sh7372.o
obj-$(CONFIG_PINCTRL_PFC_SH73A0) += pfc-sh73a0.o
obj-$(CONFIG_PINCTRL_PFC_SH7720) += pfc-sh7720.o
obj-$(CONFIG_PINCTRL_PFC_SH7722) += pfc-sh7722.o

View file

@ -439,6 +439,12 @@ static int sh_pfc_init_ranges(struct sh_pfc *pfc)
#ifdef CONFIG_OF
static const struct of_device_id sh_pfc_of_table[] = {
#ifdef CONFIG_PINCTRL_PFC_EMEV2
{
.compatible = "renesas,pfc-emev2",
.data = &emev2_pinmux_info,
},
#endif
#ifdef CONFIG_PINCTRL_PFC_R8A73A4
{
.compatible = "renesas,pfc-r8a73a4",
@ -475,12 +481,6 @@ static const struct of_device_id sh_pfc_of_table[] = {
.data = &r8a7791_pinmux_info,
},
#endif
#ifdef CONFIG_PINCTRL_PFC_SH7372
{
.compatible = "renesas,pfc-sh7372",
.data = &sh7372_pinmux_info,
},
#endif
#ifdef CONFIG_PINCTRL_PFC_SH73A0
{
.compatible = "renesas,pfc-sh73a0",
@ -579,6 +579,9 @@ static int sh_pfc_remove(struct platform_device *pdev)
}
static const struct platform_device_id sh_pfc_id_table[] = {
#ifdef CONFIG_PINCTRL_PFC_EMEV2
{ "pfc-emev2", (kernel_ulong_t)&emev2_pinmux_info },
#endif
#ifdef CONFIG_PINCTRL_PFC_R8A73A4
{ "pfc-r8a73a4", (kernel_ulong_t)&r8a73a4_pinmux_info },
#endif
@ -606,9 +609,6 @@ static const struct platform_device_id sh_pfc_id_table[] = {
#ifdef CONFIG_PINCTRL_PFC_SH7269
{ "pfc-sh7269", (kernel_ulong_t)&sh7269_pinmux_info },
#endif
#ifdef CONFIG_PINCTRL_PFC_SH7372
{ "pfc-sh7372", (kernel_ulong_t)&sh7372_pinmux_info },
#endif
#ifdef CONFIG_PINCTRL_PFC_SH73A0
{ "pfc-sh73a0", (kernel_ulong_t)&sh73a0_pinmux_info },
#endif

View file

@ -65,6 +65,7 @@ void sh_pfc_write_raw_reg(void __iomem *mapped_reg, unsigned long reg_width,
int sh_pfc_get_pin_index(struct sh_pfc *pfc, unsigned int pin);
int sh_pfc_config_mux(struct sh_pfc *pfc, unsigned mark, int pinmux_type);
extern const struct sh_pfc_soc_info emev2_pinmux_info;
extern const struct sh_pfc_soc_info r8a73a4_pinmux_info;
extern const struct sh_pfc_soc_info r8a7740_pinmux_info;
extern const struct sh_pfc_soc_info r8a7778_pinmux_info;
@ -74,7 +75,6 @@ extern const struct sh_pfc_soc_info r8a7791_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;
extern const struct sh_pfc_soc_info sh7372_pinmux_info;
extern const struct sh_pfc_soc_info sh73a0_pinmux_info;
extern const struct sh_pfc_soc_info sh7720_pinmux_info;
extern const struct sh_pfc_soc_info sh7722_pinmux_info;

File diff suppressed because it is too large Load diff

View file

@ -2241,6 +2241,13 @@ static const unsigned int intc_irq3_pins[] = {
static const unsigned int intc_irq3_mux[] = {
IRQ3_MARK,
};
/* - MLB+ ------------------------------------------------------------------- */
static const unsigned int mlb_3pin_pins[] = {
RCAR_GP_PIN(4, 0), RCAR_GP_PIN(4, 1), RCAR_GP_PIN(4, 2),
};
static const unsigned int mlb_3pin_mux[] = {
MLB_CLK_MARK, MLB_SIG_MARK, MLB_DAT_MARK,
};
/* - MMCIF0 ----------------------------------------------------------------- */
static const unsigned int mmc0_data1_pins[] = {
/* D[0] */
@ -3873,6 +3880,7 @@ static const struct sh_pfc_pin_group pinmux_groups[] = {
SH_PFC_PIN_GROUP(intc_irq1),
SH_PFC_PIN_GROUP(intc_irq2),
SH_PFC_PIN_GROUP(intc_irq3),
SH_PFC_PIN_GROUP(mlb_3pin),
SH_PFC_PIN_GROUP(mmc0_data1),
SH_PFC_PIN_GROUP(mmc0_data4),
SH_PFC_PIN_GROUP(mmc0_data8),
@ -4198,6 +4206,10 @@ static const char * const intc_groups[] = {
"intc_irq3",
};
static const char * const mlb_groups[] = {
"mlb_3pin",
};
static const char * const mmc0_groups[] = {
"mmc0_data1",
"mmc0_data4",
@ -4511,6 +4523,7 @@ static const struct sh_pfc_function pinmux_functions[] = {
SH_PFC_FUNCTION(iic2),
SH_PFC_FUNCTION(iic3),
SH_PFC_FUNCTION(intc),
SH_PFC_FUNCTION(mlb),
SH_PFC_FUNCTION(mmc0),
SH_PFC_FUNCTION(mmc1),
SH_PFC_FUNCTION(msiof0),

View file

@ -378,7 +378,7 @@ enum {
/* IPSR16 */
FN_HRX1, FN_SCIFB1_RXD, FN_VI1_R0_B, FN_GLO_SDATA_C, FN_VI1_DATA6_C,
FN_HTX1, FN_SCIFB1_TXD, FN_VI1_R1_B, FN_GLO_SS_C, FN_VI1_DATA7_C,
FN_HSCK1, FN_SCIFB1_SCK, FN_MLB_CK, FN_GLO_RFON_C,
FN_HSCK1, FN_SCIFB1_SCK, FN_MLB_CLK, FN_GLO_RFON_C,
FN_HCTS1_N, FN_SCIFB1_CTS_N, FN_MLB_SIG, FN_CAN1_TX_B,
FN_HRTS1_N, FN_SCIFB1_RTS_N, FN_MLB_DAT, FN_CAN1_RX_B,
@ -764,7 +764,7 @@ enum {
GLO_SDATA_C_MARK, VI1_DATA6_C_MARK,
HTX1_MARK, SCIFB1_TXD_MARK, VI1_R1_B_MARK,
GLO_SS_C_MARK, VI1_DATA7_C_MARK,
HSCK1_MARK, SCIFB1_SCK_MARK, MLB_CK_MARK, GLO_RFON_C_MARK,
HSCK1_MARK, SCIFB1_SCK_MARK, MLB_CLK_MARK, GLO_RFON_C_MARK,
HCTS1_N_MARK, SCIFB1_CTS_N_MARK, MLB_SIG_MARK, CAN1_TX_B_MARK,
HRTS1_N_MARK, SCIFB1_RTS_N_MARK, MLB_DAT_MARK, CAN1_RX_B_MARK,
PINMUX_MARK_END,
@ -1664,7 +1664,7 @@ static const u16 pinmux_data[] = {
PINMUX_IPSR_MODSEL_DATA(IP16_5_3, VI1_DATA7_C, SEL_VI1_2),
PINMUX_IPSR_MODSEL_DATA(IP16_7_6, HSCK1, SEL_HSCIF1_0),
PINMUX_IPSR_MODSEL_DATA(IP16_7_6, SCIFB1_SCK, SEL_SCIFB1_0),
PINMUX_IPSR_DATA(IP16_7_6, MLB_CK),
PINMUX_IPSR_DATA(IP16_7_6, MLB_CLK),
PINMUX_IPSR_MODSEL_DATA(IP16_7_6, GLO_RFON_C, SEL_GPS_2),
PINMUX_IPSR_MODSEL_DATA(IP16_9_8, HCTS1_N, SEL_HSCIF1_0),
PINMUX_IPSR_DATA(IP16_9_8, SCIFB1_CTS_N),
@ -2391,6 +2391,13 @@ static const unsigned int intc_irq3_pins[] = {
static const unsigned int intc_irq3_mux[] = {
IRQ3_MARK,
};
/* - MLB+ ------------------------------------------------------------------- */
static const unsigned int mlb_3pin_pins[] = {
RCAR_GP_PIN(7, 7), RCAR_GP_PIN(7, 8), RCAR_GP_PIN(7, 9),
};
static const unsigned int mlb_3pin_mux[] = {
MLB_CLK_MARK, MLB_SIG_MARK, MLB_DAT_MARK,
};
/* - MMCIF ------------------------------------------------------------------ */
static const unsigned int mmc_data1_pins[] = {
/* D[0] */
@ -4267,6 +4274,7 @@ static const struct sh_pfc_pin_group pinmux_groups[] = {
SH_PFC_PIN_GROUP(intc_irq1),
SH_PFC_PIN_GROUP(intc_irq2),
SH_PFC_PIN_GROUP(intc_irq3),
SH_PFC_PIN_GROUP(mlb_3pin),
SH_PFC_PIN_GROUP(mmc_data1),
SH_PFC_PIN_GROUP(mmc_data4),
SH_PFC_PIN_GROUP(mmc_data8),
@ -4648,6 +4656,10 @@ static const char * const intc_groups[] = {
"intc_irq3",
};
static const char * const mlb_groups[] = {
"mlb_3pin",
};
static const char * const mmc_groups[] = {
"mmc_data1",
"mmc_data4",
@ -4972,6 +4984,7 @@ static const struct sh_pfc_function pinmux_functions[] = {
SH_PFC_FUNCTION(i2c7),
SH_PFC_FUNCTION(i2c8),
SH_PFC_FUNCTION(intc),
SH_PFC_FUNCTION(mlb),
SH_PFC_FUNCTION(mmc),
SH_PFC_FUNCTION(msiof0),
SH_PFC_FUNCTION(msiof1),
@ -5974,7 +5987,7 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = {
/* IP16_9_8 [2] */
FN_HCTS1_N, FN_SCIFB1_CTS_N, FN_MLB_SIG, FN_CAN1_TX_B,
/* IP16_7_6 [2] */
FN_HSCK1, FN_SCIFB1_SCK, FN_MLB_CK, FN_GLO_RFON_C,
FN_HSCK1, FN_SCIFB1_SCK, FN_MLB_CLK, FN_GLO_RFON_C,
/* IP16_5_3 [3] */
FN_HTX1, FN_SCIFB1_TXD, FN_VI1_R1_B,
FN_GLO_SS_C, FN_VI1_DATA7_C,

File diff suppressed because it is too large Load diff

View file

@ -122,7 +122,7 @@ static int sh_pfc_dt_subnode_to_map(struct device *dev, struct device_node *np,
return ret;
}
ret = pinconf_generic_parse_dt_config(np, &configs, &num_configs);
ret = pinconf_generic_parse_dt_config(np, NULL, &configs, &num_configs);
if (ret < 0)
return ret;

View file

@ -167,6 +167,8 @@ struct sh_pfc_soc_info {
PINMUX_DATA(fn##_MARK, FN_##fn, FN_##ipsr)
#define PINMUX_IPSR_NOGM(ispr, fn, ms) \
PINMUX_DATA(fn##_MARK, FN_##fn, FN_##ms)
#define PINMUX_IPSR_NOFN(ipsr, fn, ms) \
PINMUX_DATA(fn##_MARK, FN_##ipsr, FN_##ms)
#define PINMUX_IPSR_MSEL(ipsr, fn, ms) \
PINMUX_DATA(fn##_MARK, FN_##fn, FN_##ipsr, FN_##ms)
#define PINMUX_IPSR_MODSEL_DATA(ipsr, fn, ms) \

View file

@ -38,7 +38,6 @@ struct sirfsoc_gpio_bank {
struct sirfsoc_gpio_chip {
struct of_mm_gpio_chip chip;
bool is_marco; /* for marco, some registers are different with prima2 */
struct sirfsoc_gpio_bank sgpio_bank[SIRFSOC_GPIO_NO_OF_BANKS];
};
@ -149,23 +148,14 @@ static void sirfsoc_pinmux_endisable(struct sirfsoc_pmx *spmx,
for (i = 0; i < mux->muxmask_counts; i++) {
u32 muxval;
if (!spmx->is_marco) {
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));
} else {
if (enable)
writel(mask[i].mask, spmx->gpio_virtbase +
SIRFSOC_GPIO_PAD_EN_CLR(mask[i].group));
else
writel(mask[i].mask, spmx->gpio_virtbase +
SIRFSOC_GPIO_PAD_EN(mask[i].group));
}
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) {
@ -223,16 +213,11 @@ static int sirfsoc_pinmux_request_gpio(struct pinctrl_dev *pmxdev,
spmx = pinctrl_dev_get_drvdata(pmxdev);
if (!spmx->is_marco) {
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));
} else {
writel(1 << (offset - range->pin_base), spmx->gpio_virtbase +
SIRFSOC_GPIO_PAD_EN(group));
}
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;
}
@ -256,7 +241,6 @@ static void __iomem *sirfsoc_rsc_of_iomap(void)
{
const struct of_device_id rsc_ids[] = {
{ .compatible = "sirf,prima2-rsc" },
{ .compatible = "sirf,marco-rsc" },
{}
};
struct device_node *np;
@ -284,7 +268,6 @@ static int sirfsoc_gpio_of_xlate(struct gpio_chip *gc,
static const struct of_device_id pinmux_ids[] = {
{ .compatible = "sirf,prima2-pinctrl", .data = &prima2_pinctrl_data, },
{ .compatible = "sirf,atlas6-pinctrl", .data = &atlas6_pinctrl_data, },
{ .compatible = "sirf,marco-pinctrl", .data = &prima2_pinctrl_data, },
{}
};
@ -317,9 +300,6 @@ static int sirfsoc_pinmux_probe(struct platform_device *pdev)
goto out_no_rsc_remap;
}
if (of_device_is_compatible(np, "sirf,marco-pinctrl"))
spmx->is_marco = 1;
pdata = of_match_node(pinmux_ids, np)->data;
sirfsoc_pin_groups = pdata->grps;
sirfsoc_pingrp_cnt = pdata->grps_cnt;
@ -803,7 +783,6 @@ static int sirfsoc_gpio_probe(struct device_node *np)
struct sirfsoc_gpio_bank *bank;
void __iomem *regs;
struct platform_device *pdev;
bool is_marco = false;
u32 pullups[SIRFSOC_GPIO_NO_OF_BANKS], pulldowns[SIRFSOC_GPIO_NO_OF_BANKS];
@ -819,9 +798,6 @@ static int sirfsoc_gpio_probe(struct device_node *np)
if (!regs)
return -ENOMEM;
if (of_device_is_compatible(np, "sirf,marco-pinctrl"))
is_marco = 1;
sgpio->chip.gc.request = sirfsoc_gpio_request;
sgpio->chip.gc.free = sirfsoc_gpio_free;
sgpio->chip.gc.direction_input = sirfsoc_gpio_direction_input;
@ -836,7 +812,6 @@ static int sirfsoc_gpio_probe(struct device_node *np)
sgpio->chip.gc.of_gpio_n_cells = 2;
sgpio->chip.gc.dev = &pdev->dev;
sgpio->chip.regs = regs;
sgpio->is_marco = is_marco;
err = gpiochip_add(&sgpio->chip.gc);
if (err) {

View file

@ -49,7 +49,6 @@ struct sirfsoc_pmx {
u32 paden_regs[SIRFSOC_GPIO_NO_OF_BANKS];
u32 dspen_regs;
u32 rsc_regs[3];
bool is_marco;
};
/* SIRFSOC_GPIO_PAD_EN set */

View file

@ -21,6 +21,10 @@ config PINCTRL_SUN6I_A31
def_bool MACH_SUN6I
select PINCTRL_SUNXI_COMMON
config PINCTRL_SUN6I_A31S
def_bool MACH_SUN6I
select PINCTRL_SUNXI_COMMON
config PINCTRL_SUN6I_A31_R
def_bool MACH_SUN6I
depends on RESET_CONTROLLER

View file

@ -6,6 +6,7 @@ obj-$(CONFIG_PINCTRL_SUN4I_A10) += pinctrl-sun4i-a10.o
obj-$(CONFIG_PINCTRL_SUN5I_A10S) += pinctrl-sun5i-a10s.o
obj-$(CONFIG_PINCTRL_SUN5I_A13) += pinctrl-sun5i-a13.o
obj-$(CONFIG_PINCTRL_SUN6I_A31) += pinctrl-sun6i-a31.o
obj-$(CONFIG_PINCTRL_SUN6I_A31S) += pinctrl-sun6i-a31s.o
obj-$(CONFIG_PINCTRL_SUN6I_A31_R) += pinctrl-sun6i-a31-r.o
obj-$(CONFIG_PINCTRL_SUN7I_A20) += pinctrl-sun7i-a20.o
obj-$(CONFIG_PINCTRL_SUN8I_A23) += pinctrl-sun8i-a23.o

View file

@ -134,24 +134,28 @@ static const struct sunxi_desc_pin sun6i_a31_pins[] = {
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "gmac"), /* RXD4 */
SUNXI_FUNCTION(0x3, "lcd1"), /* D15 */
SUNXI_FUNCTION(0x4, "clk_out_a"),
SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 15)), /* PA_EINT15 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 16),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "gmac"), /* RXD5 */
SUNXI_FUNCTION(0x3, "lcd1"), /* D16 */
SUNXI_FUNCTION(0x4, "dmic"), /* CLK */
SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 16)), /* PA_EINT16 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 17),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "gmac"), /* RXD6 */
SUNXI_FUNCTION(0x3, "lcd1"), /* D17 */
SUNXI_FUNCTION(0x4, "dmic"), /* DIN */
SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 17)), /* PA_EINT17 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 18),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "gmac"), /* RXD7 */
SUNXI_FUNCTION(0x3, "lcd1"), /* D18 */
SUNXI_FUNCTION(0x4, "clk_out_b"),
SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 18)), /* PA_EINT18 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 19),
SUNXI_FUNCTION(0x0, "gpio_in"),
@ -207,6 +211,7 @@ static const struct sunxi_desc_pin sun6i_a31_pins[] = {
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "gmac"), /* MDC */
SUNXI_FUNCTION(0x3, "lcd1"), /* HSYNC */
SUNXI_FUNCTION(0x4, "clk_out_c"),
SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 26)), /* PA_EINT26 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 27),
SUNXI_FUNCTION(0x0, "gpio_in"),

View file

@ -0,0 +1,815 @@
/*
* Allwinner A31s SoCs pinctrl driver.
*
* Copyright (C) 2014 Hans de Goede <hdegoede@redhat.com>
*
* Based on pinctrl-sun6i-a31.c, which is:
* Copyright (C) 2014 Maxime Ripard <maxime.ripard@free-electrons.com>
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
#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 sun6i_a31s_pins[] = {
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 0),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "gmac"), /* TXD0 */
SUNXI_FUNCTION(0x4, "uart1"), /* DTR */
SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 0)), /* PA_EINT0 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 1),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "gmac"), /* TXD1 */
SUNXI_FUNCTION(0x4, "uart1"), /* DSR */
SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 1)), /* PA_EINT1 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 2),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "gmac"), /* TXD2 */
SUNXI_FUNCTION(0x4, "uart1"), /* DCD */
SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 2)), /* PA_EINT2 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 3),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "gmac"), /* TXD3 */
SUNXI_FUNCTION(0x4, "uart1"), /* RING */
SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 3)), /* PA_EINT3 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 4),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "gmac"), /* TXD4 */
SUNXI_FUNCTION(0x4, "uart1"), /* TX */
SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 4)), /* PA_EINT4 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 5),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "gmac"), /* TXD5 */
SUNXI_FUNCTION(0x4, "uart1"), /* RX */
SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 5)), /* PA_EINT5 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 6),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "gmac"), /* TXD6 */
SUNXI_FUNCTION(0x4, "uart1"), /* RTS */
SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 6)), /* PA_EINT6 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 7),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "gmac"), /* TXD7 */
SUNXI_FUNCTION(0x4, "uart1"), /* CTS */
SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 7)), /* PA_EINT7 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 8),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "gmac"), /* TXCLK */
SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 8)), /* PA_EINT8 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 9),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "gmac"), /* TXEN */
SUNXI_FUNCTION(0x4, "mmc3"), /* CMD */
SUNXI_FUNCTION(0x5, "mmc2"), /* CMD */
SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 9)), /* PA_EINT9 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 10),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "gmac"), /* GTXCLK */
SUNXI_FUNCTION(0x4, "mmc3"), /* CLK */
SUNXI_FUNCTION(0x5, "mmc2"), /* CLK */
SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 10)), /* PA_EINT10 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 11),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "gmac"), /* RXD0 */
SUNXI_FUNCTION(0x4, "mmc3"), /* D0 */
SUNXI_FUNCTION(0x5, "mmc2"), /* D0 */
SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 11)), /* PA_EINT11 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 12),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "gmac"), /* RXD1 */
SUNXI_FUNCTION(0x4, "mmc3"), /* D1 */
SUNXI_FUNCTION(0x5, "mmc2"), /* D1 */
SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 12)), /* PA_EINT12 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 13),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "gmac"), /* RXD2 */
SUNXI_FUNCTION(0x4, "mmc3"), /* D2 */
SUNXI_FUNCTION(0x5, "mmc2"), /* D2 */
SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 13)), /* PA_EINT13 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 14),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "gmac"), /* RXD3 */
SUNXI_FUNCTION(0x4, "mmc3"), /* D3 */
SUNXI_FUNCTION(0x5, "mmc2"), /* D3 */
SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 14)), /* PA_EINT14 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 15),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "gmac"), /* RXD4 */
SUNXI_FUNCTION(0x4, "clk_out_a"),
SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 15)), /* PA_EINT15 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 16),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "gmac"), /* RXD5 */
SUNXI_FUNCTION(0x4, "dmic"), /* CLK */
SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 16)), /* PA_EINT16 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 17),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "gmac"), /* RXD6 */
SUNXI_FUNCTION(0x4, "dmic"), /* DIN */
SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 17)), /* PA_EINT17 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 18),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "gmac"), /* RXD7 */
SUNXI_FUNCTION(0x4, "clk_out_b"),
SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 18)), /* PA_EINT18 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 19),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "gmac"), /* RXDV */
SUNXI_FUNCTION(0x4, "pwm3"), /* Positive */
SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 19)), /* PA_EINT19 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 20),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "gmac"), /* RXCLK */
SUNXI_FUNCTION(0x4, "pwm3"), /* Negative */
SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 20)), /* PA_EINT20 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 21),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "gmac"), /* TXERR */
SUNXI_FUNCTION(0x4, "spi3"), /* CS0 */
SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 21)), /* PA_EINT21 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 22),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "gmac"), /* RXERR */
SUNXI_FUNCTION(0x4, "spi3"), /* CLK */
SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 22)), /* PA_EINT22 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 23),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "gmac"), /* COL */
SUNXI_FUNCTION(0x4, "spi3"), /* MOSI */
SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 23)), /* PA_EINT23 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 24),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "gmac"), /* CRS */
SUNXI_FUNCTION(0x4, "spi3"), /* MISO */
SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 24)), /* PA_EINT24 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 25),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "gmac"), /* CLKIN */
SUNXI_FUNCTION(0x4, "spi3"), /* CS1 */
SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 25)), /* PA_EINT25 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 26),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "gmac"), /* MDC */
SUNXI_FUNCTION(0x4, "clk_out_c"),
SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 26)), /* PA_EINT26 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 27),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "gmac"), /* MDIO */
SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 27)), /* PA_EINT27 */
/* Hole */
SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 0),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "i2s0"), /* MCLK */
SUNXI_FUNCTION(0x3, "uart3"), /* CTS */
SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 0)), /* PB_EINT0 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 1),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "i2s0"), /* BCLK */
SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 1)), /* PB_EINT1 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 2),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "i2s0"), /* LRCK */
SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 2)), /* PB_EINT2 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 3),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "i2s0"), /* DO0 */
SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 3)), /* PB_EINT3 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 4),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "i2s0"), /* DO1 */
SUNXI_FUNCTION(0x3, "uart3"), /* RTS */
SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 4)), /* PB_EINT4 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 5),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "i2s0"), /* DO2 */
SUNXI_FUNCTION(0x3, "uart3"), /* TX */
SUNXI_FUNCTION(0x4, "i2c3"), /* SCK */
SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 5)), /* PB_EINT5 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 6),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "i2s0"), /* DO3 */
SUNXI_FUNCTION(0x3, "uart3"), /* RX */
SUNXI_FUNCTION(0x4, "i2c3"), /* SDA */
SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 6)), /* PB_EINT6 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 7),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x3, "i2s0"), /* DI */
SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 7)), /* PB_EINT7 */
/* 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, "spi0")), /* MOSI */
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, "spi0")), /* MISO */
SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 2),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "nand0"), /* CLE */
SUNXI_FUNCTION(0x3, "spi0")), /* CLK */
SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 3),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "nand0")), /* CE1 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 4),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "nand0")), /* CE0 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 5),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "nand0")), /* RE */
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(0x4, "mmc3")), /* CMD */
SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 7),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "nand0"), /* RB1 */
SUNXI_FUNCTION(0x3, "mmc2"), /* CLK */
SUNXI_FUNCTION(0x4, "mmc3")), /* CLK */
SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 8),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "nand0"), /* DQ0 */
SUNXI_FUNCTION(0x3, "mmc2"), /* D0 */
SUNXI_FUNCTION(0x4, "mmc3")), /* D0 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 9),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "nand0"), /* DQ1 */
SUNXI_FUNCTION(0x3, "mmc2"), /* D1 */
SUNXI_FUNCTION(0x4, "mmc3")), /* D1 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 10),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "nand0"), /* DQ2 */
SUNXI_FUNCTION(0x3, "mmc2"), /* D2 */
SUNXI_FUNCTION(0x4, "mmc3")), /* D2 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 11),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "nand0"), /* DQ3 */
SUNXI_FUNCTION(0x3, "mmc2"), /* D3 */
SUNXI_FUNCTION(0x4, "mmc3")), /* D3 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 12),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "nand0"), /* DQ4 */
SUNXI_FUNCTION(0x3, "mmc2"), /* D4 */
SUNXI_FUNCTION(0x4, "mmc3")), /* D4 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 13),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "nand0"), /* DQ5 */
SUNXI_FUNCTION(0x3, "mmc2"), /* D5 */
SUNXI_FUNCTION(0x4, "mmc3")), /* D5 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 14),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "nand0"), /* DQ6 */
SUNXI_FUNCTION(0x3, "mmc2"), /* D6 */
SUNXI_FUNCTION(0x4, "mmc3")), /* D6 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 15),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "nand0"), /* DQ7 */
SUNXI_FUNCTION(0x3, "mmc2"), /* D7 */
SUNXI_FUNCTION(0x4, "mmc3")), /* D7 */
/* Hole in pin numbering ! */
SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 24),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "nand0"), /* DQS */
SUNXI_FUNCTION(0x3, "mmc2"), /* RST */
SUNXI_FUNCTION(0x4, "mmc3")), /* RST */
SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 25),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "nand0")), /* CE2 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 26),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "nand0")), /* CE3 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 27),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x3, "spi0")), /* CS0 */
/* Hole */
SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 0),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "lcd0"), /* D0 */
SUNXI_FUNCTION(0x3, "lvds0")), /* VP0 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 1),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "lcd0"), /* D1 */
SUNXI_FUNCTION(0x3, "lvds0")), /* VN0 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 2),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "lcd0"), /* D2 */
SUNXI_FUNCTION(0x3, "lvds0")), /* VP1 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 3),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "lcd0"), /* D3 */
SUNXI_FUNCTION(0x3, "lvds0")), /* VN1 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 4),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "lcd0"), /* D4 */
SUNXI_FUNCTION(0x3, "lvds0")), /* VP2 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 5),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "lcd0"), /* D5 */
SUNXI_FUNCTION(0x3, "lvds0")), /* VN2 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 6),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "lcd0"), /* D6 */
SUNXI_FUNCTION(0x3, "lvds0")), /* VPC */
SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 7),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "lcd0"), /* D7 */
SUNXI_FUNCTION(0x3, "lvds0")), /* VNC */
SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 8),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "lcd0"), /* D8 */
SUNXI_FUNCTION(0x3, "lvds0")), /* VP3 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 9),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "lcd0"), /* D9 */
SUNXI_FUNCTION(0x3, "lvds0")), /* VN3 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 10),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "lcd0")), /* D10 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 11),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "lcd0")), /* D11 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 12),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "lcd0")), /* D12 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 13),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "lcd0")), /* D13 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 14),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "lcd0")), /* D14 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 15),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "lcd0")), /* D15 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 16),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "lcd0")), /* D16 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 17),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "lcd0")), /* D17 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 18),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "lcd0")), /* D18 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 19),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "lcd0")), /* D19 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 20),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "lcd0")), /* D20 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 21),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "lcd0")), /* D21 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 22),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "lcd0")), /* D22 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 23),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "lcd0")), /* D23 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 24),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "lcd0")), /* CLK */
SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 25),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "lcd0")), /* DE */
SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 26),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "lcd0")), /* HSYNC */
SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 27),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "lcd0")), /* VSYNC */
/* Hole */
SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 0),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "csi"), /* PCLK */
SUNXI_FUNCTION(0x3, "ts"), /* CLK */
SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 0)), /* PE_EINT0 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 1),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "csi"), /* MCLK */
SUNXI_FUNCTION(0x3, "ts"), /* ERR */
SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 1)), /* PE_EINT1 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 2),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "csi"), /* HSYNC */
SUNXI_FUNCTION(0x3, "ts"), /* SYNC */
SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 2)), /* PE_EINT2 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 3),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "csi"), /* VSYNC */
SUNXI_FUNCTION(0x3, "ts"), /* DVLD */
SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 3)), /* PE_EINT3 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 4),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "csi"), /* D0 */
SUNXI_FUNCTION(0x3, "uart5"), /* TX */
SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 4)), /* PE_EINT4 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 5),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "csi"), /* D1 */
SUNXI_FUNCTION(0x3, "uart5"), /* RX */
SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 5)), /* PE_EINT5 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 6),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "csi"), /* D2 */
SUNXI_FUNCTION(0x3, "uart5"), /* RTS */
SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 6)), /* PE_EINT6 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 7),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "csi"), /* D3 */
SUNXI_FUNCTION(0x3, "uart5"), /* CTS */
SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 7)), /* PE_EINT7 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 8),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "csi"), /* D4 */
SUNXI_FUNCTION(0x3, "ts"), /* D0 */
SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 8)), /* PE_EINT8 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 9),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "csi"), /* D5 */
SUNXI_FUNCTION(0x3, "ts"), /* D1 */
SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 9)), /* PE_EINT9 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 10),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "csi"), /* D6 */
SUNXI_FUNCTION(0x3, "ts"), /* D2 */
SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 10)), /* PE_EINT10 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 11),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "csi"), /* D7 */
SUNXI_FUNCTION(0x3, "ts"), /* D3 */
SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 11)), /* PE_EINT11 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 12),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "csi"), /* D8 */
SUNXI_FUNCTION(0x3, "ts"), /* D4 */
SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 12)), /* PE_EINT12 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 13),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "csi"), /* D9 */
SUNXI_FUNCTION(0x3, "ts"), /* D5 */
SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 13)), /* PE_EINT13 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 14),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "csi"), /* D10 */
SUNXI_FUNCTION(0x3, "ts"), /* D6 */
SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 14)), /* PE_EINT14 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 15),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "csi"), /* D11 */
SUNXI_FUNCTION(0x3, "ts"), /* D7 */
SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 15)), /* PE_EINT15 */
/* 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(0x4, "jtag")), /* MS1 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 1),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "mmc0"), /* D0 */
SUNXI_FUNCTION(0x4, "jtag")), /* DI1 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 2),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "mmc0"), /* CLK */
SUNXI_FUNCTION(0x4, "uart0")), /* TX */
SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 3),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "mmc0"), /* CMD */
SUNXI_FUNCTION(0x4, "jtag")), /* DO1 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 4),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "mmc0"), /* D3 */
SUNXI_FUNCTION(0x4, "uart0")), /* RX */
SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 5),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "mmc0"), /* D2 */
SUNXI_FUNCTION(0x4, "jtag")), /* CK1 */
/* 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, 3, 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, 3, 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, 3, 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, 3, 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, 3, 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, 3, 5)), /* PG_EINT5 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 6),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "uart2"), /* TX */
SUNXI_FUNCTION_IRQ_BANK(0x6, 3, 6)), /* PG_EINT6 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 7),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "uart2"), /* RX */
SUNXI_FUNCTION_IRQ_BANK(0x6, 3, 7)), /* PG_EINT7 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 8),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "uart2"), /* RTS */
SUNXI_FUNCTION_IRQ_BANK(0x6, 3, 8)), /* PG_EINT8 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 9),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "uart2"), /* CTS */
SUNXI_FUNCTION_IRQ_BANK(0x6, 3, 9)), /* PG_EINT9 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 10),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "i2c3"), /* SCK */
SUNXI_FUNCTION_IRQ_BANK(0x6, 3, 10)), /* PG_EINT10 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 11),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "i2c3"), /* SDA */
SUNXI_FUNCTION_IRQ_BANK(0x6, 3, 11)), /* PG_EINT11 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 12),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "spi1"), /* CS1 */
SUNXI_FUNCTION(0x3, "i2s1"), /* MCLK */
SUNXI_FUNCTION_IRQ_BANK(0x6, 3, 12)), /* PG_EINT12 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 13),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "spi1"), /* CS0 */
SUNXI_FUNCTION(0x3, "i2s1"), /* BCLK */
SUNXI_FUNCTION_IRQ_BANK(0x6, 3, 13)), /* PG_EINT13 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 14),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "spi1"), /* CLK */
SUNXI_FUNCTION(0x3, "i2s1"), /* LRCK */
SUNXI_FUNCTION_IRQ_BANK(0x6, 3, 14)), /* PG_EINT14 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 15),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "spi1"), /* MOSI */
SUNXI_FUNCTION(0x3, "i2s1"), /* DIN */
SUNXI_FUNCTION_IRQ_BANK(0x6, 3, 15)), /* PG_EINT15 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 16),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "spi1"), /* MISO */
SUNXI_FUNCTION(0x3, "i2s1"), /* DOUT */
SUNXI_FUNCTION_IRQ_BANK(0x6, 3, 16)), /* PG_EINT16 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 17),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "uart4"), /* TX */
SUNXI_FUNCTION_IRQ_BANK(0x6, 3, 17)), /* PG_EINT17 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 18),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "uart4"), /* RX */
SUNXI_FUNCTION_IRQ_BANK(0x6, 3, 18)), /* PG_EINT18 */
/* Hole, note H starts at pin 9 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 9),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "spi2"), /* CS0 */
SUNXI_FUNCTION(0x3, "jtag"), /* MS0 */
SUNXI_FUNCTION(0x4, "pwm1")), /* Positive */
SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 10),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "spi2"), /* CLK */
SUNXI_FUNCTION(0x3, "jtag"), /* CK0 */
SUNXI_FUNCTION(0x4, "pwm1")), /* Negative */
SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 11),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "spi2"), /* MOSI */
SUNXI_FUNCTION(0x3, "jtag"), /* DO0 */
SUNXI_FUNCTION(0x4, "pwm2")), /* Positive */
SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 12),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "spi2"), /* MISO */
SUNXI_FUNCTION(0x3, "jtag"), /* DI0 */
SUNXI_FUNCTION(0x4, "pwm2")), /* Negative */
SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 13),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "pwm0")),
SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 14),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "i2c0")), /* SCK */
SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 15),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "i2c0")), /* SDA */
SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 16),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "i2c1")), /* SCK */
SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 17),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "i2c1")), /* SDA */
SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 18),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "i2c2")), /* SCK */
SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 19),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "i2c2")), /* SDA */
SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 20),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "uart0")), /* TX */
SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 21),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "uart0")), /* RX */
SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 22),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out")),
SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 23),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out")),
SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 24),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out")),
SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 25),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out")),
SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 26),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out")),
SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 27),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out")),
SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 28),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out")),
};
static const struct sunxi_pinctrl_desc sun6i_a31s_pinctrl_data = {
.pins = sun6i_a31s_pins,
.npins = ARRAY_SIZE(sun6i_a31s_pins),
.irq_banks = 4,
};
static int sun6i_a31s_pinctrl_probe(struct platform_device *pdev)
{
return sunxi_pinctrl_init(pdev,
&sun6i_a31s_pinctrl_data);
}
static struct of_device_id sun6i_a31s_pinctrl_match[] = {
{ .compatible = "allwinner,sun6i-a31s-pinctrl", },
{}
};
MODULE_DEVICE_TABLE(of, sun6i_a31s_pinctrl_match);
static struct platform_driver sun6i_a31s_pinctrl_driver = {
.probe = sun6i_a31s_pinctrl_probe,
.driver = {
.name = "sun6i-a31s-pinctrl",
.owner = THIS_MODULE,
.of_match_table = sun6i_a31s_pinctrl_match,
},
};
module_platform_driver(sun6i_a31s_pinctrl_driver);
MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
MODULE_DESCRIPTION("Allwinner A31s pinctrl driver");
MODULE_LICENSE("GPL");

View file

@ -0,0 +1,157 @@
/*
* GPIO definitions for Amlogic Meson8 SoCs
*
* Copyright (C) 2014 Beniamino Galvani <b.galvani@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _DT_BINDINGS_MESON8_GPIO_H
#define _DT_BINDINGS_MESON8_GPIO_H
/* First GPIO chip */
#define GPIOX_0 0
#define GPIOX_1 1
#define GPIOX_2 2
#define GPIOX_3 3
#define GPIOX_4 4
#define GPIOX_5 5
#define GPIOX_6 6
#define GPIOX_7 7
#define GPIOX_8 8
#define GPIOX_9 9
#define GPIOX_10 10
#define GPIOX_11 11
#define GPIOX_12 12
#define GPIOX_13 13
#define GPIOX_14 14
#define GPIOX_15 15
#define GPIOX_16 16
#define GPIOX_17 17
#define GPIOX_18 18
#define GPIOX_19 19
#define GPIOX_20 20
#define GPIOX_21 21
#define GPIOY_0 22
#define GPIOY_1 23
#define GPIOY_2 24
#define GPIOY_3 25
#define GPIOY_4 26
#define GPIOY_5 27
#define GPIOY_6 28
#define GPIOY_7 29
#define GPIOY_8 30
#define GPIOY_9 31
#define GPIOY_10 32
#define GPIOY_11 33
#define GPIOY_12 34
#define GPIOY_13 35
#define GPIOY_14 36
#define GPIOY_15 37
#define GPIOY_16 38
#define GPIODV_0 39
#define GPIODV_1 40
#define GPIODV_2 41
#define GPIODV_3 42
#define GPIODV_4 43
#define GPIODV_5 44
#define GPIODV_6 45
#define GPIODV_7 46
#define GPIODV_8 47
#define GPIODV_9 48
#define GPIODV_10 49
#define GPIODV_11 50
#define GPIODV_12 51
#define GPIODV_13 52
#define GPIODV_14 53
#define GPIODV_15 54
#define GPIODV_16 55
#define GPIODV_17 56
#define GPIODV_18 57
#define GPIODV_19 58
#define GPIODV_20 59
#define GPIODV_21 60
#define GPIODV_22 61
#define GPIODV_23 62
#define GPIODV_24 63
#define GPIODV_25 64
#define GPIODV_26 65
#define GPIODV_27 66
#define GPIODV_28 67
#define GPIODV_29 68
#define GPIOH_0 69
#define GPIOH_1 70
#define GPIOH_2 71
#define GPIOH_3 72
#define GPIOH_4 73
#define GPIOH_5 74
#define GPIOH_6 75
#define GPIOH_7 76
#define GPIOH_8 77
#define GPIOH_9 78
#define GPIOZ_0 79
#define GPIOZ_1 80
#define GPIOZ_2 81
#define GPIOZ_3 82
#define GPIOZ_4 83
#define GPIOZ_5 84
#define GPIOZ_6 85
#define GPIOZ_7 86
#define GPIOZ_8 87
#define GPIOZ_9 88
#define GPIOZ_10 89
#define GPIOZ_11 90
#define GPIOZ_12 91
#define GPIOZ_13 92
#define GPIOZ_14 93
#define CARD_0 94
#define CARD_1 95
#define CARD_2 96
#define CARD_3 97
#define CARD_4 98
#define CARD_5 99
#define CARD_6 100
#define BOOT_0 101
#define BOOT_1 102
#define BOOT_2 103
#define BOOT_3 104
#define BOOT_4 105
#define BOOT_5 106
#define BOOT_6 107
#define BOOT_7 108
#define BOOT_8 109
#define BOOT_9 110
#define BOOT_10 111
#define BOOT_11 112
#define BOOT_12 113
#define BOOT_13 114
#define BOOT_14 115
#define BOOT_15 116
#define BOOT_16 117
#define BOOT_17 118
#define BOOT_18 119
/* Second GPIO chip */
#define GPIOAO_0 0
#define GPIOAO_1 1
#define GPIOAO_2 2
#define GPIOAO_3 3
#define GPIOAO_4 4
#define GPIOAO_5 5
#define GPIOAO_6 6
#define GPIOAO_7 7
#define GPIOAO_8 8
#define GPIOAO_9 9
#define GPIOAO_10 10
#define GPIOAO_11 11
#define GPIOAO_12 12
#define GPIOAO_13 13
#define GPIO_BSD_EN 14
#define GPIO_TEST_N 15
#endif /* _DT_BINDINGS_MESON8_GPIO_H */

View file

@ -82,7 +82,7 @@ static inline int pinctrl_gpio_direction_output(unsigned gpio)
static inline struct pinctrl * __must_check pinctrl_get(struct device *dev)
{
return NULL;
return ERR_PTR(-ENOSYS);
}
static inline void pinctrl_put(struct pinctrl *p)
@ -93,7 +93,7 @@ static inline struct pinctrl_state * __must_check pinctrl_lookup_state(
struct pinctrl *p,
const char *name)
{
return NULL;
return ERR_PTR(-ENOSYS);
}
static inline int pinctrl_select_state(struct pinctrl *p,
@ -104,7 +104,7 @@ static inline int pinctrl_select_state(struct pinctrl *p,
static inline struct pinctrl * __must_check devm_pinctrl_get(struct device *dev)
{
return NULL;
return ERR_PTR(-ENOSYS);
}
static inline void devm_pinctrl_put(struct pinctrl *p)

View file

@ -115,6 +115,18 @@ enum pin_config_param {
PIN_CONFIG_END = 0x7FFF,
};
#ifdef CONFIG_DEBUG_FS
#define PCONFDUMP(a, b, c, d) { .param = a, .display = b, .format = c, \
.has_arg = d }
struct pin_config_item {
const enum pin_config_param param;
const char * const display;
const char * const format;
bool has_arg;
};
#endif /* CONFIG_DEBUG_FS */
/*
* Helpful configuration macro to be used in tables etc.
*/
@ -150,6 +162,12 @@ static inline unsigned long pinconf_to_config_packed(enum pin_config_param param
struct pinctrl_dev;
struct pinctrl_map;
struct pinconf_generic_params {
const char * const property;
enum pin_config_param param;
u32 default_value;
};
int pinconf_generic_dt_subnode_to_map(struct pinctrl_dev *pctldev,
struct device_node *np, struct pinctrl_map **map,
unsigned *reserved_maps, unsigned *num_maps,
@ -174,6 +192,17 @@ static inline int pinconf_generic_dt_node_to_map_pin(
PIN_MAP_TYPE_CONFIGS_PIN);
}
static inline int pinconf_generic_dt_node_to_map_all(
struct pinctrl_dev *pctldev, struct device_node *np_config,
struct pinctrl_map **map, unsigned *num_maps)
{
/*
* passing the type as PIN_MAP_TYPE_INVALID causes the underlying parser
* to infer the map type from the DT properties used.
*/
return pinconf_generic_dt_node_to_map(pctldev, np_config, map, num_maps,
PIN_MAP_TYPE_INVALID);
}
#endif
#endif /* CONFIG_GENERIC_PINCONF */

View file

@ -24,6 +24,7 @@ struct pinctrl_dev;
struct pinctrl_map;
struct pinmux_ops;
struct pinconf_ops;
struct pin_config_item;
struct gpio_chip;
struct device_node;
@ -117,6 +118,12 @@ struct pinctrl_ops {
* @confops: pin config operations vtable, if you support pin configuration in
* your driver
* @owner: module providing the pin controller, used for refcounting
* @num_custom_params: Number of driver-specific custom parameters to be parsed
* from the hardware description
* @custom_params: List of driver_specific custom parameters to be parsed from
* the hardware description
* @custom_conf_items: Information how to print @params in debugfs, must be
* the same size as the @custom_params, i.e. @num_custom_params
*/
struct pinctrl_desc {
const char *name;
@ -126,6 +133,11 @@ struct pinctrl_desc {
const struct pinmux_ops *pmxops;
const struct pinconf_ops *confops;
struct module *owner;
#ifdef CONFIG_GENERIC_PINCONF
unsigned int num_custom_params;
const struct pinconf_generic_params *custom_params;
const struct pin_config_item *custom_conf_items;
#endif
};
/* External interface to pin controller */