This is the bulk of pin control changes for the v4.3 development

cycle
 
 Core changes:
 
 - It is possible configure groups in debugfs.
 
 - Consolidation of chained IRQ handler install/remove replacing
   all call sites where irq_set_handler_data() and
   irq_set_chained_handler() were done in succession with a
   combined call to irq_set_chained_handler_and_data(). This
   series was created by Thomas Gleixner after the problem was
   observed by Russell King.
 
 - Tglx also made another series of patches switching
   __irq_set_handler_locked() for irq_set_handler_locked() which
   is way cleaner.
 
 - Tglx also wrote a good bunch of patches to make use of
   irq_desc_get_xxx() accessors and avoid looking up irq_descs
   from IRQ numbers. The goal is to get rid of the irq number
   from the handlers in the IRQ flow which is nice.
 
 Driver feature enhancements:
 
 - Power management support for the SiRF SoC Atlas 7.
 
 - Power down support for the Qualcomm driver.
 
 - Intel Cherryview and Baytrail: switch drivers to use raw
   spinlocks in IRQ handlers to play nice with the realtime
   patch set.
 
 - Rework and new modes handling for Qualcomm SPMI-MPP.
 
 - Pinconf power source config for SH PFC.
 
 New drivers and subdrivers:
 
 - A new driver for Conexant Digicolor CX92755.
 
 - A new driver for UniPhier PH1-LD4, PH1-Pro4, PH1-sLD8,
   PH1-Pro5, ProXtream2 and PH1-LD6b SoC pin control support.
 
 - Reverse-egineered the S/PDIF settings for the Allwinner
   sun4i driver.
 
 - Support for Qualcomm Technologies QDF2xxx ARM64 SoCs
 
 - A new Freescale i.mx6ul subdriver.
 
 Cleanup:
 
 - Remove platform data support in a number of SH PFC
   subdrivers.
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQIcBAABAgAGBQJV6YzgAAoJEEEQszewGV1zbIAQAILzMrzWkxsy7bhvL4QdP5/K
 OG3EodE//AE0G5gKugUDjg5t2lftdiIJVhjDA17ruETCSciuAxZSLThlMy1sQgyN
 LPxy9LlCrmsqrYt9+fmJ9js8j52RBJikKK0RUyUVz0VojTBplRpElyEx/KxwM5sG
 Hy3+hU61uKO0j9AyIcsa/RKP6SGavwZdHytJBsHNw+pODyE3UZCf52ChAVBsTPfE
 MV70g3Qzfqur7ZFqcNgtUV7qCyYvlF12ooiihrGFDOsTL3sSq4/OXB7z1z1mGGHL
 Dgq8pXJ6EIZlCbk+jFMTzPRSzy46dxNai0eErjTUVEldH1tOphzGMvKmOdm/nczH
 4M/UOWOKBE1aOYZNPtnUgDy2MRt5K9VJStCNSHEQCB2lGdojNAtmj2cmr8flBN5m
 gM9FDpIS1/C+OYYTkOY9ftPsH5zOk7sCLEHSH5USYRGJHihzLnkV90eiN6a7vlF1
 hyTGrIyl6e//E5JBgamjnR3+fYuxQGr6WeAZEP/gXZRm7BCKCaPwCarq+kPZVG4A
 nolZ/QQN6XYPSlveSPU97VYvLYEUvXaKN0Hf2DTbwkqvNFp7JORD65QLESPtQoIp
 x95iHMdB/1+0OfgOqMmlOtKpOKREeQ/R+KWACxsrr5Rfv3/7CP4BMRGypIZ/iPmz
 HWoyDI4lIebBR+JnjMjK
 =4QFX
 -----END PGP SIGNATURE-----

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

Pull pin control updates from Linus Walleij:
 "This is the bulk of pin control changes for the v4.3 development
  cycle.

  Like with GPIO it's a lot of stuff.  If my subsystems are any sign of
  the overall tempo of the kernel v4.3 will be a gigantic diff.

[ It looks like 4.3 is calmer than 4.2 in most other subsystems, but
  we'll see - Linus ]

  Core changes:

   - It is possible configure groups in debugfs.

   - Consolidation of chained IRQ handler install/remove replacing all
     call sites where irq_set_handler_data() and
     irq_set_chained_handler() were done in succession with a combined
     call to irq_set_chained_handler_and_data().  This series was
     created by Thomas Gleixner after the problem was observed by
     Russell King.

   - Tglx also made another series of patches switching
     __irq_set_handler_locked() for irq_set_handler_locked() which is
     way cleaner.

   - Tglx also wrote a good bunch of patches to make use of
     irq_desc_get_xxx() accessors and avoid looking up irq_descs from
     IRQ numbers.  The goal is to get rid of the irq number from the
     handlers in the IRQ flow which is nice.

  Driver feature enhancements:

   - Power management support for the SiRF SoC Atlas 7.

   - Power down support for the Qualcomm driver.

   - Intel Cherryview and Baytrail: switch drivers to use raw spinlocks
     in IRQ handlers to play nice with the realtime patch set.

   - Rework and new modes handling for Qualcomm SPMI-MPP.

   - Pinconf power source config for SH PFC.

  New drivers and subdrivers:

   - A new driver for Conexant Digicolor CX92755.

   - A new driver for UniPhier PH1-LD4, PH1-Pro4, PH1-sLD8, PH1-Pro5,
     ProXtream2 and PH1-LD6b SoC pin control support.

   - Reverse-egineered the S/PDIF settings for the Allwinner sun4i
     driver.

   - Support for Qualcomm Technologies QDF2xxx ARM64 SoCs

   - A new Freescale i.mx6ul subdriver.

  Cleanup:

   - Remove platform data support in a number of SH PFC subdrivers"

* tag 'pinctrl-v4.3-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl: (95 commits)
  pinctrl: at91: fix null pointer dereference
  pinctrl: mediatek: Implement wake handler and suspend resume
  pinctrl: mediatek: Fix multiple registration issue.
  pinctrl: sh-pfc: r8a7794: add USB pin groups
  pinctrl: at91: Use generic irq_{request,release}_resources()
  pinctrl: cherryview: Use raw_spinlock for locking
  pinctrl: baytrail: Use raw_spinlock for locking
  pinctrl: imx6ul: Remove .owner field
  pinctrl: zynq: Fix typos in smc0_nand_grp and smc0_nor_grp
  pinctrl: sh-pfc: Implement pinconf power-source param for voltage switching
  clk: rockchip: add pclk_pd_pmu to the list of rk3288 critical clocks
  pinctrl: sun4i: add spdif to pin description.
  pinctrl: atlas7: clear ugly branch statements for pull and drivestrength
  pinctrl: baytrail: Serialize all register access
  pinctrl: baytrail: Drop FSF mailing address
  pinctrl: rockchip: only enable gpio clock when it setting
  pinctrl/mediatek: fix spelling mistake in dev_err error message
  pinctrl: cherryview: Serialize all register access
  pinctrl: UniPhier: PH1-Pro5: add I2C ch6 pin-mux setting
  pinctrl: nomadik: reflect current input value
  ...
This commit is contained in:
Linus Torvalds 2015-09-04 10:22:09 -07:00
commit 88a99886c2
78 changed files with 12272 additions and 952 deletions

View File

@ -20,6 +20,10 @@ D: One of assisting postmasters for vger.kernel.org's lists
S: (ask for current address) S: (ask for current address)
S: Finland S: Finland
N: Thomas Abraham
E: thomas.ab@samsung.com
D: Samsung pin controller driver
N: Dragos Acostachioaie N: Dragos Acostachioaie
E: dragos@iname.com E: dragos@iname.com
W: http://www.arbornet.org/~dragos W: http://www.arbornet.org/~dragos

View File

@ -48,7 +48,7 @@ Optional subnode-properties:
Examples: Examples:
pinctrl@01c20800 { pio: pinctrl@01c20800 {
compatible = "allwinner,sun5i-a13-pinctrl"; compatible = "allwinner,sun5i-a13-pinctrl";
reg = <0x01c20800 0x400>; reg = <0x01c20800 0x400>;
#address-cells = <1>; #address-cells = <1>;
@ -68,3 +68,38 @@ pinctrl@01c20800 {
allwinner,pull = <0>; allwinner,pull = <0>;
}; };
}; };
GPIO and interrupt controller
-----------------------------
This hardware also acts as a GPIO controller and an interrupt
controller.
Consumers that would want to refer to one or the other (or both)
should provide through the usual *-gpios and interrupts properties a
cell with 3 arguments, first the number of the bank, then the pin
inside that bank, and finally the flags for the GPIO/interrupts.
Example:
xio: gpio@38 {
compatible = "nxp,pcf8574a";
reg = <0x38>;
gpio-controller;
#gpio-cells = <2>;
interrupt-parent = <&pio>;
interrupts = <6 0 IRQ_TYPE_EDGE_FALLING>;
interrupt-controller;
#interrupt-cells = <2>;
};
reg_usb1_vbus: usb1-vbus {
compatible = "regulator-fixed";
regulator-name = "usb1-vbus";
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <5000000>;
gpio = <&pio 7 6 GPIO_ACTIVE_HIGH>;
};

View File

@ -0,0 +1,86 @@
Conexant Digicolor CX92755 General Purpose Pin Mapping
This document describes the device tree binding of the pin mapping hardware
modules in the Conexant Digicolor CX92755 SoCs. The CX92755 in one of the
Digicolor series of SoCs.
=== Pin Controller Node ===
Required Properties:
- compatible: Must be "cnxt,cx92755-pinctrl"
- reg: Base address of the General Purpose Pin Mapping register block and the
size of the block.
- gpio-controller: Marks the device node as a GPIO controller.
- #gpio-cells: Must be <2>. The first cell is the pin number and the
second cell is used to specify flags. See include/dt-bindings/gpio/gpio.h
for possible values.
For example, the following is the bare minimum node:
pinctrl: pinctrl@f0000e20 {
compatible = "cnxt,cx92755-pinctrl";
reg = <0xf0000e20 0x100>;
gpio-controller;
#gpio-cells = <2>;
};
As a pin controller device, in addition to the required properties, this node
should also contain the pin configuration nodes that client devices reference,
if any.
For a general description of GPIO bindings, please refer to ../gpio/gpio.txt.
=== Pin Configuration Node ===
Each pin configuration node is a sub-node of the pin controller node and is a
container of an arbitrary number of subnodes, called pin group nodes in this
document.
Please refer to the pinctrl-bindings.txt in this directory for details of the
common pinctrl bindings used by client devices, including the definition of a
"pin configuration node".
=== Pin Group Node ===
A pin group node specifies the desired pin mux for an arbitrary number of
pins. The name of the pin group node is optional and not used.
A pin group node only affects the properties specified in the node, and has no
effect on any properties that are omitted.
The pin group node accepts a subset of the generic pin config properties. For
details generic pin config properties, please refer to pinctrl-bindings.txt
and <include/linux/pinctrl/pinconfig-generic.h>.
Required Pin Group Node Properties:
- pins: Multiple strings. Specifies the name(s) of one or more pins to be
configured by this node. The format of a pin name string is "GP_xy", where x
is an uppercase character from 'A' to 'R', and y is a digit from 0 to 7.
- function: String. Specifies the pin mux selection. Values must be one of:
"gpio", "client_a", "client_b", "client_c"
Example:
pinctrl: pinctrl@f0000e20 {
compatible = "cnxt,cx92755-pinctrl";
reg = <0xf0000e20 0x100>;
uart0_default: uart0_active {
data_signals {
pins = "GP_O0", "GP_O1";
function = "client_b";
};
};
};
uart0: uart@f0000740 {
compatible = "cnxt,cx92755-usart";
...
pinctrl-0 = <&uart0_default>;
pinctrl-names = "default";
};
In the example above, a single pin group configuration node defines the
"client select" for the Rx and Tx signals of uart0. The uart0 node references
that pin configuration node using the &uart0_default phandle.

View File

@ -7,8 +7,13 @@ of PMIC's from Qualcomm.
Usage: required Usage: required
Value type: <string> Value type: <string>
Definition: Should contain one of: Definition: Should contain one of:
"qcom,pm8018-mpp",
"qcom,pm8038-mpp",
"qcom,pm8821-mpp",
"qcom,pm8841-mpp", "qcom,pm8841-mpp",
"qcom,pm8916-mpp", "qcom,pm8916-mpp",
"qcom,pm8917-mpp",
"qcom,pm8921-mpp",
"qcom,pm8941-mpp", "qcom,pm8941-mpp",
"qcom,pma8084-mpp", "qcom,pma8084-mpp",
@ -77,12 +82,9 @@ to specify in a pin configuration subnode:
Value type: <string> Value type: <string>
Definition: Specify the alternative function to be configured for the Definition: Specify the alternative function to be configured for the
specified pins. Valid values are: specified pins. Valid values are:
"normal", "digital",
"paired", "analog",
"dtest1", "sink"
"dtest2",
"dtest3",
"dtest4"
- bias-disable: - bias-disable:
Usage: optional Usage: optional
@ -127,12 +129,18 @@ to specify in a pin configuration subnode:
Definition: Selects the power source for the specified pins. Valid power Definition: Selects the power source for the specified pins. Valid power
sources are defined in <dt-bindings/pinctrl/qcom,pmic-mpp.h> sources are defined in <dt-bindings/pinctrl/qcom,pmic-mpp.h>
- qcom,analog-mode: - qcom,analog-level:
Usage: optional Usage: optional
Value type: <none> Value type: <u32>
Definition: Selects Analog mode of operation: combined with input-enable Definition: Selects the source for analog output. Valued values are
and/or output-high, output-low MPP could operate as defined in <dt-binding/pinctrl/qcom,pmic-mpp.h>
Bidirectional Logic, Analog Input, Analog Output. PMIC_MPP_AOUT_LVL_*
- qcom,dtest:
Usage: optional
Value type: <u32>
Definition: Selects which dtest rail to be routed in the various functions.
Valid values are 1-4
- qcom,amux-route: - qcom,amux-route:
Usage: optional Usage: optional
@ -140,6 +148,10 @@ to specify in a pin configuration subnode:
Definition: Selects the source for analog input. Valid values are Definition: Selects the source for analog input. Valid values are
defined in <dt-bindings/pinctrl/qcom,pmic-mpp.h> defined in <dt-bindings/pinctrl/qcom,pmic-mpp.h>
PMIC_MPP_AMUX_ROUTE_CH5, PMIC_MPP_AMUX_ROUTE_CH6... PMIC_MPP_AMUX_ROUTE_CH5, PMIC_MPP_AMUX_ROUTE_CH6...
- qcom,paired:
Usage: optional
Value type: <none>
Definition: Indicates that the pin should be operating in paired mode.
Example: Example:
@ -156,7 +168,7 @@ Example:
pm8841_default: default { pm8841_default: default {
gpio { gpio {
pins = "mpp1", "mpp2", "mpp3", "mpp4"; pins = "mpp1", "mpp2", "mpp3", "mpp4";
function = "normal"; function = "digital";
input-enable; input-enable;
power-source = <PM8841_MPP_S3>; power-source = <PM8841_MPP_S3>;
}; };

View File

@ -58,12 +58,12 @@ are parsed through phandles and processed purely based on their content.
Pin Configuration Node Properties: Pin Configuration Node Properties:
- renesas,pins : An array of strings, each string containing the name of a pin. - pins : An array of strings, each string containing the name of a pin.
- renesas,groups : An array of strings, each string containing the name of a pin - groups : An array of strings, each string containing the name of a pin
group. group.
- renesas,function: A string containing the name of the function to mux to the - function: A string containing the name of the function to mux to the pin
pin group(s) specified by the renesas,groups property group(s) specified by the groups property.
Valid values for pin, group and function names can be found in the group and Valid values for pin, group and function names can be found in the group and
function arrays of the PFC data file corresponding to the SoC function arrays of the PFC data file corresponding to the SoC
@ -71,7 +71,9 @@ Pin Configuration Node Properties:
The pin configuration parameters use the generic pinconf bindings defined in The pin configuration parameters use the generic pinconf bindings defined in
pinctrl-bindings.txt in this directory. The supported parameters are pinctrl-bindings.txt in this directory. The supported parameters are
bias-disable, bias-pull-up and bias-pull-down. bias-disable, bias-pull-up, bias-pull-down and power-source. For pins that
have a configurable I/O voltage, the power-source value should be the
nominal I/O voltage in millivolts.
GPIO GPIO
@ -141,19 +143,19 @@ Example 3: KZM-A9-GT (SH-Mobile AG5) default pin state hog and pin control maps
mmcif_pins: mmcif { mmcif_pins: mmcif {
mux { mux {
renesas,groups = "mmc0_data8_0", "mmc0_ctrl_0"; groups = "mmc0_data8_0", "mmc0_ctrl_0";
renesas,function = "mmc0"; function = "mmc0";
}; };
cfg { cfg {
renesas,groups = "mmc0_data8_0"; groups = "mmc0_data8_0";
renesas,pins = "PORT279"; pins = "PORT279";
bias-pull-up; bias-pull-up;
}; };
}; };
scifa4_pins: scifa4 { scifa4_pins: scifa4 {
renesas,groups = "scifa4_data", "scifa4_ctrl"; groups = "scifa4_data", "scifa4_ctrl";
renesas,function = "scifa4"; function = "scifa4";
}; };
}; };

View File

@ -3,7 +3,9 @@ ST Ericsson Nomadik pinmux controller
Required properties: Required properties:
- compatible: "stericsson,db8500-pinctrl", "stericsson,db8540-pinctrl", - compatible: "stericsson,db8500-pinctrl", "stericsson,db8540-pinctrl",
"stericsson,stn8815-pinctrl" "stericsson,stn8815-pinctrl"
- reg: Should contain the register physical address and length of the PRCMU. - nomadik-gpio-chips: array of phandles to the corresponding GPIO chips
(these have the register ranges used by the pin controller).
- prcm: phandle to the PRCMU managing the back end of this pin controller
Please refer to pinctrl-bindings.txt in this directory for details of the 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 common pinctrl bindings used by client devices, including the meaning of the
@ -74,7 +76,8 @@ Example board file extract:
pinctrl@80157000 { pinctrl@80157000 {
compatible = "stericsson,db8500-pinctrl"; compatible = "stericsson,db8500-pinctrl";
reg = <0x80157000 0x2000>; nomadik-gpio-chips = <&gpio0>, <&gpio1>, <&gpio2>, <&gpio3>;
prcm = <&prcmu>;
pinctrl-names = "default"; pinctrl-names = "default";

View File

@ -8045,7 +8045,6 @@ F: drivers/pinctrl/sh-pfc/
PIN CONTROLLER - SAMSUNG PIN CONTROLLER - SAMSUNG
M: Tomasz Figa <tomasz.figa@gmail.com> M: Tomasz Figa <tomasz.figa@gmail.com>
M: Thomas Abraham <thomas.abraham@linaro.org>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
L: linux-samsung-soc@vger.kernel.org (moderated for non-subscribers) L: linux-samsung-soc@vger.kernel.org (moderated for non-subscribers)
S: Maintained S: Maintained

View File

@ -294,7 +294,7 @@
gpio-controller; gpio-controller;
#gpio-cells = <2>; #gpio-cells = <2>;
gpio-bank = <0>; gpio-bank = <0>;
gpio-ranges = <&pinctrl 0 0 32>;
clocks = <&prcc_pclk 1 9>; clocks = <&prcc_pclk 1 9>;
}; };
@ -309,7 +309,7 @@
gpio-controller; gpio-controller;
#gpio-cells = <2>; #gpio-cells = <2>;
gpio-bank = <1>; gpio-bank = <1>;
gpio-ranges = <&pinctrl 0 32 5>;
clocks = <&prcc_pclk 1 9>; clocks = <&prcc_pclk 1 9>;
}; };
@ -324,7 +324,7 @@
gpio-controller; gpio-controller;
#gpio-cells = <2>; #gpio-cells = <2>;
gpio-bank = <2>; gpio-bank = <2>;
gpio-ranges = <&pinctrl 0 64 32>;
clocks = <&prcc_pclk 3 8>; clocks = <&prcc_pclk 3 8>;
}; };
@ -339,7 +339,7 @@
gpio-controller; gpio-controller;
#gpio-cells = <2>; #gpio-cells = <2>;
gpio-bank = <3>; gpio-bank = <3>;
gpio-ranges = <&pinctrl 0 96 2>;
clocks = <&prcc_pclk 3 8>; clocks = <&prcc_pclk 3 8>;
}; };
@ -354,7 +354,7 @@
gpio-controller; gpio-controller;
#gpio-cells = <2>; #gpio-cells = <2>;
gpio-bank = <4>; gpio-bank = <4>;
gpio-ranges = <&pinctrl 0 128 32>;
clocks = <&prcc_pclk 3 8>; clocks = <&prcc_pclk 3 8>;
}; };
@ -369,7 +369,7 @@
gpio-controller; gpio-controller;
#gpio-cells = <2>; #gpio-cells = <2>;
gpio-bank = <5>; gpio-bank = <5>;
gpio-ranges = <&pinctrl 0 160 12>;
clocks = <&prcc_pclk 3 8>; clocks = <&prcc_pclk 3 8>;
}; };
@ -384,7 +384,7 @@
gpio-controller; gpio-controller;
#gpio-cells = <2>; #gpio-cells = <2>;
gpio-bank = <6>; gpio-bank = <6>;
gpio-ranges = <&pinctrl 0 192 32>;
clocks = <&prcc_pclk 2 11>; clocks = <&prcc_pclk 2 11>;
}; };
@ -399,7 +399,7 @@
gpio-controller; gpio-controller;
#gpio-cells = <2>; #gpio-cells = <2>;
gpio-bank = <7>; gpio-bank = <7>;
gpio-ranges = <&pinctrl 0 224 7>;
clocks = <&prcc_pclk 2 11>; clocks = <&prcc_pclk 2 11>;
}; };
@ -414,12 +414,15 @@
gpio-controller; gpio-controller;
#gpio-cells = <2>; #gpio-cells = <2>;
gpio-bank = <8>; gpio-bank = <8>;
gpio-ranges = <&pinctrl 0 256 12>;
clocks = <&prcc_pclk 5 1>; clocks = <&prcc_pclk 5 1>;
}; };
pinctrl { pinctrl: pinctrl {
compatible = "stericsson,db8500-pinctrl"; compatible = "stericsson,db8500-pinctrl";
nomadik-gpio-chips = <&gpio0>, <&gpio1>, <&gpio2>, <&gpio3>,
<&gpio4>, <&gpio5>, <&gpio6>, <&gpio7>,
<&gpio8>;
prcm = <&prcmu>; prcm = <&prcmu>;
}; };

View File

@ -59,6 +59,7 @@
gpio-controller; gpio-controller;
#gpio-cells = <2>; #gpio-cells = <2>;
gpio-bank = <0>; gpio-bank = <0>;
gpio-ranges = <&pinctrl 0 0 32>;
clocks = <&pclk>; clocks = <&pclk>;
}; };
@ -72,6 +73,7 @@
gpio-controller; gpio-controller;
#gpio-cells = <2>; #gpio-cells = <2>;
gpio-bank = <1>; gpio-bank = <1>;
gpio-ranges = <&pinctrl 0 32 32>;
clocks = <&pclk>; clocks = <&pclk>;
}; };
@ -85,12 +87,14 @@
gpio-controller; gpio-controller;
#gpio-cells = <2>; #gpio-cells = <2>;
gpio-bank = <2>; gpio-bank = <2>;
gpio-ranges = <&pinctrl 0 64 32>;
clocks = <&pclk>; clocks = <&pclk>;
}; };
gpio3: gpio@101e7000 { gpio3: gpio@101e7000 {
compatible = "st,nomadik-gpio"; compatible = "st,nomadik-gpio";
reg = <0x101e7000 0x80>; reg = <0x101e7000 0x80>;
ngpio = <28>;
interrupt-parent = <&vica>; interrupt-parent = <&vica>;
interrupts = <9>; interrupts = <9>;
interrupt-controller; interrupt-controller;
@ -98,11 +102,13 @@
gpio-controller; gpio-controller;
#gpio-cells = <2>; #gpio-cells = <2>;
gpio-bank = <3>; gpio-bank = <3>;
gpio-ranges = <&pinctrl 0 96 28>;
clocks = <&pclk>; clocks = <&pclk>;
}; };
pinctrl { pinctrl: pinctrl {
compatible = "stericsson,stn8815-pinctrl"; compatible = "stericsson,stn8815-pinctrl";
nomadik-gpio-chips = <&gpio0>, <&gpio1>, <&gpio2>, <&gpio3>;
/* Pin configurations */ /* Pin configurations */
uart1 { uart1 {
uart1_default_mux: uart1_mux { uart1_default_mux: uart1_mux {

View File

@ -11,7 +11,7 @@ obj-y += bus/
obj-$(CONFIG_GENERIC_PHY) += phy/ obj-$(CONFIG_GENERIC_PHY) += phy/
# GPIO must come after pinctrl as gpios may need to mux pins etc # GPIO must come after pinctrl as gpios may need to mux pins etc
obj-y += pinctrl/ obj-$(CONFIG_PINCTRL) += pinctrl/
obj-y += gpio/ obj-y += gpio/
obj-y += pwm/ obj-y += pwm/
obj-$(CONFIG_PCI) += pci/ obj-$(CONFIG_PCI) += pci/

View File

@ -780,6 +780,7 @@ static const char *const rk3288_critical_clocks[] __initconst = {
"aclk_cpu", "aclk_cpu",
"aclk_peri", "aclk_peri",
"hclk_peri", "hclk_peri",
"pclk_pd_pmu",
}; };
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP

View File

@ -82,6 +82,12 @@ config PINCTRL_AMD
Requires ACPI/FDT device enumeration code to set up a platform Requires ACPI/FDT device enumeration code to set up a platform
device. device.
config PINCTRL_DIGICOLOR
bool
depends on OF && (ARCH_DIGICOLOR || COMPILE_TEST)
select PINMUX
select GENERIC_PINCONF
config PINCTRL_LANTIQ config PINCTRL_LANTIQ
bool bool
depends on LANTIQ depends on LANTIQ
@ -240,6 +246,7 @@ source "drivers/pinctrl/samsung/Kconfig"
source "drivers/pinctrl/sh-pfc/Kconfig" source "drivers/pinctrl/sh-pfc/Kconfig"
source "drivers/pinctrl/spear/Kconfig" source "drivers/pinctrl/spear/Kconfig"
source "drivers/pinctrl/sunxi/Kconfig" source "drivers/pinctrl/sunxi/Kconfig"
source "drivers/pinctrl/uniphier/Kconfig"
source "drivers/pinctrl/vt8500/Kconfig" source "drivers/pinctrl/vt8500/Kconfig"
source "drivers/pinctrl/mediatek/Kconfig" source "drivers/pinctrl/mediatek/Kconfig"

View File

@ -2,12 +2,10 @@
subdir-ccflags-$(CONFIG_DEBUG_PINCTRL) += -DDEBUG subdir-ccflags-$(CONFIG_DEBUG_PINCTRL) += -DDEBUG
obj-$(CONFIG_PINCTRL) += core.o pinctrl-utils.o obj-y += core.o pinctrl-utils.o
obj-$(CONFIG_PINMUX) += pinmux.o obj-$(CONFIG_PINMUX) += pinmux.o
obj-$(CONFIG_PINCONF) += pinconf.o obj-$(CONFIG_PINCONF) += pinconf.o
ifeq ($(CONFIG_OF),y) obj-$(CONFIG_OF) += devicetree.o
obj-$(CONFIG_PINCTRL) += devicetree.o
endif
obj-$(CONFIG_GENERIC_PINCONF) += pinconf-generic.o obj-$(CONFIG_GENERIC_PINCONF) += pinconf-generic.o
obj-$(CONFIG_PINCTRL_ADI2) += pinctrl-adi2.o obj-$(CONFIG_PINCTRL_ADI2) += pinctrl-adi2.o
obj-$(CONFIG_PINCTRL_AS3722) += pinctrl-as3722.o obj-$(CONFIG_PINCTRL_AS3722) += pinctrl-as3722.o
@ -15,6 +13,7 @@ obj-$(CONFIG_PINCTRL_BF54x) += pinctrl-adi2-bf54x.o
obj-$(CONFIG_PINCTRL_BF60x) += pinctrl-adi2-bf60x.o obj-$(CONFIG_PINCTRL_BF60x) += pinctrl-adi2-bf60x.o
obj-$(CONFIG_PINCTRL_AT91) += pinctrl-at91.o obj-$(CONFIG_PINCTRL_AT91) += pinctrl-at91.o
obj-$(CONFIG_PINCTRL_AMD) += pinctrl-amd.o obj-$(CONFIG_PINCTRL_AMD) += pinctrl-amd.o
obj-$(CONFIG_PINCTRL_DIGICOLOR) += pinctrl-digicolor.o
obj-$(CONFIG_PINCTRL_FALCON) += pinctrl-falcon.o obj-$(CONFIG_PINCTRL_FALCON) += pinctrl-falcon.o
obj-$(CONFIG_PINCTRL_MESON) += meson/ obj-$(CONFIG_PINCTRL_MESON) += meson/
obj-$(CONFIG_PINCTRL_PALMAS) += pinctrl-palmas.o obj-$(CONFIG_PINCTRL_PALMAS) += pinctrl-palmas.o
@ -51,5 +50,6 @@ obj-$(CONFIG_PINCTRL_SAMSUNG) += samsung/
obj-$(CONFIG_PINCTRL_SH_PFC) += sh-pfc/ obj-$(CONFIG_PINCTRL_SH_PFC) += sh-pfc/
obj-$(CONFIG_PLAT_SPEAR) += spear/ obj-$(CONFIG_PLAT_SPEAR) += spear/
obj-$(CONFIG_ARCH_SUNXI) += sunxi/ obj-$(CONFIG_ARCH_SUNXI) += sunxi/
obj-$(CONFIG_ARCH_UNIPHIER) += uniphier/
obj-$(CONFIG_ARCH_VT8500) += vt8500/ obj-$(CONFIG_ARCH_VT8500) += vt8500/
obj-$(CONFIG_ARCH_MEDIATEK) += mediatek/ obj-$(CONFIG_ARCH_MEDIATEK) += mediatek/

View File

@ -586,9 +586,9 @@ static int bcm2835_gpio_irq_set_type(struct irq_data *data, unsigned int type)
ret = __bcm2835_gpio_irq_set_type_disabled(pc, gpio, type); ret = __bcm2835_gpio_irq_set_type_disabled(pc, gpio, type);
if (type & IRQ_TYPE_EDGE_BOTH) if (type & IRQ_TYPE_EDGE_BOTH)
__irq_set_handler_locked(data->irq, handle_edge_irq); irq_set_handler_locked(data, handle_edge_irq);
else else
__irq_set_handler_locked(data->irq, handle_level_irq); irq_set_handler_locked(data, handle_level_irq);
spin_unlock_irqrestore(&pc->irq_lock[bank], flags); spin_unlock_irqrestore(&pc->irq_lock[bank], flags);
@ -989,7 +989,6 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev)
irq_set_chip_and_handler(irq, &bcm2835_gpio_irq_chip, irq_set_chip_and_handler(irq, &bcm2835_gpio_irq_chip,
handle_level_irq); handle_level_irq);
irq_set_chip_data(irq, pc); irq_set_chip_data(irq, pc);
set_irq_flags(irq, IRQF_VALID);
} }
for (i = 0; i < BCM2835_NUM_BANKS; i++) { for (i = 0; i < BCM2835_NUM_BANKS; i++) {

View File

@ -231,8 +231,7 @@ static int pinctrl_register_one_pin(struct pinctrl_dev *pctldev,
pindesc = pin_desc_get(pctldev, number); pindesc = pin_desc_get(pctldev, number);
if (pindesc != NULL) { if (pindesc != NULL) {
pr_err("pin %d already registered on %s\n", number, dev_err(pctldev->dev, "pin %d already registered\n", number);
pctldev->desc->name);
return -EINVAL; return -EINVAL;
} }

View File

@ -97,13 +97,7 @@ static int dt_remember_or_free_map(struct pinctrl *p, const char *statename,
struct pinctrl_dev *of_pinctrl_get(struct device_node *np) struct pinctrl_dev *of_pinctrl_get(struct device_node *np)
{ {
struct pinctrl_dev *pctldev; return get_pinctrl_dev_from_of_node(np);
pctldev = get_pinctrl_dev_from_of_node(np);
if (!pctldev)
return NULL;
return pctldev;
} }
static int dt_to_map_one_config(struct pinctrl *p, const char *statename, static int dt_to_map_one_config(struct pinctrl *p, const char *statename,

View File

@ -87,6 +87,13 @@ config PINCTRL_IMX6SX
help help
Say Y here to enable the imx6sx pinctrl driver Say Y here to enable the imx6sx pinctrl driver
config PINCTRL_IMX6UL
bool "IMX6UL pinctrl driver"
depends on SOC_IMX6UL
select PINCTRL_IMX
help
Say Y here to enable the imx6ul pinctrl driver
config PINCTRL_IMX7D config PINCTRL_IMX7D
bool "IMX7D pinctrl driver" bool "IMX7D pinctrl driver"
depends on SOC_IMX7D depends on SOC_IMX7D

View File

@ -12,6 +12,7 @@ obj-$(CONFIG_PINCTRL_IMX6Q) += pinctrl-imx6q.o
obj-$(CONFIG_PINCTRL_IMX6Q) += pinctrl-imx6dl.o obj-$(CONFIG_PINCTRL_IMX6Q) += pinctrl-imx6dl.o
obj-$(CONFIG_PINCTRL_IMX6SL) += pinctrl-imx6sl.o obj-$(CONFIG_PINCTRL_IMX6SL) += pinctrl-imx6sl.o
obj-$(CONFIG_PINCTRL_IMX6SX) += pinctrl-imx6sx.o obj-$(CONFIG_PINCTRL_IMX6SX) += pinctrl-imx6sx.o
obj-$(CONFIG_PINCTRL_IMX6UL) += pinctrl-imx6ul.o
obj-$(CONFIG_PINCTRL_IMX7D) += pinctrl-imx7d.o obj-$(CONFIG_PINCTRL_IMX7D) += pinctrl-imx7d.o
obj-$(CONFIG_PINCTRL_VF610) += pinctrl-vf610.o obj-$(CONFIG_PINCTRL_VF610) += pinctrl-vf610.o
obj-$(CONFIG_PINCTRL_MXS) += pinctrl-mxs.o obj-$(CONFIG_PINCTRL_MXS) += pinctrl-mxs.o

View File

@ -0,0 +1,322 @@
/*
* Copyright (C) 2015 Freescale Semiconductor, Inc.
*
* 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.
*/
#include <linux/err.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/pinctrl/pinctrl.h>
#include "pinctrl-imx.h"
enum imx6ul_pads {
MX6UL_PAD_RESERVE0 = 0,
MX6UL_PAD_RESERVE1 = 1,
MX6UL_PAD_RESERVE2 = 2,
MX6UL_PAD_RESERVE3 = 3,
MX6UL_PAD_RESERVE4 = 4,
MX6UL_PAD_RESERVE5 = 5,
MX6UL_PAD_RESERVE6 = 6,
MX6UL_PAD_RESERVE7 = 7,
MX6UL_PAD_RESERVE8 = 8,
MX6UL_PAD_RESERVE9 = 9,
MX6UL_PAD_RESERVE10 = 10,
MX6UL_PAD_SNVS_TAMPER4 = 11,
MX6UL_PAD_RESERVE12 = 12,
MX6UL_PAD_RESERVE13 = 13,
MX6UL_PAD_RESERVE14 = 14,
MX6UL_PAD_RESERVE15 = 15,
MX6UL_PAD_RESERVE16 = 16,
MX6UL_PAD_JTAG_MOD = 17,
MX6UL_PAD_JTAG_TMS = 18,
MX6UL_PAD_JTAG_TDO = 19,
MX6UL_PAD_JTAG_TDI = 20,
MX6UL_PAD_JTAG_TCK = 21,
MX6UL_PAD_JTAG_TRST_B = 22,
MX6UL_PAD_GPIO1_IO00 = 23,
MX6UL_PAD_GPIO1_IO01 = 24,
MX6UL_PAD_GPIO1_IO02 = 25,
MX6UL_PAD_GPIO1_IO03 = 26,
MX6UL_PAD_GPIO1_IO04 = 27,
MX6UL_PAD_GPIO1_IO05 = 28,
MX6UL_PAD_GPIO1_IO06 = 29,
MX6UL_PAD_GPIO1_IO07 = 30,
MX6UL_PAD_GPIO1_IO08 = 31,
MX6UL_PAD_GPIO1_IO09 = 32,
MX6UL_PAD_UART1_TX_DATA = 33,
MX6UL_PAD_UART1_RX_DATA = 34,
MX6UL_PAD_UART1_CTS_B = 35,
MX6UL_PAD_UART1_RTS_B = 36,
MX6UL_PAD_UART2_TX_DATA = 37,
MX6UL_PAD_UART2_RX_DATA = 38,
MX6UL_PAD_UART2_CTS_B = 39,
MX6UL_PAD_UART2_RTS_B = 40,
MX6UL_PAD_UART3_TX_DATA = 41,
MX6UL_PAD_UART3_RX_DATA = 42,
MX6UL_PAD_UART3_CTS_B = 43,
MX6UL_PAD_UART3_RTS_B = 44,
MX6UL_PAD_UART4_TX_DATA = 45,
MX6UL_PAD_UART4_RX_DATA = 46,
MX6UL_PAD_UART5_TX_DATA = 47,
MX6UL_PAD_UART5_RX_DATA = 48,
MX6UL_PAD_ENET1_RX_DATA0 = 49,
MX6UL_PAD_ENET1_RX_DATA1 = 50,
MX6UL_PAD_ENET1_RX_EN = 51,
MX6UL_PAD_ENET1_TX_DATA0 = 52,
MX6UL_PAD_ENET1_TX_DATA1 = 53,
MX6UL_PAD_ENET1_TX_EN = 54,
MX6UL_PAD_ENET1_TX_CLK = 55,
MX6UL_PAD_ENET1_RX_ER = 56,
MX6UL_PAD_ENET2_RX_DATA0 = 57,
MX6UL_PAD_ENET2_RX_DATA1 = 58,
MX6UL_PAD_ENET2_RX_EN = 59,
MX6UL_PAD_ENET2_TX_DATA0 = 60,
MX6UL_PAD_ENET2_TX_DATA1 = 61,
MX6UL_PAD_ENET2_TX_EN = 62,
MX6UL_PAD_ENET2_TX_CLK = 63,
MX6UL_PAD_ENET2_RX_ER = 64,
MX6UL_PAD_LCD_CLK = 65,
MX6UL_PAD_LCD_ENABLE = 66,
MX6UL_PAD_LCD_HSYNC = 67,
MX6UL_PAD_LCD_VSYNC = 68,
MX6UL_PAD_LCD_RESET = 69,
MX6UL_PAD_LCD_DATA00 = 70,
MX6UL_PAD_LCD_DATA01 = 71,
MX6UL_PAD_LCD_DATA02 = 72,
MX6UL_PAD_LCD_DATA03 = 73,
MX6UL_PAD_LCD_DATA04 = 74,
MX6UL_PAD_LCD_DATA05 = 75,
MX6UL_PAD_LCD_DATA06 = 76,
MX6UL_PAD_LCD_DATA07 = 77,
MX6UL_PAD_LCD_DATA08 = 78,
MX6UL_PAD_LCD_DATA09 = 79,
MX6UL_PAD_LCD_DATA10 = 80,
MX6UL_PAD_LCD_DATA11 = 81,
MX6UL_PAD_LCD_DATA12 = 82,
MX6UL_PAD_LCD_DATA13 = 83,
MX6UL_PAD_LCD_DATA14 = 84,
MX6UL_PAD_LCD_DATA15 = 85,
MX6UL_PAD_LCD_DATA16 = 86,
MX6UL_PAD_LCD_DATA17 = 87,
MX6UL_PAD_LCD_DATA18 = 88,
MX6UL_PAD_LCD_DATA19 = 89,
MX6UL_PAD_LCD_DATA20 = 90,
MX6UL_PAD_LCD_DATA21 = 91,
MX6UL_PAD_LCD_DATA22 = 92,
MX6UL_PAD_LCD_DATA23 = 93,
MX6UL_PAD_NAND_RE_B = 94,
MX6UL_PAD_NAND_WE_B = 95,
MX6UL_PAD_NAND_DATA00 = 96,
MX6UL_PAD_NAND_DATA01 = 97,
MX6UL_PAD_NAND_DATA02 = 98,
MX6UL_PAD_NAND_DATA03 = 99,
MX6UL_PAD_NAND_DATA04 = 100,
MX6UL_PAD_NAND_DATA05 = 101,
MX6UL_PAD_NAND_DATA06 = 102,
MX6UL_PAD_NAND_DATA07 = 103,
MX6UL_PAD_NAND_ALE = 104,
MX6UL_PAD_NAND_WP_B = 105,
MX6UL_PAD_NAND_READY_B = 106,
MX6UL_PAD_NAND_CE0_B = 107,
MX6UL_PAD_NAND_CE1_B = 108,
MX6UL_PAD_NAND_CLE = 109,
MX6UL_PAD_NAND_DQS = 110,
MX6UL_PAD_SD1_CMD = 111,
MX6UL_PAD_SD1_CLK = 112,
MX6UL_PAD_SD1_DATA0 = 113,
MX6UL_PAD_SD1_DATA1 = 114,
MX6UL_PAD_SD1_DATA2 = 115,
MX6UL_PAD_SD1_DATA3 = 116,
MX6UL_PAD_CSI_MCLK = 117,
MX6UL_PAD_CSI_PIXCLK = 118,
MX6UL_PAD_CSI_VSYNC = 119,
MX6UL_PAD_CSI_HSYNC = 120,
MX6UL_PAD_CSI_DATA00 = 121,
MX6UL_PAD_CSI_DATA01 = 122,
MX6UL_PAD_CSI_DATA02 = 123,
MX6UL_PAD_CSI_DATA03 = 124,
MX6UL_PAD_CSI_DATA04 = 125,
MX6UL_PAD_CSI_DATA05 = 126,
MX6UL_PAD_CSI_DATA06 = 127,
MX6UL_PAD_CSI_DATA07 = 128,
};
/* Pad names for the pinmux subsystem */
static const struct pinctrl_pin_desc imx6ul_pinctrl_pads[] = {
IMX_PINCTRL_PIN(MX6UL_PAD_RESERVE0),
IMX_PINCTRL_PIN(MX6UL_PAD_RESERVE1),
IMX_PINCTRL_PIN(MX6UL_PAD_RESERVE2),
IMX_PINCTRL_PIN(MX6UL_PAD_RESERVE3),
IMX_PINCTRL_PIN(MX6UL_PAD_RESERVE4),
IMX_PINCTRL_PIN(MX6UL_PAD_RESERVE5),
IMX_PINCTRL_PIN(MX6UL_PAD_RESERVE6),
IMX_PINCTRL_PIN(MX6UL_PAD_RESERVE7),
IMX_PINCTRL_PIN(MX6UL_PAD_RESERVE8),
IMX_PINCTRL_PIN(MX6UL_PAD_RESERVE9),
IMX_PINCTRL_PIN(MX6UL_PAD_RESERVE10),
IMX_PINCTRL_PIN(MX6UL_PAD_SNVS_TAMPER4),
IMX_PINCTRL_PIN(MX6UL_PAD_RESERVE12),
IMX_PINCTRL_PIN(MX6UL_PAD_RESERVE13),
IMX_PINCTRL_PIN(MX6UL_PAD_RESERVE14),
IMX_PINCTRL_PIN(MX6UL_PAD_RESERVE15),
IMX_PINCTRL_PIN(MX6UL_PAD_RESERVE16),
IMX_PINCTRL_PIN(MX6UL_PAD_JTAG_MOD),
IMX_PINCTRL_PIN(MX6UL_PAD_JTAG_TMS),
IMX_PINCTRL_PIN(MX6UL_PAD_JTAG_TDO),
IMX_PINCTRL_PIN(MX6UL_PAD_JTAG_TDI),
IMX_PINCTRL_PIN(MX6UL_PAD_JTAG_TCK),
IMX_PINCTRL_PIN(MX6UL_PAD_JTAG_TRST_B),
IMX_PINCTRL_PIN(MX6UL_PAD_GPIO1_IO00),
IMX_PINCTRL_PIN(MX6UL_PAD_GPIO1_IO01),
IMX_PINCTRL_PIN(MX6UL_PAD_GPIO1_IO02),
IMX_PINCTRL_PIN(MX6UL_PAD_GPIO1_IO03),
IMX_PINCTRL_PIN(MX6UL_PAD_GPIO1_IO04),
IMX_PINCTRL_PIN(MX6UL_PAD_GPIO1_IO05),
IMX_PINCTRL_PIN(MX6UL_PAD_GPIO1_IO06),
IMX_PINCTRL_PIN(MX6UL_PAD_GPIO1_IO07),
IMX_PINCTRL_PIN(MX6UL_PAD_GPIO1_IO08),
IMX_PINCTRL_PIN(MX6UL_PAD_GPIO1_IO09),
IMX_PINCTRL_PIN(MX6UL_PAD_UART1_TX_DATA),
IMX_PINCTRL_PIN(MX6UL_PAD_UART1_RX_DATA),
IMX_PINCTRL_PIN(MX6UL_PAD_UART1_CTS_B),
IMX_PINCTRL_PIN(MX6UL_PAD_UART1_RTS_B),
IMX_PINCTRL_PIN(MX6UL_PAD_UART2_TX_DATA),
IMX_PINCTRL_PIN(MX6UL_PAD_UART2_RX_DATA),
IMX_PINCTRL_PIN(MX6UL_PAD_UART2_CTS_B),
IMX_PINCTRL_PIN(MX6UL_PAD_UART2_RTS_B),
IMX_PINCTRL_PIN(MX6UL_PAD_UART3_TX_DATA),
IMX_PINCTRL_PIN(MX6UL_PAD_UART3_RX_DATA),
IMX_PINCTRL_PIN(MX6UL_PAD_UART3_CTS_B),
IMX_PINCTRL_PIN(MX6UL_PAD_UART3_RTS_B),
IMX_PINCTRL_PIN(MX6UL_PAD_UART4_TX_DATA),
IMX_PINCTRL_PIN(MX6UL_PAD_UART4_RX_DATA),
IMX_PINCTRL_PIN(MX6UL_PAD_UART5_TX_DATA),
IMX_PINCTRL_PIN(MX6UL_PAD_UART5_RX_DATA),
IMX_PINCTRL_PIN(MX6UL_PAD_ENET1_RX_DATA0),
IMX_PINCTRL_PIN(MX6UL_PAD_ENET1_RX_DATA1),
IMX_PINCTRL_PIN(MX6UL_PAD_ENET1_RX_EN),
IMX_PINCTRL_PIN(MX6UL_PAD_ENET1_TX_DATA0),
IMX_PINCTRL_PIN(MX6UL_PAD_ENET1_TX_DATA1),
IMX_PINCTRL_PIN(MX6UL_PAD_ENET1_TX_EN),
IMX_PINCTRL_PIN(MX6UL_PAD_ENET1_TX_CLK),
IMX_PINCTRL_PIN(MX6UL_PAD_ENET1_RX_ER),
IMX_PINCTRL_PIN(MX6UL_PAD_ENET2_RX_DATA0),
IMX_PINCTRL_PIN(MX6UL_PAD_ENET2_RX_DATA1),
IMX_PINCTRL_PIN(MX6UL_PAD_ENET2_RX_EN),
IMX_PINCTRL_PIN(MX6UL_PAD_ENET2_TX_DATA0),
IMX_PINCTRL_PIN(MX6UL_PAD_ENET2_TX_DATA1),
IMX_PINCTRL_PIN(MX6UL_PAD_ENET2_TX_EN),
IMX_PINCTRL_PIN(MX6UL_PAD_ENET2_TX_CLK),
IMX_PINCTRL_PIN(MX6UL_PAD_ENET2_RX_ER),
IMX_PINCTRL_PIN(MX6UL_PAD_LCD_CLK),
IMX_PINCTRL_PIN(MX6UL_PAD_LCD_ENABLE),
IMX_PINCTRL_PIN(MX6UL_PAD_LCD_HSYNC),
IMX_PINCTRL_PIN(MX6UL_PAD_LCD_VSYNC),
IMX_PINCTRL_PIN(MX6UL_PAD_LCD_RESET),
IMX_PINCTRL_PIN(MX6UL_PAD_LCD_DATA00),
IMX_PINCTRL_PIN(MX6UL_PAD_LCD_DATA01),
IMX_PINCTRL_PIN(MX6UL_PAD_LCD_DATA02),
IMX_PINCTRL_PIN(MX6UL_PAD_LCD_DATA03),
IMX_PINCTRL_PIN(MX6UL_PAD_LCD_DATA04),
IMX_PINCTRL_PIN(MX6UL_PAD_LCD_DATA05),
IMX_PINCTRL_PIN(MX6UL_PAD_LCD_DATA06),
IMX_PINCTRL_PIN(MX6UL_PAD_LCD_DATA07),
IMX_PINCTRL_PIN(MX6UL_PAD_LCD_DATA08),
IMX_PINCTRL_PIN(MX6UL_PAD_LCD_DATA09),
IMX_PINCTRL_PIN(MX6UL_PAD_LCD_DATA10),
IMX_PINCTRL_PIN(MX6UL_PAD_LCD_DATA11),
IMX_PINCTRL_PIN(MX6UL_PAD_LCD_DATA12),
IMX_PINCTRL_PIN(MX6UL_PAD_LCD_DATA13),
IMX_PINCTRL_PIN(MX6UL_PAD_LCD_DATA14),
IMX_PINCTRL_PIN(MX6UL_PAD_LCD_DATA15),
IMX_PINCTRL_PIN(MX6UL_PAD_LCD_DATA16),
IMX_PINCTRL_PIN(MX6UL_PAD_LCD_DATA17),
IMX_PINCTRL_PIN(MX6UL_PAD_LCD_DATA18),
IMX_PINCTRL_PIN(MX6UL_PAD_LCD_DATA19),
IMX_PINCTRL_PIN(MX6UL_PAD_LCD_DATA20),
IMX_PINCTRL_PIN(MX6UL_PAD_LCD_DATA21),
IMX_PINCTRL_PIN(MX6UL_PAD_LCD_DATA22),
IMX_PINCTRL_PIN(MX6UL_PAD_LCD_DATA23),
IMX_PINCTRL_PIN(MX6UL_PAD_NAND_RE_B),
IMX_PINCTRL_PIN(MX6UL_PAD_NAND_WE_B),
IMX_PINCTRL_PIN(MX6UL_PAD_NAND_DATA00),
IMX_PINCTRL_PIN(MX6UL_PAD_NAND_DATA01),
IMX_PINCTRL_PIN(MX6UL_PAD_NAND_DATA02),
IMX_PINCTRL_PIN(MX6UL_PAD_NAND_DATA03),
IMX_PINCTRL_PIN(MX6UL_PAD_NAND_DATA04),
IMX_PINCTRL_PIN(MX6UL_PAD_NAND_DATA05),
IMX_PINCTRL_PIN(MX6UL_PAD_NAND_DATA06),
IMX_PINCTRL_PIN(MX6UL_PAD_NAND_DATA07),
IMX_PINCTRL_PIN(MX6UL_PAD_NAND_ALE),
IMX_PINCTRL_PIN(MX6UL_PAD_NAND_WP_B),
IMX_PINCTRL_PIN(MX6UL_PAD_NAND_READY_B),
IMX_PINCTRL_PIN(MX6UL_PAD_NAND_CE0_B),
IMX_PINCTRL_PIN(MX6UL_PAD_NAND_CE1_B),
IMX_PINCTRL_PIN(MX6UL_PAD_NAND_CLE),
IMX_PINCTRL_PIN(MX6UL_PAD_NAND_DQS),
IMX_PINCTRL_PIN(MX6UL_PAD_SD1_CMD),
IMX_PINCTRL_PIN(MX6UL_PAD_SD1_CLK),
IMX_PINCTRL_PIN(MX6UL_PAD_SD1_DATA0),
IMX_PINCTRL_PIN(MX6UL_PAD_SD1_DATA1),
IMX_PINCTRL_PIN(MX6UL_PAD_SD1_DATA2),
IMX_PINCTRL_PIN(MX6UL_PAD_SD1_DATA3),
IMX_PINCTRL_PIN(MX6UL_PAD_CSI_MCLK),
IMX_PINCTRL_PIN(MX6UL_PAD_CSI_PIXCLK),
IMX_PINCTRL_PIN(MX6UL_PAD_CSI_VSYNC),
IMX_PINCTRL_PIN(MX6UL_PAD_CSI_HSYNC),
IMX_PINCTRL_PIN(MX6UL_PAD_CSI_DATA00),
IMX_PINCTRL_PIN(MX6UL_PAD_CSI_DATA01),
IMX_PINCTRL_PIN(MX6UL_PAD_CSI_DATA02),
IMX_PINCTRL_PIN(MX6UL_PAD_CSI_DATA03),
IMX_PINCTRL_PIN(MX6UL_PAD_CSI_DATA04),
IMX_PINCTRL_PIN(MX6UL_PAD_CSI_DATA05),
IMX_PINCTRL_PIN(MX6UL_PAD_CSI_DATA06),
IMX_PINCTRL_PIN(MX6UL_PAD_CSI_DATA07),
};
static struct imx_pinctrl_soc_info imx6ul_pinctrl_info = {
.pins = imx6ul_pinctrl_pads,
.npins = ARRAY_SIZE(imx6ul_pinctrl_pads),
};
static struct of_device_id imx6ul_pinctrl_of_match[] = {
{ .compatible = "fsl,imx6ul-iomuxc", },
{ /* sentinel */ }
};
static int imx6ul_pinctrl_probe(struct platform_device *pdev)
{
return imx_pinctrl_probe(pdev, &imx6ul_pinctrl_info);
}
static struct platform_driver imx6ul_pinctrl_driver = {
.driver = {
.name = "imx6ul-pinctrl",
.of_match_table = of_match_ptr(imx6ul_pinctrl_of_match),
},
.probe = imx6ul_pinctrl_probe,
.remove = imx_pinctrl_remove,
};
static int __init imx6ul_pinctrl_init(void)
{
return platform_driver_register(&imx6ul_pinctrl_driver);
}
arch_initcall(imx6ul_pinctrl_init);
static void __exit imx6ul_pinctrl_exit(void)
{
platform_driver_unregister(&imx6ul_pinctrl_driver);
}
module_exit(imx6ul_pinctrl_exit);
MODULE_AUTHOR("Anson Huang <Anson.Huang@freescale.com>");
MODULE_DESCRIPTION("Freescale imx6ul pinctrl driver");
MODULE_LICENSE("GPL v2");

View File

@ -12,11 +12,6 @@
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details. * more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
*
*/ */
#include <linux/kernel.h> #include <linux/kernel.h>
@ -146,7 +141,7 @@ struct byt_gpio_pin_context {
struct byt_gpio { struct byt_gpio {
struct gpio_chip chip; struct gpio_chip chip;
struct platform_device *pdev; struct platform_device *pdev;
spinlock_t lock; raw_spinlock_t lock;
void __iomem *reg_base; void __iomem *reg_base;
struct pinctrl_gpio_range *range; struct pinctrl_gpio_range *range;
struct byt_gpio_pin_context *saved_context; struct byt_gpio_pin_context *saved_context;
@ -174,11 +169,11 @@ static void byt_gpio_clear_triggering(struct byt_gpio *vg, unsigned offset)
unsigned long flags; unsigned long flags;
u32 value; u32 value;
spin_lock_irqsave(&vg->lock, flags); raw_spin_lock_irqsave(&vg->lock, flags);
value = readl(reg); value = readl(reg);
value &= ~(BYT_TRIG_POS | BYT_TRIG_NEG | BYT_TRIG_LVL); value &= ~(BYT_TRIG_POS | BYT_TRIG_NEG | BYT_TRIG_LVL);
writel(value, reg); writel(value, reg);
spin_unlock_irqrestore(&vg->lock, flags); raw_spin_unlock_irqrestore(&vg->lock, flags);
} }
static u32 byt_get_gpio_mux(struct byt_gpio *vg, unsigned offset) static u32 byt_get_gpio_mux(struct byt_gpio *vg, unsigned offset)
@ -201,6 +196,9 @@ static int byt_gpio_request(struct gpio_chip *chip, unsigned offset)
struct byt_gpio *vg = to_byt_gpio(chip); struct byt_gpio *vg = to_byt_gpio(chip);
void __iomem *reg = byt_gpio_reg(chip, offset, BYT_CONF0_REG); void __iomem *reg = byt_gpio_reg(chip, offset, BYT_CONF0_REG);
u32 value, gpio_mux; u32 value, gpio_mux;
unsigned long flags;
raw_spin_lock_irqsave(&vg->lock, flags);
/* /*
* In most cases, func pin mux 000 means GPIO function. * In most cases, func pin mux 000 means GPIO function.
@ -214,18 +212,16 @@ static int byt_gpio_request(struct gpio_chip *chip, unsigned offset)
value = readl(reg) & BYT_PIN_MUX; value = readl(reg) & BYT_PIN_MUX;
gpio_mux = byt_get_gpio_mux(vg, offset); gpio_mux = byt_get_gpio_mux(vg, offset);
if (WARN_ON(gpio_mux != value)) { if (WARN_ON(gpio_mux != value)) {
unsigned long flags;
spin_lock_irqsave(&vg->lock, flags);
value = readl(reg) & ~BYT_PIN_MUX; value = readl(reg) & ~BYT_PIN_MUX;
value |= gpio_mux; value |= gpio_mux;
writel(value, reg); writel(value, reg);
spin_unlock_irqrestore(&vg->lock, flags);
dev_warn(&vg->pdev->dev, dev_warn(&vg->pdev->dev,
"pin %u forcibly re-configured as GPIO\n", offset); "pin %u forcibly re-configured as GPIO\n", offset);
} }
raw_spin_unlock_irqrestore(&vg->lock, flags);
pm_runtime_get(&vg->pdev->dev); pm_runtime_get(&vg->pdev->dev);
return 0; return 0;
@ -250,7 +246,7 @@ static int byt_irq_type(struct irq_data *d, unsigned type)
if (offset >= vg->chip.ngpio) if (offset >= vg->chip.ngpio)
return -EINVAL; return -EINVAL;
spin_lock_irqsave(&vg->lock, flags); raw_spin_lock_irqsave(&vg->lock, flags);
value = readl(reg); value = readl(reg);
WARN(value & BYT_DIRECT_IRQ_EN, WARN(value & BYT_DIRECT_IRQ_EN,
@ -265,11 +261,11 @@ static int byt_irq_type(struct irq_data *d, unsigned type)
writel(value, reg); writel(value, reg);
if (type & IRQ_TYPE_EDGE_BOTH) if (type & IRQ_TYPE_EDGE_BOTH)
__irq_set_handler_locked(d->irq, handle_edge_irq); irq_set_handler_locked(d, handle_edge_irq);
else if (type & IRQ_TYPE_LEVEL_MASK) else if (type & IRQ_TYPE_LEVEL_MASK)
__irq_set_handler_locked(d->irq, handle_level_irq); irq_set_handler_locked(d, handle_level_irq);
spin_unlock_irqrestore(&vg->lock, flags); raw_spin_unlock_irqrestore(&vg->lock, flags);
return 0; return 0;
} }
@ -277,7 +273,15 @@ static int byt_irq_type(struct irq_data *d, unsigned type)
static int byt_gpio_get(struct gpio_chip *chip, unsigned offset) static int byt_gpio_get(struct gpio_chip *chip, unsigned offset)
{ {
void __iomem *reg = byt_gpio_reg(chip, offset, BYT_VAL_REG); void __iomem *reg = byt_gpio_reg(chip, offset, BYT_VAL_REG);
return readl(reg) & BYT_LEVEL; struct byt_gpio *vg = to_byt_gpio(chip);
unsigned long flags;
u32 val;
raw_spin_lock_irqsave(&vg->lock, flags);
val = readl(reg);
raw_spin_unlock_irqrestore(&vg->lock, flags);
return val & BYT_LEVEL;
} }
static void byt_gpio_set(struct gpio_chip *chip, unsigned offset, int value) static void byt_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
@ -287,7 +291,7 @@ static void byt_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
unsigned long flags; unsigned long flags;
u32 old_val; u32 old_val;
spin_lock_irqsave(&vg->lock, flags); raw_spin_lock_irqsave(&vg->lock, flags);
old_val = readl(reg); old_val = readl(reg);
@ -296,7 +300,7 @@ static void byt_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
else else
writel(old_val & ~BYT_LEVEL, reg); writel(old_val & ~BYT_LEVEL, reg);
spin_unlock_irqrestore(&vg->lock, flags); raw_spin_unlock_irqrestore(&vg->lock, flags);
} }
static int byt_gpio_direction_input(struct gpio_chip *chip, unsigned offset) static int byt_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
@ -306,13 +310,13 @@ static int byt_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
unsigned long flags; unsigned long flags;
u32 value; u32 value;
spin_lock_irqsave(&vg->lock, flags); raw_spin_lock_irqsave(&vg->lock, flags);
value = readl(reg) | BYT_DIR_MASK; value = readl(reg) | BYT_DIR_MASK;
value &= ~BYT_INPUT_EN; /* active low */ value &= ~BYT_INPUT_EN; /* active low */
writel(value, reg); writel(value, reg);
spin_unlock_irqrestore(&vg->lock, flags); raw_spin_unlock_irqrestore(&vg->lock, flags);
return 0; return 0;
} }
@ -326,7 +330,7 @@ static int byt_gpio_direction_output(struct gpio_chip *chip,
unsigned long flags; unsigned long flags;
u32 reg_val; u32 reg_val;
spin_lock_irqsave(&vg->lock, flags); raw_spin_lock_irqsave(&vg->lock, flags);
/* /*
* Before making any direction modifications, do a check if gpio * Before making any direction modifications, do a check if gpio
@ -345,7 +349,7 @@ static int byt_gpio_direction_output(struct gpio_chip *chip,
else else
writel(reg_val & ~BYT_LEVEL, reg); writel(reg_val & ~BYT_LEVEL, reg);
spin_unlock_irqrestore(&vg->lock, flags); raw_spin_unlock_irqrestore(&vg->lock, flags);
return 0; return 0;
} }
@ -354,18 +358,19 @@ static void byt_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
{ {
struct byt_gpio *vg = to_byt_gpio(chip); struct byt_gpio *vg = to_byt_gpio(chip);
int i; int i;
unsigned long flags;
u32 conf0, val, offs; u32 conf0, val, offs;
spin_lock_irqsave(&vg->lock, flags);
for (i = 0; i < vg->chip.ngpio; i++) { for (i = 0; i < vg->chip.ngpio; i++) {
const char *pull_str = NULL; const char *pull_str = NULL;
const char *pull = NULL; const char *pull = NULL;
unsigned long flags;
const char *label; const char *label;
offs = vg->range->pins[i] * 16; offs = vg->range->pins[i] * 16;
raw_spin_lock_irqsave(&vg->lock, flags);
conf0 = readl(vg->reg_base + offs + BYT_CONF0_REG); conf0 = readl(vg->reg_base + offs + BYT_CONF0_REG);
val = readl(vg->reg_base + offs + BYT_VAL_REG); val = readl(vg->reg_base + offs + BYT_VAL_REG);
raw_spin_unlock_irqrestore(&vg->lock, flags);
label = gpiochip_is_requested(chip, i); label = gpiochip_is_requested(chip, i);
if (!label) if (!label)
@ -418,7 +423,6 @@ static void byt_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
seq_puts(s, "\n"); seq_puts(s, "\n");
} }
spin_unlock_irqrestore(&vg->lock, flags);
} }
static void byt_gpio_irq_handler(unsigned irq, struct irq_desc *desc) static void byt_gpio_irq_handler(unsigned irq, struct irq_desc *desc)
@ -450,8 +454,10 @@ static void byt_irq_ack(struct irq_data *d)
unsigned offset = irqd_to_hwirq(d); unsigned offset = irqd_to_hwirq(d);
void __iomem *reg; void __iomem *reg;
raw_spin_lock(&vg->lock);
reg = byt_gpio_reg(&vg->chip, offset, BYT_INT_STAT_REG); reg = byt_gpio_reg(&vg->chip, offset, BYT_INT_STAT_REG);
writel(BIT(offset % 32), reg); writel(BIT(offset % 32), reg);
raw_spin_unlock(&vg->lock);
} }
static void byt_irq_unmask(struct irq_data *d) static void byt_irq_unmask(struct irq_data *d)
@ -463,9 +469,9 @@ static void byt_irq_unmask(struct irq_data *d)
void __iomem *reg; void __iomem *reg;
u32 value; u32 value;
spin_lock_irqsave(&vg->lock, flags);
reg = byt_gpio_reg(&vg->chip, offset, BYT_CONF0_REG); reg = byt_gpio_reg(&vg->chip, offset, BYT_CONF0_REG);
raw_spin_lock_irqsave(&vg->lock, flags);
value = readl(reg); value = readl(reg);
switch (irqd_get_trigger_type(d)) { switch (irqd_get_trigger_type(d)) {
@ -486,7 +492,7 @@ static void byt_irq_unmask(struct irq_data *d)
writel(value, reg); writel(value, reg);
spin_unlock_irqrestore(&vg->lock, flags); raw_spin_unlock_irqrestore(&vg->lock, flags);
} }
static void byt_irq_mask(struct irq_data *d) static void byt_irq_mask(struct irq_data *d)
@ -578,7 +584,7 @@ static int byt_gpio_probe(struct platform_device *pdev)
if (IS_ERR(vg->reg_base)) if (IS_ERR(vg->reg_base))
return PTR_ERR(vg->reg_base); return PTR_ERR(vg->reg_base);
spin_lock_init(&vg->lock); raw_spin_lock_init(&vg->lock);
gc = &vg->chip; gc = &vg->chip;
gc->label = dev_name(&pdev->dev); gc->label = dev_name(&pdev->dev);

View File

@ -174,7 +174,7 @@ struct chv_pinctrl {
struct pinctrl_dev *pctldev; struct pinctrl_dev *pctldev;
struct gpio_chip chip; struct gpio_chip chip;
void __iomem *regs; void __iomem *regs;
spinlock_t lock; raw_spinlock_t lock;
unsigned intr_lines[16]; unsigned intr_lines[16];
const struct chv_community *community; const struct chv_community *community;
u32 saved_intmask; u32 saved_intmask;
@ -720,13 +720,13 @@ static void chv_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
u32 ctrl0, ctrl1; u32 ctrl0, ctrl1;
bool locked; bool locked;
spin_lock_irqsave(&pctrl->lock, flags); raw_spin_lock_irqsave(&pctrl->lock, flags);
ctrl0 = readl(chv_padreg(pctrl, offset, CHV_PADCTRL0)); ctrl0 = readl(chv_padreg(pctrl, offset, CHV_PADCTRL0));
ctrl1 = readl(chv_padreg(pctrl, offset, CHV_PADCTRL1)); ctrl1 = readl(chv_padreg(pctrl, offset, CHV_PADCTRL1));
locked = chv_pad_locked(pctrl, offset); locked = chv_pad_locked(pctrl, offset);
spin_unlock_irqrestore(&pctrl->lock, flags); raw_spin_unlock_irqrestore(&pctrl->lock, flags);
if (ctrl0 & CHV_PADCTRL0_GPIOEN) { if (ctrl0 & CHV_PADCTRL0_GPIOEN) {
seq_puts(s, "GPIO "); seq_puts(s, "GPIO ");
@ -789,14 +789,14 @@ static int chv_pinmux_set_mux(struct pinctrl_dev *pctldev, unsigned function,
grp = &pctrl->community->groups[group]; grp = &pctrl->community->groups[group];
spin_lock_irqsave(&pctrl->lock, flags); raw_spin_lock_irqsave(&pctrl->lock, flags);
/* Check first that the pad is not locked */ /* Check first that the pad is not locked */
for (i = 0; i < grp->npins; i++) { for (i = 0; i < grp->npins; i++) {
if (chv_pad_locked(pctrl, grp->pins[i])) { if (chv_pad_locked(pctrl, grp->pins[i])) {
dev_warn(pctrl->dev, "unable to set mode for locked pin %u\n", dev_warn(pctrl->dev, "unable to set mode for locked pin %u\n",
grp->pins[i]); grp->pins[i]);
spin_unlock_irqrestore(&pctrl->lock, flags); raw_spin_unlock_irqrestore(&pctrl->lock, flags);
return -EBUSY; return -EBUSY;
} }
} }
@ -839,7 +839,7 @@ static int chv_pinmux_set_mux(struct pinctrl_dev *pctldev, unsigned function,
pin, altfunc->mode, altfunc->invert_oe ? "" : "not "); pin, altfunc->mode, altfunc->invert_oe ? "" : "not ");
} }
spin_unlock_irqrestore(&pctrl->lock, flags); raw_spin_unlock_irqrestore(&pctrl->lock, flags);
return 0; return 0;
} }
@ -853,13 +853,13 @@ static int chv_gpio_request_enable(struct pinctrl_dev *pctldev,
void __iomem *reg; void __iomem *reg;
u32 value; u32 value;
spin_lock_irqsave(&pctrl->lock, flags); raw_spin_lock_irqsave(&pctrl->lock, flags);
if (chv_pad_locked(pctrl, offset)) { if (chv_pad_locked(pctrl, offset)) {
value = readl(chv_padreg(pctrl, offset, CHV_PADCTRL0)); value = readl(chv_padreg(pctrl, offset, CHV_PADCTRL0));
if (!(value & CHV_PADCTRL0_GPIOEN)) { if (!(value & CHV_PADCTRL0_GPIOEN)) {
/* Locked so cannot enable */ /* Locked so cannot enable */
spin_unlock_irqrestore(&pctrl->lock, flags); raw_spin_unlock_irqrestore(&pctrl->lock, flags);
return -EBUSY; return -EBUSY;
} }
} else { } else {
@ -899,7 +899,7 @@ static int chv_gpio_request_enable(struct pinctrl_dev *pctldev,
chv_writel(value, reg); chv_writel(value, reg);
} }
spin_unlock_irqrestore(&pctrl->lock, flags); raw_spin_unlock_irqrestore(&pctrl->lock, flags);
return 0; return 0;
} }
@ -913,13 +913,13 @@ static void chv_gpio_disable_free(struct pinctrl_dev *pctldev,
void __iomem *reg; void __iomem *reg;
u32 value; u32 value;
spin_lock_irqsave(&pctrl->lock, flags); raw_spin_lock_irqsave(&pctrl->lock, flags);
reg = chv_padreg(pctrl, offset, CHV_PADCTRL0); reg = chv_padreg(pctrl, offset, CHV_PADCTRL0);
value = readl(reg) & ~CHV_PADCTRL0_GPIOEN; value = readl(reg) & ~CHV_PADCTRL0_GPIOEN;
chv_writel(value, reg); chv_writel(value, reg);
spin_unlock_irqrestore(&pctrl->lock, flags); raw_spin_unlock_irqrestore(&pctrl->lock, flags);
} }
static int chv_gpio_set_direction(struct pinctrl_dev *pctldev, static int chv_gpio_set_direction(struct pinctrl_dev *pctldev,
@ -931,7 +931,7 @@ static int chv_gpio_set_direction(struct pinctrl_dev *pctldev,
unsigned long flags; unsigned long flags;
u32 ctrl0; u32 ctrl0;
spin_lock_irqsave(&pctrl->lock, flags); raw_spin_lock_irqsave(&pctrl->lock, flags);
ctrl0 = readl(reg) & ~CHV_PADCTRL0_GPIOCFG_MASK; ctrl0 = readl(reg) & ~CHV_PADCTRL0_GPIOCFG_MASK;
if (input) if (input)
@ -940,7 +940,7 @@ static int chv_gpio_set_direction(struct pinctrl_dev *pctldev,
ctrl0 |= CHV_PADCTRL0_GPIOCFG_GPO << CHV_PADCTRL0_GPIOCFG_SHIFT; ctrl0 |= CHV_PADCTRL0_GPIOCFG_GPO << CHV_PADCTRL0_GPIOCFG_SHIFT;
chv_writel(ctrl0, reg); chv_writel(ctrl0, reg);
spin_unlock_irqrestore(&pctrl->lock, flags); raw_spin_unlock_irqrestore(&pctrl->lock, flags);
return 0; return 0;
} }
@ -965,10 +965,10 @@ static int chv_config_get(struct pinctrl_dev *pctldev, unsigned pin,
u16 arg = 0; u16 arg = 0;
u32 term; u32 term;
spin_lock_irqsave(&pctrl->lock, flags); raw_spin_lock_irqsave(&pctrl->lock, flags);
ctrl0 = readl(chv_padreg(pctrl, pin, CHV_PADCTRL0)); ctrl0 = readl(chv_padreg(pctrl, pin, CHV_PADCTRL0));
ctrl1 = readl(chv_padreg(pctrl, pin, CHV_PADCTRL1)); ctrl1 = readl(chv_padreg(pctrl, pin, CHV_PADCTRL1));
spin_unlock_irqrestore(&pctrl->lock, flags); raw_spin_unlock_irqrestore(&pctrl->lock, flags);
term = (ctrl0 & CHV_PADCTRL0_TERM_MASK) >> CHV_PADCTRL0_TERM_SHIFT; term = (ctrl0 & CHV_PADCTRL0_TERM_MASK) >> CHV_PADCTRL0_TERM_SHIFT;
@ -1042,7 +1042,7 @@ static int chv_config_set_pull(struct chv_pinctrl *pctrl, unsigned pin,
unsigned long flags; unsigned long flags;
u32 ctrl0, pull; u32 ctrl0, pull;
spin_lock_irqsave(&pctrl->lock, flags); raw_spin_lock_irqsave(&pctrl->lock, flags);
ctrl0 = readl(reg); ctrl0 = readl(reg);
switch (param) { switch (param) {
@ -1065,7 +1065,7 @@ static int chv_config_set_pull(struct chv_pinctrl *pctrl, unsigned pin,
pull = CHV_PADCTRL0_TERM_20K << CHV_PADCTRL0_TERM_SHIFT; pull = CHV_PADCTRL0_TERM_20K << CHV_PADCTRL0_TERM_SHIFT;
break; break;
default: default:
spin_unlock_irqrestore(&pctrl->lock, flags); raw_spin_unlock_irqrestore(&pctrl->lock, flags);
return -EINVAL; return -EINVAL;
} }
@ -1083,7 +1083,7 @@ static int chv_config_set_pull(struct chv_pinctrl *pctrl, unsigned pin,
pull = CHV_PADCTRL0_TERM_20K << CHV_PADCTRL0_TERM_SHIFT; pull = CHV_PADCTRL0_TERM_20K << CHV_PADCTRL0_TERM_SHIFT;
break; break;
default: default:
spin_unlock_irqrestore(&pctrl->lock, flags); raw_spin_unlock_irqrestore(&pctrl->lock, flags);
return -EINVAL; return -EINVAL;
} }
@ -1091,12 +1091,12 @@ static int chv_config_set_pull(struct chv_pinctrl *pctrl, unsigned pin,
break; break;
default: default:
spin_unlock_irqrestore(&pctrl->lock, flags); raw_spin_unlock_irqrestore(&pctrl->lock, flags);
return -EINVAL; return -EINVAL;
} }
chv_writel(ctrl0, reg); chv_writel(ctrl0, reg);
spin_unlock_irqrestore(&pctrl->lock, flags); raw_spin_unlock_irqrestore(&pctrl->lock, flags);
return 0; return 0;
} }
@ -1169,9 +1169,12 @@ static int chv_gpio_get(struct gpio_chip *chip, unsigned offset)
{ {
struct chv_pinctrl *pctrl = gpiochip_to_pinctrl(chip); struct chv_pinctrl *pctrl = gpiochip_to_pinctrl(chip);
int pin = chv_gpio_offset_to_pin(pctrl, offset); int pin = chv_gpio_offset_to_pin(pctrl, offset);
unsigned long flags;
u32 ctrl0, cfg; u32 ctrl0, cfg;
raw_spin_lock_irqsave(&pctrl->lock, flags);
ctrl0 = readl(chv_padreg(pctrl, pin, CHV_PADCTRL0)); ctrl0 = readl(chv_padreg(pctrl, pin, CHV_PADCTRL0));
raw_spin_unlock_irqrestore(&pctrl->lock, flags);
cfg = ctrl0 & CHV_PADCTRL0_GPIOCFG_MASK; cfg = ctrl0 & CHV_PADCTRL0_GPIOCFG_MASK;
cfg >>= CHV_PADCTRL0_GPIOCFG_SHIFT; cfg >>= CHV_PADCTRL0_GPIOCFG_SHIFT;
@ -1189,7 +1192,7 @@ static void chv_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
void __iomem *reg; void __iomem *reg;
u32 ctrl0; u32 ctrl0;
spin_lock_irqsave(&pctrl->lock, flags); raw_spin_lock_irqsave(&pctrl->lock, flags);
reg = chv_padreg(pctrl, pin, CHV_PADCTRL0); reg = chv_padreg(pctrl, pin, CHV_PADCTRL0);
ctrl0 = readl(reg); ctrl0 = readl(reg);
@ -1201,7 +1204,7 @@ static void chv_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
chv_writel(ctrl0, reg); chv_writel(ctrl0, reg);
spin_unlock_irqrestore(&pctrl->lock, flags); raw_spin_unlock_irqrestore(&pctrl->lock, flags);
} }
static int chv_gpio_get_direction(struct gpio_chip *chip, unsigned offset) static int chv_gpio_get_direction(struct gpio_chip *chip, unsigned offset)
@ -1209,8 +1212,11 @@ static int chv_gpio_get_direction(struct gpio_chip *chip, unsigned offset)
struct chv_pinctrl *pctrl = gpiochip_to_pinctrl(chip); struct chv_pinctrl *pctrl = gpiochip_to_pinctrl(chip);
unsigned pin = chv_gpio_offset_to_pin(pctrl, offset); unsigned pin = chv_gpio_offset_to_pin(pctrl, offset);
u32 ctrl0, direction; u32 ctrl0, direction;
unsigned long flags;
raw_spin_lock_irqsave(&pctrl->lock, flags);
ctrl0 = readl(chv_padreg(pctrl, pin, CHV_PADCTRL0)); ctrl0 = readl(chv_padreg(pctrl, pin, CHV_PADCTRL0));
raw_spin_unlock_irqrestore(&pctrl->lock, flags);
direction = ctrl0 & CHV_PADCTRL0_GPIOCFG_MASK; direction = ctrl0 & CHV_PADCTRL0_GPIOCFG_MASK;
direction >>= CHV_PADCTRL0_GPIOCFG_SHIFT; direction >>= CHV_PADCTRL0_GPIOCFG_SHIFT;
@ -1248,14 +1254,14 @@ static void chv_gpio_irq_ack(struct irq_data *d)
int pin = chv_gpio_offset_to_pin(pctrl, irqd_to_hwirq(d)); int pin = chv_gpio_offset_to_pin(pctrl, irqd_to_hwirq(d));
u32 intr_line; u32 intr_line;
spin_lock(&pctrl->lock); raw_spin_lock(&pctrl->lock);
intr_line = readl(chv_padreg(pctrl, pin, CHV_PADCTRL0)); intr_line = readl(chv_padreg(pctrl, pin, CHV_PADCTRL0));
intr_line &= CHV_PADCTRL0_INTSEL_MASK; intr_line &= CHV_PADCTRL0_INTSEL_MASK;
intr_line >>= CHV_PADCTRL0_INTSEL_SHIFT; intr_line >>= CHV_PADCTRL0_INTSEL_SHIFT;
chv_writel(BIT(intr_line), pctrl->regs + CHV_INTSTAT); chv_writel(BIT(intr_line), pctrl->regs + CHV_INTSTAT);
spin_unlock(&pctrl->lock); raw_spin_unlock(&pctrl->lock);
} }
static void chv_gpio_irq_mask_unmask(struct irq_data *d, bool mask) static void chv_gpio_irq_mask_unmask(struct irq_data *d, bool mask)
@ -1266,7 +1272,7 @@ static void chv_gpio_irq_mask_unmask(struct irq_data *d, bool mask)
u32 value, intr_line; u32 value, intr_line;
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&pctrl->lock, flags); raw_spin_lock_irqsave(&pctrl->lock, flags);
intr_line = readl(chv_padreg(pctrl, pin, CHV_PADCTRL0)); intr_line = readl(chv_padreg(pctrl, pin, CHV_PADCTRL0));
intr_line &= CHV_PADCTRL0_INTSEL_MASK; intr_line &= CHV_PADCTRL0_INTSEL_MASK;
@ -1279,7 +1285,7 @@ static void chv_gpio_irq_mask_unmask(struct irq_data *d, bool mask)
value |= BIT(intr_line); value |= BIT(intr_line);
chv_writel(value, pctrl->regs + CHV_INTMASK); chv_writel(value, pctrl->regs + CHV_INTMASK);
spin_unlock_irqrestore(&pctrl->lock, flags); raw_spin_unlock_irqrestore(&pctrl->lock, flags);
} }
static void chv_gpio_irq_mask(struct irq_data *d) static void chv_gpio_irq_mask(struct irq_data *d)
@ -1313,6 +1319,7 @@ static unsigned chv_gpio_irq_startup(struct irq_data *d)
unsigned long flags; unsigned long flags;
u32 intsel, value; u32 intsel, value;
raw_spin_lock_irqsave(&pctrl->lock, flags);
intsel = readl(chv_padreg(pctrl, pin, CHV_PADCTRL0)); intsel = readl(chv_padreg(pctrl, pin, CHV_PADCTRL0));
intsel &= CHV_PADCTRL0_INTSEL_MASK; intsel &= CHV_PADCTRL0_INTSEL_MASK;
intsel >>= CHV_PADCTRL0_INTSEL_SHIFT; intsel >>= CHV_PADCTRL0_INTSEL_SHIFT;
@ -1323,12 +1330,11 @@ static unsigned chv_gpio_irq_startup(struct irq_data *d)
else else
handler = handle_edge_irq; handler = handle_edge_irq;
spin_lock_irqsave(&pctrl->lock, flags);
if (!pctrl->intr_lines[intsel]) { if (!pctrl->intr_lines[intsel]) {
__irq_set_handler_locked(d->irq, handler); irq_set_handler_locked(d, handler);
pctrl->intr_lines[intsel] = offset; pctrl->intr_lines[intsel] = offset;
} }
spin_unlock_irqrestore(&pctrl->lock, flags); raw_spin_unlock_irqrestore(&pctrl->lock, flags);
} }
chv_gpio_irq_unmask(d); chv_gpio_irq_unmask(d);
@ -1344,7 +1350,7 @@ static int chv_gpio_irq_type(struct irq_data *d, unsigned type)
unsigned long flags; unsigned long flags;
u32 value; u32 value;
spin_lock_irqsave(&pctrl->lock, flags); raw_spin_lock_irqsave(&pctrl->lock, flags);
/* /*
* Pins which can be used as shared interrupt are configured in * Pins which can be used as shared interrupt are configured in
@ -1389,11 +1395,11 @@ static int chv_gpio_irq_type(struct irq_data *d, unsigned type)
pctrl->intr_lines[value] = offset; pctrl->intr_lines[value] = offset;
if (type & IRQ_TYPE_EDGE_BOTH) if (type & IRQ_TYPE_EDGE_BOTH)
__irq_set_handler_locked(d->irq, handle_edge_irq); irq_set_handler_locked(d, handle_edge_irq);
else if (type & IRQ_TYPE_LEVEL_MASK) else if (type & IRQ_TYPE_LEVEL_MASK)
__irq_set_handler_locked(d->irq, handle_level_irq); irq_set_handler_locked(d, handle_level_irq);
spin_unlock_irqrestore(&pctrl->lock, flags); raw_spin_unlock_irqrestore(&pctrl->lock, flags);
return 0; return 0;
} }
@ -1412,7 +1418,7 @@ static void chv_gpio_irq_handler(unsigned irq, struct irq_desc *desc)
{ {
struct gpio_chip *gc = irq_desc_get_handler_data(desc); struct gpio_chip *gc = irq_desc_get_handler_data(desc);
struct chv_pinctrl *pctrl = gpiochip_to_pinctrl(gc); struct chv_pinctrl *pctrl = gpiochip_to_pinctrl(gc);
struct irq_chip *chip = irq_get_chip(irq); struct irq_chip *chip = irq_desc_get_chip(desc);
unsigned long pending; unsigned long pending;
u32 intr_line; u32 intr_line;
@ -1505,7 +1511,7 @@ static int chv_pinctrl_probe(struct platform_device *pdev)
if (i == ARRAY_SIZE(chv_communities)) if (i == ARRAY_SIZE(chv_communities))
return -ENODEV; return -ENODEV;
spin_lock_init(&pctrl->lock); raw_spin_lock_init(&pctrl->lock);
pctrl->dev = &pdev->dev; pctrl->dev = &pdev->dev;
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP

View File

@ -758,9 +758,9 @@ static int intel_gpio_irq_type(struct irq_data *d, unsigned type)
writel(value, reg); writel(value, reg);
if (type & IRQ_TYPE_EDGE_BOTH) if (type & IRQ_TYPE_EDGE_BOTH)
__irq_set_handler_locked(d->irq, handle_edge_irq); irq_set_handler_locked(d, handle_edge_irq);
else if (type & IRQ_TYPE_LEVEL_MASK) else if (type & IRQ_TYPE_LEVEL_MASK)
__irq_set_handler_locked(d->irq, handle_level_irq); irq_set_handler_locked(d, handle_level_irq);
spin_unlock_irqrestore(&pctrl->lock, flags); spin_unlock_irqrestore(&pctrl->lock, flags);
@ -840,7 +840,7 @@ static void intel_gpio_irq_handler(unsigned irq, struct irq_desc *desc)
{ {
struct gpio_chip *gc = irq_desc_get_handler_data(desc); struct gpio_chip *gc = irq_desc_get_handler_data(desc);
struct intel_pinctrl *pctrl = gpiochip_to_pinctrl(gc); struct intel_pinctrl *pctrl = gpiochip_to_pinctrl(gc);
struct irq_chip *chip = irq_get_chip(irq); struct irq_chip *chip = irq_desc_get_chip(desc);
int i; int i;
chained_irq_enter(chip, desc); chained_irq_enter(chip, desc);

View File

@ -385,6 +385,7 @@ static struct platform_driver mtk_pinctrl_driver = {
.driver = { .driver = {
.name = "mediatek-mt8173-pinctrl", .name = "mediatek-mt8173-pinctrl",
.of_match_table = mt8173_pctrl_match, .of_match_table = mt8173_pctrl_match,
.pm = &mtk_eint_pm_ops,
}, },
}; };

View File

@ -33,6 +33,7 @@
#include <linux/mfd/syscon.h> #include <linux/mfd/syscon.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/pm.h>
#include <dt-bindings/pinctrl/mt65xx.h> #include <dt-bindings/pinctrl/mt65xx.h>
#include "../core.h" #include "../core.h"
@ -702,7 +703,7 @@ static int mtk_pmx_set_mux(struct pinctrl_dev *pctldev,
ret = mtk_pctrl_is_function_valid(pctl, g->pin, function); ret = mtk_pctrl_is_function_valid(pctl, g->pin, function);
if (!ret) { if (!ret) {
dev_err(pctl->dev, "invaild function %d on group %d .\n", dev_err(pctl->dev, "invalid function %d on group %d .\n",
function, group); function, group);
return -EINVAL; return -EINVAL;
} }
@ -1062,6 +1063,77 @@ static int mtk_eint_set_type(struct irq_data *d,
return 0; return 0;
} }
static int mtk_eint_irq_set_wake(struct irq_data *d, unsigned int on)
{
struct mtk_pinctrl *pctl = irq_data_get_irq_chip_data(d);
int shift = d->hwirq & 0x1f;
int reg = d->hwirq >> 5;
if (on)
pctl->wake_mask[reg] |= BIT(shift);
else
pctl->wake_mask[reg] &= ~BIT(shift);
return 0;
}
static void mtk_eint_chip_write_mask(const struct mtk_eint_offsets *chip,
void __iomem *eint_reg_base, u32 *buf)
{
int port;
void __iomem *reg;
for (port = 0; port < chip->ports; port++) {
reg = eint_reg_base + (port << 2);
writel_relaxed(~buf[port], reg + chip->mask_set);
writel_relaxed(buf[port], reg + chip->mask_clr);
}
}
static void mtk_eint_chip_read_mask(const struct mtk_eint_offsets *chip,
void __iomem *eint_reg_base, u32 *buf)
{
int port;
void __iomem *reg;
for (port = 0; port < chip->ports; port++) {
reg = eint_reg_base + chip->mask + (port << 2);
buf[port] = ~readl_relaxed(reg);
/* Mask is 0 when irq is enabled, and 1 when disabled. */
}
}
static int mtk_eint_suspend(struct device *device)
{
void __iomem *reg;
struct mtk_pinctrl *pctl = dev_get_drvdata(device);
const struct mtk_eint_offsets *eint_offsets =
&pctl->devdata->eint_offsets;
reg = pctl->eint_reg_base;
mtk_eint_chip_read_mask(eint_offsets, reg, pctl->cur_mask);
mtk_eint_chip_write_mask(eint_offsets, reg, pctl->wake_mask);
return 0;
}
static int mtk_eint_resume(struct device *device)
{
struct mtk_pinctrl *pctl = dev_get_drvdata(device);
const struct mtk_eint_offsets *eint_offsets =
&pctl->devdata->eint_offsets;
mtk_eint_chip_write_mask(eint_offsets,
pctl->eint_reg_base, pctl->cur_mask);
return 0;
}
const struct dev_pm_ops mtk_eint_pm_ops = {
.suspend = mtk_eint_suspend,
.resume = mtk_eint_resume,
};
static void mtk_eint_ack(struct irq_data *d) static void mtk_eint_ack(struct irq_data *d)
{ {
struct mtk_pinctrl *pctl = irq_data_get_irq_chip_data(d); struct mtk_pinctrl *pctl = irq_data_get_irq_chip_data(d);
@ -1076,10 +1148,12 @@ static void mtk_eint_ack(struct irq_data *d)
static struct irq_chip mtk_pinctrl_irq_chip = { static struct irq_chip mtk_pinctrl_irq_chip = {
.name = "mt-eint", .name = "mt-eint",
.irq_disable = mtk_eint_mask,
.irq_mask = mtk_eint_mask, .irq_mask = mtk_eint_mask,
.irq_unmask = mtk_eint_unmask, .irq_unmask = mtk_eint_unmask,
.irq_ack = mtk_eint_ack, .irq_ack = mtk_eint_ack,
.irq_set_type = mtk_eint_set_type, .irq_set_type = mtk_eint_set_type,
.irq_set_wake = mtk_eint_irq_set_wake,
.irq_request_resources = mtk_pinctrl_irq_request_resources, .irq_request_resources = mtk_pinctrl_irq_request_resources,
.irq_release_resources = mtk_pinctrl_irq_release_resources, .irq_release_resources = mtk_pinctrl_irq_release_resources,
}; };
@ -1118,8 +1192,8 @@ mtk_eint_debounce_process(struct mtk_pinctrl *pctl, int index)
static void mtk_eint_irq_handler(unsigned irq, struct irq_desc *desc) static void mtk_eint_irq_handler(unsigned irq, struct irq_desc *desc)
{ {
struct irq_chip *chip = irq_get_chip(irq); struct irq_chip *chip = irq_desc_get_chip(desc);
struct mtk_pinctrl *pctl = irq_get_handler_data(irq); struct mtk_pinctrl *pctl = irq_desc_get_handler_data(desc);
unsigned int status, eint_num; unsigned int status, eint_num;
int offset, index, virq; int offset, index, virq;
const struct mtk_eint_offsets *eint_offsets = const struct mtk_eint_offsets *eint_offsets =
@ -1202,12 +1276,6 @@ static int mtk_pctrl_build_state(struct platform_device *pdev)
return 0; return 0;
} }
static struct pinctrl_desc mtk_pctrl_desc = {
.confops = &mtk_pconf_ops,
.pctlops = &mtk_pctrl_ops,
.pmxops = &mtk_pmx_ops,
};
int mtk_pctrl_init(struct platform_device *pdev, int mtk_pctrl_init(struct platform_device *pdev,
const struct mtk_pinctrl_devdata *data, const struct mtk_pinctrl_devdata *data,
struct regmap *regmap) struct regmap *regmap)
@ -1217,7 +1285,7 @@ int mtk_pctrl_init(struct platform_device *pdev,
struct device_node *np = pdev->dev.of_node, *node; struct device_node *np = pdev->dev.of_node, *node;
struct property *prop; struct property *prop;
struct resource *res; struct resource *res;
int i, ret, irq; int i, ret, irq, ports_buf;
pctl = devm_kzalloc(&pdev->dev, sizeof(*pctl), GFP_KERNEL); pctl = devm_kzalloc(&pdev->dev, sizeof(*pctl), GFP_KERNEL);
if (!pctl) if (!pctl)
@ -1265,12 +1333,17 @@ int mtk_pctrl_init(struct platform_device *pdev,
for (i = 0; i < pctl->devdata->npins; i++) for (i = 0; i < pctl->devdata->npins; i++)
pins[i] = pctl->devdata->pins[i].pin; pins[i] = pctl->devdata->pins[i].pin;
mtk_pctrl_desc.name = dev_name(&pdev->dev);
mtk_pctrl_desc.owner = THIS_MODULE; pctl->pctl_desc.name = dev_name(&pdev->dev);
mtk_pctrl_desc.pins = pins; pctl->pctl_desc.owner = THIS_MODULE;
mtk_pctrl_desc.npins = pctl->devdata->npins; pctl->pctl_desc.pins = pins;
pctl->pctl_desc.npins = pctl->devdata->npins;
pctl->pctl_desc.confops = &mtk_pconf_ops;
pctl->pctl_desc.pctlops = &mtk_pctrl_ops;
pctl->pctl_desc.pmxops = &mtk_pmx_ops;
pctl->dev = &pdev->dev; pctl->dev = &pdev->dev;
pctl->pctl_dev = pinctrl_register(&mtk_pctrl_desc, &pdev->dev, pctl);
pctl->pctl_dev = pinctrl_register(&pctl->pctl_desc, &pdev->dev, pctl);
if (IS_ERR(pctl->pctl_dev)) { if (IS_ERR(pctl->pctl_dev)) {
dev_err(&pdev->dev, "couldn't register pinctrl driver\n"); dev_err(&pdev->dev, "couldn't register pinctrl driver\n");
return PTR_ERR(pctl->pctl_dev); return PTR_ERR(pctl->pctl_dev);
@ -1319,6 +1392,21 @@ int mtk_pctrl_init(struct platform_device *pdev,
goto chip_error; goto chip_error;
} }
ports_buf = pctl->devdata->eint_offsets.ports;
pctl->wake_mask = devm_kcalloc(&pdev->dev, ports_buf,
sizeof(*pctl->wake_mask), GFP_KERNEL);
if (!pctl->wake_mask) {
ret = -ENOMEM;
goto chip_error;
}
pctl->cur_mask = devm_kcalloc(&pdev->dev, ports_buf,
sizeof(*pctl->cur_mask), GFP_KERNEL);
if (!pctl->cur_mask) {
ret = -ENOMEM;
goto chip_error;
}
pctl->eint_dual_edges = devm_kcalloc(&pdev->dev, pctl->devdata->ap_num, pctl->eint_dual_edges = devm_kcalloc(&pdev->dev, pctl->devdata->ap_num,
sizeof(int), GFP_KERNEL); sizeof(int), GFP_KERNEL);
if (!pctl->eint_dual_edges) { if (!pctl->eint_dual_edges) {
@ -1348,11 +1436,9 @@ int mtk_pctrl_init(struct platform_device *pdev,
irq_set_chip_and_handler(virq, &mtk_pinctrl_irq_chip, irq_set_chip_and_handler(virq, &mtk_pinctrl_irq_chip,
handle_level_irq); handle_level_irq);
irq_set_chip_data(virq, pctl); irq_set_chip_data(virq, pctl);
set_irq_flags(virq, IRQF_VALID);
}; };
irq_set_chained_handler_and_data(irq, mtk_eint_irq_handler, pctl); irq_set_chained_handler_and_data(irq, mtk_eint_irq_handler, pctl);
set_irq_flags(irq, IRQF_VALID);
return 0; return 0;
chip_error: chip_error:

View File

@ -256,6 +256,7 @@ struct mtk_pinctrl_devdata {
struct mtk_pinctrl { struct mtk_pinctrl {
struct regmap *regmap1; struct regmap *regmap1;
struct regmap *regmap2; struct regmap *regmap2;
struct pinctrl_desc pctl_desc;
struct device *dev; struct device *dev;
struct gpio_chip *chip; struct gpio_chip *chip;
struct mtk_pinctrl_group *groups; struct mtk_pinctrl_group *groups;
@ -266,6 +267,8 @@ struct mtk_pinctrl {
void __iomem *eint_reg_base; void __iomem *eint_reg_base;
struct irq_domain *domain; struct irq_domain *domain;
int *eint_dual_edges; int *eint_dual_edges;
u32 *wake_mask;
u32 *cur_mask;
}; };
int mtk_pctrl_init(struct platform_device *pdev, int mtk_pctrl_init(struct platform_device *pdev,
@ -281,4 +284,6 @@ int mtk_pconf_spec_set_ies_smt_range(struct regmap *regmap,
const struct mtk_pin_ies_smt_set *ies_smt_infos, unsigned int info_num, const struct mtk_pin_ies_smt_set *ies_smt_infos, unsigned int info_num,
unsigned int pin, unsigned char align, int value); unsigned int pin, unsigned char align, int value);
extern const struct dev_pm_ops mtk_eint_pm_ops;
#endif /* __PINCTRL_MTK_COMMON_H */ #endif /* __PINCTRL_MTK_COMMON_H */

View File

@ -355,25 +355,6 @@ static const struct pinctrl_pin_desc nmk_db8500_pins[] = {
PINCTRL_PIN(DB8500_PIN_AC27, "GPIO267_AC27"), PINCTRL_PIN(DB8500_PIN_AC27, "GPIO267_AC27"),
}; };
#define DB8500_GPIO_RANGE(a, b, c) { .name = "DB8500", .id = a, .base = b, \
.pin_base = b, .npins = c }
/*
* This matches the 32-pin gpio chips registered by the GPIO portion. This
* cannot be const since we assign the struct gpio_chip * pointer at runtime.
*/
static struct pinctrl_gpio_range nmk_db8500_ranges[] = {
DB8500_GPIO_RANGE(0, 0, 32),
DB8500_GPIO_RANGE(1, 32, 5),
DB8500_GPIO_RANGE(2, 64, 32),
DB8500_GPIO_RANGE(3, 96, 2),
DB8500_GPIO_RANGE(4, 128, 32),
DB8500_GPIO_RANGE(5, 160, 12),
DB8500_GPIO_RANGE(6, 192, 32),
DB8500_GPIO_RANGE(7, 224, 7),
DB8500_GPIO_RANGE(8, 256, 12),
};
/* /*
* Read the pin group names like this: * Read the pin group names like this:
* u0_a_1 = first groups of pins for uart0 on alt function a * u0_a_1 = first groups of pins for uart0 on alt function a
@ -1238,8 +1219,6 @@ static const u16 db8500_prcm_gpiocr_regs[] = {
}; };
static const struct nmk_pinctrl_soc_data nmk_db8500_soc = { static const struct nmk_pinctrl_soc_data nmk_db8500_soc = {
.gpio_ranges = nmk_db8500_ranges,
.gpio_num_ranges = ARRAY_SIZE(nmk_db8500_ranges),
.pins = nmk_db8500_pins, .pins = nmk_db8500_pins,
.npins = ARRAY_SIZE(nmk_db8500_pins), .npins = ARRAY_SIZE(nmk_db8500_pins),
.functions = nmk_db8500_functions, .functions = nmk_db8500_functions,

View File

@ -341,28 +341,6 @@ static const struct pinctrl_pin_desc nmk_db8540_pins[] = {
PINCTRL_PIN(DB8540_PIN_D17, "GPIO267_D17"), PINCTRL_PIN(DB8540_PIN_D17, "GPIO267_D17"),
}; };
#define DB8540_GPIO_RANGE(a, b, c) { .name = "db8540", .id = a, .base = b, \
.pin_base = b, .npins = c }
/*
* This matches the 32-pin gpio chips registered by the GPIO portion. This
* cannot be const since we assign the struct gpio_chip * pointer at runtime.
*/
static struct pinctrl_gpio_range nmk_db8540_ranges[] = {
DB8540_GPIO_RANGE(0, 0, 18),
DB8540_GPIO_RANGE(0, 22, 7),
DB8540_GPIO_RANGE(1, 33, 6),
DB8540_GPIO_RANGE(2, 64, 4),
DB8540_GPIO_RANGE(2, 70, 18),
DB8540_GPIO_RANGE(3, 116, 12),
DB8540_GPIO_RANGE(4, 128, 32),
DB8540_GPIO_RANGE(5, 160, 9),
DB8540_GPIO_RANGE(6, 192, 23),
DB8540_GPIO_RANGE(6, 219, 5),
DB8540_GPIO_RANGE(7, 224, 9),
DB8540_GPIO_RANGE(8, 256, 12),
};
/* /*
* Read the pin group names like this: * Read the pin group names like this:
* u0_a_1 = first groups of pins for uart0 on alt function a * u0_a_1 = first groups of pins for uart0 on alt function a
@ -1247,8 +1225,6 @@ static const u16 db8540_prcm_gpiocr_regs[] = {
}; };
static const struct nmk_pinctrl_soc_data nmk_db8540_soc = { static const struct nmk_pinctrl_soc_data nmk_db8540_soc = {
.gpio_ranges = nmk_db8540_ranges,
.gpio_num_ranges = ARRAY_SIZE(nmk_db8540_ranges),
.pins = nmk_db8540_pins, .pins = nmk_db8540_pins,
.npins = ARRAY_SIZE(nmk_db8540_pins), .npins = ARRAY_SIZE(nmk_db8540_pins),
.functions = nmk_db8540_functions, .functions = nmk_db8540_functions,

View File

@ -264,20 +264,6 @@ static const struct pinctrl_pin_desc nmk_stn8815_pins[] = {
PINCTRL_PIN(STN8815_PIN_J22, "GPIO123_J22"), PINCTRL_PIN(STN8815_PIN_J22, "GPIO123_J22"),
}; };
#define STN8815_GPIO_RANGE(a, b, c) { .name = "STN8815", .id = a, .base = b, \
.pin_base = b, .npins = c }
/*
* This matches the 32-pin gpio chips registered by the GPIO portion. This
* cannot be const since we assign the struct gpio_chip * pointer at runtime.
*/
static struct pinctrl_gpio_range nmk_stn8815_ranges[] = {
STN8815_GPIO_RANGE(0, 0, 32),
STN8815_GPIO_RANGE(1, 32, 32),
STN8815_GPIO_RANGE(2, 64, 32),
STN8815_GPIO_RANGE(3, 96, 28),
};
/* /*
* Read the pin group names like this: * Read the pin group names like this:
* u0_a_1 = first groups of pins for uart0 on alt function a * u0_a_1 = first groups of pins for uart0 on alt function a
@ -285,9 +271,11 @@ static struct pinctrl_gpio_range nmk_stn8815_ranges[] = {
*/ */
/* Altfunction A */ /* Altfunction A */
static const unsigned u0_a_1_pins[] = { STN8815_PIN_B4, STN8815_PIN_D5, static const unsigned u0txrx_a_1_pins[] = { STN8815_PIN_B4, STN8815_PIN_D5 };
STN8815_PIN_C5, STN8815_PIN_A4, STN8815_PIN_B5, STN8815_PIN_D6, static const unsigned u0ctsrts_a_1_pins[] = { STN8815_PIN_C5, STN8815_PIN_B6 };
STN8815_PIN_C6, STN8815_PIN_B6 }; /* Modem pins: DCD, DSR, RI, DTR */
static const unsigned u0modem_a_1_pins[] = { STN8815_PIN_A4, STN8815_PIN_B5,
STN8815_PIN_D6, STN8815_PIN_C6 };
static const unsigned mmcsd_a_1_pins[] = { STN8815_PIN_B10, STN8815_PIN_A10, static const unsigned mmcsd_a_1_pins[] = { STN8815_PIN_B10, STN8815_PIN_A10,
STN8815_PIN_C11, STN8815_PIN_B11, STN8815_PIN_A11, STN8815_PIN_C12, STN8815_PIN_C11, STN8815_PIN_B11, STN8815_PIN_A11, STN8815_PIN_C12,
STN8815_PIN_B12, STN8815_PIN_A12, STN8815_PIN_C13, STN8815_PIN_C15 }; STN8815_PIN_B12, STN8815_PIN_A12, STN8815_PIN_C13, STN8815_PIN_C15 };
@ -304,7 +292,9 @@ static const unsigned i2cusb_b_1_pins[] = { STN8815_PIN_C21, STN8815_PIN_C20 };
.npins = ARRAY_SIZE(a##_pins), .altsetting = b } .npins = ARRAY_SIZE(a##_pins), .altsetting = b }
static const struct nmk_pingroup nmk_stn8815_groups[] = { static const struct nmk_pingroup nmk_stn8815_groups[] = {
STN8815_PIN_GROUP(u0_a_1, NMK_GPIO_ALT_A), STN8815_PIN_GROUP(u0txrx_a_1, NMK_GPIO_ALT_A),
STN8815_PIN_GROUP(u0ctsrts_a_1, NMK_GPIO_ALT_A),
STN8815_PIN_GROUP(u0modem_a_1, NMK_GPIO_ALT_A),
STN8815_PIN_GROUP(mmcsd_a_1, NMK_GPIO_ALT_A), STN8815_PIN_GROUP(mmcsd_a_1, NMK_GPIO_ALT_A),
STN8815_PIN_GROUP(mmcsd_b_1, NMK_GPIO_ALT_B), STN8815_PIN_GROUP(mmcsd_b_1, NMK_GPIO_ALT_B),
STN8815_PIN_GROUP(u1_a_1, NMK_GPIO_ALT_A), STN8815_PIN_GROUP(u1_a_1, NMK_GPIO_ALT_A),
@ -318,7 +308,7 @@ static const struct nmk_pingroup nmk_stn8815_groups[] = {
#define STN8815_FUNC_GROUPS(a, b...) \ #define STN8815_FUNC_GROUPS(a, b...) \
static const char * const a##_groups[] = { b }; static const char * const a##_groups[] = { b };
STN8815_FUNC_GROUPS(u0, "u0_a_1"); STN8815_FUNC_GROUPS(u0, "u0txrx_a_1", "u0ctsrts_a_1", "u0modem_a_1");
STN8815_FUNC_GROUPS(mmcsd, "mmcsd_a_1", "mmcsd_b_1"); STN8815_FUNC_GROUPS(mmcsd, "mmcsd_a_1", "mmcsd_b_1");
STN8815_FUNC_GROUPS(u1, "u1_a_1", "u1_b_1"); STN8815_FUNC_GROUPS(u1, "u1_a_1", "u1_b_1");
STN8815_FUNC_GROUPS(i2c1, "i2c1_a_1"); STN8815_FUNC_GROUPS(i2c1, "i2c1_a_1");
@ -342,8 +332,6 @@ static const struct nmk_function nmk_stn8815_functions[] = {
}; };
static const struct nmk_pinctrl_soc_data nmk_stn8815_soc = { static const struct nmk_pinctrl_soc_data nmk_stn8815_soc = {
.gpio_ranges = nmk_stn8815_ranges,
.gpio_num_ranges = ARRAY_SIZE(nmk_stn8815_ranges),
.pins = nmk_stn8815_pins, .pins = nmk_stn8815_pins,
.npins = ARRAY_SIZE(nmk_stn8815_pins), .npins = ARRAY_SIZE(nmk_stn8815_pins),
.functions = nmk_stn8815_functions, .functions = nmk_stn8815_functions,

View File

@ -203,6 +203,7 @@ typedef unsigned long pin_cfg_t;
#define GPIO_BLOCK_SHIFT 5 #define GPIO_BLOCK_SHIFT 5
#define NMK_GPIO_PER_CHIP (1 << GPIO_BLOCK_SHIFT) #define NMK_GPIO_PER_CHIP (1 << GPIO_BLOCK_SHIFT)
#define NMK_MAX_BANKS DIV_ROUND_UP(ARCH_NR_GPIOS, NMK_GPIO_PER_CHIP)
/* Register in the logic block */ /* Register in the logic block */
#define NMK_GPIO_DAT 0x00 #define NMK_GPIO_DAT 0x00
@ -282,8 +283,7 @@ struct nmk_pinctrl {
void __iomem *prcm_base; void __iomem *prcm_base;
}; };
static struct nmk_gpio_chip * static struct nmk_gpio_chip *nmk_gpio_chips[NMK_MAX_BANKS];
nmk_gpio_chips[DIV_ROUND_UP(ARCH_NR_GPIOS, NMK_GPIO_PER_CHIP)];
static DEFINE_SPINLOCK(nmk_gpio_slpm_lock); static DEFINE_SPINLOCK(nmk_gpio_slpm_lock);
@ -843,10 +843,9 @@ static void nmk_gpio_irq_shutdown(struct irq_data *d)
clk_disable(nmk_chip->clk); clk_disable(nmk_chip->clk);
} }
static void __nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc, static void __nmk_gpio_irq_handler(struct irq_desc *desc, u32 status)
u32 status)
{ {
struct irq_chip *host_chip = irq_get_chip(irq); struct irq_chip *host_chip = irq_desc_get_chip(desc);
struct gpio_chip *chip = irq_desc_get_handler_data(desc); struct gpio_chip *chip = irq_desc_get_handler_data(desc);
chained_irq_enter(host_chip, desc); chained_irq_enter(host_chip, desc);
@ -871,17 +870,16 @@ static void nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
status = readl(nmk_chip->addr + NMK_GPIO_IS); status = readl(nmk_chip->addr + NMK_GPIO_IS);
clk_disable(nmk_chip->clk); clk_disable(nmk_chip->clk);
__nmk_gpio_irq_handler(irq, desc, status); __nmk_gpio_irq_handler(desc, status);
} }
static void nmk_gpio_latent_irq_handler(unsigned int irq, static void nmk_gpio_latent_irq_handler(unsigned int irq, struct irq_desc *desc)
struct irq_desc *desc)
{ {
struct gpio_chip *chip = irq_desc_get_handler_data(desc); struct gpio_chip *chip = irq_desc_get_handler_data(desc);
struct nmk_gpio_chip *nmk_chip = container_of(chip, struct nmk_gpio_chip, chip); struct nmk_gpio_chip *nmk_chip = container_of(chip, struct nmk_gpio_chip, chip);
u32 status = nmk_chip->get_latent_status(nmk_chip->bank); u32 status = nmk_chip->get_latent_status(nmk_chip->bank);
__nmk_gpio_irq_handler(irq, desc, status); __nmk_gpio_irq_handler(desc, status);
} }
/* I/O Functions */ /* I/O Functions */
@ -1012,6 +1010,7 @@ static void nmk_gpio_dbg_show_one(struct seq_file *s,
int irq = gpio_to_irq(gpio); int irq = gpio_to_irq(gpio);
struct irq_desc *desc = irq_to_desc(irq); struct irq_desc *desc = irq_to_desc(irq);
int pullidx = 0; int pullidx = 0;
int val;
if (pull) if (pull)
pullidx = data_out ? 1 : 2; pullidx = data_out ? 1 : 2;
@ -1021,6 +1020,10 @@ static void nmk_gpio_dbg_show_one(struct seq_file *s,
label ?: "(none)", label ?: "(none)",
pulls[pullidx], pulls[pullidx],
(mode < 0) ? "unknown" : modes[mode]); (mode < 0) ? "unknown" : modes[mode]);
val = nmk_gpio_get_input(chip, offset);
seq_printf(s, " VAL %d", val);
/* /*
* This races with request_irq(), set_irq_type(), * This races with request_irq(), set_irq_type(),
* and set_irq_wake() ... but those are "rare". * and set_irq_wake() ... but those are "rare".
@ -1162,29 +1165,90 @@ void nmk_gpio_read_pull(int gpio_bank, u32 *pull_up)
} }
} }
/*
* We will allocate memory for the state container using devm* allocators
* binding to the first device reaching this point, it doesn't matter if
* it is the pin controller or GPIO driver. However we need to use the right
* platform device when looking up resources so pay attention to pdev.
*/
static struct nmk_gpio_chip *nmk_gpio_populate_chip(struct device_node *np,
struct platform_device *pdev)
{
struct nmk_gpio_chip *nmk_chip;
struct platform_device *gpio_pdev;
struct gpio_chip *chip;
struct resource *res;
struct clk *clk;
void __iomem *base;
u32 id;
gpio_pdev = of_find_device_by_node(np);
if (!gpio_pdev) {
pr_err("populate \"%s\": device not found\n", np->name);
return ERR_PTR(-ENODEV);
}
if (of_property_read_u32(np, "gpio-bank", &id)) {
dev_err(&pdev->dev, "populate: gpio-bank property not found\n");
return ERR_PTR(-EINVAL);
}
/* Already populated? */
nmk_chip = nmk_gpio_chips[id];
if (nmk_chip)
return nmk_chip;
nmk_chip = devm_kzalloc(&pdev->dev, sizeof(*nmk_chip), GFP_KERNEL);
if (!nmk_chip)
return ERR_PTR(-ENOMEM);
nmk_chip->bank = id;
chip = &nmk_chip->chip;
chip->base = id * NMK_GPIO_PER_CHIP;
chip->ngpio = NMK_GPIO_PER_CHIP;
chip->label = dev_name(&gpio_pdev->dev);
chip->dev = &gpio_pdev->dev;
res = platform_get_resource(gpio_pdev, IORESOURCE_MEM, 0);
base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(base))
return base;
nmk_chip->addr = base;
clk = clk_get(&gpio_pdev->dev, NULL);
if (IS_ERR(clk))
return (void *) clk;
clk_prepare(clk);
nmk_chip->clk = clk;
BUG_ON(nmk_chip->bank >= ARRAY_SIZE(nmk_gpio_chips));
nmk_gpio_chips[id] = nmk_chip;
return nmk_chip;
}
static int nmk_gpio_probe(struct platform_device *dev) static int nmk_gpio_probe(struct platform_device *dev)
{ {
struct device_node *np = dev->dev.of_node; struct device_node *np = dev->dev.of_node;
struct nmk_gpio_chip *nmk_chip; struct nmk_gpio_chip *nmk_chip;
struct gpio_chip *chip; struct gpio_chip *chip;
struct irq_chip *irqchip; struct irq_chip *irqchip;
struct resource *res;
struct clk *clk;
int latent_irq; int latent_irq;
bool supports_sleepmode; bool supports_sleepmode;
void __iomem *base;
int irq; int irq;
int ret; int ret;
nmk_chip = nmk_gpio_populate_chip(np, dev);
if (IS_ERR(nmk_chip)) {
dev_err(&dev->dev, "could not populate nmk chip struct\n");
return PTR_ERR(nmk_chip);
}
if (of_get_property(np, "st,supports-sleepmode", NULL)) if (of_get_property(np, "st,supports-sleepmode", NULL))
supports_sleepmode = true; supports_sleepmode = true;
else else
supports_sleepmode = false; supports_sleepmode = false;
if (of_property_read_u32(np, "gpio-bank", &dev->id)) { /* Correct platform device ID */
dev_err(&dev->dev, "gpio-bank property not found\n"); dev->id = nmk_chip->bank;
return -EINVAL;
}
irq = platform_get_irq(dev, 0); irq = platform_get_irq(dev, 0);
if (irq < 0) if (irq < 0)
@ -1193,27 +1257,10 @@ static int nmk_gpio_probe(struct platform_device *dev)
/* It's OK for this IRQ not to be present */ /* It's OK for this IRQ not to be present */
latent_irq = platform_get_irq(dev, 1); latent_irq = platform_get_irq(dev, 1);
res = platform_get_resource(dev, IORESOURCE_MEM, 0);
base = devm_ioremap_resource(&dev->dev, res);
if (IS_ERR(base))
return PTR_ERR(base);
clk = devm_clk_get(&dev->dev, NULL);
if (IS_ERR(clk))
return PTR_ERR(clk);
clk_prepare(clk);
nmk_chip = devm_kzalloc(&dev->dev, sizeof(*nmk_chip), GFP_KERNEL);
if (!nmk_chip)
return -ENOMEM;
/* /*
* The virt address in nmk_chip->addr is in the nomadik register space, * The virt address in nmk_chip->addr is in the nomadik register space,
* so we can simply convert the resource address, without remapping * so we can simply convert the resource address, without remapping
*/ */
nmk_chip->bank = dev->id;
nmk_chip->clk = clk;
nmk_chip->addr = base;
nmk_chip->parent_irq = irq; nmk_chip->parent_irq = irq;
nmk_chip->latent_parent_irq = latent_irq; nmk_chip->latent_parent_irq = latent_irq;
nmk_chip->sleepmode = supports_sleepmode; nmk_chip->sleepmode = supports_sleepmode;
@ -1228,10 +1275,6 @@ static int nmk_gpio_probe(struct platform_device *dev)
chip->set = nmk_gpio_set_output; chip->set = nmk_gpio_set_output;
chip->dbg_show = nmk_gpio_dbg_show; chip->dbg_show = nmk_gpio_dbg_show;
chip->can_sleep = false; chip->can_sleep = false;
chip->base = dev->id * NMK_GPIO_PER_CHIP;
chip->ngpio = NMK_GPIO_PER_CHIP;
chip->label = dev_name(&dev->dev);
chip->dev = &dev->dev;
chip->owner = THIS_MODULE; chip->owner = THIS_MODULE;
irqchip = &nmk_chip->irqchip; irqchip = &nmk_chip->irqchip;
@ -1253,14 +1296,10 @@ static int nmk_gpio_probe(struct platform_device *dev)
clk_disable(nmk_chip->clk); clk_disable(nmk_chip->clk);
chip->of_node = np; chip->of_node = np;
ret = gpiochip_add(&nmk_chip->chip); ret = gpiochip_add(chip);
if (ret) if (ret)
return ret; return ret;
BUG_ON(nmk_chip->bank >= ARRAY_SIZE(nmk_gpio_chips));
nmk_gpio_chips[nmk_chip->bank] = nmk_chip;
platform_set_drvdata(dev, nmk_chip); platform_set_drvdata(dev, nmk_chip);
/* /*
@ -1320,35 +1359,40 @@ static int nmk_get_group_pins(struct pinctrl_dev *pctldev, unsigned selector,
return 0; return 0;
} }
static struct pinctrl_gpio_range * static struct nmk_gpio_chip *find_nmk_gpio_from_pin(unsigned pin)
nmk_match_gpio_range(struct pinctrl_dev *pctldev, unsigned offset)
{ {
struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev);
int i; int i;
struct nmk_gpio_chip *nmk_gpio;
for (i = 0; i < npct->soc->gpio_num_ranges; i++) { for(i = 0; i < NMK_MAX_BANKS; i++) {
struct pinctrl_gpio_range *range; nmk_gpio = nmk_gpio_chips[i];
if (!nmk_gpio)
range = &npct->soc->gpio_ranges[i]; continue;
if (offset >= range->pin_base && if (pin >= nmk_gpio->chip.base &&
offset <= (range->pin_base + range->npins - 1)) pin < nmk_gpio->chip.base + nmk_gpio->chip.ngpio)
return range; return nmk_gpio;
} }
return NULL; return NULL;
} }
static struct gpio_chip *find_gc_from_pin(unsigned pin)
{
struct nmk_gpio_chip *nmk_gpio = find_nmk_gpio_from_pin(pin);
if (nmk_gpio)
return &nmk_gpio->chip;
return NULL;
}
static void nmk_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s, static void nmk_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
unsigned offset) unsigned offset)
{ {
struct pinctrl_gpio_range *range; struct gpio_chip *chip = find_gc_from_pin(offset);
struct gpio_chip *chip;
range = nmk_match_gpio_range(pctldev, offset); if (!chip) {
if (!range || !range->gc) {
seq_printf(s, "invalid pin offset"); seq_printf(s, "invalid pin offset");
return; return;
} }
chip = range->gc;
nmk_gpio_dbg_show_one(s, pctldev, chip, offset - chip->base, offset); nmk_gpio_dbg_show_one(s, pctldev, chip, offset - chip->base, offset);
} }
@ -1693,25 +1737,16 @@ static int nmk_pmx_set(struct pinctrl_dev *pctldev, unsigned function,
} }
for (i = 0; i < g->npins; i++) { for (i = 0; i < g->npins; i++) {
struct pinctrl_gpio_range *range;
struct nmk_gpio_chip *nmk_chip; struct nmk_gpio_chip *nmk_chip;
struct gpio_chip *chip;
unsigned bit; unsigned bit;
range = nmk_match_gpio_range(pctldev, g->pins[i]); nmk_chip = find_nmk_gpio_from_pin(g->pins[i]);
if (!range) { if (!nmk_chip) {
dev_err(npct->dev, dev_err(npct->dev,
"invalid pin offset %d in group %s at index %d\n", "invalid pin offset %d in group %s at index %d\n",
g->pins[i], g->name, i); g->pins[i], g->name, i);
goto out_glitch; goto out_glitch;
} }
if (!range->gc) {
dev_err(npct->dev, "GPIO chip missing in range for pin offset %d in group %s at index %d\n",
g->pins[i], g->name, i);
goto out_glitch;
}
chip = range->gc;
nmk_chip = container_of(chip, struct nmk_gpio_chip, chip);
dev_dbg(npct->dev, "setting pin %d to altsetting %d\n", g->pins[i], g->altsetting); dev_dbg(npct->dev, "setting pin %d to altsetting %d\n", g->pins[i], g->altsetting);
clk_enable(nmk_chip->clk); clk_enable(nmk_chip->clk);
@ -1827,25 +1862,17 @@ static int nmk_pin_config_set(struct pinctrl_dev *pctldev, unsigned pin,
}; };
struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev); struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev);
struct nmk_gpio_chip *nmk_chip; struct nmk_gpio_chip *nmk_chip;
struct pinctrl_gpio_range *range;
struct gpio_chip *chip;
unsigned bit; unsigned bit;
pin_cfg_t cfg; pin_cfg_t cfg;
int pull, slpm, output, val, i; int pull, slpm, output, val, i;
bool lowemi, gpiomode, sleep; bool lowemi, gpiomode, sleep;
range = nmk_match_gpio_range(pctldev, pin); nmk_chip = find_nmk_gpio_from_pin(pin);
if (!range) { if (!nmk_chip) {
dev_err(npct->dev, "invalid pin offset %d\n", pin); dev_err(npct->dev,
"invalid pin offset %d\n", pin);
return -EINVAL; return -EINVAL;
} }
if (!range->gc) {
dev_err(npct->dev, "GPIO chip missing in range for pin %d\n",
pin);
return -EINVAL;
}
chip = range->gc;
nmk_chip = container_of(chip, struct nmk_gpio_chip, chip);
for (i = 0; i < num_configs; i++) { for (i = 0; i < num_configs; i++) {
/* /*
@ -1997,6 +2024,31 @@ static int nmk_pinctrl_probe(struct platform_device *pdev)
if (version == PINCTRL_NMK_DB8540) if (version == PINCTRL_NMK_DB8540)
nmk_pinctrl_db8540_init(&npct->soc); nmk_pinctrl_db8540_init(&npct->soc);
/*
* Since we depend on the GPIO chips to provide clock and register base
* for the pin control operations, make sure that we have these
* populated before we continue. Follow the phandles to instantiate
* them. The GPIO portion of the actual hardware may be probed before
* or after this point: it shouldn't matter as the APIs are orthogonal.
*/
for (i = 0; i < NMK_MAX_BANKS; i++) {
struct device_node *gpio_np;
struct nmk_gpio_chip *nmk_chip;
gpio_np = of_parse_phandle(np, "nomadik-gpio-chips", i);
if (gpio_np) {
dev_info(&pdev->dev,
"populate NMK GPIO %d \"%s\"\n",
i, gpio_np->name);
nmk_chip = nmk_gpio_populate_chip(gpio_np, pdev);
if (IS_ERR(nmk_chip))
dev_err(&pdev->dev,
"could not populate nmk chip struct "
"- continue anyway\n");
of_node_put(gpio_np);
}
}
prcm_np = of_parse_phandle(np, "prcm", 0); prcm_np = of_parse_phandle(np, "prcm", 0);
if (prcm_np) if (prcm_np)
npct->prcm_base = of_iomap(prcm_np, 0); npct->prcm_base = of_iomap(prcm_np, 0);
@ -2011,19 +2063,6 @@ static int nmk_pinctrl_probe(struct platform_device *pdev)
} }
} }
/*
* We need all the GPIO drivers to probe FIRST, or we will not be able
* to obtain references to the struct gpio_chip * for them, and we
* need this to proceed.
*/
for (i = 0; i < npct->soc->gpio_num_ranges; i++) {
if (!nmk_gpio_chips[npct->soc->gpio_ranges[i].id]) {
dev_warn(&pdev->dev, "GPIO chip %d not registered yet\n", i);
return -EPROBE_DEFER;
}
npct->soc->gpio_ranges[i].gc = &nmk_gpio_chips[npct->soc->gpio_ranges[i].id]->chip;
}
nmk_pinctrl_desc.pins = npct->soc->pins; nmk_pinctrl_desc.pins = npct->soc->pins;
nmk_pinctrl_desc.npins = npct->soc->npins; nmk_pinctrl_desc.npins = npct->soc->npins;
npct->dev = &pdev->dev; npct->dev = &pdev->dev;
@ -2034,10 +2073,6 @@ static int nmk_pinctrl_probe(struct platform_device *pdev)
return PTR_ERR(npct->pctl); return PTR_ERR(npct->pctl);
} }
/* We will handle a range of GPIO pins */
for (i = 0; i < npct->soc->gpio_num_ranges; i++)
pinctrl_add_gpio_range(npct->pctl, &npct->soc->gpio_ranges[i]);
platform_set_drvdata(pdev, npct); platform_set_drvdata(pdev, npct);
dev_info(&pdev->dev, "initialized Nomadik pin control driver\n"); dev_info(&pdev->dev, "initialized Nomadik pin control driver\n");
@ -2072,15 +2107,15 @@ static struct platform_driver nmk_pinctrl_driver = {
static int __init nmk_gpio_init(void) static int __init nmk_gpio_init(void)
{ {
int ret; return platform_driver_register(&nmk_gpio_driver);
}
subsys_initcall(nmk_gpio_init);
ret = platform_driver_register(&nmk_gpio_driver); static int __init nmk_pinctrl_init(void)
if (ret) {
return ret;
return platform_driver_register(&nmk_pinctrl_driver); return platform_driver_register(&nmk_pinctrl_driver);
} }
core_initcall(nmk_pinctrl_init);
core_initcall(nmk_gpio_init);
MODULE_AUTHOR("Prafulla WADASKAR and Alessandro Rubini"); MODULE_AUTHOR("Prafulla WADASKAR and Alessandro Rubini");
MODULE_DESCRIPTION("Nomadik GPIO Driver"); MODULE_DESCRIPTION("Nomadik GPIO Driver");

View File

@ -121,8 +121,6 @@ struct nmk_pingroup {
/** /**
* struct nmk_pinctrl_soc_data - Nomadik pin controller per-SoC configuration * struct nmk_pinctrl_soc_data - Nomadik pin controller per-SoC configuration
* @gpio_ranges: An array of GPIO ranges for this SoC
* @gpio_num_ranges: The number of GPIO ranges for this SoC
* @pins: An array describing all pins the pin controller affects. * @pins: An array describing all pins the pin controller affects.
* All pins which are also GPIOs must be listed first within the * All pins which are also GPIOs must be listed first within the
* array, and be numbered identically to the GPIO controller's * array, and be numbered identically to the GPIO controller's
@ -137,8 +135,6 @@ struct nmk_pingroup {
* @prcm_gpiocr_registers: The array of PRCM GPIOCR registers on this SoC * @prcm_gpiocr_registers: The array of PRCM GPIOCR registers on this SoC
*/ */
struct nmk_pinctrl_soc_data { struct nmk_pinctrl_soc_data {
struct pinctrl_gpio_range *gpio_ranges;
unsigned gpio_num_ranges;
const struct pinctrl_pin_desc *pins; const struct pinctrl_pin_desc *pins;
unsigned npins; unsigned npins;
const struct nmk_function *functions; const struct nmk_function *functions;

View File

@ -61,8 +61,8 @@ int pin_config_get_for_pin(struct pinctrl_dev *pctldev, unsigned pin,
const struct pinconf_ops *ops = pctldev->desc->confops; const struct pinconf_ops *ops = pctldev->desc->confops;
if (!ops || !ops->pin_config_get) { if (!ops || !ops->pin_config_get) {
dev_dbg(pctldev->dev, "cannot get pin configuration, missing " dev_dbg(pctldev->dev,
"pin_config_get() function in driver\n"); "cannot get pin configuration, .pin_config_get missing in driver\n");
return -ENOTSUPP; return -ENOTSUPP;
} }
@ -202,18 +202,34 @@ int pinconf_apply_setting(struct pinctrl_setting const *setting)
#ifdef CONFIG_DEBUG_FS #ifdef CONFIG_DEBUG_FS
void pinconf_show_map(struct seq_file *s, struct pinctrl_map const *map) static void pinconf_show_config(struct seq_file *s, struct pinctrl_dev *pctldev,
unsigned long *configs, unsigned num_configs)
{ {
struct pinctrl_dev *pctldev;
const struct pinconf_ops *confops; const struct pinconf_ops *confops;
int i; int i;
pctldev = get_pinctrl_dev_from_devname(map->ctrl_dev_name);
if (pctldev) if (pctldev)
confops = pctldev->desc->confops; confops = pctldev->desc->confops;
else else
confops = NULL; confops = NULL;
for (i = 0; i < num_configs; i++) {
seq_puts(s, "config ");
if (confops && confops->pin_config_config_dbg_show)
confops->pin_config_config_dbg_show(pctldev, s,
configs[i]);
else
seq_printf(s, "%08lx", configs[i]);
seq_puts(s, "\n");
}
}
void pinconf_show_map(struct seq_file *s, struct pinctrl_map const *map)
{
struct pinctrl_dev *pctldev;
pctldev = get_pinctrl_dev_from_devname(map->ctrl_dev_name);
switch (map->type) { switch (map->type) {
case PIN_MAP_TYPE_CONFIGS_PIN: case PIN_MAP_TYPE_CONFIGS_PIN:
seq_printf(s, "pin "); seq_printf(s, "pin ");
@ -227,15 +243,8 @@ void pinconf_show_map(struct seq_file *s, struct pinctrl_map const *map)
seq_printf(s, "%s\n", map->data.configs.group_or_pin); seq_printf(s, "%s\n", map->data.configs.group_or_pin);
for (i = 0; i < map->data.configs.num_configs; i++) { pinconf_show_config(s, pctldev, map->data.configs.configs,
seq_printf(s, "config "); map->data.configs.num_configs);
if (confops && confops->pin_config_config_dbg_show)
confops->pin_config_config_dbg_show(pctldev, s,
map->data.configs.configs[i]);
else
seq_printf(s, "%08lx", map->data.configs.configs[i]);
seq_printf(s, "\n");
}
} }
void pinconf_show_setting(struct seq_file *s, void pinconf_show_setting(struct seq_file *s,
@ -243,9 +252,7 @@ void pinconf_show_setting(struct seq_file *s,
{ {
struct pinctrl_dev *pctldev = setting->pctldev; struct pinctrl_dev *pctldev = setting->pctldev;
const struct pinctrl_ops *pctlops = pctldev->desc->pctlops; const struct pinctrl_ops *pctlops = pctldev->desc->pctlops;
const struct pinconf_ops *confops = pctldev->desc->confops;
struct pin_desc *desc; struct pin_desc *desc;
int i;
switch (setting->type) { switch (setting->type) {
case PIN_MAP_TYPE_CONFIGS_PIN: case PIN_MAP_TYPE_CONFIGS_PIN:
@ -269,17 +276,8 @@ void pinconf_show_setting(struct seq_file *s,
* FIXME: We should really get the pin controler to dump the config * FIXME: We should really get the pin controler to dump the config
* values, so they can be decoded to something meaningful. * values, so they can be decoded to something meaningful.
*/ */
for (i = 0; i < setting->data.configs.num_configs; i++) { pinconf_show_config(s, pctldev, setting->data.configs.configs,
seq_printf(s, " "); setting->data.configs.num_configs);
if (confops && confops->pin_config_config_dbg_show)
confops->pin_config_config_dbg_show(pctldev, s,
setting->data.configs.configs[i]);
else
seq_printf(s, "%08lx",
setting->data.configs.configs[i]);
}
seq_printf(s, "\n");
} }
static void pinconf_dump_pin(struct pinctrl_dev *pctldev, static void pinconf_dump_pin(struct pinctrl_dev *pctldev,
@ -412,10 +410,8 @@ static int pinconf_dbg_config_print(struct seq_file *s, void *d)
const struct pinctrl_map *map; const struct pinctrl_map *map;
const struct pinctrl_map *found = NULL; const struct pinctrl_map *found = NULL;
struct pinctrl_dev *pctldev; struct pinctrl_dev *pctldev;
const struct pinconf_ops *confops = NULL;
struct dbg_cfg *dbg = &pinconf_dbg_conf; struct dbg_cfg *dbg = &pinconf_dbg_conf;
int i, j; int i, j;
unsigned long config;
mutex_lock(&pinctrl_maps_mutex); mutex_lock(&pinctrl_maps_mutex);
@ -449,16 +445,10 @@ static int pinconf_dbg_config_print(struct seq_file *s, void *d)
} }
pctldev = get_pinctrl_dev_from_devname(found->ctrl_dev_name); pctldev = get_pinctrl_dev_from_devname(found->ctrl_dev_name);
config = *found->data.configs.configs; seq_printf(s, "Dev %s has config of %s in state %s:\n",
seq_printf(s, "Dev %s has config of %s in state %s: 0x%08lX\n", dbg->dev_name, dbg->pin_name, dbg->state_name);
dbg->dev_name, dbg->pin_name, pinconf_show_config(s, pctldev, found->data.configs.configs,
dbg->state_name, config); found->data.configs.num_configs);
if (pctldev)
confops = pctldev->desc->confops;
if (confops && confops->pin_config_config_dbg_show)
confops->pin_config_config_dbg_show(pctldev, s, config);
exit: exit:
mutex_unlock(&pinctrl_maps_mutex); mutex_unlock(&pinctrl_maps_mutex);
@ -470,10 +460,12 @@ exit:
* pinconf_dbg_config_write() - modify the pinctrl config in the pinctrl * pinconf_dbg_config_write() - modify the pinctrl config in the pinctrl
* map, of a dev/pin/state entry based on user entries to pinconf-config * map, of a dev/pin/state entry based on user entries to pinconf-config
* @user_buf: contains the modification request with expected format: * @user_buf: contains the modification request with expected format:
* modify config_pin <devicename> <state> <pinname> <newvalue> * modify <config> <devicename> <state> <name> <newvalue>
* modify is literal string, alternatives like add/delete not supported yet * modify is literal string, alternatives like add/delete not supported yet
* config_pin is literal, alternatives like config_mux not supported yet * <config> is the configuration to be changed. Supported configs are
* <devicename> <state> <pinname> are values that should match the pinctrl-maps * "config_pin" or "config_group", alternatives like config_mux are not
* supported yet.
* <devicename> <state> <name> are values that should match the pinctrl-maps
* <newvalue> reflects the new config and is driver dependant * <newvalue> reflects the new config and is driver dependant
*/ */
static ssize_t pinconf_dbg_config_write(struct file *file, static ssize_t pinconf_dbg_config_write(struct file *file,
@ -511,13 +503,19 @@ static ssize_t pinconf_dbg_config_write(struct file *file,
if (strcmp(token, "modify")) if (strcmp(token, "modify"))
return -EINVAL; return -EINVAL;
/* Get arg type: "config_pin" type supported so far */ /*
* Get arg type: "config_pin" and "config_group"
* types are supported so far
*/
token = strsep(&b, " "); token = strsep(&b, " ");
if (!token) if (!token)
return -EINVAL; return -EINVAL;
if (strcmp(token, "config_pin")) if (!strcmp(token, "config_pin"))
dbg->map_type = PIN_MAP_TYPE_CONFIGS_PIN;
else if (!strcmp(token, "config_group"))
dbg->map_type = PIN_MAP_TYPE_CONFIGS_GROUP;
else
return -EINVAL; return -EINVAL;
dbg->map_type = PIN_MAP_TYPE_CONFIGS_PIN;
/* get arg 'device_name' */ /* get arg 'device_name' */
token = strsep(&b, " "); token = strsep(&b, " ");

View File

@ -394,25 +394,25 @@ static const unsigned short ppi2_16b_mux[] = {
static const unsigned short lp0_mux[] = { static const unsigned short lp0_mux[] = {
P_LP0_CLK, P_LP0_ACK, P_LP0_D0, P_LP0_D1, P_LP0_D2, P_LP0_CLK, P_LP0_ACK, P_LP0_D0, P_LP0_D1, P_LP0_D2,
P_LP0_D3, P_LP0_D4, P_LP0_D5, P_LP0_D6, P_LP0_D7, P_LP0_D3, P_LP0_D4, P_LP0_D5, P_LP0_D6, P_LP0_D7,
0 0
}; };
static const unsigned short lp1_mux[] = { static const unsigned short lp1_mux[] = {
P_LP1_CLK, P_LP1_ACK, P_LP1_D0, P_LP1_D1, P_LP1_D2, P_LP1_CLK, P_LP1_ACK, P_LP1_D0, P_LP1_D1, P_LP1_D2,
P_LP1_D3, P_LP1_D4, P_LP1_D5, P_LP1_D6, P_LP1_D7, P_LP1_D3, P_LP1_D4, P_LP1_D5, P_LP1_D6, P_LP1_D7,
0 0
}; };
static const unsigned short lp2_mux[] = { static const unsigned short lp2_mux[] = {
P_LP2_CLK, P_LP2_ACK, P_LP2_D0, P_LP2_D1, P_LP2_D2, P_LP2_CLK, P_LP2_ACK, P_LP2_D0, P_LP2_D1, P_LP2_D2,
P_LP2_D3, P_LP2_D4, P_LP2_D5, P_LP2_D6, P_LP2_D7, P_LP2_D3, P_LP2_D4, P_LP2_D5, P_LP2_D6, P_LP2_D7,
0 0
}; };
static const unsigned short lp3_mux[] = { static const unsigned short lp3_mux[] = {
P_LP3_CLK, P_LP3_ACK, P_LP3_D0, P_LP3_D1, P_LP3_D2, P_LP3_CLK, P_LP3_ACK, P_LP3_D0, P_LP3_D1, P_LP3_D2,
P_LP3_D3, P_LP3_D4, P_LP3_D5, P_LP3_D6, P_LP3_D7, P_LP3_D3, P_LP3_D4, P_LP3_D5, P_LP3_D6, P_LP3_D7,
0 0
}; };
static const struct adi_pin_group adi_pin_groups[] = { static const struct adi_pin_group adi_pin_groups[] = {

View File

@ -427,10 +427,10 @@ static int adi_gpio_irq_type(struct irq_data *d, unsigned int type)
if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) { if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) {
writel(pintmask, &pint_regs->edge_set); writel(pintmask, &pint_regs->edge_set);
__irq_set_handler_locked(irq, handle_edge_irq); irq_set_handler_locked(d, handle_edge_irq);
} else { } else {
writel(pintmask, &pint_regs->edge_clear); writel(pintmask, &pint_regs->edge_clear);
__irq_set_handler_locked(irq, handle_level_irq); irq_set_handler_locked(d, handle_level_irq);
} }
out: out:

View File

@ -420,7 +420,7 @@ static int amd_gpio_irq_set_type(struct irq_data *d, unsigned int type)
pin_reg &= ~(ACTIVE_LEVEL_MASK << ACTIVE_LEVEL_OFF); pin_reg &= ~(ACTIVE_LEVEL_MASK << ACTIVE_LEVEL_OFF);
pin_reg |= ACTIVE_HIGH << ACTIVE_LEVEL_OFF; pin_reg |= ACTIVE_HIGH << ACTIVE_LEVEL_OFF;
pin_reg |= DB_TYPE_REMOVE_GLITCH << DB_CNTRL_OFF; pin_reg |= DB_TYPE_REMOVE_GLITCH << DB_CNTRL_OFF;
__irq_set_handler_locked(d->irq, handle_edge_irq); irq_set_handler_locked(d, handle_edge_irq);
break; break;
case IRQ_TYPE_EDGE_FALLING: case IRQ_TYPE_EDGE_FALLING:
@ -428,7 +428,7 @@ static int amd_gpio_irq_set_type(struct irq_data *d, unsigned int type)
pin_reg &= ~(ACTIVE_LEVEL_MASK << ACTIVE_LEVEL_OFF); pin_reg &= ~(ACTIVE_LEVEL_MASK << ACTIVE_LEVEL_OFF);
pin_reg |= ACTIVE_LOW << ACTIVE_LEVEL_OFF; pin_reg |= ACTIVE_LOW << ACTIVE_LEVEL_OFF;
pin_reg |= DB_TYPE_REMOVE_GLITCH << DB_CNTRL_OFF; pin_reg |= DB_TYPE_REMOVE_GLITCH << DB_CNTRL_OFF;
__irq_set_handler_locked(d->irq, handle_edge_irq); irq_set_handler_locked(d, handle_edge_irq);
break; break;
case IRQ_TYPE_EDGE_BOTH: case IRQ_TYPE_EDGE_BOTH:
@ -436,7 +436,7 @@ static int amd_gpio_irq_set_type(struct irq_data *d, unsigned int type)
pin_reg &= ~(ACTIVE_LEVEL_MASK << ACTIVE_LEVEL_OFF); pin_reg &= ~(ACTIVE_LEVEL_MASK << ACTIVE_LEVEL_OFF);
pin_reg |= BOTH_EADGE << ACTIVE_LEVEL_OFF; pin_reg |= BOTH_EADGE << ACTIVE_LEVEL_OFF;
pin_reg |= DB_TYPE_REMOVE_GLITCH << DB_CNTRL_OFF; pin_reg |= DB_TYPE_REMOVE_GLITCH << DB_CNTRL_OFF;
__irq_set_handler_locked(d->irq, handle_edge_irq); irq_set_handler_locked(d, handle_edge_irq);
break; break;
case IRQ_TYPE_LEVEL_HIGH: case IRQ_TYPE_LEVEL_HIGH:
@ -445,7 +445,7 @@ static int amd_gpio_irq_set_type(struct irq_data *d, unsigned int type)
pin_reg |= ACTIVE_HIGH << ACTIVE_LEVEL_OFF; pin_reg |= ACTIVE_HIGH << ACTIVE_LEVEL_OFF;
pin_reg &= ~(DB_CNTRl_MASK << DB_CNTRL_OFF); pin_reg &= ~(DB_CNTRl_MASK << DB_CNTRL_OFF);
pin_reg |= DB_TYPE_PRESERVE_LOW_GLITCH << DB_CNTRL_OFF; pin_reg |= DB_TYPE_PRESERVE_LOW_GLITCH << DB_CNTRL_OFF;
__irq_set_handler_locked(d->irq, handle_level_irq); irq_set_handler_locked(d, handle_level_irq);
break; break;
case IRQ_TYPE_LEVEL_LOW: case IRQ_TYPE_LEVEL_LOW:
@ -454,7 +454,7 @@ static int amd_gpio_irq_set_type(struct irq_data *d, unsigned int type)
pin_reg |= ACTIVE_LOW << ACTIVE_LEVEL_OFF; pin_reg |= ACTIVE_LOW << ACTIVE_LEVEL_OFF;
pin_reg &= ~(DB_CNTRl_MASK << DB_CNTRL_OFF); pin_reg &= ~(DB_CNTRl_MASK << DB_CNTRL_OFF);
pin_reg |= DB_TYPE_PRESERVE_HIGH_GLITCH << DB_CNTRL_OFF; pin_reg |= DB_TYPE_PRESERVE_HIGH_GLITCH << DB_CNTRL_OFF;
__irq_set_handler_locked(d->irq, handle_level_irq); irq_set_handler_locked(d, handle_level_irq);
break; break;
case IRQ_TYPE_NONE: case IRQ_TYPE_NONE:
@ -492,8 +492,9 @@ static struct irq_chip amd_gpio_irqchip = {
.irq_set_type = amd_gpio_irq_set_type, .irq_set_type = amd_gpio_irq_set_type,
}; };
static void amd_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) static void amd_gpio_irq_handler(unsigned int __irq, struct irq_desc *desc)
{ {
unsigned int irq = irq_desc_get_irq(desc);
u32 i; u32 i;
u32 off; u32 off;
u32 reg; u32 reg;
@ -501,7 +502,7 @@ static void amd_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
u64 reg64; u64 reg64;
int handled = 0; int handled = 0;
unsigned long flags; unsigned long flags;
struct irq_chip *chip = irq_get_chip(irq); struct irq_chip *chip = irq_desc_get_chip(desc);
struct gpio_chip *gc = irq_desc_get_handler_data(desc); struct gpio_chip *gc = irq_desc_get_handler_data(desc);
struct amd_gpio *gpio_dev = to_amd_gpio(gc); struct amd_gpio *gpio_dev = to_amd_gpio(gc);

View File

@ -320,6 +320,9 @@ static const struct pinctrl_ops at91_pctrl_ops = {
static void __iomem *pin_to_controller(struct at91_pinctrl *info, static void __iomem *pin_to_controller(struct at91_pinctrl *info,
unsigned int bank) unsigned int bank)
{ {
if (!gpio_chips[bank])
return NULL;
return gpio_chips[bank]->regbase; return gpio_chips[bank]->regbase;
} }
@ -729,6 +732,10 @@ static int at91_pmx_set(struct pinctrl_dev *pctldev, unsigned selector,
pin = &pins_conf[i]; pin = &pins_conf[i];
at91_pin_dbg(info->dev, pin); at91_pin_dbg(info->dev, pin);
pio = pin_to_controller(info, pin->bank); pio = pin_to_controller(info, pin->bank);
if (!pio)
continue;
mask = pin_to_mask(pin->pin); mask = pin_to_mask(pin->pin);
at91_mux_disable_interrupt(pio, mask); at91_mux_disable_interrupt(pio, mask);
switch (pin->mux) { switch (pin->mux) {
@ -848,6 +855,10 @@ static int at91_pinconf_get(struct pinctrl_dev *pctldev,
*config = 0; *config = 0;
dev_dbg(info->dev, "%s:%d, pin_id=%d", __func__, __LINE__, pin_id); dev_dbg(info->dev, "%s:%d, pin_id=%d", __func__, __LINE__, pin_id);
pio = pin_to_controller(info, pin_to_bank(pin_id)); pio = pin_to_controller(info, pin_to_bank(pin_id));
if (!pio)
return -EINVAL;
pin = pin_id % MAX_NB_GPIO_PER_BANK; pin = pin_id % MAX_NB_GPIO_PER_BANK;
if (at91_mux_get_multidrive(pio, pin)) if (at91_mux_get_multidrive(pio, pin))
@ -889,6 +900,10 @@ static int at91_pinconf_set(struct pinctrl_dev *pctldev,
"%s:%d, pin_id=%d, config=0x%lx", "%s:%d, pin_id=%d, config=0x%lx",
__func__, __LINE__, pin_id, config); __func__, __LINE__, pin_id, config);
pio = pin_to_controller(info, pin_to_bank(pin_id)); pio = pin_to_controller(info, pin_to_bank(pin_id));
if (!pio)
return -EINVAL;
pin = pin_id % MAX_NB_GPIO_PER_BANK; pin = pin_id % MAX_NB_GPIO_PER_BANK;
mask = pin_to_mask(pin); mask = pin_to_mask(pin);
@ -1444,22 +1459,22 @@ static int alt_gpio_irq_type(struct irq_data *d, unsigned type)
switch (type) { switch (type) {
case IRQ_TYPE_EDGE_RISING: case IRQ_TYPE_EDGE_RISING:
__irq_set_handler_locked(d->irq, handle_simple_irq); irq_set_handler_locked(d, handle_simple_irq);
writel_relaxed(mask, pio + PIO_ESR); writel_relaxed(mask, pio + PIO_ESR);
writel_relaxed(mask, pio + PIO_REHLSR); writel_relaxed(mask, pio + PIO_REHLSR);
break; break;
case IRQ_TYPE_EDGE_FALLING: case IRQ_TYPE_EDGE_FALLING:
__irq_set_handler_locked(d->irq, handle_simple_irq); irq_set_handler_locked(d, handle_simple_irq);
writel_relaxed(mask, pio + PIO_ESR); writel_relaxed(mask, pio + PIO_ESR);
writel_relaxed(mask, pio + PIO_FELLSR); writel_relaxed(mask, pio + PIO_FELLSR);
break; break;
case IRQ_TYPE_LEVEL_LOW: case IRQ_TYPE_LEVEL_LOW:
__irq_set_handler_locked(d->irq, handle_level_irq); irq_set_handler_locked(d, handle_level_irq);
writel_relaxed(mask, pio + PIO_LSR); writel_relaxed(mask, pio + PIO_LSR);
writel_relaxed(mask, pio + PIO_FELLSR); writel_relaxed(mask, pio + PIO_FELLSR);
break; break;
case IRQ_TYPE_LEVEL_HIGH: case IRQ_TYPE_LEVEL_HIGH:
__irq_set_handler_locked(d->irq, handle_level_irq); irq_set_handler_locked(d, handle_level_irq);
writel_relaxed(mask, pio + PIO_LSR); writel_relaxed(mask, pio + PIO_LSR);
writel_relaxed(mask, pio + PIO_REHLSR); writel_relaxed(mask, pio + PIO_REHLSR);
break; break;
@ -1468,7 +1483,7 @@ static int alt_gpio_irq_type(struct irq_data *d, unsigned type)
* disable additional interrupt modes: * disable additional interrupt modes:
* fall back to default behavior * fall back to default behavior
*/ */
__irq_set_handler_locked(d->irq, handle_simple_irq); irq_set_handler_locked(d, handle_simple_irq);
writel_relaxed(mask, pio + PIO_AIMDR); writel_relaxed(mask, pio + PIO_AIMDR);
return 0; return 0;
case IRQ_TYPE_NONE: case IRQ_TYPE_NONE:
@ -1488,28 +1503,6 @@ static void gpio_irq_ack(struct irq_data *d)
/* the interrupt is already cleared before by reading ISR */ /* the interrupt is already cleared before by reading ISR */
} }
static int gpio_irq_request_res(struct irq_data *d)
{
struct at91_gpio_chip *at91_gpio = irq_data_get_irq_chip_data(d);
unsigned pin = d->hwirq;
int ret;
ret = gpiochip_lock_as_irq(&at91_gpio->chip, pin);
if (ret)
dev_err(at91_gpio->chip.dev, "unable to lock pind %lu IRQ\n",
d->hwirq);
return ret;
}
static void gpio_irq_release_res(struct irq_data *d)
{
struct at91_gpio_chip *at91_gpio = irq_data_get_irq_chip_data(d);
unsigned pin = d->hwirq;
gpiochip_unlock_as_irq(&at91_gpio->chip, pin);
}
#ifdef CONFIG_PM #ifdef CONFIG_PM
static u32 wakeups[MAX_GPIO_BANKS]; static u32 wakeups[MAX_GPIO_BANKS];
@ -1585,8 +1578,6 @@ void at91_pinctrl_gpio_resume(void)
static struct irq_chip gpio_irqchip = { static struct irq_chip gpio_irqchip = {
.name = "GPIO", .name = "GPIO",
.irq_ack = gpio_irq_ack, .irq_ack = gpio_irq_ack,
.irq_request_resources = gpio_irq_request_res,
.irq_release_resources = gpio_irq_release_res,
.irq_disable = gpio_irq_mask, .irq_disable = gpio_irq_mask,
.irq_mask = gpio_irq_mask, .irq_mask = gpio_irq_mask,
.irq_unmask = gpio_irq_unmask, .irq_unmask = gpio_irq_unmask,
@ -1596,7 +1587,7 @@ static struct irq_chip gpio_irqchip = {
static void gpio_irq_handler(unsigned irq, struct irq_desc *desc) static void gpio_irq_handler(unsigned irq, struct irq_desc *desc)
{ {
struct irq_chip *chip = irq_get_chip(irq); struct irq_chip *chip = irq_desc_get_chip(desc);
struct gpio_chip *gpio_chip = irq_desc_get_handler_data(desc); struct gpio_chip *gpio_chip = irq_desc_get_handler_data(desc);
struct at91_gpio_chip *at91_gpio = container_of(gpio_chip, struct at91_gpio_chip *at91_gpio = container_of(gpio_chip,
struct at91_gpio_chip, chip); struct at91_gpio_chip, chip);

View File

@ -519,10 +519,11 @@ static struct irq_chip u300_gpio_irqchip = {
.irq_set_type = u300_gpio_irq_type, .irq_set_type = u300_gpio_irq_type,
}; };
static void u300_gpio_irq_handler(unsigned irq, struct irq_desc *desc) static void u300_gpio_irq_handler(unsigned __irq, struct irq_desc *desc)
{ {
struct irq_chip *parent_chip = irq_get_chip(irq); unsigned int irq = irq_desc_get_irq(desc);
struct gpio_chip *chip = irq_get_handler_data(irq); struct irq_chip *parent_chip = irq_desc_get_chip(desc);
struct gpio_chip *chip = irq_desc_get_handler_data(desc);
struct u300_gpio *gpio = to_u300_gpio(chip); struct u300_gpio *gpio = to_u300_gpio(chip);
struct u300_gpio_port *port = &gpio->ports[irq - chip->base]; struct u300_gpio_port *port = &gpio->ports[irq - chip->base];
int pinoffset = port->number << 3; /* get the right stride */ int pinoffset = port->number << 3; /* get the right stride */

View File

@ -0,0 +1,378 @@
/*
* Driver for Conexant Digicolor General Purpose Pin Mapping
*
* Author: Baruch Siach <baruch@tkos.co.il>
*
* Copyright (C) 2015 Paradox Innovation Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* TODO:
* - GPIO interrupt support
* - Pin pad configuration (pull up/down, strength)
*/
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/io.h>
#include <linux/gpio.h>
#include <linux/gpio/driver.h>
#include <linux/spinlock.h>
#include <linux/pinctrl/machine.h>
#include <linux/pinctrl/pinconf.h>
#include <linux/pinctrl/pinconf-generic.h>
#include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/pinmux.h>
#include "pinctrl-utils.h"
#define DRIVER_NAME "pinctrl-digicolor"
#define GP_CLIENTSEL(clct) ((clct)*8 + 0x20)
#define GP_DRIVE0(clct) (GP_CLIENTSEL(clct) + 2)
#define GP_OUTPUT0(clct) (GP_CLIENTSEL(clct) + 3)
#define GP_INPUT(clct) (GP_CLIENTSEL(clct) + 6)
#define PIN_COLLECTIONS ('R' - 'A' + 1)
#define PINS_PER_COLLECTION 8
#define PINS_COUNT (PIN_COLLECTIONS * PINS_PER_COLLECTION)
struct dc_pinmap {
void __iomem *regs;
struct device *dev;
struct pinctrl_dev *pctl;
struct pinctrl_desc *desc;
const char *pin_names[PINS_COUNT];
struct gpio_chip chip;
spinlock_t lock;
};
static int dc_get_groups_count(struct pinctrl_dev *pctldev)
{
return PINS_COUNT;
}
static const char *dc_get_group_name(struct pinctrl_dev *pctldev,
unsigned selector)
{
struct dc_pinmap *pmap = pinctrl_dev_get_drvdata(pctldev);
/* Exactly one group per pin */
return pmap->desc->pins[selector].name;
}
static int dc_get_group_pins(struct pinctrl_dev *pctldev, unsigned selector,
const unsigned **pins,
unsigned *num_pins)
{
struct dc_pinmap *pmap = pinctrl_dev_get_drvdata(pctldev);
*pins = &pmap->desc->pins[selector].number;
*num_pins = 1;
return 0;
}
static struct pinctrl_ops dc_pinctrl_ops = {
.get_groups_count = dc_get_groups_count,
.get_group_name = dc_get_group_name,
.get_group_pins = dc_get_group_pins,
.dt_node_to_map = pinconf_generic_dt_node_to_map_pin,
.dt_free_map = pinctrl_utils_dt_free_map,
};
static const char *const dc_functions[] = {
"gpio",
"client_a",
"client_b",
"client_c",
};
static int dc_get_functions_count(struct pinctrl_dev *pctldev)
{
return ARRAY_SIZE(dc_functions);
}
static const char *dc_get_fname(struct pinctrl_dev *pctldev, unsigned selector)
{
return dc_functions[selector];
}
static int dc_get_groups(struct pinctrl_dev *pctldev, unsigned selector,
const char * const **groups,
unsigned * const num_groups)
{
struct dc_pinmap *pmap = pinctrl_dev_get_drvdata(pctldev);
*groups = pmap->pin_names;
*num_groups = PINS_COUNT;
return 0;
}
static void dc_client_sel(int pin_num, int *reg, int *bit)
{
*bit = (pin_num % PINS_PER_COLLECTION) * 2;
*reg = GP_CLIENTSEL(pin_num/PINS_PER_COLLECTION);
if (*bit >= PINS_PER_COLLECTION) {
*bit -= PINS_PER_COLLECTION;
*reg += 1;
}
}
static int dc_set_mux(struct pinctrl_dev *pctldev, unsigned selector,
unsigned group)
{
struct dc_pinmap *pmap = pinctrl_dev_get_drvdata(pctldev);
int bit_off, reg_off;
u8 reg;
dc_client_sel(group, &reg_off, &bit_off);
reg = readb_relaxed(pmap->regs + reg_off);
reg &= ~(3 << bit_off);
reg |= (selector << bit_off);
writeb_relaxed(reg, pmap->regs + reg_off);
return 0;
}
static int dc_pmx_request_gpio(struct pinctrl_dev *pcdev,
struct pinctrl_gpio_range *range,
unsigned offset)
{
struct dc_pinmap *pmap = pinctrl_dev_get_drvdata(pcdev);
int bit_off, reg_off;
u8 reg;
dc_client_sel(offset, &reg_off, &bit_off);
reg = readb_relaxed(pmap->regs + reg_off);
if ((reg & (3 << bit_off)) != 0)
return -EBUSY;
return 0;
}
static struct pinmux_ops dc_pmxops = {
.get_functions_count = dc_get_functions_count,
.get_function_name = dc_get_fname,
.get_function_groups = dc_get_groups,
.set_mux = dc_set_mux,
.gpio_request_enable = dc_pmx_request_gpio,
};
static int dc_gpio_request(struct gpio_chip *chip, unsigned gpio)
{
return pinctrl_request_gpio(chip->base + gpio);
}
static void dc_gpio_free(struct gpio_chip *chip, unsigned gpio)
{
pinctrl_free_gpio(chip->base + gpio);
}
static int dc_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
{
struct dc_pinmap *pmap = container_of(chip, struct dc_pinmap, chip);
int reg_off = GP_DRIVE0(gpio/PINS_PER_COLLECTION);
int bit_off = gpio % PINS_PER_COLLECTION;
u8 drive;
unsigned long flags;
spin_lock_irqsave(&pmap->lock, flags);
drive = readb_relaxed(pmap->regs + reg_off);
drive &= ~BIT(bit_off);
writeb_relaxed(drive, pmap->regs + reg_off);
spin_unlock_irqrestore(&pmap->lock, flags);
return 0;
}
static void dc_gpio_set(struct gpio_chip *chip, unsigned gpio, int value);
static int dc_gpio_direction_output(struct gpio_chip *chip, unsigned gpio,
int value)
{
struct dc_pinmap *pmap = container_of(chip, struct dc_pinmap, chip);
int reg_off = GP_DRIVE0(gpio/PINS_PER_COLLECTION);
int bit_off = gpio % PINS_PER_COLLECTION;
u8 drive;
unsigned long flags;
dc_gpio_set(chip, gpio, value);
spin_lock_irqsave(&pmap->lock, flags);
drive = readb_relaxed(pmap->regs + reg_off);
drive |= BIT(bit_off);
writeb_relaxed(drive, pmap->regs + reg_off);
spin_unlock_irqrestore(&pmap->lock, flags);
return 0;
}
static int dc_gpio_get(struct gpio_chip *chip, unsigned gpio)
{
struct dc_pinmap *pmap = container_of(chip, struct dc_pinmap, chip);
int reg_off = GP_INPUT(gpio/PINS_PER_COLLECTION);
int bit_off = gpio % PINS_PER_COLLECTION;
u8 input;
input = readb_relaxed(pmap->regs + reg_off);
return !!(input & BIT(bit_off));
}
static void dc_gpio_set(struct gpio_chip *chip, unsigned gpio, int value)
{
struct dc_pinmap *pmap = container_of(chip, struct dc_pinmap, chip);
int reg_off = GP_OUTPUT0(gpio/PINS_PER_COLLECTION);
int bit_off = gpio % PINS_PER_COLLECTION;
u8 output;
unsigned long flags;
spin_lock_irqsave(&pmap->lock, flags);
output = readb_relaxed(pmap->regs + reg_off);
if (value)
output |= BIT(bit_off);
else
output &= ~BIT(bit_off);
writeb_relaxed(output, pmap->regs + reg_off);
spin_unlock_irqrestore(&pmap->lock, flags);
}
static int dc_gpiochip_add(struct dc_pinmap *pmap, struct device_node *np)
{
struct gpio_chip *chip = &pmap->chip;
int ret;
chip->label = DRIVER_NAME;
chip->dev = pmap->dev;
chip->request = dc_gpio_request;
chip->free = dc_gpio_free;
chip->direction_input = dc_gpio_direction_input;
chip->direction_output = dc_gpio_direction_output;
chip->get = dc_gpio_get;
chip->set = dc_gpio_set;
chip->base = -1;
chip->ngpio = PINS_COUNT;
chip->of_node = np;
chip->of_gpio_n_cells = 2;
spin_lock_init(&pmap->lock);
ret = gpiochip_add(chip);
if (ret < 0)
return ret;
ret = gpiochip_add_pin_range(chip, dev_name(pmap->dev), 0, 0,
PINS_COUNT);
if (ret < 0) {
gpiochip_remove(chip);
return ret;
}
return 0;
}
static int dc_pinctrl_probe(struct platform_device *pdev)
{
struct dc_pinmap *pmap;
struct resource *r;
struct pinctrl_pin_desc *pins;
struct pinctrl_desc *pctl_desc;
char *pin_names;
int name_len = strlen("GP_xx") + 1;
int i, j, ret;
pmap = devm_kzalloc(&pdev->dev, sizeof(*pmap), GFP_KERNEL);
if (!pmap)
return -ENOMEM;
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
pmap->regs = devm_ioremap_resource(&pdev->dev, r);
if (IS_ERR(pmap->regs))
return PTR_ERR(pmap->regs);
pins = devm_kzalloc(&pdev->dev, sizeof(*pins)*PINS_COUNT, GFP_KERNEL);
if (!pins)
return -ENOMEM;
pin_names = devm_kzalloc(&pdev->dev, name_len * PINS_COUNT,
GFP_KERNEL);
if (!pin_names)
return -ENOMEM;
for (i = 0; i < PIN_COLLECTIONS; i++) {
for (j = 0; j < PINS_PER_COLLECTION; j++) {
int pin_id = i*PINS_PER_COLLECTION + j;
char *name = &pin_names[pin_id * name_len];
snprintf(name, name_len, "GP_%c%c", 'A'+i, '0'+j);
pins[pin_id].number = pin_id;
pins[pin_id].name = name;
pmap->pin_names[pin_id] = name;
}
}
pctl_desc = devm_kzalloc(&pdev->dev, sizeof(*pctl_desc), GFP_KERNEL);
if (!pctl_desc)
return -ENOMEM;
pctl_desc->name = DRIVER_NAME,
pctl_desc->owner = THIS_MODULE,
pctl_desc->pctlops = &dc_pinctrl_ops,
pctl_desc->pmxops = &dc_pmxops,
pctl_desc->npins = PINS_COUNT;
pctl_desc->pins = pins;
pmap->desc = pctl_desc;
pmap->dev = &pdev->dev;
pmap->pctl = pinctrl_register(pctl_desc, &pdev->dev, pmap);
if (!pmap->pctl) {
dev_err(&pdev->dev, "pinctrl driver registration failed\n");
return -EINVAL;
}
ret = dc_gpiochip_add(pmap, pdev->dev.of_node);
if (ret < 0) {
pinctrl_unregister(pmap->pctl);
return ret;
}
return 0;
}
static int dc_pinctrl_remove(struct platform_device *pdev)
{
struct dc_pinmap *pmap = platform_get_drvdata(pdev);
pinctrl_unregister(pmap->pctl);
gpiochip_remove(&pmap->chip);
return 0;
}
static const struct of_device_id dc_pinctrl_ids[] = {
{ .compatible = "cnxt,cx92755-pinctrl" },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, dc_pinctrl_ids);
static struct platform_driver dc_pinctrl_driver = {
.driver = {
.name = DRIVER_NAME,
.of_match_table = dc_pinctrl_ids,
},
.probe = dc_pinctrl_probe,
.remove = dc_pinctrl_remove,
};
module_platform_driver(dc_pinctrl_driver);

View File

@ -37,6 +37,9 @@
#define LPC18XX_SCU_PIN_EHD_MASK 0x300 #define LPC18XX_SCU_PIN_EHD_MASK 0x300
#define LPC18XX_SCU_PIN_EHD_POS 8 #define LPC18XX_SCU_PIN_EHD_POS 8
#define LPC18XX_SCU_USB1_EPD BIT(2)
#define LPC18XX_SCU_USB1_EPWR BIT(4)
#define LPC18XX_SCU_I2C0_EFP BIT(0) #define LPC18XX_SCU_I2C0_EFP BIT(0)
#define LPC18XX_SCU_I2C0_EHD BIT(2) #define LPC18XX_SCU_I2C0_EHD BIT(2)
#define LPC18XX_SCU_I2C0_EZI BIT(3) #define LPC18XX_SCU_I2C0_EZI BIT(3)
@ -617,8 +620,31 @@ static const struct pinctrl_pin_desc lpc18xx_pins[] = {
static int lpc18xx_pconf_get_usb1(enum pin_config_param param, int *arg, u32 reg) static int lpc18xx_pconf_get_usb1(enum pin_config_param param, int *arg, u32 reg)
{ {
/* TODO */ switch (param) {
return -ENOTSUPP; case PIN_CONFIG_LOW_POWER_MODE:
if (reg & LPC18XX_SCU_USB1_EPWR)
*arg = 0;
else
*arg = 1;
break;
case PIN_CONFIG_BIAS_DISABLE:
if (reg & LPC18XX_SCU_USB1_EPD)
return -EINVAL;
break;
case PIN_CONFIG_BIAS_PULL_DOWN:
if (reg & LPC18XX_SCU_USB1_EPD)
*arg = 1;
else
return -EINVAL;
break;
default:
return -ENOTSUPP;
}
return 0;
} }
static int lpc18xx_pconf_get_i2c0(enum pin_config_param param, int *arg, u32 reg, static int lpc18xx_pconf_get_i2c0(enum pin_config_param param, int *arg, u32 reg,
@ -782,8 +808,28 @@ static int lpc18xx_pconf_set_usb1(struct pinctrl_dev *pctldev,
enum pin_config_param param, enum pin_config_param param,
u16 param_val, u32 *reg) u16 param_val, u32 *reg)
{ {
/* TODO */ switch (param) {
return -ENOTSUPP; case PIN_CONFIG_LOW_POWER_MODE:
if (param_val)
*reg &= ~LPC18XX_SCU_USB1_EPWR;
else
*reg |= LPC18XX_SCU_USB1_EPWR;
break;
case PIN_CONFIG_BIAS_DISABLE:
*reg &= ~LPC18XX_SCU_USB1_EPD;
break;
case PIN_CONFIG_BIAS_PULL_DOWN:
*reg |= LPC18XX_SCU_USB1_EPD;
break;
default:
dev_err(pctldev->dev, "Property not supported\n");
return -ENOTSUPP;
}
return 0;
} }
static int lpc18xx_pconf_set_i2c0(struct pinctrl_dev *pctldev, static int lpc18xx_pconf_set_i2c0(struct pinctrl_dev *pctldev,

View File

@ -1310,9 +1310,11 @@ static int pistachio_gpio_irq_set_type(struct irq_data *data, unsigned int type)
return 0; return 0;
} }
static void pistachio_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) static void pistachio_gpio_irq_handler(unsigned int __irq,
struct irq_desc *desc)
{ {
struct gpio_chip *gc = irq_get_handler_data(irq); unsigned int irq = irq_desc_get_irq(desc);
struct gpio_chip *gc = irq_desc_get_handler_data(desc);
struct pistachio_gpio_bank *bank = gc_to_bank(gc); struct pistachio_gpio_bank *bank = gc_to_bank(gc);
struct irq_chip *chip = irq_get_chip(irq); struct irq_chip *chip = irq_get_chip(irq);
unsigned long pending; unsigned long pending;

View File

@ -945,6 +945,7 @@ static int _rockchip_pmx_gpio_set_direction(struct gpio_chip *chip,
if (ret < 0) if (ret < 0)
return ret; return ret;
clk_enable(bank->clk);
spin_lock_irqsave(&bank->slock, flags); spin_lock_irqsave(&bank->slock, flags);
data = readl_relaxed(bank->reg_base + GPIO_SWPORT_DDR); data = readl_relaxed(bank->reg_base + GPIO_SWPORT_DDR);
@ -956,6 +957,7 @@ static int _rockchip_pmx_gpio_set_direction(struct gpio_chip *chip,
writel_relaxed(data, bank->reg_base + GPIO_SWPORT_DDR); writel_relaxed(data, bank->reg_base + GPIO_SWPORT_DDR);
spin_unlock_irqrestore(&bank->slock, flags); spin_unlock_irqrestore(&bank->slock, flags);
clk_disable(bank->clk);
return 0; return 0;
} }
@ -1389,6 +1391,7 @@ static void rockchip_gpio_set(struct gpio_chip *gc, unsigned offset, int value)
unsigned long flags; unsigned long flags;
u32 data; u32 data;
clk_enable(bank->clk);
spin_lock_irqsave(&bank->slock, flags); spin_lock_irqsave(&bank->slock, flags);
data = readl(reg); data = readl(reg);
@ -1398,6 +1401,7 @@ static void rockchip_gpio_set(struct gpio_chip *gc, unsigned offset, int value)
writel(data, reg); writel(data, reg);
spin_unlock_irqrestore(&bank->slock, flags); spin_unlock_irqrestore(&bank->slock, flags);
clk_disable(bank->clk);
} }
/* /*
@ -1409,7 +1413,9 @@ static int rockchip_gpio_get(struct gpio_chip *gc, unsigned offset)
struct rockchip_pin_bank *bank = gc_to_pin_bank(gc); struct rockchip_pin_bank *bank = gc_to_pin_bank(gc);
u32 data; u32 data;
clk_enable(bank->clk);
data = readl(bank->reg_base + GPIO_EXT_PORT); data = readl(bank->reg_base + GPIO_EXT_PORT);
clk_disable(bank->clk);
data >>= offset; data >>= offset;
data &= 1; data &= 1;
return data; return data;
@ -1469,10 +1475,10 @@ static const struct gpio_chip rockchip_gpiolib_chip = {
* Interrupt handling * Interrupt handling
*/ */
static void rockchip_irq_demux(unsigned int irq, struct irq_desc *desc) static void rockchip_irq_demux(unsigned int __irq, struct irq_desc *desc)
{ {
struct irq_chip *chip = irq_get_chip(irq); struct irq_chip *chip = irq_desc_get_chip(desc);
struct rockchip_pin_bank *bank = irq_get_handler_data(irq); struct rockchip_pin_bank *bank = irq_desc_get_handler_data(desc);
u32 pend; u32 pend;
dev_dbg(bank->drvdata->dev, "got irq for bank %s\n", bank->name); dev_dbg(bank->drvdata->dev, "got irq for bank %s\n", bank->name);
@ -1482,7 +1488,7 @@ static void rockchip_irq_demux(unsigned int irq, struct irq_desc *desc)
pend = readl_relaxed(bank->reg_base + GPIO_INT_STATUS); pend = readl_relaxed(bank->reg_base + GPIO_INT_STATUS);
while (pend) { while (pend) {
unsigned int virq; unsigned int irq, virq;
irq = __ffs(pend); irq = __ffs(pend);
pend &= ~BIT(irq); pend &= ~BIT(irq);
@ -1546,6 +1552,7 @@ static int rockchip_irq_set_type(struct irq_data *d, unsigned int type)
if (ret < 0) if (ret < 0)
return ret; return ret;
clk_enable(bank->clk);
spin_lock_irqsave(&bank->slock, flags); spin_lock_irqsave(&bank->slock, flags);
data = readl_relaxed(bank->reg_base + GPIO_SWPORT_DDR); data = readl_relaxed(bank->reg_base + GPIO_SWPORT_DDR);
@ -1555,9 +1562,9 @@ static int rockchip_irq_set_type(struct irq_data *d, unsigned int type)
spin_unlock_irqrestore(&bank->slock, flags); spin_unlock_irqrestore(&bank->slock, flags);
if (type & IRQ_TYPE_EDGE_BOTH) if (type & IRQ_TYPE_EDGE_BOTH)
__irq_set_handler_locked(d->irq, handle_edge_irq); irq_set_handler_locked(d, handle_edge_irq);
else else
__irq_set_handler_locked(d->irq, handle_level_irq); irq_set_handler_locked(d, handle_level_irq);
spin_lock_irqsave(&bank->slock, flags); spin_lock_irqsave(&bank->slock, flags);
irq_gc_lock(gc); irq_gc_lock(gc);
@ -1603,6 +1610,7 @@ static int rockchip_irq_set_type(struct irq_data *d, unsigned int type)
default: default:
irq_gc_unlock(gc); irq_gc_unlock(gc);
spin_unlock_irqrestore(&bank->slock, flags); spin_unlock_irqrestore(&bank->slock, flags);
clk_disable(bank->clk);
return -EINVAL; return -EINVAL;
} }
@ -1611,6 +1619,7 @@ static int rockchip_irq_set_type(struct irq_data *d, unsigned int type)
irq_gc_unlock(gc); irq_gc_unlock(gc);
spin_unlock_irqrestore(&bank->slock, flags); spin_unlock_irqrestore(&bank->slock, flags);
clk_disable(bank->clk);
return 0; return 0;
} }
@ -1620,8 +1629,10 @@ static void rockchip_irq_suspend(struct irq_data *d)
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
struct rockchip_pin_bank *bank = gc->private; struct rockchip_pin_bank *bank = gc->private;
clk_enable(bank->clk);
bank->saved_masks = irq_reg_readl(gc, GPIO_INTMASK); bank->saved_masks = irq_reg_readl(gc, GPIO_INTMASK);
irq_reg_writel(gc, ~gc->wake_active, GPIO_INTMASK); irq_reg_writel(gc, ~gc->wake_active, GPIO_INTMASK);
clk_disable(bank->clk);
} }
static void rockchip_irq_resume(struct irq_data *d) static void rockchip_irq_resume(struct irq_data *d)
@ -1629,7 +1640,27 @@ static void rockchip_irq_resume(struct irq_data *d)
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
struct rockchip_pin_bank *bank = gc->private; struct rockchip_pin_bank *bank = gc->private;
clk_enable(bank->clk);
irq_reg_writel(gc, bank->saved_masks, GPIO_INTMASK); irq_reg_writel(gc, bank->saved_masks, GPIO_INTMASK);
clk_disable(bank->clk);
}
static void rockchip_irq_gc_mask_clr_bit(struct irq_data *d)
{
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
struct rockchip_pin_bank *bank = gc->private;
clk_enable(bank->clk);
irq_gc_mask_clr_bit(d);
}
void rockchip_irq_gc_mask_set_bit(struct irq_data *d)
{
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
struct rockchip_pin_bank *bank = gc->private;
irq_gc_mask_set_bit(d);
clk_disable(bank->clk);
} }
static int rockchip_interrupts_register(struct platform_device *pdev, static int rockchip_interrupts_register(struct platform_device *pdev,
@ -1640,7 +1671,7 @@ static int rockchip_interrupts_register(struct platform_device *pdev,
unsigned int clr = IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN; unsigned int clr = IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN;
struct irq_chip_generic *gc; struct irq_chip_generic *gc;
int ret; int ret;
int i; int i, j;
for (i = 0; i < ctrl->nr_banks; ++i, ++bank) { for (i = 0; i < ctrl->nr_banks; ++i, ++bank) {
if (!bank->valid) { if (!bank->valid) {
@ -1649,11 +1680,19 @@ static int rockchip_interrupts_register(struct platform_device *pdev,
continue; continue;
} }
ret = clk_enable(bank->clk);
if (ret) {
dev_err(&pdev->dev, "failed to enable clock for bank %s\n",
bank->name);
continue;
}
bank->domain = irq_domain_add_linear(bank->of_node, 32, bank->domain = irq_domain_add_linear(bank->of_node, 32,
&irq_generic_chip_ops, NULL); &irq_generic_chip_ops, NULL);
if (!bank->domain) { if (!bank->domain) {
dev_warn(&pdev->dev, "could not initialize irq domain for bank %s\n", dev_warn(&pdev->dev, "could not initialize irq domain for bank %s\n",
bank->name); bank->name);
clk_disable(bank->clk);
continue; continue;
} }
@ -1664,6 +1703,7 @@ static int rockchip_interrupts_register(struct platform_device *pdev,
dev_err(&pdev->dev, "could not alloc generic chips for bank %s\n", dev_err(&pdev->dev, "could not alloc generic chips for bank %s\n",
bank->name); bank->name);
irq_domain_remove(bank->domain); irq_domain_remove(bank->domain);
clk_disable(bank->clk);
continue; continue;
} }
@ -1681,16 +1721,23 @@ static int rockchip_interrupts_register(struct platform_device *pdev,
gc->chip_types[0].regs.mask = GPIO_INTMASK; gc->chip_types[0].regs.mask = GPIO_INTMASK;
gc->chip_types[0].regs.ack = GPIO_PORTS_EOI; gc->chip_types[0].regs.ack = GPIO_PORTS_EOI;
gc->chip_types[0].chip.irq_ack = irq_gc_ack_set_bit; 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_mask = rockchip_irq_gc_mask_set_bit;
gc->chip_types[0].chip.irq_unmask = irq_gc_mask_clr_bit; gc->chip_types[0].chip.irq_unmask =
rockchip_irq_gc_mask_clr_bit;
gc->chip_types[0].chip.irq_set_wake = irq_gc_set_wake; 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_suspend = rockchip_irq_suspend;
gc->chip_types[0].chip.irq_resume = rockchip_irq_resume; gc->chip_types[0].chip.irq_resume = rockchip_irq_resume;
gc->chip_types[0].chip.irq_set_type = rockchip_irq_set_type; gc->chip_types[0].chip.irq_set_type = rockchip_irq_set_type;
gc->wake_enabled = IRQ_MSK(bank->nr_pins); gc->wake_enabled = IRQ_MSK(bank->nr_pins);
irq_set_handler_data(bank->irq, bank); irq_set_chained_handler_and_data(bank->irq,
irq_set_chained_handler(bank->irq, rockchip_irq_demux); rockchip_irq_demux, bank);
/* map the gpio irqs here, when the clock is still running */
for (j = 0 ; j < 32 ; j++)
irq_create_mapping(bank->domain, j);
clk_disable(bank->clk);
} }
return 0; return 0;
@ -1808,7 +1855,7 @@ static int rockchip_get_bank_data(struct rockchip_pin_bank *bank,
if (IS_ERR(bank->clk)) if (IS_ERR(bank->clk))
return PTR_ERR(bank->clk); return PTR_ERR(bank->clk);
return clk_prepare_enable(bank->clk); return clk_prepare(bank->clk);
} }
static const struct of_device_id rockchip_pinctrl_dt_match[]; static const struct of_device_id rockchip_pinctrl_dt_match[];

View File

@ -1684,7 +1684,7 @@ static void pcs_irq_chain_handler(unsigned int irq, struct irq_desc *desc)
struct pcs_soc_data *pcs_soc = irq_desc_get_handler_data(desc); struct pcs_soc_data *pcs_soc = irq_desc_get_handler_data(desc);
struct irq_chip *chip; struct irq_chip *chip;
chip = irq_get_chip(irq); chip = irq_desc_get_chip(desc);
chained_irq_enter(chip, desc); chained_irq_enter(chip, desc);
pcs_irq_handle(pcs_soc); pcs_irq_handle(pcs_soc);
/* REVISIT: export and add handle_bad_irq(irq, desc)? */ /* REVISIT: export and add handle_bad_irq(irq, desc)? */
@ -1716,12 +1716,7 @@ static int pcs_irqdomain_map(struct irq_domain *d, unsigned int irq,
irq_set_chip_data(irq, pcs_soc); irq_set_chip_data(irq, pcs_soc);
irq_set_chip_and_handler(irq, &pcs->chip, irq_set_chip_and_handler(irq, &pcs->chip,
handle_level_irq); handle_level_irq);
#ifdef CONFIG_ARM
set_irq_flags(irq, IRQF_VALID);
#else
irq_set_noprobe(irq); irq_set_noprobe(irq);
#endif
return 0; return 0;
} }
@ -1768,9 +1763,9 @@ static int pcs_irq_init_chained_handler(struct pcs_device *pcs,
return res; return res;
} }
} else { } else {
irq_set_handler_data(pcs_soc->irq, pcs_soc); irq_set_chained_handler_and_data(pcs_soc->irq,
irq_set_chained_handler(pcs_soc->irq, pcs_irq_chain_handler,
pcs_irq_chain_handler); pcs_soc);
} }
/* /*
@ -1983,7 +1978,6 @@ static const struct pcs_soc_data pinctrl_single_omap_wkup = {
}; };
static const struct pcs_soc_data pinctrl_single_dra7 = { static const struct pcs_soc_data pinctrl_single_dra7 = {
.flags = PCS_QUIRK_SHARED_IRQ,
.irq_enable_mask = (1 << 24), /* WAKEUPENABLE */ .irq_enable_mask = (1 << 24), /* WAKEUPENABLE */
.irq_status_mask = (1 << 25), /* WAKEUPEVENT */ .irq_status_mask = (1 << 25), /* WAKEUPEVENT */
}; };

View File

@ -1463,7 +1463,7 @@ static void __gpio_irq_handler(struct st_gpio_bank *bank)
static void st_gpio_irq_handler(unsigned irq, struct irq_desc *desc) static void st_gpio_irq_handler(unsigned irq, struct irq_desc *desc)
{ {
/* interrupt dedicated per bank */ /* interrupt dedicated per bank */
struct irq_chip *chip = irq_get_chip(irq); struct irq_chip *chip = irq_desc_get_chip(desc);
struct gpio_chip *gc = irq_desc_get_handler_data(desc); struct gpio_chip *gc = irq_desc_get_handler_data(desc);
struct st_gpio_bank *bank = gpio_chip_to_bank(gc); struct st_gpio_bank *bank = gpio_chip_to_bank(gc);
@ -1474,8 +1474,8 @@ static void st_gpio_irq_handler(unsigned irq, struct irq_desc *desc)
static void st_gpio_irqmux_handler(unsigned irq, struct irq_desc *desc) static void st_gpio_irqmux_handler(unsigned irq, struct irq_desc *desc)
{ {
struct irq_chip *chip = irq_get_chip(irq); struct irq_chip *chip = irq_desc_get_chip(desc);
struct st_pinctrl *info = irq_get_handler_data(irq); struct st_pinctrl *info = irq_desc_get_handler_data(desc);
unsigned long status; unsigned long status;
int n; int n;

View File

@ -706,10 +706,10 @@ static const char * const sdio1_wp_groups[] = {"gpio0_0_grp",
"gpio0_39_grp", "gpio0_41_grp", "gpio0_43_grp", "gpio0_39_grp", "gpio0_41_grp", "gpio0_43_grp",
"gpio0_45_grp", "gpio0_47_grp", "gpio0_49_grp", "gpio0_45_grp", "gpio0_47_grp", "gpio0_49_grp",
"gpio0_51_grp", "gpio0_53_grp", "sdio1_emio_wp_grp"}; "gpio0_51_grp", "gpio0_53_grp", "sdio1_emio_wp_grp"};
static const char * const smc0_nor_groups[] = {"smc0_nor"}; static const char * const smc0_nor_groups[] = {"smc0_nor_grp"};
static const char * const smc0_nor_cs1_groups[] = {"smc0_nor_cs1_grp"}; static const char * const smc0_nor_cs1_groups[] = {"smc0_nor_cs1_grp"};
static const char * const smc0_nor_addr25_groups[] = {"smc0_nor_addr25_grp"}; static const char * const smc0_nor_addr25_groups[] = {"smc0_nor_addr25_grp"};
static const char * const smc0_nand_groups[] = {"smc0_nand"}; static const char * const smc0_nand_groups[] = {"smc0_nand_grp"};
static const char * const can0_groups[] = {"can0_0_grp", "can0_1_grp", static const char * const can0_groups[] = {"can0_0_grp", "can0_1_grp",
"can0_2_grp", "can0_3_grp", "can0_4_grp", "can0_5_grp", "can0_2_grp", "can0_3_grp", "can0_4_grp", "can0_5_grp",
"can0_6_grp", "can0_7_grp", "can0_8_grp", "can0_9_grp", "can0_6_grp", "can0_7_grp", "can0_8_grp", "can0_9_grp",

View File

@ -322,8 +322,7 @@ static int pinmux_func_name_to_selector(struct pinctrl_dev *pctldev,
selector++; selector++;
} }
pr_err("%s does not support function %s\n", dev_err(pctldev->dev, "function '%s' not supported\n", function);
pinctrl_dev_get_name(pctldev), function);
return -EINVAL; return -EINVAL;
} }

View File

@ -63,6 +63,14 @@ config PINCTRL_MSM8916
This is the pinctrl, pinmux, pinconf and gpiolib driver for the This is the pinctrl, pinmux, pinconf and gpiolib driver for the
Qualcomm TLMM block found on the Qualcomm 8916 platform. Qualcomm TLMM block found on the Qualcomm 8916 platform.
config PINCTRL_QDF2XXX
tristate "Qualcomm Technologies QDF2xxx pin controller driver"
depends on GPIOLIB && ACPI
select PINCTRL_MSM
help
This is the GPIO driver for the TLMM block found on the
Qualcomm Technologies QDF2xxx SOCs.
config PINCTRL_QCOM_SPMI_PMIC config PINCTRL_QCOM_SPMI_PMIC
tristate "Qualcomm SPMI PMIC pin controller driver" tristate "Qualcomm SPMI PMIC pin controller driver"
depends on GPIOLIB && OF && SPMI depends on GPIOLIB && OF && SPMI
@ -76,4 +84,16 @@ config PINCTRL_QCOM_SPMI_PMIC
which are using SPMI for communication with SoC. Example PMIC's which are using SPMI for communication with SoC. Example PMIC's
devices are pm8841, pm8941 and pma8084. devices are pm8841, pm8941 and pma8084.
config PINCTRL_QCOM_SSBI_PMIC
tristate "Qualcomm SSBI PMIC pin controller driver"
depends on GPIOLIB && OF
select PINMUX
select PINCONF
select GENERIC_PINCONF
help
This is the pinctrl, pinmux, pinconf and gpiolib driver for the
Qualcomm GPIO and MPP blocks found in the Qualcomm PMIC's chips,
which are using SSBI for communication with SoC. Example PMIC's
devices are pm8058 and pm8921.
endif endif

View File

@ -7,5 +7,8 @@ obj-$(CONFIG_PINCTRL_MSM8660) += pinctrl-msm8660.o
obj-$(CONFIG_PINCTRL_MSM8960) += pinctrl-msm8960.o obj-$(CONFIG_PINCTRL_MSM8960) += pinctrl-msm8960.o
obj-$(CONFIG_PINCTRL_MSM8X74) += pinctrl-msm8x74.o obj-$(CONFIG_PINCTRL_MSM8X74) += pinctrl-msm8x74.o
obj-$(CONFIG_PINCTRL_MSM8916) += pinctrl-msm8916.o obj-$(CONFIG_PINCTRL_MSM8916) += pinctrl-msm8916.o
obj-$(CONFIG_PINCTRL_QDF2XXX) += pinctrl-qdf2xxx.o
obj-$(CONFIG_PINCTRL_QCOM_SPMI_PMIC) += pinctrl-spmi-gpio.o obj-$(CONFIG_PINCTRL_QCOM_SPMI_PMIC) += pinctrl-spmi-gpio.o
obj-$(CONFIG_PINCTRL_QCOM_SPMI_PMIC) += pinctrl-spmi-mpp.o obj-$(CONFIG_PINCTRL_QCOM_SPMI_PMIC) += pinctrl-spmi-mpp.o
obj-$(CONFIG_PINCTRL_QCOM_SSBI_PMIC) += pinctrl-ssbi-gpio.o
obj-$(CONFIG_PINCTRL_QCOM_SSBI_PMIC) += pinctrl-ssbi-mpp.o

View File

@ -28,6 +28,7 @@
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/reboot.h> #include <linux/reboot.h>
#include <linux/pm.h>
#include "../core.h" #include "../core.h"
#include "../pinconf.h" #include "../pinconf.h"
@ -733,9 +734,9 @@ static int msm_gpio_irq_set_type(struct irq_data *d, unsigned int type)
spin_unlock_irqrestore(&pctrl->lock, flags); spin_unlock_irqrestore(&pctrl->lock, flags);
if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH)) if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
__irq_set_handler_locked(d->irq, handle_level_irq); irq_set_handler_locked(d, handle_level_irq);
else if (type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)) else if (type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
__irq_set_handler_locked(d->irq, handle_edge_irq); irq_set_handler_locked(d, handle_edge_irq);
return 0; return 0;
} }
@ -764,12 +765,13 @@ static struct irq_chip msm_gpio_irq_chip = {
.irq_set_wake = msm_gpio_irq_set_wake, .irq_set_wake = msm_gpio_irq_set_wake,
}; };
static void msm_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) static void msm_gpio_irq_handler(unsigned int __irq, struct irq_desc *desc)
{ {
unsigned int irq = irq_desc_get_irq(desc);
struct gpio_chip *gc = irq_desc_get_handler_data(desc); struct gpio_chip *gc = irq_desc_get_handler_data(desc);
const struct msm_pingroup *g; const struct msm_pingroup *g;
struct msm_pinctrl *pctrl = to_msm_pinctrl(gc); struct msm_pinctrl *pctrl = to_msm_pinctrl(gc);
struct irq_chip *chip = irq_get_chip(irq); struct irq_chip *chip = irq_desc_get_chip(desc);
int irq_pin; int irq_pin;
int handled = 0; int handled = 0;
u32 val; u32 val;
@ -855,6 +857,13 @@ static int msm_ps_hold_restart(struct notifier_block *nb, unsigned long action,
return NOTIFY_DONE; return NOTIFY_DONE;
} }
static struct msm_pinctrl *poweroff_pctrl;
static void msm_ps_hold_poweroff(void)
{
msm_ps_hold_restart(&poweroff_pctrl->restart_nb, 0, NULL);
}
static void msm_pinctrl_setup_pm_reset(struct msm_pinctrl *pctrl) static void msm_pinctrl_setup_pm_reset(struct msm_pinctrl *pctrl)
{ {
int i; int i;
@ -867,6 +876,8 @@ static void msm_pinctrl_setup_pm_reset(struct msm_pinctrl *pctrl)
if (register_restart_handler(&pctrl->restart_nb)) if (register_restart_handler(&pctrl->restart_nb))
dev_err(pctrl->dev, dev_err(pctrl->dev,
"failed to setup restart handler.\n"); "failed to setup restart handler.\n");
poweroff_pctrl = pctrl;
pm_power_off = msm_ps_hold_poweroff;
break; break;
} }
} }

View File

@ -0,0 +1,122 @@
/*
* Copyright (c) 2015, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* GPIO and pin control functions on this SOC are handled by the "TLMM"
* device. The driver which controls this device is pinctrl-msm.c. Each
* SOC with a TLMM is expected to create a client driver that registers
* with pinctrl-msm.c. This means that all TLMM drivers are pin control
* drivers.
*
* This pin control driver is intended to be used only an ACPI-enabled
* system. As such, UEFI will handle all pin control configuration, so
* this driver does not provide pin control functions. It is effectively
* a GPIO-only driver. The alternative is to duplicate the GPIO code of
* pinctrl-msm.c into another driver.
*/
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/pinctrl/pinctrl.h>
#include <linux/acpi.h>
#include "pinctrl-msm.h"
static struct msm_pinctrl_soc_data qdf2xxx_pinctrl;
static int qdf2xxx_pinctrl_probe(struct platform_device *pdev)
{
struct pinctrl_pin_desc *pins;
struct msm_pingroup *groups;
unsigned int i;
u32 num_gpios;
int ret;
/* Query the number of GPIOs from ACPI */
ret = device_property_read_u32(&pdev->dev, "num-gpios", &num_gpios);
if (ret < 0)
return ret;
if (!num_gpios) {
dev_warn(&pdev->dev, "missing num-gpios property\n");
return -ENODEV;
}
pins = devm_kcalloc(&pdev->dev, num_gpios,
sizeof(struct pinctrl_pin_desc), GFP_KERNEL);
groups = devm_kcalloc(&pdev->dev, num_gpios,
sizeof(struct msm_pingroup), GFP_KERNEL);
for (i = 0; i < num_gpios; i++) {
pins[i].number = i;
groups[i].npins = 1,
groups[i].pins = &pins[i].number;
groups[i].ctl_reg = 0x10000 * i;
groups[i].io_reg = 0x04 + 0x10000 * i;
groups[i].intr_cfg_reg = 0x08 + 0x10000 * i;
groups[i].intr_status_reg = 0x0c + 0x10000 * i;
groups[i].intr_target_reg = 0x08 + 0x10000 * i;
groups[i].mux_bit = 2;
groups[i].pull_bit = 0;
groups[i].drv_bit = 6;
groups[i].oe_bit = 9;
groups[i].in_bit = 0;
groups[i].out_bit = 1;
groups[i].intr_enable_bit = 0;
groups[i].intr_status_bit = 0;
groups[i].intr_target_bit = 5;
groups[i].intr_target_kpss_val = 1;
groups[i].intr_raw_status_bit = 4;
groups[i].intr_polarity_bit = 1;
groups[i].intr_detection_bit = 2;
groups[i].intr_detection_width = 2;
}
qdf2xxx_pinctrl.pins = pins;
qdf2xxx_pinctrl.groups = groups;
qdf2xxx_pinctrl.npins = num_gpios;
qdf2xxx_pinctrl.ngroups = num_gpios;
qdf2xxx_pinctrl.ngpios = num_gpios;
return msm_pinctrl_probe(pdev, &qdf2xxx_pinctrl);
}
static const struct acpi_device_id qdf2xxx_acpi_ids[] = {
{"QCOM8001"},
{},
};
MODULE_DEVICE_TABLE(acpi, qdf2xxx_acpi_ids);
static struct platform_driver qdf2xxx_pinctrl_driver = {
.driver = {
.name = "qdf2xxx-pinctrl",
.acpi_match_table = ACPI_PTR(qdf2xxx_acpi_ids),
},
.probe = qdf2xxx_pinctrl_probe,
.remove = msm_pinctrl_remove,
};
static int __init qdf2xxx_pinctrl_init(void)
{
return platform_driver_register(&qdf2xxx_pinctrl_driver);
}
arch_initcall(qdf2xxx_pinctrl_init);
static void __exit qdf2xxx_pinctrl_exit(void)
{
platform_driver_unregister(&qdf2xxx_pinctrl_driver);
}
module_exit(qdf2xxx_pinctrl_exit);
MODULE_DESCRIPTION("Qualcomm Technologies QDF2xxx pin control driver");
MODULE_LICENSE("GPL v2");

View File

@ -61,7 +61,9 @@
#define PMIC_MPP_REG_DIG_PULL_CTL 0x42 #define PMIC_MPP_REG_DIG_PULL_CTL 0x42
#define PMIC_MPP_REG_DIG_IN_CTL 0x43 #define PMIC_MPP_REG_DIG_IN_CTL 0x43
#define PMIC_MPP_REG_EN_CTL 0x46 #define PMIC_MPP_REG_EN_CTL 0x46
#define PMIC_MPP_REG_AOUT_CTL 0x48
#define PMIC_MPP_REG_AIN_CTL 0x4a #define PMIC_MPP_REG_AIN_CTL 0x4a
#define PMIC_MPP_REG_SINK_CTL 0x4c
/* PMIC_MPP_REG_MODE_CTL */ /* PMIC_MPP_REG_MODE_CTL */
#define PMIC_MPP_REG_MODE_VALUE_MASK 0x1 #define PMIC_MPP_REG_MODE_VALUE_MASK 0x1
@ -85,11 +87,25 @@
#define PMIC_MPP_REG_AIN_ROUTE_SHIFT 0 #define PMIC_MPP_REG_AIN_ROUTE_SHIFT 0
#define PMIC_MPP_REG_AIN_ROUTE_MASK 0x7 #define PMIC_MPP_REG_AIN_ROUTE_MASK 0x7
#define PMIC_MPP_MODE_DIGITAL_INPUT 0
#define PMIC_MPP_MODE_DIGITAL_OUTPUT 1
#define PMIC_MPP_MODE_DIGITAL_BIDIR 2
#define PMIC_MPP_MODE_ANALOG_BIDIR 3
#define PMIC_MPP_MODE_ANALOG_INPUT 4
#define PMIC_MPP_MODE_ANALOG_OUTPUT 5
#define PMIC_MPP_MODE_CURRENT_SINK 6
#define PMIC_MPP_SELECTOR_NORMAL 0
#define PMIC_MPP_SELECTOR_PAIRED 1
#define PMIC_MPP_SELECTOR_DTEST_FIRST 4
#define PMIC_MPP_PHYSICAL_OFFSET 1 #define PMIC_MPP_PHYSICAL_OFFSET 1
/* Qualcomm specific pin configurations */ /* Qualcomm specific pin configurations */
#define PMIC_MPP_CONF_AMUX_ROUTE (PIN_CONFIG_END + 1) #define PMIC_MPP_CONF_AMUX_ROUTE (PIN_CONFIG_END + 1)
#define PMIC_MPP_CONF_ANALOG_MODE (PIN_CONFIG_END + 2) #define PMIC_MPP_CONF_ANALOG_LEVEL (PIN_CONFIG_END + 2)
#define PMIC_MPP_CONF_DTEST_SELECTOR (PIN_CONFIG_END + 3)
#define PMIC_MPP_CONF_PAIRED (PIN_CONFIG_END + 4)
/** /**
* struct pmic_mpp_pad - keep current MPP settings * struct pmic_mpp_pad - keep current MPP settings
@ -99,13 +115,15 @@
* @out_value: Cached pin output value. * @out_value: Cached pin output value.
* @output_enabled: Set to true if MPP output logic is enabled. * @output_enabled: Set to true if MPP output logic is enabled.
* @input_enabled: Set to true if MPP input buffer logic is enabled. * @input_enabled: Set to true if MPP input buffer logic is enabled.
* @analog_mode: Set to true when MPP should operate in Analog Input, Analog * @paired: Pin operates in paired mode
* Output or Bidirectional Analog mode.
* @num_sources: Number of power-sources supported by this MPP. * @num_sources: Number of power-sources supported by this MPP.
* @power_source: Current power-source used. * @power_source: Current power-source used.
* @amux_input: Set the source for analog input. * @amux_input: Set the source for analog input.
* @aout_level: Analog output level
* @pullup: Pullup resistor value. Valid in Bidirectional mode only. * @pullup: Pullup resistor value. Valid in Bidirectional mode only.
* @function: See pmic_mpp_functions[]. * @function: See pmic_mpp_functions[].
* @drive_strength: Amount of current in sink mode
* @dtest: DTEST route selector
*/ */
struct pmic_mpp_pad { struct pmic_mpp_pad {
u16 base; u16 base;
@ -114,12 +132,15 @@ struct pmic_mpp_pad {
bool out_value; bool out_value;
bool output_enabled; bool output_enabled;
bool input_enabled; bool input_enabled;
bool analog_mode; bool paired;
unsigned int num_sources; unsigned int num_sources;
unsigned int power_source; unsigned int power_source;
unsigned int amux_input; unsigned int amux_input;
unsigned int aout_level;
unsigned int pullup; unsigned int pullup;
unsigned int function; unsigned int function;
unsigned int drive_strength;
unsigned int dtest;
}; };
struct pmic_mpp_state { struct pmic_mpp_state {
@ -129,25 +150,32 @@ struct pmic_mpp_state {
struct gpio_chip chip; struct gpio_chip chip;
}; };
struct pmic_mpp_bindings { static const struct pinconf_generic_params pmic_mpp_bindings[] = {
const char *property; {"qcom,amux-route", PMIC_MPP_CONF_AMUX_ROUTE, 0},
unsigned param; {"qcom,analog-level", PMIC_MPP_CONF_ANALOG_LEVEL, 0},
{"qcom,dtest", PMIC_MPP_CONF_DTEST_SELECTOR, 0},
{"qcom,paired", PMIC_MPP_CONF_PAIRED, 0},
}; };
static struct pmic_mpp_bindings pmic_mpp_bindings[] = { #ifdef CONFIG_DEBUG_FS
{"qcom,amux-route", PMIC_MPP_CONF_AMUX_ROUTE}, static const struct pin_config_item pmic_conf_items[] = {
{"qcom,analog-mode", PMIC_MPP_CONF_ANALOG_MODE}, PCONFDUMP(PMIC_MPP_CONF_AMUX_ROUTE, "analog mux", NULL, true),
PCONFDUMP(PMIC_MPP_CONF_ANALOG_LEVEL, "analog level", NULL, true),
PCONFDUMP(PMIC_MPP_CONF_DTEST_SELECTOR, "dtest", NULL, true),
PCONFDUMP(PMIC_MPP_CONF_PAIRED, "paired", NULL, false),
}; };
#endif
static const char *const pmic_mpp_groups[] = { static const char *const pmic_mpp_groups[] = {
"mpp1", "mpp2", "mpp3", "mpp4", "mpp5", "mpp6", "mpp7", "mpp8", "mpp1", "mpp2", "mpp3", "mpp4", "mpp5", "mpp6", "mpp7", "mpp8",
}; };
#define PMIC_MPP_DIGITAL 0
#define PMIC_MPP_ANALOG 1
#define PMIC_MPP_SINK 2
static const char *const pmic_mpp_functions[] = { static const char *const pmic_mpp_functions[] = {
PMIC_MPP_FUNC_NORMAL, PMIC_MPP_FUNC_PAIRED, "digital", "analog", "sink"
"reserved1", "reserved2",
PMIC_MPP_FUNC_DTEST1, PMIC_MPP_FUNC_DTEST2,
PMIC_MPP_FUNC_DTEST3, PMIC_MPP_FUNC_DTEST4,
}; };
static inline struct pmic_mpp_state *to_mpp_state(struct gpio_chip *chip) static inline struct pmic_mpp_state *to_mpp_state(struct gpio_chip *chip)
@ -204,118 +232,11 @@ static int pmic_mpp_get_group_pins(struct pinctrl_dev *pctldev,
return 0; return 0;
} }
static int pmic_mpp_parse_dt_config(struct device_node *np,
struct pinctrl_dev *pctldev,
unsigned long **configs,
unsigned int *nconfs)
{
struct pmic_mpp_bindings *par;
unsigned long cfg;
int ret, i;
u32 val;
for (i = 0; i < ARRAY_SIZE(pmic_mpp_bindings); i++) {
par = &pmic_mpp_bindings[i];
ret = of_property_read_u32(np, par->property, &val);
/* property not found */
if (ret == -EINVAL)
continue;
/* use zero as default value, when no value is specified */
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_mpp_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_mpp_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_mpp_dt_node_to_map(struct pinctrl_dev *pctldev,
struct device_node *np_config,
struct pinctrl_map **map, unsigned *nmaps)
{
struct device_node *np;
enum pinctrl_map_type type;
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_mpp_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_mpp_pinctrl_ops = { static const struct pinctrl_ops pmic_mpp_pinctrl_ops = {
.get_groups_count = pmic_mpp_get_groups_count, .get_groups_count = pmic_mpp_get_groups_count,
.get_group_name = pmic_mpp_get_group_name, .get_group_name = pmic_mpp_get_group_name,
.get_group_pins = pmic_mpp_get_group_pins, .get_group_pins = pmic_mpp_get_group_pins,
.dt_node_to_map = pmic_mpp_dt_node_to_map, .dt_node_to_map = pinconf_generic_dt_node_to_map_group,
.dt_free_map = pinctrl_utils_dt_free_map, .dt_free_map = pinctrl_utils_dt_free_map,
}; };
@ -340,6 +261,53 @@ static int pmic_mpp_get_function_groups(struct pinctrl_dev *pctldev,
return 0; return 0;
} }
static int pmic_mpp_write_mode_ctl(struct pmic_mpp_state *state,
struct pmic_mpp_pad *pad)
{
unsigned int mode;
unsigned int sel;
unsigned int val;
unsigned int en;
switch (pad->function) {
case PMIC_MPP_ANALOG:
if (pad->input_enabled && pad->output_enabled)
mode = PMIC_MPP_MODE_ANALOG_BIDIR;
else if (pad->input_enabled)
mode = PMIC_MPP_MODE_ANALOG_INPUT;
else
mode = PMIC_MPP_MODE_ANALOG_OUTPUT;
break;
case PMIC_MPP_DIGITAL:
if (pad->input_enabled && pad->output_enabled)
mode = PMIC_MPP_MODE_DIGITAL_BIDIR;
else if (pad->input_enabled)
mode = PMIC_MPP_MODE_DIGITAL_INPUT;
else
mode = PMIC_MPP_MODE_DIGITAL_OUTPUT;
break;
case PMIC_MPP_SINK:
default:
mode = PMIC_MPP_MODE_CURRENT_SINK;
break;
}
if (pad->dtest)
sel = PMIC_MPP_SELECTOR_DTEST_FIRST + pad->dtest - 1;
else if (pad->paired)
sel = PMIC_MPP_SELECTOR_PAIRED;
else
sel = PMIC_MPP_SELECTOR_NORMAL;
en = !!pad->out_value;
val = mode << PMIC_MPP_REG_MODE_DIR_SHIFT |
sel << PMIC_MPP_REG_MODE_FUNCTION_SHIFT |
en;
return pmic_mpp_write(state, pad, PMIC_MPP_REG_MODE_CTL, val);
}
static int pmic_mpp_set_mux(struct pinctrl_dev *pctldev, unsigned function, static int pmic_mpp_set_mux(struct pinctrl_dev *pctldev, unsigned function,
unsigned pin) unsigned pin)
{ {
@ -352,31 +320,7 @@ static int pmic_mpp_set_mux(struct pinctrl_dev *pctldev, unsigned function,
pad->function = function; pad->function = function;
if (!pad->analog_mode) { ret = pmic_mpp_write_mode_ctl(state, pad);
val = 0; /* just digital input */
if (pad->output_enabled) {
if (pad->input_enabled)
val = 2; /* digital input and output */
else
val = 1; /* just digital output */
}
} else {
val = 4; /* just analog input */
if (pad->output_enabled) {
if (pad->input_enabled)
val = 3; /* analog input and output */
else
val = 5; /* just analog output */
}
}
val = val << PMIC_MPP_REG_MODE_DIR_SHIFT;
val |= pad->function << PMIC_MPP_REG_MODE_FUNCTION_SHIFT;
val |= pad->out_value & PMIC_MPP_REG_MODE_VALUE_MASK;
ret = pmic_mpp_write(state, pad, PMIC_MPP_REG_MODE_CTL, val);
if (ret < 0)
return ret;
val = pad->is_enabled << PMIC_MPP_REG_MASTER_EN_SHIFT; val = pad->is_enabled << PMIC_MPP_REG_MASTER_EN_SHIFT;
@ -433,11 +377,20 @@ static int pmic_mpp_config_get(struct pinctrl_dev *pctldev,
case PIN_CONFIG_OUTPUT: case PIN_CONFIG_OUTPUT:
arg = pad->out_value; arg = pad->out_value;
break; break;
case PMIC_MPP_CONF_DTEST_SELECTOR:
arg = pad->dtest;
break;
case PMIC_MPP_CONF_AMUX_ROUTE: case PMIC_MPP_CONF_AMUX_ROUTE:
arg = pad->amux_input; arg = pad->amux_input;
break; break;
case PMIC_MPP_CONF_ANALOG_MODE: case PMIC_MPP_CONF_PAIRED:
arg = pad->analog_mode; arg = pad->paired;
break;
case PIN_CONFIG_DRIVE_STRENGTH:
arg = pad->drive_strength;
break;
case PMIC_MPP_CONF_ANALOG_LEVEL:
arg = pad->aout_level;
break; break;
default: default:
return -EINVAL; return -EINVAL;
@ -459,6 +412,9 @@ static int pmic_mpp_config_set(struct pinctrl_dev *pctldev, unsigned int pin,
pad = pctldev->desc->pins[pin].drv_data; pad = pctldev->desc->pins[pin].drv_data;
/* Make it possible to enable the pin, by not setting high impedance */
pad->is_enabled = true;
for (i = 0; i < nconfs; i++) { for (i = 0; i < nconfs; i++) {
param = pinconf_to_config_param(configs[i]); param = pinconf_to_config_param(configs[i]);
arg = pinconf_to_config_argument(configs[i]); arg = pinconf_to_config_argument(configs[i]);
@ -497,13 +453,22 @@ static int pmic_mpp_config_set(struct pinctrl_dev *pctldev, unsigned int pin,
pad->output_enabled = true; pad->output_enabled = true;
pad->out_value = arg; pad->out_value = arg;
break; break;
case PMIC_MPP_CONF_DTEST_SELECTOR:
pad->dtest = arg;
break;
case PIN_CONFIG_DRIVE_STRENGTH:
arg = pad->drive_strength;
break;
case PMIC_MPP_CONF_AMUX_ROUTE: case PMIC_MPP_CONF_AMUX_ROUTE:
if (arg >= PMIC_MPP_AMUX_ROUTE_ABUS4) if (arg >= PMIC_MPP_AMUX_ROUTE_ABUS4)
return -EINVAL; return -EINVAL;
pad->amux_input = arg; pad->amux_input = arg;
break; break;
case PMIC_MPP_CONF_ANALOG_MODE: case PMIC_MPP_CONF_ANALOG_LEVEL:
pad->analog_mode = true; pad->aout_level = arg;
break;
case PMIC_MPP_CONF_PAIRED:
pad->paired = !!arg;
break; break;
default: default:
return -EINVAL; return -EINVAL;
@ -528,29 +493,17 @@ static int pmic_mpp_config_set(struct pinctrl_dev *pctldev, unsigned int pin,
if (ret < 0) if (ret < 0)
return ret; return ret;
if (!pad->analog_mode) { ret = pmic_mpp_write(state, pad, PMIC_MPP_REG_AOUT_CTL, pad->aout_level);
val = 0; /* just digital input */ if (ret < 0)
if (pad->output_enabled) { return ret;
if (pad->input_enabled)
val = 2; /* digital input and output */
else
val = 1; /* just digital output */
}
} else {
val = 4; /* just analog input */
if (pad->output_enabled) {
if (pad->input_enabled)
val = 3; /* analog input and output */
else
val = 5; /* just analog output */
}
}
val = val << PMIC_MPP_REG_MODE_DIR_SHIFT; ret = pmic_mpp_write_mode_ctl(state, pad);
val |= pad->function << PMIC_MPP_REG_MODE_FUNCTION_SHIFT; if (ret < 0)
val |= pad->out_value & PMIC_MPP_REG_MODE_VALUE_MASK; return ret;
return pmic_mpp_write(state, pad, PMIC_MPP_REG_MODE_CTL, val); val = pad->is_enabled << PMIC_MPP_REG_MASTER_EN_SHIFT;
return pmic_mpp_write(state, pad, PMIC_MPP_REG_EN_CTL, val);
} }
static void pmic_mpp_config_dbg_show(struct pinctrl_dev *pctldev, static void pmic_mpp_config_dbg_show(struct pinctrl_dev *pctldev,
@ -558,20 +511,17 @@ static void pmic_mpp_config_dbg_show(struct pinctrl_dev *pctldev,
{ {
struct pmic_mpp_state *state = pinctrl_dev_get_drvdata(pctldev); struct pmic_mpp_state *state = pinctrl_dev_get_drvdata(pctldev);
struct pmic_mpp_pad *pad; struct pmic_mpp_pad *pad;
int ret, val; int ret;
static const char *const biases[] = { static const char *const biases[] = {
"0.6kOhm", "10kOhm", "30kOhm", "Disabled" "0.6kOhm", "10kOhm", "30kOhm", "Disabled"
}; };
pad = pctldev->desc->pins[pin].drv_data; pad = pctldev->desc->pins[pin].drv_data;
seq_printf(s, " mpp%-2d:", pin + PMIC_MPP_PHYSICAL_OFFSET); seq_printf(s, " mpp%-2d:", pin + PMIC_MPP_PHYSICAL_OFFSET);
val = pmic_mpp_read(state, pad, PMIC_MPP_REG_EN_CTL); if (!pad->is_enabled) {
if (val < 0 || !(val >> PMIC_MPP_REG_MASTER_EN_SHIFT)) {
seq_puts(s, " ---"); seq_puts(s, " ---");
} else { } else {
@ -585,15 +535,20 @@ static void pmic_mpp_config_dbg_show(struct pinctrl_dev *pctldev,
} }
seq_printf(s, " %-4s", pad->output_enabled ? "out" : "in"); seq_printf(s, " %-4s", pad->output_enabled ? "out" : "in");
seq_printf(s, " %-4s", pad->analog_mode ? "ana" : "dig");
seq_printf(s, " %-7s", pmic_mpp_functions[pad->function]); seq_printf(s, " %-7s", pmic_mpp_functions[pad->function]);
seq_printf(s, " vin-%d", pad->power_source); seq_printf(s, " vin-%d", pad->power_source);
seq_printf(s, " %d", pad->aout_level);
seq_printf(s, " %-8s", biases[pad->pullup]); seq_printf(s, " %-8s", biases[pad->pullup]);
seq_printf(s, " %-4s", pad->out_value ? "high" : "low"); seq_printf(s, " %-4s", pad->out_value ? "high" : "low");
if (pad->dtest)
seq_printf(s, " dtest%d", pad->dtest);
if (pad->paired)
seq_puts(s, " paired");
} }
} }
static const struct pinconf_ops pmic_mpp_pinconf_ops = { static const struct pinconf_ops pmic_mpp_pinconf_ops = {
.is_generic = true,
.pin_config_group_get = pmic_mpp_config_get, .pin_config_group_get = pmic_mpp_config_get,
.pin_config_group_set = pmic_mpp_config_set, .pin_config_group_set = pmic_mpp_config_set,
.pin_config_group_dbg_show = pmic_mpp_config_dbg_show, .pin_config_group_dbg_show = pmic_mpp_config_dbg_show,
@ -709,6 +664,7 @@ static int pmic_mpp_populate(struct pmic_mpp_state *state,
struct pmic_mpp_pad *pad) struct pmic_mpp_pad *pad)
{ {
int type, subtype, val, dir; int type, subtype, val, dir;
unsigned int sel;
type = pmic_mpp_read(state, pad, PMIC_MPP_REG_TYPE); type = pmic_mpp_read(state, pad, PMIC_MPP_REG_TYPE);
if (type < 0) if (type < 0)
@ -751,43 +707,53 @@ static int pmic_mpp_populate(struct pmic_mpp_state *state,
dir &= PMIC_MPP_REG_MODE_DIR_MASK; dir &= PMIC_MPP_REG_MODE_DIR_MASK;
switch (dir) { switch (dir) {
case 0: case PMIC_MPP_MODE_DIGITAL_INPUT:
pad->input_enabled = true; pad->input_enabled = true;
pad->output_enabled = false; pad->output_enabled = false;
pad->analog_mode = false; pad->function = PMIC_MPP_DIGITAL;
break; break;
case 1: case PMIC_MPP_MODE_DIGITAL_OUTPUT:
pad->input_enabled = false; pad->input_enabled = false;
pad->output_enabled = true; pad->output_enabled = true;
pad->analog_mode = false; pad->function = PMIC_MPP_DIGITAL;
break; break;
case 2: case PMIC_MPP_MODE_DIGITAL_BIDIR:
pad->input_enabled = true; pad->input_enabled = true;
pad->output_enabled = true; pad->output_enabled = true;
pad->analog_mode = false; pad->function = PMIC_MPP_DIGITAL;
break; break;
case 3: case PMIC_MPP_MODE_ANALOG_BIDIR:
pad->input_enabled = true; pad->input_enabled = true;
pad->output_enabled = true; pad->output_enabled = true;
pad->analog_mode = true; pad->function = PMIC_MPP_ANALOG;
break; break;
case 4: case PMIC_MPP_MODE_ANALOG_INPUT:
pad->input_enabled = true; pad->input_enabled = true;
pad->output_enabled = false; pad->output_enabled = false;
pad->analog_mode = true; pad->function = PMIC_MPP_ANALOG;
break; break;
case 5: case PMIC_MPP_MODE_ANALOG_OUTPUT:
pad->input_enabled = false; pad->input_enabled = false;
pad->output_enabled = true; pad->output_enabled = true;
pad->analog_mode = true; pad->function = PMIC_MPP_ANALOG;
break;
case PMIC_MPP_MODE_CURRENT_SINK:
pad->input_enabled = false;
pad->output_enabled = true;
pad->function = PMIC_MPP_SINK;
break; break;
default: default:
dev_err(state->dev, "unknown MPP direction\n"); dev_err(state->dev, "unknown MPP direction\n");
return -ENODEV; return -ENODEV;
} }
pad->function = val >> PMIC_MPP_REG_MODE_FUNCTION_SHIFT; sel = val >> PMIC_MPP_REG_MODE_FUNCTION_SHIFT;
pad->function &= PMIC_MPP_REG_MODE_FUNCTION_MASK; sel &= PMIC_MPP_REG_MODE_FUNCTION_MASK;
if (sel >= PMIC_MPP_SELECTOR_DTEST_FIRST)
pad->dtest = sel + 1;
else if (sel == PMIC_MPP_SELECTOR_PAIRED)
pad->paired = true;
val = pmic_mpp_read(state, pad, PMIC_MPP_REG_DIG_VIN_CTL); val = pmic_mpp_read(state, pad, PMIC_MPP_REG_DIG_VIN_CTL);
if (val < 0) if (val < 0)
@ -810,8 +776,24 @@ static int pmic_mpp_populate(struct pmic_mpp_state *state,
pad->amux_input = val >> PMIC_MPP_REG_AIN_ROUTE_SHIFT; pad->amux_input = val >> PMIC_MPP_REG_AIN_ROUTE_SHIFT;
pad->amux_input &= PMIC_MPP_REG_AIN_ROUTE_MASK; pad->amux_input &= PMIC_MPP_REG_AIN_ROUTE_MASK;
/* Pin could be disabled with PIN_CONFIG_BIAS_HIGH_IMPEDANCE */ val = pmic_mpp_read(state, pad, PMIC_MPP_REG_SINK_CTL);
pad->is_enabled = true; if (val < 0)
return val;
pad->drive_strength = val;
val = pmic_mpp_read(state, pad, PMIC_MPP_REG_AOUT_CTL);
if (val < 0)
return val;
pad->aout_level = val;
val = pmic_mpp_read(state, pad, PMIC_MPP_REG_EN_CTL);
if (val < 0)
return val;
pad->is_enabled = !!val;
return 0; return 0;
} }
@ -866,6 +848,12 @@ static int pmic_mpp_probe(struct platform_device *pdev)
pctrldesc->pins = pindesc; pctrldesc->pins = pindesc;
pctrldesc->npins = npins; pctrldesc->npins = npins;
pctrldesc->num_custom_params = ARRAY_SIZE(pmic_mpp_bindings);
pctrldesc->custom_params = pmic_mpp_bindings;
#ifdef CONFIG_DEBUG_FS
pctrldesc->custom_conf_items = pmic_conf_items;
#endif
for (i = 0; i < npins; i++, pindesc++) { for (i = 0; i < npins; i++, pindesc++) {
pad = &pads[i]; pad = &pads[i];
pindesc->drv_data = pad; pindesc->drv_data = pad;

View File

@ -0,0 +1,791 @@
/*
* Copyright (c) 2015, Sony Mobile Communications AB.
* Copyright (c) 2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/pinmux.h>
#include <linux/pinctrl/pinconf.h>
#include <linux/pinctrl/pinconf-generic.h>
#include <linux/slab.h>
#include <linux/regmap.h>
#include <linux/gpio.h>
#include <linux/interrupt.h>
#include <linux/of_device.h>
#include <dt-bindings/pinctrl/qcom,pmic-gpio.h>
#include "../core.h"
#include "../pinctrl-utils.h"
/* mode */
#define PM8XXX_GPIO_MODE_ENABLED BIT(0)
#define PM8XXX_GPIO_MODE_INPUT 0
#define PM8XXX_GPIO_MODE_OUTPUT 2
/* output buffer */
#define PM8XXX_GPIO_PUSH_PULL 0
#define PM8XXX_GPIO_OPEN_DRAIN 1
/* bias */
#define PM8XXX_GPIO_BIAS_PU_30 0
#define PM8XXX_GPIO_BIAS_PU_1P5 1
#define PM8XXX_GPIO_BIAS_PU_31P5 2
#define PM8XXX_GPIO_BIAS_PU_1P5_30 3
#define PM8XXX_GPIO_BIAS_PD 4
#define PM8XXX_GPIO_BIAS_NP 5
/* GPIO registers */
#define SSBI_REG_ADDR_GPIO_BASE 0x150
#define SSBI_REG_ADDR_GPIO(n) (SSBI_REG_ADDR_GPIO_BASE + n)
#define PM8XXX_BANK_WRITE BIT(7)
#define PM8XXX_MAX_GPIOS 44
/* custom pinconf parameters */
#define PM8XXX_QCOM_DRIVE_STRENGH (PIN_CONFIG_END + 1)
#define PM8XXX_QCOM_PULL_UP_STRENGTH (PIN_CONFIG_END + 2)
/**
* struct pm8xxx_pin_data - dynamic configuration for a pin
* @reg: address of the control register
* @irq: IRQ from the PMIC interrupt controller
* @power_source: logical selected voltage source, mapping in static data
* is used translate to register values
* @mode: operating mode for the pin (input/output)
* @open_drain: output buffer configured as open-drain (vs push-pull)
* @output_value: configured output value
* @bias: register view of configured bias
* @pull_up_strength: placeholder for selected pull up strength
* only used to configure bias when pull up is selected
* @output_strength: selector of output-strength
* @disable: pin disabled / configured as tristate
* @function: pinmux selector
* @inverted: pin logic is inverted
*/
struct pm8xxx_pin_data {
unsigned reg;
int irq;
u8 power_source;
u8 mode;
bool open_drain;
bool output_value;
u8 bias;
u8 pull_up_strength;
u8 output_strength;
bool disable;
u8 function;
bool inverted;
};
struct pm8xxx_gpio {
struct device *dev;
struct regmap *regmap;
struct pinctrl_dev *pctrl;
struct gpio_chip chip;
struct pinctrl_desc desc;
unsigned npins;
};
static const struct pinconf_generic_params pm8xxx_gpio_bindings[] = {
{"qcom,drive-strength", PM8XXX_QCOM_DRIVE_STRENGH, 0},
{"qcom,pull-up-strength", PM8XXX_QCOM_PULL_UP_STRENGTH, 0},
};
#ifdef CONFIG_DEBUG_FS
static const struct pin_config_item pm8xxx_conf_items[ARRAY_SIZE(pm8xxx_gpio_bindings)] = {
PCONFDUMP(PM8XXX_QCOM_DRIVE_STRENGH, "drive-strength", NULL, true),
PCONFDUMP(PM8XXX_QCOM_PULL_UP_STRENGTH, "pull up strength", NULL, true),
};
#endif
static const char * const pm8xxx_groups[PM8XXX_MAX_GPIOS] = {
"gpio1", "gpio2", "gpio3", "gpio4", "gpio5", "gpio6", "gpio7", "gpio8",
"gpio9", "gpio10", "gpio11", "gpio12", "gpio13", "gpio14", "gpio15",
"gpio16", "gpio17", "gpio18", "gpio19", "gpio20", "gpio21", "gpio22",
"gpio23", "gpio24", "gpio25", "gpio26", "gpio27", "gpio28", "gpio29",
"gpio30", "gpio31", "gpio32", "gpio33", "gpio34", "gpio35", "gpio36",
"gpio37", "gpio38", "gpio39", "gpio40", "gpio41", "gpio42", "gpio43",
"gpio44",
};
static const char * const pm8xxx_gpio_functions[] = {
PMIC_GPIO_FUNC_NORMAL, PMIC_GPIO_FUNC_PAIRED,
PMIC_GPIO_FUNC_FUNC1, PMIC_GPIO_FUNC_FUNC2,
PMIC_GPIO_FUNC_DTEST1, PMIC_GPIO_FUNC_DTEST2,
PMIC_GPIO_FUNC_DTEST3, PMIC_GPIO_FUNC_DTEST4,
};
static int pm8xxx_read_bank(struct pm8xxx_gpio *pctrl,
struct pm8xxx_pin_data *pin, int bank)
{
unsigned int val = bank << 4;
int ret;
ret = regmap_write(pctrl->regmap, pin->reg, val);
if (ret) {
dev_err(pctrl->dev, "failed to select bank %d\n", bank);
return ret;
}
ret = regmap_read(pctrl->regmap, pin->reg, &val);
if (ret) {
dev_err(pctrl->dev, "failed to read register %d\n", bank);
return ret;
}
return val;
}
static int pm8xxx_write_bank(struct pm8xxx_gpio *pctrl,
struct pm8xxx_pin_data *pin,
int bank,
u8 val)
{
int ret;
val |= PM8XXX_BANK_WRITE;
val |= bank << 4;
ret = regmap_write(pctrl->regmap, pin->reg, val);
if (ret)
dev_err(pctrl->dev, "failed to write register\n");
return ret;
}
static int pm8xxx_get_groups_count(struct pinctrl_dev *pctldev)
{
struct pm8xxx_gpio *pctrl = pinctrl_dev_get_drvdata(pctldev);
return pctrl->npins;
}
static const char *pm8xxx_get_group_name(struct pinctrl_dev *pctldev,
unsigned group)
{
return pm8xxx_groups[group];
}
static int pm8xxx_get_group_pins(struct pinctrl_dev *pctldev,
unsigned group,
const unsigned **pins,
unsigned *num_pins)
{
struct pm8xxx_gpio *pctrl = pinctrl_dev_get_drvdata(pctldev);
*pins = &pctrl->desc.pins[group].number;
*num_pins = 1;
return 0;
}
static const struct pinctrl_ops pm8xxx_pinctrl_ops = {
.get_groups_count = pm8xxx_get_groups_count,
.get_group_name = pm8xxx_get_group_name,
.get_group_pins = pm8xxx_get_group_pins,
.dt_node_to_map = pinconf_generic_dt_node_to_map_group,
.dt_free_map = pinctrl_utils_dt_free_map,
};
static int pm8xxx_get_functions_count(struct pinctrl_dev *pctldev)
{
return ARRAY_SIZE(pm8xxx_gpio_functions);
}
static const char *pm8xxx_get_function_name(struct pinctrl_dev *pctldev,
unsigned function)
{
return pm8xxx_gpio_functions[function];
}
static int pm8xxx_get_function_groups(struct pinctrl_dev *pctldev,
unsigned function,
const char * const **groups,
unsigned * const num_groups)
{
struct pm8xxx_gpio *pctrl = pinctrl_dev_get_drvdata(pctldev);
*groups = pm8xxx_groups;
*num_groups = pctrl->npins;
return 0;
}
static int pm8xxx_pinmux_set_mux(struct pinctrl_dev *pctldev,
unsigned function,
unsigned group)
{
struct pm8xxx_gpio *pctrl = pinctrl_dev_get_drvdata(pctldev);
struct pm8xxx_pin_data *pin = pctrl->desc.pins[group].drv_data;
u8 val;
pin->function = function;
val = pin->function << 1;
pm8xxx_write_bank(pctrl, pin, 4, val);
return 0;
}
static const struct pinmux_ops pm8xxx_pinmux_ops = {
.get_functions_count = pm8xxx_get_functions_count,
.get_function_name = pm8xxx_get_function_name,
.get_function_groups = pm8xxx_get_function_groups,
.set_mux = pm8xxx_pinmux_set_mux,
};
static int pm8xxx_pin_config_get(struct pinctrl_dev *pctldev,
unsigned int offset,
unsigned long *config)
{
struct pm8xxx_gpio *pctrl = pinctrl_dev_get_drvdata(pctldev);
struct pm8xxx_pin_data *pin = pctrl->desc.pins[offset].drv_data;
unsigned param = pinconf_to_config_param(*config);
unsigned arg;
switch (param) {
case PIN_CONFIG_BIAS_DISABLE:
arg = pin->bias == PM8XXX_GPIO_BIAS_NP;
break;
case PIN_CONFIG_BIAS_PULL_DOWN:
arg = pin->bias == PM8XXX_GPIO_BIAS_PD;
break;
case PIN_CONFIG_BIAS_PULL_UP:
arg = pin->bias <= PM8XXX_GPIO_BIAS_PU_1P5_30;
break;
case PM8XXX_QCOM_PULL_UP_STRENGTH:
arg = pin->pull_up_strength;
break;
case PIN_CONFIG_BIAS_HIGH_IMPEDANCE:
arg = pin->disable;
break;
case PIN_CONFIG_INPUT_ENABLE:
arg = pin->mode == PM8XXX_GPIO_MODE_INPUT;
break;
case PIN_CONFIG_OUTPUT:
if (pin->mode & PM8XXX_GPIO_MODE_OUTPUT)
arg = pin->output_value;
else
arg = 0;
break;
case PIN_CONFIG_POWER_SOURCE:
arg = pin->power_source;
break;
case PM8XXX_QCOM_DRIVE_STRENGH:
arg = pin->output_strength;
break;
case PIN_CONFIG_DRIVE_PUSH_PULL:
arg = !pin->open_drain;
break;
case PIN_CONFIG_DRIVE_OPEN_DRAIN:
arg = pin->open_drain;
break;
default:
return -EINVAL;
}
*config = pinconf_to_config_packed(param, arg);
return 0;
}
static int pm8xxx_pin_config_set(struct pinctrl_dev *pctldev,
unsigned int offset,
unsigned long *configs,
unsigned num_configs)
{
struct pm8xxx_gpio *pctrl = pinctrl_dev_get_drvdata(pctldev);
struct pm8xxx_pin_data *pin = pctrl->desc.pins[offset].drv_data;
unsigned param;
unsigned arg;
unsigned i;
u8 banks = 0;
u8 val;
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:
pin->bias = PM8XXX_GPIO_BIAS_NP;
banks |= BIT(2);
pin->disable = 0;
banks |= BIT(3);
break;
case PIN_CONFIG_BIAS_PULL_DOWN:
pin->bias = PM8XXX_GPIO_BIAS_PD;
banks |= BIT(2);
pin->disable = 0;
banks |= BIT(3);
break;
case PM8XXX_QCOM_PULL_UP_STRENGTH:
if (arg > PM8XXX_GPIO_BIAS_PU_1P5_30) {
dev_err(pctrl->dev, "invalid pull-up strength\n");
return -EINVAL;
}
pin->pull_up_strength = arg;
/* FALLTHROUGH */
case PIN_CONFIG_BIAS_PULL_UP:
pin->bias = pin->pull_up_strength;
banks |= BIT(2);
pin->disable = 0;
banks |= BIT(3);
break;
case PIN_CONFIG_BIAS_HIGH_IMPEDANCE:
pin->disable = 1;
banks |= BIT(3);
break;
case PIN_CONFIG_INPUT_ENABLE:
pin->mode = PM8XXX_GPIO_MODE_INPUT;
banks |= BIT(0) | BIT(1);
break;
case PIN_CONFIG_OUTPUT:
pin->mode = PM8XXX_GPIO_MODE_OUTPUT;
pin->output_value = !!arg;
banks |= BIT(0) | BIT(1);
break;
case PIN_CONFIG_POWER_SOURCE:
pin->power_source = arg;
banks |= BIT(0);
break;
case PM8XXX_QCOM_DRIVE_STRENGH:
if (arg > PMIC_GPIO_STRENGTH_LOW) {
dev_err(pctrl->dev, "invalid drive strength\n");
return -EINVAL;
}
pin->output_strength = arg;
banks |= BIT(3);
break;
case PIN_CONFIG_DRIVE_PUSH_PULL:
pin->open_drain = 0;
banks |= BIT(1);
break;
case PIN_CONFIG_DRIVE_OPEN_DRAIN:
pin->open_drain = 1;
banks |= BIT(1);
break;
default:
dev_err(pctrl->dev,
"unsupported config parameter: %x\n",
param);
return -EINVAL;
}
}
if (banks & BIT(0)) {
val = pin->power_source << 1;
val |= PM8XXX_GPIO_MODE_ENABLED;
pm8xxx_write_bank(pctrl, pin, 0, val);
}
if (banks & BIT(1)) {
val = pin->mode << 2;
val |= pin->open_drain << 1;
val |= pin->output_value;
pm8xxx_write_bank(pctrl, pin, 1, val);
}
if (banks & BIT(2)) {
val = pin->bias << 1;
pm8xxx_write_bank(pctrl, pin, 2, val);
}
if (banks & BIT(3)) {
val = pin->output_strength << 2;
val |= pin->disable;
pm8xxx_write_bank(pctrl, pin, 3, val);
}
if (banks & BIT(4)) {
val = pin->function << 1;
pm8xxx_write_bank(pctrl, pin, 4, val);
}
if (banks & BIT(5)) {
val = 0;
if (!pin->inverted)
val |= BIT(3);
pm8xxx_write_bank(pctrl, pin, 5, val);
}
return 0;
}
static const struct pinconf_ops pm8xxx_pinconf_ops = {
.is_generic = true,
.pin_config_group_get = pm8xxx_pin_config_get,
.pin_config_group_set = pm8xxx_pin_config_set,
};
static struct pinctrl_desc pm8xxx_pinctrl_desc = {
.name = "pm8xxx_gpio",
.pctlops = &pm8xxx_pinctrl_ops,
.pmxops = &pm8xxx_pinmux_ops,
.confops = &pm8xxx_pinconf_ops,
.owner = THIS_MODULE,
};
static int pm8xxx_gpio_direction_input(struct gpio_chip *chip,
unsigned offset)
{
struct pm8xxx_gpio *pctrl = container_of(chip, struct pm8xxx_gpio, chip);
struct pm8xxx_pin_data *pin = pctrl->desc.pins[offset].drv_data;
u8 val;
pin->mode = PM8XXX_GPIO_MODE_INPUT;
val = pin->mode << 2;
pm8xxx_write_bank(pctrl, pin, 1, val);
return 0;
}
static int pm8xxx_gpio_direction_output(struct gpio_chip *chip,
unsigned offset,
int value)
{
struct pm8xxx_gpio *pctrl = container_of(chip, struct pm8xxx_gpio, chip);
struct pm8xxx_pin_data *pin = pctrl->desc.pins[offset].drv_data;
u8 val;
pin->mode = PM8XXX_GPIO_MODE_OUTPUT;
pin->output_value = !!value;
val = pin->mode << 2;
val |= pin->open_drain << 1;
val |= pin->output_value;
pm8xxx_write_bank(pctrl, pin, 1, val);
return 0;
}
static int pm8xxx_gpio_get(struct gpio_chip *chip, unsigned offset)
{
struct pm8xxx_gpio *pctrl = container_of(chip, struct pm8xxx_gpio, chip);
struct pm8xxx_pin_data *pin = pctrl->desc.pins[offset].drv_data;
bool state;
int ret;
if (pin->mode == PM8XXX_GPIO_MODE_OUTPUT) {
ret = pin->output_value;
} else {
ret = irq_get_irqchip_state(pin->irq, IRQCHIP_STATE_LINE_LEVEL, &state);
if (!ret)
ret = !!state;
}
return ret;
}
static void pm8xxx_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
{
struct pm8xxx_gpio *pctrl = container_of(chip, struct pm8xxx_gpio, chip);
struct pm8xxx_pin_data *pin = pctrl->desc.pins[offset].drv_data;
u8 val;
pin->output_value = !!value;
val = pin->mode << 2;
val |= pin->open_drain << 1;
val |= pin->output_value;
pm8xxx_write_bank(pctrl, pin, 1, val);
}
static int pm8xxx_gpio_of_xlate(struct gpio_chip *chip,
const struct of_phandle_args *gpio_desc,
u32 *flags)
{
if (chip->of_gpio_n_cells < 2)
return -EINVAL;
if (flags)
*flags = gpio_desc->args[1];
return gpio_desc->args[0] - 1;
}
static int pm8xxx_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
{
struct pm8xxx_gpio *pctrl = container_of(chip, struct pm8xxx_gpio, chip);
struct pm8xxx_pin_data *pin = pctrl->desc.pins[offset].drv_data;
return pin->irq;
}
#ifdef CONFIG_DEBUG_FS
#include <linux/seq_file.h>
static void pm8xxx_gpio_dbg_show_one(struct seq_file *s,
struct pinctrl_dev *pctldev,
struct gpio_chip *chip,
unsigned offset,
unsigned gpio)
{
struct pm8xxx_gpio *pctrl = container_of(chip, struct pm8xxx_gpio, chip);
struct pm8xxx_pin_data *pin = pctrl->desc.pins[offset].drv_data;
static const char * const modes[] = {
"in", "both", "out", "off"
};
static const char * const biases[] = {
"pull-up 30uA", "pull-up 1.5uA", "pull-up 31.5uA",
"pull-up 1.5uA + 30uA boost", "pull-down 10uA", "no pull"
};
static const char * const buffer_types[] = {
"push-pull", "open-drain"
};
static const char * const strengths[] = {
"no", "high", "medium", "low"
};
seq_printf(s, " gpio%-2d:", offset + 1);
if (pin->disable) {
seq_puts(s, " ---");
} else {
seq_printf(s, " %-4s", modes[pin->mode]);
seq_printf(s, " %-7s", pm8xxx_gpio_functions[pin->function]);
seq_printf(s, " VIN%d", pin->power_source);
seq_printf(s, " %-27s", biases[pin->bias]);
seq_printf(s, " %-10s", buffer_types[pin->open_drain]);
seq_printf(s, " %-4s", pin->output_value ? "high" : "low");
seq_printf(s, " %-7s", strengths[pin->output_strength]);
if (pin->inverted)
seq_puts(s, " inverted");
}
}
static void pm8xxx_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
{
unsigned gpio = chip->base;
unsigned i;
for (i = 0; i < chip->ngpio; i++, gpio++) {
pm8xxx_gpio_dbg_show_one(s, NULL, chip, i, gpio);
seq_puts(s, "\n");
}
}
#else
#define msm_gpio_dbg_show NULL
#endif
static struct gpio_chip pm8xxx_gpio_template = {
.direction_input = pm8xxx_gpio_direction_input,
.direction_output = pm8xxx_gpio_direction_output,
.get = pm8xxx_gpio_get,
.set = pm8xxx_gpio_set,
.of_xlate = pm8xxx_gpio_of_xlate,
.to_irq = pm8xxx_gpio_to_irq,
.dbg_show = pm8xxx_gpio_dbg_show,
.owner = THIS_MODULE,
};
static int pm8xxx_pin_populate(struct pm8xxx_gpio *pctrl,
struct pm8xxx_pin_data *pin)
{
int val;
val = pm8xxx_read_bank(pctrl, pin, 0);
if (val < 0)
return val;
pin->power_source = (val >> 1) & 0x7;
val = pm8xxx_read_bank(pctrl, pin, 1);
if (val < 0)
return val;
pin->mode = (val >> 2) & 0x3;
pin->open_drain = !!(val & BIT(1));
pin->output_value = val & BIT(0);
val = pm8xxx_read_bank(pctrl, pin, 2);
if (val < 0)
return val;
pin->bias = (val >> 1) & 0x7;
if (pin->bias <= PM8XXX_GPIO_BIAS_PU_1P5_30)
pin->pull_up_strength = pin->bias;
else
pin->pull_up_strength = PM8XXX_GPIO_BIAS_PU_30;
val = pm8xxx_read_bank(pctrl, pin, 3);
if (val < 0)
return val;
pin->output_strength = (val >> 2) & 0x3;
pin->disable = val & BIT(0);
val = pm8xxx_read_bank(pctrl, pin, 4);
if (val < 0)
return val;
pin->function = (val >> 1) & 0x7;
val = pm8xxx_read_bank(pctrl, pin, 5);
if (val < 0)
return val;
pin->inverted = !(val & BIT(3));
return 0;
}
static const struct of_device_id pm8xxx_gpio_of_match[] = {
{ .compatible = "qcom,pm8018-gpio", .data = (void *)6 },
{ .compatible = "qcom,pm8038-gpio", .data = (void *)12 },
{ .compatible = "qcom,pm8058-gpio", .data = (void *)40 },
{ .compatible = "qcom,pm8917-gpio", .data = (void *)38 },
{ .compatible = "qcom,pm8921-gpio", .data = (void *)44 },
{ },
};
MODULE_DEVICE_TABLE(of, pm8xxx_gpio_of_match);
static int pm8xxx_gpio_probe(struct platform_device *pdev)
{
struct pm8xxx_pin_data *pin_data;
struct pinctrl_pin_desc *pins;
struct pm8xxx_gpio *pctrl;
int ret;
int i;
pctrl = devm_kzalloc(&pdev->dev, sizeof(*pctrl), GFP_KERNEL);
if (!pctrl)
return -ENOMEM;
pctrl->dev = &pdev->dev;
pctrl->npins = (unsigned)of_device_get_match_data(&pdev->dev);
pctrl->regmap = dev_get_regmap(pdev->dev.parent, NULL);
if (!pctrl->regmap) {
dev_err(&pdev->dev, "parent regmap unavailable\n");
return -ENXIO;
}
pctrl->desc = pm8xxx_pinctrl_desc;
pctrl->desc.npins = pctrl->npins;
pins = devm_kcalloc(&pdev->dev,
pctrl->desc.npins,
sizeof(struct pinctrl_pin_desc),
GFP_KERNEL);
if (!pins)
return -ENOMEM;
pin_data = devm_kcalloc(&pdev->dev,
pctrl->desc.npins,
sizeof(struct pm8xxx_pin_data),
GFP_KERNEL);
if (!pin_data)
return -ENOMEM;
for (i = 0; i < pctrl->desc.npins; i++) {
pin_data[i].reg = SSBI_REG_ADDR_GPIO(i);
pin_data[i].irq = platform_get_irq(pdev, i);
if (pin_data[i].irq < 0) {
dev_err(&pdev->dev,
"missing interrupts for pin %d\n", i);
return pin_data[i].irq;
}
ret = pm8xxx_pin_populate(pctrl, &pin_data[i]);
if (ret)
return ret;
pins[i].number = i;
pins[i].name = pm8xxx_groups[i];
pins[i].drv_data = &pin_data[i];
}
pctrl->desc.pins = pins;
pctrl->desc.num_custom_params = ARRAY_SIZE(pm8xxx_gpio_bindings);
pctrl->desc.custom_params = pm8xxx_gpio_bindings;
#ifdef CONFIG_DEBUG_FS
pctrl->desc.custom_conf_items = pm8xxx_conf_items;
#endif
pctrl->pctrl = pinctrl_register(&pctrl->desc, &pdev->dev, pctrl);
if (!pctrl->pctrl) {
dev_err(&pdev->dev, "couldn't register pm8xxx gpio driver\n");
return -ENODEV;
}
pctrl->chip = pm8xxx_gpio_template;
pctrl->chip.base = -1;
pctrl->chip.dev = &pdev->dev;
pctrl->chip.of_node = pdev->dev.of_node;
pctrl->chip.of_gpio_n_cells = 2;
pctrl->chip.label = dev_name(pctrl->dev);
pctrl->chip.ngpio = pctrl->npins;
ret = gpiochip_add(&pctrl->chip);
if (ret) {
dev_err(&pdev->dev, "failed register gpiochip\n");
goto unregister_pinctrl;
}
ret = gpiochip_add_pin_range(&pctrl->chip,
dev_name(pctrl->dev),
0, 0, pctrl->chip.ngpio);
if (ret) {
dev_err(pctrl->dev, "failed to add pin range\n");
goto unregister_gpiochip;
}
platform_set_drvdata(pdev, pctrl);
dev_dbg(&pdev->dev, "Qualcomm pm8xxx gpio driver probed\n");
return 0;
unregister_gpiochip:
gpiochip_remove(&pctrl->chip);
unregister_pinctrl:
pinctrl_unregister(pctrl->pctrl);
return ret;
}
static int pm8xxx_gpio_remove(struct platform_device *pdev)
{
struct pm8xxx_gpio *pctrl = platform_get_drvdata(pdev);
gpiochip_remove(&pctrl->chip);
pinctrl_unregister(pctrl->pctrl);
return 0;
}
static struct platform_driver pm8xxx_gpio_driver = {
.driver = {
.name = "qcom-ssbi-gpio",
.of_match_table = pm8xxx_gpio_of_match,
},
.probe = pm8xxx_gpio_probe,
.remove = pm8xxx_gpio_remove,
};
module_platform_driver(pm8xxx_gpio_driver);
MODULE_AUTHOR("Bjorn Andersson <bjorn.andersson@sonymobile.com>");
MODULE_DESCRIPTION("Qualcomm PM8xxx GPIO driver");
MODULE_LICENSE("GPL v2");

View File

@ -0,0 +1,882 @@
/*
* Copyright (c) 2015, Sony Mobile Communications AB.
* Copyright (c) 2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/pinmux.h>
#include <linux/pinctrl/pinconf.h>
#include <linux/pinctrl/pinconf-generic.h>
#include <linux/slab.h>
#include <linux/regmap.h>
#include <linux/gpio.h>
#include <linux/interrupt.h>
#include <linux/of_device.h>
#include <dt-bindings/pinctrl/qcom,pmic-mpp.h>
#include "../core.h"
#include "../pinctrl-utils.h"
/* MPP registers */
#define SSBI_REG_ADDR_MPP_BASE 0x50
#define SSBI_REG_ADDR_MPP(n) (SSBI_REG_ADDR_MPP_BASE + n)
/* MPP Type: type */
#define PM8XXX_MPP_TYPE_D_INPUT 0
#define PM8XXX_MPP_TYPE_D_OUTPUT 1
#define PM8XXX_MPP_TYPE_D_BI_DIR 2
#define PM8XXX_MPP_TYPE_A_INPUT 3
#define PM8XXX_MPP_TYPE_A_OUTPUT 4
#define PM8XXX_MPP_TYPE_SINK 5
#define PM8XXX_MPP_TYPE_DTEST_SINK 6
#define PM8XXX_MPP_TYPE_DTEST_OUTPUT 7
/* Digital Input: control */
#define PM8XXX_MPP_DIN_TO_INT 0
#define PM8XXX_MPP_DIN_TO_DBUS1 1
#define PM8XXX_MPP_DIN_TO_DBUS2 2
#define PM8XXX_MPP_DIN_TO_DBUS3 3
/* Digital Output: control */
#define PM8XXX_MPP_DOUT_CTRL_LOW 0
#define PM8XXX_MPP_DOUT_CTRL_HIGH 1
#define PM8XXX_MPP_DOUT_CTRL_MPP 2
#define PM8XXX_MPP_DOUT_CTRL_INV_MPP 3
/* Bidirectional: control */
#define PM8XXX_MPP_BI_PULLUP_1KOHM 0
#define PM8XXX_MPP_BI_PULLUP_OPEN 1
#define PM8XXX_MPP_BI_PULLUP_10KOHM 2
#define PM8XXX_MPP_BI_PULLUP_30KOHM 3
/* Analog Output: control */
#define PM8XXX_MPP_AOUT_CTRL_DISABLE 0
#define PM8XXX_MPP_AOUT_CTRL_ENABLE 1
#define PM8XXX_MPP_AOUT_CTRL_MPP_HIGH_EN 2
#define PM8XXX_MPP_AOUT_CTRL_MPP_LOW_EN 3
/* Current Sink: control */
#define PM8XXX_MPP_CS_CTRL_DISABLE 0
#define PM8XXX_MPP_CS_CTRL_ENABLE 1
#define PM8XXX_MPP_CS_CTRL_MPP_HIGH_EN 2
#define PM8XXX_MPP_CS_CTRL_MPP_LOW_EN 3
/* DTEST Current Sink: control */
#define PM8XXX_MPP_DTEST_CS_CTRL_EN1 0
#define PM8XXX_MPP_DTEST_CS_CTRL_EN2 1
#define PM8XXX_MPP_DTEST_CS_CTRL_EN3 2
#define PM8XXX_MPP_DTEST_CS_CTRL_EN4 3
/* DTEST Digital Output: control */
#define PM8XXX_MPP_DTEST_DBUS1 0
#define PM8XXX_MPP_DTEST_DBUS2 1
#define PM8XXX_MPP_DTEST_DBUS3 2
#define PM8XXX_MPP_DTEST_DBUS4 3
/* custom pinconf parameters */
#define PM8XXX_CONFIG_AMUX (PIN_CONFIG_END + 1)
#define PM8XXX_CONFIG_DTEST_SELECTOR (PIN_CONFIG_END + 2)
#define PM8XXX_CONFIG_ALEVEL (PIN_CONFIG_END + 3)
#define PM8XXX_CONFIG_PAIRED (PIN_CONFIG_END + 4)
/**
* struct pm8xxx_pin_data - dynamic configuration for a pin
* @reg: address of the control register
* @irq: IRQ from the PMIC interrupt controller
* @mode: operating mode for the pin (digital, analog or current sink)
* @input: pin is input
* @output: pin is output
* @high_z: pin is floating
* @paired: mpp operates in paired mode
* @output_value: logical output value of the mpp
* @power_source: selected power source
* @dtest: DTEST route selector
* @amux: input muxing in analog mode
* @aout_level: selector of the output in analog mode
* @drive_strength: drive strength of the current sink
* @pullup: pull up value, when in digital bidirectional mode
*/
struct pm8xxx_pin_data {
unsigned reg;
int irq;
u8 mode;
bool input;
bool output;
bool high_z;
bool paired;
bool output_value;
u8 power_source;
u8 dtest;
u8 amux;
u8 aout_level;
u8 drive_strength;
unsigned pullup;
};
struct pm8xxx_mpp {
struct device *dev;
struct regmap *regmap;
struct pinctrl_dev *pctrl;
struct gpio_chip chip;
struct pinctrl_desc desc;
unsigned npins;
};
static const struct pinconf_generic_params pm8xxx_mpp_bindings[] = {
{"qcom,amux-route", PM8XXX_CONFIG_AMUX, 0},
{"qcom,analog-level", PM8XXX_CONFIG_ALEVEL, 0},
{"qcom,dtest", PM8XXX_CONFIG_DTEST_SELECTOR, 0},
{"qcom,paired", PM8XXX_CONFIG_PAIRED, 0},
};
#ifdef CONFIG_DEBUG_FS
static const struct pin_config_item pm8xxx_conf_items[] = {
PCONFDUMP(PM8XXX_CONFIG_AMUX, "analog mux", NULL, true),
PCONFDUMP(PM8XXX_CONFIG_ALEVEL, "analog level", NULL, true),
PCONFDUMP(PM8XXX_CONFIG_DTEST_SELECTOR, "dtest", NULL, true),
PCONFDUMP(PM8XXX_CONFIG_PAIRED, "paired", NULL, false),
};
#endif
#define PM8XXX_MAX_MPPS 12
static const char * const pm8xxx_groups[PM8XXX_MAX_MPPS] = {
"mpp1", "mpp2", "mpp3", "mpp4", "mpp5", "mpp6", "mpp7", "mpp8",
"mpp9", "mpp10", "mpp11", "mpp12",
};
#define PM8XXX_MPP_DIGITAL 0
#define PM8XXX_MPP_ANALOG 1
#define PM8XXX_MPP_SINK 2
static const char * const pm8xxx_mpp_functions[] = {
"digital", "analog", "sink",
};
static int pm8xxx_mpp_update(struct pm8xxx_mpp *pctrl,
struct pm8xxx_pin_data *pin)
{
unsigned level;
unsigned ctrl;
unsigned type;
int ret;
u8 val;
switch (pin->mode) {
case PM8XXX_MPP_DIGITAL:
if (pin->dtest) {
type = PM8XXX_MPP_TYPE_DTEST_OUTPUT;
ctrl = pin->dtest - 1;
} else if (pin->input && pin->output) {
type = PM8XXX_MPP_TYPE_D_BI_DIR;
if (pin->high_z)
ctrl = PM8XXX_MPP_BI_PULLUP_OPEN;
else if (pin->pullup == 600)
ctrl = PM8XXX_MPP_BI_PULLUP_1KOHM;
else if (pin->pullup == 10000)
ctrl = PM8XXX_MPP_BI_PULLUP_10KOHM;
else
ctrl = PM8XXX_MPP_BI_PULLUP_30KOHM;
} else if (pin->input) {
type = PM8XXX_MPP_TYPE_D_INPUT;
if (pin->dtest)
ctrl = pin->dtest;
else
ctrl = PM8XXX_MPP_DIN_TO_INT;
} else {
type = PM8XXX_MPP_TYPE_D_OUTPUT;
ctrl = !!pin->output_value;
if (pin->paired)
ctrl |= BIT(1);
}
level = pin->power_source;
break;
case PM8XXX_MPP_ANALOG:
if (pin->output) {
type = PM8XXX_MPP_TYPE_A_OUTPUT;
level = pin->aout_level;
ctrl = pin->output_value;
if (pin->paired)
ctrl |= BIT(1);
} else {
type = PM8XXX_MPP_TYPE_A_INPUT;
level = pin->amux;
ctrl = 0;
}
break;
case PM8XXX_MPP_SINK:
level = (pin->drive_strength / 5) - 1;
if (pin->dtest) {
type = PM8XXX_MPP_TYPE_DTEST_SINK;
ctrl = pin->dtest - 1;
} else {
type = PM8XXX_MPP_TYPE_SINK;
ctrl = pin->output_value;
if (pin->paired)
ctrl |= BIT(1);
}
break;
default:
return -EINVAL;
}
val = type << 5 | level << 2 | ctrl;
ret = regmap_write(pctrl->regmap, pin->reg, val);
if (ret)
dev_err(pctrl->dev, "failed to write register\n");
return ret;
}
static int pm8xxx_get_groups_count(struct pinctrl_dev *pctldev)
{
struct pm8xxx_mpp *pctrl = pinctrl_dev_get_drvdata(pctldev);
return pctrl->npins;
}
static const char *pm8xxx_get_group_name(struct pinctrl_dev *pctldev,
unsigned group)
{
return pm8xxx_groups[group];
}
static int pm8xxx_get_group_pins(struct pinctrl_dev *pctldev,
unsigned group,
const unsigned **pins,
unsigned *num_pins)
{
struct pm8xxx_mpp *pctrl = pinctrl_dev_get_drvdata(pctldev);
*pins = &pctrl->desc.pins[group].number;
*num_pins = 1;
return 0;
}
static const struct pinctrl_ops pm8xxx_pinctrl_ops = {
.get_groups_count = pm8xxx_get_groups_count,
.get_group_name = pm8xxx_get_group_name,
.get_group_pins = pm8xxx_get_group_pins,
.dt_node_to_map = pinconf_generic_dt_node_to_map_group,
.dt_free_map = pinctrl_utils_dt_free_map,
};
static int pm8xxx_get_functions_count(struct pinctrl_dev *pctldev)
{
return ARRAY_SIZE(pm8xxx_mpp_functions);
}
static const char *pm8xxx_get_function_name(struct pinctrl_dev *pctldev,
unsigned function)
{
return pm8xxx_mpp_functions[function];
}
static int pm8xxx_get_function_groups(struct pinctrl_dev *pctldev,
unsigned function,
const char * const **groups,
unsigned * const num_groups)
{
struct pm8xxx_mpp *pctrl = pinctrl_dev_get_drvdata(pctldev);
*groups = pm8xxx_groups;
*num_groups = pctrl->npins;
return 0;
}
static int pm8xxx_pinmux_set_mux(struct pinctrl_dev *pctldev,
unsigned function,
unsigned group)
{
struct pm8xxx_mpp *pctrl = pinctrl_dev_get_drvdata(pctldev);
struct pm8xxx_pin_data *pin = pctrl->desc.pins[group].drv_data;
pin->mode = function;
pm8xxx_mpp_update(pctrl, pin);
return 0;
}
static const struct pinmux_ops pm8xxx_pinmux_ops = {
.get_functions_count = pm8xxx_get_functions_count,
.get_function_name = pm8xxx_get_function_name,
.get_function_groups = pm8xxx_get_function_groups,
.set_mux = pm8xxx_pinmux_set_mux,
};
static int pm8xxx_pin_config_get(struct pinctrl_dev *pctldev,
unsigned int offset,
unsigned long *config)
{
struct pm8xxx_mpp *pctrl = pinctrl_dev_get_drvdata(pctldev);
struct pm8xxx_pin_data *pin = pctrl->desc.pins[offset].drv_data;
unsigned param = pinconf_to_config_param(*config);
unsigned arg;
switch (param) {
case PIN_CONFIG_BIAS_PULL_UP:
arg = pin->pullup;
break;
case PIN_CONFIG_BIAS_HIGH_IMPEDANCE:
arg = pin->high_z;
break;
case PIN_CONFIG_INPUT_ENABLE:
arg = pin->input;
break;
case PIN_CONFIG_OUTPUT:
arg = pin->output_value;
break;
case PIN_CONFIG_POWER_SOURCE:
arg = pin->power_source;
break;
case PIN_CONFIG_DRIVE_STRENGTH:
arg = pin->drive_strength;
break;
case PM8XXX_CONFIG_DTEST_SELECTOR:
arg = pin->dtest;
break;
case PM8XXX_CONFIG_AMUX:
arg = pin->amux;
break;
case PM8XXX_CONFIG_ALEVEL:
arg = pin->aout_level;
break;
case PM8XXX_CONFIG_PAIRED:
arg = pin->paired;
break;
default:
return -EINVAL;
}
*config = pinconf_to_config_packed(param, arg);
return 0;
}
static int pm8xxx_pin_config_set(struct pinctrl_dev *pctldev,
unsigned int offset,
unsigned long *configs,
unsigned num_configs)
{
struct pm8xxx_mpp *pctrl = pinctrl_dev_get_drvdata(pctldev);
struct pm8xxx_pin_data *pin = pctrl->desc.pins[offset].drv_data;
unsigned param;
unsigned arg;
unsigned i;
for (i = 0; i < num_configs; i++) {
param = pinconf_to_config_param(configs[i]);
arg = pinconf_to_config_argument(configs[i]);
switch (param) {
case PIN_CONFIG_BIAS_PULL_UP:
pin->pullup = arg;
break;
case PIN_CONFIG_BIAS_HIGH_IMPEDANCE:
pin->high_z = true;
break;
case PIN_CONFIG_INPUT_ENABLE:
pin->input = true;
break;
case PIN_CONFIG_OUTPUT:
pin->output = true;
pin->output_value = !!arg;
break;
case PIN_CONFIG_POWER_SOURCE:
pin->power_source = arg;
break;
case PIN_CONFIG_DRIVE_STRENGTH:
pin->drive_strength = arg;
break;
case PM8XXX_CONFIG_DTEST_SELECTOR:
pin->dtest = arg;
break;
case PM8XXX_CONFIG_AMUX:
pin->amux = arg;
break;
case PM8XXX_CONFIG_ALEVEL:
pin->aout_level = arg;
break;
case PM8XXX_CONFIG_PAIRED:
pin->paired = !!arg;
break;
default:
dev_err(pctrl->dev,
"unsupported config parameter: %x\n",
param);
return -EINVAL;
}
}
pm8xxx_mpp_update(pctrl, pin);
return 0;
}
static const struct pinconf_ops pm8xxx_pinconf_ops = {
.is_generic = true,
.pin_config_group_get = pm8xxx_pin_config_get,
.pin_config_group_set = pm8xxx_pin_config_set,
};
static struct pinctrl_desc pm8xxx_pinctrl_desc = {
.name = "pm8xxx_mpp",
.pctlops = &pm8xxx_pinctrl_ops,
.pmxops = &pm8xxx_pinmux_ops,
.confops = &pm8xxx_pinconf_ops,
.owner = THIS_MODULE,
};
static int pm8xxx_mpp_direction_input(struct gpio_chip *chip,
unsigned offset)
{
struct pm8xxx_mpp *pctrl = container_of(chip, struct pm8xxx_mpp, chip);
struct pm8xxx_pin_data *pin = pctrl->desc.pins[offset].drv_data;
switch (pin->mode) {
case PM8XXX_MPP_DIGITAL:
pin->input = true;
break;
case PM8XXX_MPP_ANALOG:
pin->input = true;
pin->output = true;
break;
case PM8XXX_MPP_SINK:
return -EINVAL;
}
pm8xxx_mpp_update(pctrl, pin);
return 0;
}
static int pm8xxx_mpp_direction_output(struct gpio_chip *chip,
unsigned offset,
int value)
{
struct pm8xxx_mpp *pctrl = container_of(chip, struct pm8xxx_mpp, chip);
struct pm8xxx_pin_data *pin = pctrl->desc.pins[offset].drv_data;
switch (pin->mode) {
case PM8XXX_MPP_DIGITAL:
pin->output = true;
break;
case PM8XXX_MPP_ANALOG:
pin->input = false;
pin->output = true;
break;
case PM8XXX_MPP_SINK:
pin->input = false;
pin->output = true;
break;
}
pm8xxx_mpp_update(pctrl, pin);
return 0;
}
static int pm8xxx_mpp_get(struct gpio_chip *chip, unsigned offset)
{
struct pm8xxx_mpp *pctrl = container_of(chip, struct pm8xxx_mpp, chip);
struct pm8xxx_pin_data *pin = pctrl->desc.pins[offset].drv_data;
bool state;
int ret;
if (!pin->input)
return pin->output_value;
ret = irq_get_irqchip_state(pin->irq, IRQCHIP_STATE_LINE_LEVEL, &state);
if (!ret)
ret = !!state;
return ret;
}
static void pm8xxx_mpp_set(struct gpio_chip *chip, unsigned offset, int value)
{
struct pm8xxx_mpp *pctrl = container_of(chip, struct pm8xxx_mpp, chip);
struct pm8xxx_pin_data *pin = pctrl->desc.pins[offset].drv_data;
pin->output_value = !!value;
pm8xxx_mpp_update(pctrl, pin);
}
static int pm8xxx_mpp_of_xlate(struct gpio_chip *chip,
const struct of_phandle_args *gpio_desc,
u32 *flags)
{
if (chip->of_gpio_n_cells < 2)
return -EINVAL;
if (flags)
*flags = gpio_desc->args[1];
return gpio_desc->args[0] - 1;
}
static int pm8xxx_mpp_to_irq(struct gpio_chip *chip, unsigned offset)
{
struct pm8xxx_mpp *pctrl = container_of(chip, struct pm8xxx_mpp, chip);
struct pm8xxx_pin_data *pin = pctrl->desc.pins[offset].drv_data;
return pin->irq;
}
#ifdef CONFIG_DEBUG_FS
#include <linux/seq_file.h>
static void pm8xxx_mpp_dbg_show_one(struct seq_file *s,
struct pinctrl_dev *pctldev,
struct gpio_chip *chip,
unsigned offset,
unsigned gpio)
{
struct pm8xxx_mpp *pctrl = container_of(chip, struct pm8xxx_mpp, chip);
struct pm8xxx_pin_data *pin = pctrl->desc.pins[offset].drv_data;
static const char * const aout_lvls[] = {
"1v25", "1v25_2", "0v625", "0v3125", "mpp", "abus1", "abus2",
"abus3"
};
static const char * const amuxs[] = {
"amux5", "amux6", "amux7", "amux8", "amux9", "abus1", "abus2",
"abus3",
};
seq_printf(s, " mpp%-2d:", offset + 1);
switch (pin->mode) {
case PM8XXX_MPP_DIGITAL:
seq_puts(s, " digital ");
if (pin->dtest) {
seq_printf(s, "dtest%d\n", pin->dtest);
} else if (pin->input && pin->output) {
if (pin->high_z)
seq_puts(s, "bi-dir high-z");
else
seq_printf(s, "bi-dir %dOhm", pin->pullup);
} else if (pin->input) {
if (pin->dtest)
seq_printf(s, "in dtest%d", pin->dtest);
else
seq_puts(s, "in gpio");
} else if (pin->output) {
seq_puts(s, "out ");
if (!pin->paired) {
seq_puts(s, pin->output_value ?
"high" : "low");
} else {
seq_puts(s, pin->output_value ?
"inverted" : "follow");
}
}
break;
case PM8XXX_MPP_ANALOG:
seq_puts(s, " analog ");
if (pin->output) {
seq_printf(s, "out %s ", aout_lvls[pin->aout_level]);
if (!pin->paired) {
seq_puts(s, pin->output_value ?
"high" : "low");
} else {
seq_puts(s, pin->output_value ?
"inverted" : "follow");
}
} else {
seq_printf(s, "input mux %s", amuxs[pin->amux]);
}
break;
case PM8XXX_MPP_SINK:
seq_printf(s, " sink %dmA ", pin->drive_strength);
if (pin->dtest) {
seq_printf(s, "dtest%d", pin->dtest);
} else {
if (!pin->paired) {
seq_puts(s, pin->output_value ?
"high" : "low");
} else {
seq_puts(s, pin->output_value ?
"inverted" : "follow");
}
}
break;
}
}
static void pm8xxx_mpp_dbg_show(struct seq_file *s, struct gpio_chip *chip)
{
unsigned gpio = chip->base;
unsigned i;
for (i = 0; i < chip->ngpio; i++, gpio++) {
pm8xxx_mpp_dbg_show_one(s, NULL, chip, i, gpio);
seq_puts(s, "\n");
}
}
#else
#define msm_mpp_dbg_show NULL
#endif
static struct gpio_chip pm8xxx_mpp_template = {
.direction_input = pm8xxx_mpp_direction_input,
.direction_output = pm8xxx_mpp_direction_output,
.get = pm8xxx_mpp_get,
.set = pm8xxx_mpp_set,
.of_xlate = pm8xxx_mpp_of_xlate,
.to_irq = pm8xxx_mpp_to_irq,
.dbg_show = pm8xxx_mpp_dbg_show,
.owner = THIS_MODULE,
};
static int pm8xxx_pin_populate(struct pm8xxx_mpp *pctrl,
struct pm8xxx_pin_data *pin)
{
unsigned int val;
unsigned level;
unsigned ctrl;
unsigned type;
int ret;
ret = regmap_read(pctrl->regmap, pin->reg, &val);
if (ret) {
dev_err(pctrl->dev, "failed to read register\n");
return ret;
}
type = (val >> 5) & 7;
level = (val >> 2) & 7;
ctrl = (val) & 3;
switch (type) {
case PM8XXX_MPP_TYPE_D_INPUT:
pin->mode = PM8XXX_MPP_DIGITAL;
pin->input = true;
pin->power_source = level;
pin->dtest = ctrl;
break;
case PM8XXX_MPP_TYPE_D_OUTPUT:
pin->mode = PM8XXX_MPP_DIGITAL;
pin->output = true;
pin->power_source = level;
pin->output_value = !!(ctrl & BIT(0));
pin->paired = !!(ctrl & BIT(1));
break;
case PM8XXX_MPP_TYPE_D_BI_DIR:
pin->mode = PM8XXX_MPP_DIGITAL;
pin->input = true;
pin->output = true;
pin->power_source = level;
switch (ctrl) {
case PM8XXX_MPP_BI_PULLUP_1KOHM:
pin->pullup = 600;
break;
case PM8XXX_MPP_BI_PULLUP_OPEN:
pin->high_z = true;
break;
case PM8XXX_MPP_BI_PULLUP_10KOHM:
pin->pullup = 10000;
break;
case PM8XXX_MPP_BI_PULLUP_30KOHM:
pin->pullup = 30000;
break;
}
break;
case PM8XXX_MPP_TYPE_A_INPUT:
pin->mode = PM8XXX_MPP_ANALOG;
pin->input = true;
pin->amux = level;
break;
case PM8XXX_MPP_TYPE_A_OUTPUT:
pin->mode = PM8XXX_MPP_ANALOG;
pin->output = true;
pin->aout_level = level;
pin->output_value = !!(ctrl & BIT(0));
pin->paired = !!(ctrl & BIT(1));
break;
case PM8XXX_MPP_TYPE_SINK:
pin->mode = PM8XXX_MPP_SINK;
pin->drive_strength = 5 * (level + 1);
pin->output_value = !!(ctrl & BIT(0));
pin->paired = !!(ctrl & BIT(1));
break;
case PM8XXX_MPP_TYPE_DTEST_SINK:
pin->mode = PM8XXX_MPP_SINK;
pin->dtest = ctrl + 1;
pin->drive_strength = 5 * (level + 1);
break;
case PM8XXX_MPP_TYPE_DTEST_OUTPUT:
pin->mode = PM8XXX_MPP_DIGITAL;
pin->power_source = level;
if (ctrl >= 1)
pin->dtest = ctrl;
break;
}
return 0;
}
static const struct of_device_id pm8xxx_mpp_of_match[] = {
{ .compatible = "qcom,pm8018-mpp", .data = (void *)6 },
{ .compatible = "qcom,pm8038-mpp", .data = (void *)6 },
{ .compatible = "qcom,pm8917-mpp", .data = (void *)10 },
{ .compatible = "qcom,pm8821-mpp", .data = (void *)4 },
{ .compatible = "qcom,pm8921-mpp", .data = (void *)12 },
{ },
};
MODULE_DEVICE_TABLE(of, pm8xxx_mpp_of_match);
static int pm8xxx_mpp_probe(struct platform_device *pdev)
{
struct pm8xxx_pin_data *pin_data;
struct pinctrl_pin_desc *pins;
struct pm8xxx_mpp *pctrl;
int ret;
int i;
pctrl = devm_kzalloc(&pdev->dev, sizeof(*pctrl), GFP_KERNEL);
if (!pctrl)
return -ENOMEM;
pctrl->dev = &pdev->dev;
pctrl->npins = (unsigned)of_device_get_match_data(&pdev->dev);
pctrl->regmap = dev_get_regmap(pdev->dev.parent, NULL);
if (!pctrl->regmap) {
dev_err(&pdev->dev, "parent regmap unavailable\n");
return -ENXIO;
}
pctrl->desc = pm8xxx_pinctrl_desc;
pctrl->desc.npins = pctrl->npins;
pins = devm_kcalloc(&pdev->dev,
pctrl->desc.npins,
sizeof(struct pinctrl_pin_desc),
GFP_KERNEL);
if (!pins)
return -ENOMEM;
pin_data = devm_kcalloc(&pdev->dev,
pctrl->desc.npins,
sizeof(struct pm8xxx_pin_data),
GFP_KERNEL);
if (!pin_data)
return -ENOMEM;
for (i = 0; i < pctrl->desc.npins; i++) {
pin_data[i].reg = SSBI_REG_ADDR_MPP(i);
pin_data[i].irq = platform_get_irq(pdev, i);
if (pin_data[i].irq < 0) {
dev_err(&pdev->dev,
"missing interrupts for pin %d\n", i);
return pin_data[i].irq;
}
ret = pm8xxx_pin_populate(pctrl, &pin_data[i]);
if (ret)
return ret;
pins[i].number = i;
pins[i].name = pm8xxx_groups[i];
pins[i].drv_data = &pin_data[i];
}
pctrl->desc.pins = pins;
pctrl->desc.num_custom_params = ARRAY_SIZE(pm8xxx_mpp_bindings);
pctrl->desc.custom_params = pm8xxx_mpp_bindings;
#ifdef CONFIG_DEBUG_FS
pctrl->desc.custom_conf_items = pm8xxx_conf_items;
#endif
pctrl->pctrl = pinctrl_register(&pctrl->desc, &pdev->dev, pctrl);
if (!pctrl->pctrl) {
dev_err(&pdev->dev, "couldn't register pm8xxx mpp driver\n");
return -ENODEV;
}
pctrl->chip = pm8xxx_mpp_template;
pctrl->chip.base = -1;
pctrl->chip.dev = &pdev->dev;
pctrl->chip.of_node = pdev->dev.of_node;
pctrl->chip.of_gpio_n_cells = 2;
pctrl->chip.label = dev_name(pctrl->dev);
pctrl->chip.ngpio = pctrl->npins;
ret = gpiochip_add(&pctrl->chip);
if (ret) {
dev_err(&pdev->dev, "failed register gpiochip\n");
goto unregister_pinctrl;
}
ret = gpiochip_add_pin_range(&pctrl->chip,
dev_name(pctrl->dev),
0, 0, pctrl->chip.ngpio);
if (ret) {
dev_err(pctrl->dev, "failed to add pin range\n");
goto unregister_gpiochip;
}
platform_set_drvdata(pdev, pctrl);
dev_dbg(&pdev->dev, "Qualcomm pm8xxx mpp driver probed\n");
return 0;
unregister_gpiochip:
gpiochip_remove(&pctrl->chip);
unregister_pinctrl:
pinctrl_unregister(pctrl->pctrl);
return ret;
}
static int pm8xxx_mpp_remove(struct platform_device *pdev)
{
struct pm8xxx_mpp *pctrl = platform_get_drvdata(pdev);
gpiochip_remove(&pctrl->chip);
pinctrl_unregister(pctrl->pctrl);
return 0;
}
static struct platform_driver pm8xxx_mpp_driver = {
.driver = {
.name = "qcom-ssbi-mpp",
.of_match_table = pm8xxx_mpp_of_match,
},
.probe = pm8xxx_mpp_probe,
.remove = pm8xxx_mpp_remove,
};
module_platform_driver(pm8xxx_mpp_driver);
MODULE_AUTHOR("Bjorn Andersson <bjorn.andersson@sonymobile.com>");
MODULE_DESCRIPTION("Qualcomm PM8xxx MPP driver");
MODULE_LICENSE("GPL v2");

View File

@ -148,9 +148,9 @@ static int exynos_irq_set_type(struct irq_data *irqd, unsigned int type)
} }
if (type & IRQ_TYPE_EDGE_BOTH) if (type & IRQ_TYPE_EDGE_BOTH)
__irq_set_handler_locked(irqd->irq, handle_edge_irq); irq_set_handler_locked(irqd, handle_edge_irq);
else else
__irq_set_handler_locked(irqd->irq, handle_level_irq); irq_set_handler_locked(irqd, handle_level_irq);
con = readl(d->virt_base + reg_con); con = readl(d->virt_base + reg_con);
con &= ~(EXYNOS_EINT_CON_MASK << shift); con &= ~(EXYNOS_EINT_CON_MASK << shift);
@ -256,7 +256,6 @@ static int exynos_eint_irq_map(struct irq_domain *h, unsigned int virq,
irq_set_chip_data(virq, b); irq_set_chip_data(virq, b);
irq_set_chip_and_handler(virq, &b->irq_chip->chip, irq_set_chip_and_handler(virq, &b->irq_chip->chip,
handle_level_irq); handle_level_irq);
set_irq_flags(virq, IRQF_VALID);
return 0; return 0;
} }
@ -422,9 +421,9 @@ static const struct of_device_id exynos_wkup_irq_ids[] = {
/* interrupt handler for wakeup interrupts 0..15 */ /* interrupt handler for wakeup interrupts 0..15 */
static void exynos_irq_eint0_15(unsigned int irq, struct irq_desc *desc) static void exynos_irq_eint0_15(unsigned int irq, struct irq_desc *desc)
{ {
struct exynos_weint_data *eintd = irq_get_handler_data(irq); struct exynos_weint_data *eintd = irq_desc_get_handler_data(desc);
struct samsung_pin_bank *bank = eintd->bank; struct samsung_pin_bank *bank = eintd->bank;
struct irq_chip *chip = irq_get_chip(irq); struct irq_chip *chip = irq_desc_get_chip(desc);
int eint_irq; int eint_irq;
chained_irq_enter(chip, desc); chained_irq_enter(chip, desc);
@ -454,8 +453,8 @@ static inline void exynos_irq_demux_eint(unsigned long pend,
/* interrupt handler for wakeup interrupt 16 */ /* interrupt handler for wakeup interrupt 16 */
static void exynos_irq_demux_eint16_31(unsigned int irq, struct irq_desc *desc) static void exynos_irq_demux_eint16_31(unsigned int irq, struct irq_desc *desc)
{ {
struct irq_chip *chip = irq_get_chip(irq); struct irq_chip *chip = irq_desc_get_chip(desc);
struct exynos_muxed_weint_data *eintd = irq_get_handler_data(irq); struct exynos_muxed_weint_data *eintd = irq_desc_get_handler_data(desc);
struct samsung_pinctrl_drv_data *d = eintd->banks[0]->drvdata; struct samsung_pinctrl_drv_data *d = eintd->banks[0]->drvdata;
unsigned long pend; unsigned long pend;
unsigned long mask; unsigned long mask;
@ -542,8 +541,9 @@ static int exynos_eint_wkup_init(struct samsung_pinctrl_drv_data *d)
} }
weint_data[idx].irq = idx; weint_data[idx].irq = idx;
weint_data[idx].bank = bank; weint_data[idx].bank = bank;
irq_set_handler_data(irq, &weint_data[idx]); irq_set_chained_handler_and_data(irq,
irq_set_chained_handler(irq, exynos_irq_eint0_15); exynos_irq_eint0_15,
&weint_data[idx]);
} }
} }

View File

@ -44,9 +44,7 @@
#define PIN_NAME_LENGTH 10 #define PIN_NAME_LENGTH 10
#define GROUP_SUFFIX "-grp" #define GROUP_SUFFIX "-grp"
#define GSUFFIX_LEN sizeof(GROUP_SUFFIX)
#define FUNCTION_SUFFIX "-mux" #define FUNCTION_SUFFIX "-mux"
#define FSUFFIX_LEN sizeof(FUNCTION_SUFFIX)
/* /*
* pin configuration type and its value are packed together into a 16-bits. * pin configuration type and its value are packed together into a 16-bits.
@ -205,22 +203,17 @@ static int exynos5440_dt_node_to_map(struct pinctrl_dev *pctldev,
/* Allocate memory for pin-map entries */ /* Allocate memory for pin-map entries */
map = kzalloc(sizeof(*map) * map_cnt, GFP_KERNEL); map = kzalloc(sizeof(*map) * map_cnt, GFP_KERNEL);
if (!map) { if (!map)
dev_err(dev, "could not alloc memory for pin-maps\n");
return -ENOMEM; return -ENOMEM;
}
*nmaps = 0; *nmaps = 0;
/* /*
* Allocate memory for pin group name. The pin group name is derived * Allocate memory for pin group name. The pin group name is derived
* from the node name from which these map entries are be created. * from the node name from which these map entries are be created.
*/ */
gname = kzalloc(strlen(np->name) + GSUFFIX_LEN, GFP_KERNEL); gname = kasprintf(GFP_KERNEL, "%s%s", np->name, GROUP_SUFFIX);
if (!gname) { if (!gname)
dev_err(dev, "failed to alloc memory for group name\n");
goto free_map; goto free_map;
}
snprintf(gname, strlen(np->name) + 4, "%s%s", np->name, GROUP_SUFFIX);
/* /*
* don't have config options? then skip over to creating function * don't have config options? then skip over to creating function
@ -231,10 +224,8 @@ static int exynos5440_dt_node_to_map(struct pinctrl_dev *pctldev,
/* Allocate memory for config entries */ /* Allocate memory for config entries */
cfg = kzalloc(sizeof(*cfg) * cfg_cnt, GFP_KERNEL); cfg = kzalloc(sizeof(*cfg) * cfg_cnt, GFP_KERNEL);
if (!cfg) { if (!cfg)
dev_err(dev, "failed to alloc memory for configs\n");
goto free_gname; goto free_gname;
}
/* Prepare a list of config settings */ /* Prepare a list of config settings */
for (idx = 0, cfg_cnt = 0; idx < ARRAY_SIZE(pcfgs); idx++) { for (idx = 0, cfg_cnt = 0; idx < ARRAY_SIZE(pcfgs); idx++) {
@ -254,13 +245,10 @@ static int exynos5440_dt_node_to_map(struct pinctrl_dev *pctldev,
skip_cfgs: skip_cfgs:
/* create the function map entry */ /* create the function map entry */
if (of_find_property(np, "samsung,exynos5440-pin-function", NULL)) { if (of_find_property(np, "samsung,exynos5440-pin-function", NULL)) {
fname = kzalloc(strlen(np->name) + FSUFFIX_LEN, GFP_KERNEL); fname = kasprintf(GFP_KERNEL,
if (!fname) { "%s%s", np->name, FUNCTION_SUFFIX);
dev_err(dev, "failed to alloc memory for func name\n"); if (!fname)
goto free_cfg; goto free_cfg;
}
snprintf(fname, strlen(np->name) + 4, "%s%s", np->name,
FUNCTION_SUFFIX);
map[*nmaps].data.mux.group = gname; map[*nmaps].data.mux.group = gname;
map[*nmaps].data.mux.function = fname; map[*nmaps].data.mux.function = fname;
@ -651,10 +639,8 @@ static int exynos5440_pinctrl_parse_dt_pins(struct platform_device *pdev,
} }
*pin_list = devm_kzalloc(dev, *npins * sizeof(**pin_list), GFP_KERNEL); *pin_list = devm_kzalloc(dev, *npins * sizeof(**pin_list), GFP_KERNEL);
if (!*pin_list) { if (!*pin_list)
dev_err(dev, "failed to allocate memory for pin list\n");
return -ENOMEM; return -ENOMEM;
}
return of_property_read_u32_array(cfg_np, "samsung,exynos5440-pins", return of_property_read_u32_array(cfg_np, "samsung,exynos5440-pins",
*pin_list, *npins); *pin_list, *npins);
@ -682,17 +668,15 @@ static int exynos5440_pinctrl_parse_dt(struct platform_device *pdev,
return -EINVAL; return -EINVAL;
groups = devm_kzalloc(dev, grp_cnt * sizeof(*groups), GFP_KERNEL); groups = devm_kzalloc(dev, grp_cnt * sizeof(*groups), GFP_KERNEL);
if (!groups) { if (!groups)
dev_err(dev, "failed allocate memory for ping group list\n");
return -EINVAL; return -EINVAL;
}
grp = groups; grp = groups;
functions = devm_kzalloc(dev, grp_cnt * sizeof(*functions), GFP_KERNEL); functions = devm_kzalloc(dev, grp_cnt * sizeof(*functions), GFP_KERNEL);
if (!functions) { if (!functions)
dev_err(dev, "failed to allocate memory for function list\n");
return -EINVAL; return -EINVAL;
}
func = functions; func = functions;
/* /*
@ -710,14 +694,10 @@ static int exynos5440_pinctrl_parse_dt(struct platform_device *pdev,
} }
/* derive pin group name from the node name */ /* derive pin group name from the node name */
gname = devm_kzalloc(dev, strlen(cfg_np->name) + GSUFFIX_LEN, gname = devm_kasprintf(dev, GFP_KERNEL,
GFP_KERNEL); "%s%s", cfg_np->name, GROUP_SUFFIX);
if (!gname) { if (!gname)
dev_err(dev, "failed to alloc memory for group name\n");
return -ENOMEM; return -ENOMEM;
}
snprintf(gname, strlen(cfg_np->name) + 4, "%s%s", cfg_np->name,
GROUP_SUFFIX);
grp->name = gname; grp->name = gname;
grp->pins = pin_list; grp->pins = pin_list;
@ -731,22 +711,15 @@ skip_to_pin_function:
continue; continue;
/* derive function name from the node name */ /* derive function name from the node name */
fname = devm_kzalloc(dev, strlen(cfg_np->name) + FSUFFIX_LEN, fname = devm_kasprintf(dev, GFP_KERNEL,
GFP_KERNEL); "%s%s", cfg_np->name, FUNCTION_SUFFIX);
if (!fname) { if (!fname)
dev_err(dev, "failed to alloc memory for func name\n");
return -ENOMEM; return -ENOMEM;
}
snprintf(fname, strlen(cfg_np->name) + 4, "%s%s", cfg_np->name,
FUNCTION_SUFFIX);
func->name = fname; func->name = fname;
func->groups = devm_kzalloc(dev, sizeof(char *), GFP_KERNEL); func->groups = devm_kzalloc(dev, sizeof(char *), GFP_KERNEL);
if (!func->groups) { if (!func->groups)
dev_err(dev, "failed to alloc memory for group list "
"in pin function");
return -ENOMEM; return -ENOMEM;
}
func->groups[0] = gname; func->groups[0] = gname;
func->num_groups = gname ? 1 : 0; func->num_groups = gname ? 1 : 0;
func->function = function; func->function = function;
@ -774,10 +747,8 @@ static int exynos5440_pinctrl_register(struct platform_device *pdev,
int pin, ret; int pin, ret;
ctrldesc = devm_kzalloc(dev, sizeof(*ctrldesc), GFP_KERNEL); ctrldesc = devm_kzalloc(dev, sizeof(*ctrldesc), GFP_KERNEL);
if (!ctrldesc) { if (!ctrldesc)
dev_err(dev, "could not allocate memory for pinctrl desc\n");
return -ENOMEM; return -ENOMEM;
}
ctrldesc->name = "exynos5440-pinctrl"; ctrldesc->name = "exynos5440-pinctrl";
ctrldesc->owner = THIS_MODULE; ctrldesc->owner = THIS_MODULE;
@ -787,10 +758,8 @@ static int exynos5440_pinctrl_register(struct platform_device *pdev,
pindesc = devm_kzalloc(&pdev->dev, sizeof(*pindesc) * pindesc = devm_kzalloc(&pdev->dev, sizeof(*pindesc) *
EXYNOS5440_MAX_PINS, GFP_KERNEL); EXYNOS5440_MAX_PINS, GFP_KERNEL);
if (!pindesc) { if (!pindesc)
dev_err(&pdev->dev, "mem alloc for pin descriptors failed\n");
return -ENOMEM; return -ENOMEM;
}
ctrldesc->pins = pindesc; ctrldesc->pins = pindesc;
ctrldesc->npins = EXYNOS5440_MAX_PINS; ctrldesc->npins = EXYNOS5440_MAX_PINS;
@ -804,10 +773,8 @@ static int exynos5440_pinctrl_register(struct platform_device *pdev,
*/ */
pin_names = devm_kzalloc(&pdev->dev, sizeof(char) * PIN_NAME_LENGTH * pin_names = devm_kzalloc(&pdev->dev, sizeof(char) * PIN_NAME_LENGTH *
ctrldesc->npins, GFP_KERNEL); ctrldesc->npins, GFP_KERNEL);
if (!pin_names) { if (!pin_names)
dev_err(&pdev->dev, "mem alloc for pin names failed\n");
return -ENOMEM; return -ENOMEM;
}
/* for each pin, set the name of the pin */ /* for each pin, set the name of the pin */
for (pin = 0; pin < ctrldesc->npins; pin++) { for (pin = 0; pin < ctrldesc->npins; pin++) {
@ -844,10 +811,8 @@ static int exynos5440_gpiolib_register(struct platform_device *pdev,
int ret; int ret;
gc = devm_kzalloc(&pdev->dev, sizeof(*gc), GFP_KERNEL); gc = devm_kzalloc(&pdev->dev, sizeof(*gc), GFP_KERNEL);
if (!gc) { if (!gc)
dev_err(&pdev->dev, "mem alloc for gpio_chip failed\n");
return -ENOMEM; return -ENOMEM;
}
priv->gc = gc; priv->gc = gc;
gc->base = 0; gc->base = 0;
@ -929,7 +894,6 @@ static int exynos5440_gpio_irq_map(struct irq_domain *h, unsigned int virq,
irq_set_chip_data(virq, d); irq_set_chip_data(virq, d);
irq_set_chip_and_handler(virq, &exynos5440_gpio_irq_chip, irq_set_chip_and_handler(virq, &exynos5440_gpio_irq_chip,
handle_level_irq); handle_level_irq);
set_irq_flags(virq, IRQF_VALID);
return 0; return 0;
} }
@ -949,10 +913,8 @@ static int exynos5440_gpio_irq_init(struct platform_device *pdev,
intd = devm_kzalloc(dev, sizeof(*intd) * EXYNOS5440_MAX_GPIO_INT, intd = devm_kzalloc(dev, sizeof(*intd) * EXYNOS5440_MAX_GPIO_INT,
GFP_KERNEL); GFP_KERNEL);
if (!intd) { if (!intd)
dev_err(dev, "failed to allocate memory for gpio intr data\n");
return -ENOMEM; return -ENOMEM;
}
for (i = 0; i < EXYNOS5440_MAX_GPIO_INT; i++) { for (i = 0; i < EXYNOS5440_MAX_GPIO_INT; i++) {
irq = irq_of_parse_and_map(dev->of_node, i); irq = irq_of_parse_and_map(dev->of_node, i);
@ -995,10 +957,8 @@ static int exynos5440_pinctrl_probe(struct platform_device *pdev)
} }
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv) { if (!priv)
dev_err(dev, "could not allocate memory for private data\n");
return -ENOMEM; return -ENOMEM;
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
priv->reg_base = devm_ioremap_resource(&pdev->dev, res); priv->reg_base = devm_ioremap_resource(&pdev->dev, res);

View File

@ -131,13 +131,13 @@ static int s3c24xx_eint_get_trigger(unsigned int type)
} }
} }
static void s3c24xx_eint_set_handler(unsigned int irq, unsigned int type) static void s3c24xx_eint_set_handler(struct irq_data *d, unsigned int type)
{ {
/* Edge- and level-triggered interrupts need different handlers */ /* Edge- and level-triggered interrupts need different handlers */
if (type & IRQ_TYPE_EDGE_BOTH) if (type & IRQ_TYPE_EDGE_BOTH)
__irq_set_handler_locked(irq, handle_edge_irq); irq_set_handler_locked(d, handle_edge_irq);
else else
__irq_set_handler_locked(irq, handle_level_irq); irq_set_handler_locked(d, handle_level_irq);
} }
static void s3c24xx_eint_set_function(struct samsung_pinctrl_drv_data *d, static void s3c24xx_eint_set_function(struct samsung_pinctrl_drv_data *d,
@ -181,7 +181,7 @@ static int s3c24xx_eint_type(struct irq_data *data, unsigned int type)
return -EINVAL; return -EINVAL;
} }
s3c24xx_eint_set_handler(data->irq, type); s3c24xx_eint_set_handler(data, type);
/* Set up interrupt trigger */ /* Set up interrupt trigger */
reg = d->virt_base + EINT_REG(index); reg = d->virt_base + EINT_REG(index);
@ -243,7 +243,7 @@ static struct irq_chip s3c2410_eint0_3_chip = {
static void s3c2410_demux_eint0_3(unsigned int irq, struct irq_desc *desc) static void s3c2410_demux_eint0_3(unsigned int irq, struct irq_desc *desc)
{ {
struct irq_data *data = irq_desc_get_irq_data(desc); struct irq_data *data = irq_desc_get_irq_data(desc);
struct s3c24xx_eint_data *eint_data = irq_get_handler_data(irq); struct s3c24xx_eint_data *eint_data = irq_desc_get_handler_data(desc);
unsigned int virq; unsigned int virq;
/* the first 4 eints have a simple 1 to 1 mapping */ /* the first 4 eints have a simple 1 to 1 mapping */
@ -297,9 +297,9 @@ static struct irq_chip s3c2412_eint0_3_chip = {
static void s3c2412_demux_eint0_3(unsigned int irq, struct irq_desc *desc) static void s3c2412_demux_eint0_3(unsigned int irq, struct irq_desc *desc)
{ {
struct irq_chip *chip = irq_get_chip(irq); struct s3c24xx_eint_data *eint_data = irq_desc_get_handler_data(desc);
struct irq_data *data = irq_desc_get_irq_data(desc); struct irq_data *data = irq_desc_get_irq_data(desc);
struct s3c24xx_eint_data *eint_data = irq_get_handler_data(irq); struct irq_chip *chip = irq_data_get_irq_chip(data);
unsigned int virq; unsigned int virq;
chained_irq_enter(chip, desc); chained_irq_enter(chip, desc);
@ -357,11 +357,11 @@ static struct irq_chip s3c24xx_eint_chip = {
.irq_set_type = s3c24xx_eint_type, .irq_set_type = s3c24xx_eint_type,
}; };
static inline void s3c24xx_demux_eint(unsigned int irq, struct irq_desc *desc, static inline void s3c24xx_demux_eint(struct irq_desc *desc,
u32 offset, u32 range) u32 offset, u32 range)
{ {
struct irq_chip *chip = irq_get_chip(irq); struct s3c24xx_eint_data *data = irq_desc_get_handler_data(desc);
struct s3c24xx_eint_data *data = irq_get_handler_data(irq); struct irq_chip *chip = irq_desc_get_irq_chip(desc);
struct samsung_pinctrl_drv_data *d = data->drvdata; struct samsung_pinctrl_drv_data *d = data->drvdata;
unsigned int pend, mask; unsigned int pend, mask;
@ -374,7 +374,7 @@ static inline void s3c24xx_demux_eint(unsigned int irq, struct irq_desc *desc,
pend &= range; pend &= range;
while (pend) { while (pend) {
unsigned int virq; unsigned int virq, irq;
irq = __ffs(pend); irq = __ffs(pend);
pend &= ~(1 << irq); pend &= ~(1 << irq);
@ -390,12 +390,12 @@ static inline void s3c24xx_demux_eint(unsigned int irq, struct irq_desc *desc,
static void s3c24xx_demux_eint4_7(unsigned int irq, struct irq_desc *desc) static void s3c24xx_demux_eint4_7(unsigned int irq, struct irq_desc *desc)
{ {
s3c24xx_demux_eint(irq, desc, 0, 0xf0); s3c24xx_demux_eint(desc, 0, 0xf0);
} }
static void s3c24xx_demux_eint8_23(unsigned int irq, struct irq_desc *desc) static void s3c24xx_demux_eint8_23(unsigned int irq, struct irq_desc *desc)
{ {
s3c24xx_demux_eint(irq, desc, 8, 0xffff00); s3c24xx_demux_eint(desc, 8, 0xffff00);
} }
static irq_flow_handler_t s3c2410_eint_handlers[NUM_EINT_IRQ] = { static irq_flow_handler_t s3c2410_eint_handlers[NUM_EINT_IRQ] = {
@ -437,7 +437,6 @@ static int s3c24xx_gpf_irq_map(struct irq_domain *h, unsigned int virq,
handle_edge_irq); handle_edge_irq);
} }
irq_set_chip_data(virq, bank); irq_set_chip_data(virq, bank);
set_irq_flags(virq, IRQF_VALID);
return 0; return 0;
} }
@ -457,7 +456,6 @@ static int s3c24xx_gpg_irq_map(struct irq_domain *h, unsigned int virq,
irq_set_chip_and_handler(virq, &s3c24xx_eint_chip, handle_edge_irq); irq_set_chip_and_handler(virq, &s3c24xx_eint_chip, handle_edge_irq);
irq_set_chip_data(virq, bank); irq_set_chip_data(virq, bank);
set_irq_flags(virq, IRQF_VALID);
return 0; return 0;
} }

View File

@ -260,13 +260,13 @@ static int s3c64xx_irq_get_trigger(unsigned int type)
return trigger; return trigger;
} }
static void s3c64xx_irq_set_handler(unsigned int irq, unsigned int type) static void s3c64xx_irq_set_handler(struct irq_data *d, unsigned int type)
{ {
/* Edge- and level-triggered interrupts need different handlers */ /* Edge- and level-triggered interrupts need different handlers */
if (type & IRQ_TYPE_EDGE_BOTH) if (type & IRQ_TYPE_EDGE_BOTH)
__irq_set_handler_locked(irq, handle_edge_irq); irq_set_handler_locked(d, handle_edge_irq);
else else
__irq_set_handler_locked(irq, handle_level_irq); irq_set_handler_locked(d, handle_level_irq);
} }
static void s3c64xx_irq_set_function(struct samsung_pinctrl_drv_data *d, static void s3c64xx_irq_set_function(struct samsung_pinctrl_drv_data *d,
@ -356,7 +356,7 @@ static int s3c64xx_gpio_irq_set_type(struct irq_data *irqd, unsigned int type)
return -EINVAL; return -EINVAL;
} }
s3c64xx_irq_set_handler(irqd->irq, type); s3c64xx_irq_set_handler(irqd, type);
/* Set up interrupt trigger */ /* Set up interrupt trigger */
reg = d->virt_base + EINTCON_REG(bank->eint_offset); reg = d->virt_base + EINTCON_REG(bank->eint_offset);
@ -395,7 +395,6 @@ static int s3c64xx_gpio_irq_map(struct irq_domain *h, unsigned int virq,
irq_set_chip_and_handler(virq, irq_set_chip_and_handler(virq,
&s3c64xx_gpio_irq_chip, handle_level_irq); &s3c64xx_gpio_irq_chip, handle_level_irq);
irq_set_chip_data(virq, bank); irq_set_chip_data(virq, bank);
set_irq_flags(virq, IRQF_VALID);
return 0; return 0;
} }
@ -410,8 +409,8 @@ static const struct irq_domain_ops s3c64xx_gpio_irqd_ops = {
static void s3c64xx_eint_gpio_irq(unsigned int irq, struct irq_desc *desc) static void s3c64xx_eint_gpio_irq(unsigned int irq, struct irq_desc *desc)
{ {
struct irq_chip *chip = irq_get_chip(irq); struct irq_chip *chip = irq_desc_get_chip(desc);
struct s3c64xx_eint_gpio_data *data = irq_get_handler_data(irq); struct s3c64xx_eint_gpio_data *data = irq_desc_get_handler_data(desc);
struct samsung_pinctrl_drv_data *drvdata = data->drvdata; struct samsung_pinctrl_drv_data *drvdata = data->drvdata;
chained_irq_enter(chip, desc); chained_irq_enter(chip, desc);
@ -567,7 +566,7 @@ static int s3c64xx_eint0_irq_set_type(struct irq_data *irqd, unsigned int type)
return -EINVAL; return -EINVAL;
} }
s3c64xx_irq_set_handler(irqd->irq, type); s3c64xx_irq_set_handler(irqd, type);
/* Set up interrupt trigger */ /* Set up interrupt trigger */
reg = d->virt_base + EINT0CON0_REG; reg = d->virt_base + EINT0CON0_REG;
@ -599,11 +598,10 @@ static struct irq_chip s3c64xx_eint0_irq_chip = {
.irq_set_type = s3c64xx_eint0_irq_set_type, .irq_set_type = s3c64xx_eint0_irq_set_type,
}; };
static inline void s3c64xx_irq_demux_eint(unsigned int irq, static inline void s3c64xx_irq_demux_eint(struct irq_desc *desc, u32 range)
struct irq_desc *desc, u32 range)
{ {
struct irq_chip *chip = irq_get_chip(irq); struct irq_chip *chip = irq_desc_get_chip(desc);
struct s3c64xx_eint0_data *data = irq_get_handler_data(irq); struct s3c64xx_eint0_data *data = irq_desc_get_handler_data(desc);
struct samsung_pinctrl_drv_data *drvdata = data->drvdata; struct samsung_pinctrl_drv_data *drvdata = data->drvdata;
unsigned int pend, mask; unsigned int pend, mask;
@ -616,11 +614,10 @@ static inline void s3c64xx_irq_demux_eint(unsigned int irq,
pend &= range; pend &= range;
while (pend) { while (pend) {
unsigned int virq; unsigned int virq, irq;
irq = fls(pend) - 1; irq = fls(pend) - 1;
pend &= ~(1 << irq); pend &= ~(1 << irq);
virq = irq_linear_revmap(data->domains[irq], data->pins[irq]); virq = irq_linear_revmap(data->domains[irq], data->pins[irq]);
/* /*
* Something must be really wrong if an unmapped EINT * Something must be really wrong if an unmapped EINT
@ -636,22 +633,22 @@ static inline void s3c64xx_irq_demux_eint(unsigned int irq,
static void s3c64xx_demux_eint0_3(unsigned int irq, struct irq_desc *desc) static void s3c64xx_demux_eint0_3(unsigned int irq, struct irq_desc *desc)
{ {
s3c64xx_irq_demux_eint(irq, desc, 0xf); s3c64xx_irq_demux_eint(desc, 0xf);
} }
static void s3c64xx_demux_eint4_11(unsigned int irq, struct irq_desc *desc) static void s3c64xx_demux_eint4_11(unsigned int irq, struct irq_desc *desc)
{ {
s3c64xx_irq_demux_eint(irq, desc, 0xff0); s3c64xx_irq_demux_eint(desc, 0xff0);
} }
static void s3c64xx_demux_eint12_19(unsigned int irq, struct irq_desc *desc) static void s3c64xx_demux_eint12_19(unsigned int irq, struct irq_desc *desc)
{ {
s3c64xx_irq_demux_eint(irq, desc, 0xff000); s3c64xx_irq_demux_eint(desc, 0xff000);
} }
static void s3c64xx_demux_eint20_27(unsigned int irq, struct irq_desc *desc) static void s3c64xx_demux_eint20_27(unsigned int irq, struct irq_desc *desc)
{ {
s3c64xx_irq_demux_eint(irq, desc, 0xff00000); s3c64xx_irq_demux_eint(desc, 0xff00000);
} }
static irq_flow_handler_t s3c64xx_eint0_handlers[NUM_EINT0_IRQ] = { static irq_flow_handler_t s3c64xx_eint0_handlers[NUM_EINT0_IRQ] = {
@ -673,7 +670,6 @@ static int s3c64xx_eint0_irq_map(struct irq_domain *h, unsigned int virq,
irq_set_chip_and_handler(virq, irq_set_chip_and_handler(virq,
&s3c64xx_eint0_irq_chip, handle_level_irq); &s3c64xx_eint0_irq_chip, handle_level_irq);
irq_set_chip_data(virq, ddata); irq_set_chip_data(virq, ddata);
set_irq_flags(virq, IRQF_VALID);
return 0; return 0;
} }

View File

@ -29,24 +29,25 @@
static int sh_pfc_map_resources(struct sh_pfc *pfc, static int sh_pfc_map_resources(struct sh_pfc *pfc,
struct platform_device *pdev) struct platform_device *pdev)
{ {
unsigned int num_windows = 0; unsigned int num_windows, num_irqs;
unsigned int num_irqs = 0;
struct sh_pfc_window *windows; struct sh_pfc_window *windows;
unsigned int *irqs = NULL; unsigned int *irqs = NULL;
struct resource *res; struct resource *res;
unsigned int i; unsigned int i;
int irq;
/* Count the MEM and IRQ resources. */ /* Count the MEM and IRQ resources. */
for (i = 0; i < pdev->num_resources; ++i) { for (num_windows = 0;; num_windows++) {
switch (resource_type(&pdev->resource[i])) { res = platform_get_resource(pdev, IORESOURCE_MEM, num_windows);
case IORESOURCE_MEM: if (!res)
num_windows++;
break; break;
}
case IORESOURCE_IRQ: for (num_irqs = 0;; num_irqs++) {
num_irqs++; irq = platform_get_irq(pdev, num_irqs);
if (irq == -EPROBE_DEFER)
return irq;
if (irq < 0)
break; break;
}
} }
if (num_windows == 0) if (num_windows == 0)
@ -72,22 +73,17 @@ static int sh_pfc_map_resources(struct sh_pfc *pfc,
} }
/* Fill them. */ /* Fill them. */
for (i = 0, res = pdev->resource; i < pdev->num_resources; i++, res++) { for (i = 0; i < num_windows; i++) {
switch (resource_type(res)) { res = platform_get_resource(pdev, IORESOURCE_MEM, i);
case IORESOURCE_MEM: windows->phys = res->start;
windows->phys = res->start; windows->size = resource_size(res);
windows->size = resource_size(res); windows->virt = devm_ioremap_resource(pfc->dev, res);
windows->virt = devm_ioremap_resource(pfc->dev, res); if (IS_ERR(windows->virt))
if (IS_ERR(windows->virt)) return -ENOMEM;
return -ENOMEM; windows++;
windows++;
break;
case IORESOURCE_IRQ:
*irqs++ = res->start;
break;
}
} }
for (i = 0; i < num_irqs; i++)
*irqs++ = platform_get_irq(pdev, i);
return 0; return 0;
} }
@ -591,9 +587,6 @@ static int sh_pfc_remove(struct platform_device *pdev)
} }
static const struct platform_device_id sh_pfc_id_table[] = { static const struct platform_device_id sh_pfc_id_table[] = {
#ifdef CONFIG_PINCTRL_PFC_R8A7740
{ "pfc-r8a7740", (kernel_ulong_t)&r8a7740_pinmux_info },
#endif
#ifdef CONFIG_PINCTRL_PFC_R8A7778 #ifdef CONFIG_PINCTRL_PFC_R8A7778
{ "pfc-r8a7778", (kernel_ulong_t)&r8a7778_pinmux_info }, { "pfc-r8a7778", (kernel_ulong_t)&r8a7778_pinmux_info },
#endif #endif
@ -609,9 +602,6 @@ static const struct platform_device_id sh_pfc_id_table[] = {
#ifdef CONFIG_PINCTRL_PFC_SH7269 #ifdef CONFIG_PINCTRL_PFC_SH7269
{ "pfc-sh7269", (kernel_ulong_t)&sh7269_pinmux_info }, { "pfc-sh7269", (kernel_ulong_t)&sh7269_pinmux_info },
#endif #endif
#ifdef CONFIG_PINCTRL_PFC_SH73A0
{ "pfc-sh73a0", (kernel_ulong_t)&sh73a0_pinmux_info },
#endif
#ifdef CONFIG_PINCTRL_PFC_SH7720 #ifdef CONFIG_PINCTRL_PFC_SH7720
{ "pfc-sh7720", (kernel_ulong_t)&sh7720_pinmux_info }, { "pfc-sh7720", (kernel_ulong_t)&sh7720_pinmux_info },
#endif #endif

View File

@ -22,10 +22,6 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/pinctrl/pinconf-generic.h> #include <linux/pinctrl/pinconf-generic.h>
#ifndef CONFIG_ARCH_MULTIPLATFORM
#include <mach/irqs.h>
#endif
#include "core.h" #include "core.h"
#include "sh_pfc.h" #include "sh_pfc.h"

View File

@ -27,10 +27,27 @@
#include "core.h" #include "core.h"
#include "sh_pfc.h" #include "sh_pfc.h"
#define PORT_GP_30(bank, fn, sfx) \
PORT_GP_1(bank, 0, fn, sfx), PORT_GP_1(bank, 1, fn, sfx), \
PORT_GP_1(bank, 2, fn, sfx), PORT_GP_1(bank, 3, fn, sfx), \
PORT_GP_1(bank, 4, fn, sfx), PORT_GP_1(bank, 5, fn, sfx), \
PORT_GP_1(bank, 6, fn, sfx), PORT_GP_1(bank, 7, fn, sfx), \
PORT_GP_1(bank, 8, fn, sfx), PORT_GP_1(bank, 9, fn, sfx), \
PORT_GP_1(bank, 10, fn, sfx), PORT_GP_1(bank, 11, fn, sfx), \
PORT_GP_1(bank, 12, fn, sfx), PORT_GP_1(bank, 13, fn, sfx), \
PORT_GP_1(bank, 14, fn, sfx), PORT_GP_1(bank, 15, fn, sfx), \
PORT_GP_1(bank, 16, fn, sfx), PORT_GP_1(bank, 17, fn, sfx), \
PORT_GP_1(bank, 18, fn, sfx), PORT_GP_1(bank, 19, fn, sfx), \
PORT_GP_1(bank, 20, fn, sfx), PORT_GP_1(bank, 21, fn, sfx), \
PORT_GP_1(bank, 22, fn, sfx), PORT_GP_1(bank, 23, fn, sfx), \
PORT_GP_1(bank, 24, fn, sfx), PORT_GP_1(bank, 25, fn, sfx), \
PORT_GP_1(bank, 26, fn, sfx), PORT_GP_1(bank, 27, fn, sfx), \
PORT_GP_1(bank, 28, fn, sfx), PORT_GP_1(bank, 29, fn, sfx)
#define CPU_ALL_PORT(fn, sfx) \ #define CPU_ALL_PORT(fn, sfx) \
PORT_GP_32(0, fn, sfx), \ PORT_GP_32(0, fn, sfx), \
PORT_GP_32(1, fn, sfx), \ PORT_GP_30(1, fn, sfx), \
PORT_GP_32(2, fn, sfx), \ PORT_GP_30(2, fn, sfx), \
PORT_GP_32(3, fn, sfx), \ PORT_GP_32(3, fn, sfx), \
PORT_GP_32(4, fn, sfx), \ PORT_GP_32(4, fn, sfx), \
PORT_GP_32(5, fn, sfx) PORT_GP_32(5, fn, sfx)

View File

@ -14,15 +14,30 @@
#include "core.h" #include "core.h"
#include "sh_pfc.h" #include "sh_pfc.h"
#define PORT_GP_26(bank, fn, sfx) \
PORT_GP_1(bank, 0, fn, sfx), PORT_GP_1(bank, 1, fn, sfx), \
PORT_GP_1(bank, 2, fn, sfx), PORT_GP_1(bank, 3, fn, sfx), \
PORT_GP_1(bank, 4, fn, sfx), PORT_GP_1(bank, 5, fn, sfx), \
PORT_GP_1(bank, 6, fn, sfx), PORT_GP_1(bank, 7, fn, sfx), \
PORT_GP_1(bank, 8, fn, sfx), PORT_GP_1(bank, 9, fn, sfx), \
PORT_GP_1(bank, 10, fn, sfx), PORT_GP_1(bank, 11, fn, sfx), \
PORT_GP_1(bank, 12, fn, sfx), PORT_GP_1(bank, 13, fn, sfx), \
PORT_GP_1(bank, 14, fn, sfx), PORT_GP_1(bank, 15, fn, sfx), \
PORT_GP_1(bank, 16, fn, sfx), PORT_GP_1(bank, 17, fn, sfx), \
PORT_GP_1(bank, 18, fn, sfx), PORT_GP_1(bank, 19, fn, sfx), \
PORT_GP_1(bank, 20, fn, sfx), PORT_GP_1(bank, 21, fn, sfx), \
PORT_GP_1(bank, 22, fn, sfx), PORT_GP_1(bank, 23, fn, sfx), \
PORT_GP_1(bank, 24, fn, sfx), PORT_GP_1(bank, 25, fn, sfx)
#define CPU_ALL_PORT(fn, sfx) \ #define CPU_ALL_PORT(fn, sfx) \
PORT_GP_32(0, fn, sfx), \ PORT_GP_32(0, fn, sfx), \
PORT_GP_32(1, fn, sfx), \ PORT_GP_26(1, fn, sfx), \
PORT_GP_32(2, fn, sfx), \ PORT_GP_32(2, fn, sfx), \
PORT_GP_32(3, fn, sfx), \ PORT_GP_32(3, fn, sfx), \
PORT_GP_32(4, fn, sfx), \ PORT_GP_32(4, fn, sfx), \
PORT_GP_32(5, fn, sfx), \ PORT_GP_32(5, fn, sfx), \
PORT_GP_32(6, fn, sfx), \ PORT_GP_32(6, fn, sfx), \
PORT_GP_32(7, fn, sfx) PORT_GP_26(7, fn, sfx)
enum { enum {
PINMUX_RESERVED = 0, PINMUX_RESERVED = 0,

View File

@ -2770,6 +2770,24 @@ static const unsigned int sdhi2_wp_pins[] = {
static const unsigned int sdhi2_wp_mux[] = { static const unsigned int sdhi2_wp_mux[] = {
SD2_WP_MARK, SD2_WP_MARK,
}; };
/* - USB0 ------------------------------------------------------------------- */
static const unsigned int usb0_pins[] = {
RCAR_GP_PIN(5, 24), /* PWEN */
RCAR_GP_PIN(5, 25), /* OVC */
};
static const unsigned int usb0_mux[] = {
USB0_PWEN_MARK,
USB0_OVC_MARK,
};
/* - USB1 ------------------------------------------------------------------- */
static const unsigned int usb1_pins[] = {
RCAR_GP_PIN(5, 26), /* PWEN */
RCAR_GP_PIN(5, 27), /* OVC */
};
static const unsigned int usb1_mux[] = {
USB1_PWEN_MARK,
USB1_OVC_MARK,
};
static const struct sh_pfc_pin_group pinmux_groups[] = { static const struct sh_pfc_pin_group pinmux_groups[] = {
SH_PFC_PIN_GROUP(eth_link), SH_PFC_PIN_GROUP(eth_link),
@ -2945,6 +2963,8 @@ static const struct sh_pfc_pin_group pinmux_groups[] = {
SH_PFC_PIN_GROUP(sdhi2_ctrl), SH_PFC_PIN_GROUP(sdhi2_ctrl),
SH_PFC_PIN_GROUP(sdhi2_cd), SH_PFC_PIN_GROUP(sdhi2_cd),
SH_PFC_PIN_GROUP(sdhi2_wp), SH_PFC_PIN_GROUP(sdhi2_wp),
SH_PFC_PIN_GROUP(usb0),
SH_PFC_PIN_GROUP(usb1),
}; };
static const char * const eth_groups[] = { static const char * const eth_groups[] = {
@ -3219,6 +3239,14 @@ static const char * const sdhi2_groups[] = {
"sdhi2_wp", "sdhi2_wp",
}; };
static const char * const usb0_groups[] = {
"usb0",
};
static const char * const usb1_groups[] = {
"usb1",
};
static const struct sh_pfc_function pinmux_functions[] = { static const struct sh_pfc_function pinmux_functions[] = {
SH_PFC_FUNCTION(eth), SH_PFC_FUNCTION(eth),
SH_PFC_FUNCTION(hscif0), SH_PFC_FUNCTION(hscif0),
@ -3253,6 +3281,8 @@ static const struct sh_pfc_function pinmux_functions[] = {
SH_PFC_FUNCTION(sdhi0), SH_PFC_FUNCTION(sdhi0),
SH_PFC_FUNCTION(sdhi1), SH_PFC_FUNCTION(sdhi1),
SH_PFC_FUNCTION(sdhi2), SH_PFC_FUNCTION(sdhi2),
SH_PFC_FUNCTION(usb0),
SH_PFC_FUNCTION(usb1),
}; };
static const struct pinmux_cfg_reg pinmux_config_regs[] = { static const struct pinmux_cfg_reg pinmux_config_regs[] = {

View File

@ -26,10 +26,6 @@
#include <linux/regulator/machine.h> #include <linux/regulator/machine.h>
#include <linux/slab.h> #include <linux/slab.h>
#ifndef CONFIG_ARCH_MULTIPLATFORM
#include <mach/irqs.h>
#endif
#include "core.h" #include "core.h"
#include "sh_pfc.h" #include "sh_pfc.h"

View File

@ -40,6 +40,10 @@ struct sh_pfc_pinctrl {
struct pinctrl_pin_desc *pins; struct pinctrl_pin_desc *pins;
struct sh_pfc_pin_config *configs; struct sh_pfc_pin_config *configs;
const char *func_prop_name;
const char *groups_prop_name;
const char *pins_prop_name;
}; };
static int sh_pfc_get_groups_count(struct pinctrl_dev *pctldev) static int sh_pfc_get_groups_count(struct pinctrl_dev *pctldev)
@ -96,10 +100,13 @@ static int sh_pfc_map_add_config(struct pinctrl_map *map,
return 0; return 0;
} }
static int sh_pfc_dt_subnode_to_map(struct device *dev, struct device_node *np, static int sh_pfc_dt_subnode_to_map(struct pinctrl_dev *pctldev,
struct device_node *np,
struct pinctrl_map **map, struct pinctrl_map **map,
unsigned int *num_maps, unsigned int *index) unsigned int *num_maps, unsigned int *index)
{ {
struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
struct device *dev = pmx->pfc->dev;
struct pinctrl_map *maps = *map; struct pinctrl_map *maps = *map;
unsigned int nmaps = *num_maps; unsigned int nmaps = *num_maps;
unsigned int idx = *index; unsigned int idx = *index;
@ -113,10 +120,27 @@ static int sh_pfc_dt_subnode_to_map(struct device *dev, struct device_node *np,
const char *pin; const char *pin;
int ret; int ret;
/* Support both the old Renesas-specific properties and the new standard
* properties. Mixing old and new properties isn't allowed, neither
* inside a subnode nor across subnodes.
*/
if (!pmx->func_prop_name) {
if (of_find_property(np, "groups", NULL) ||
of_find_property(np, "pins", NULL)) {
pmx->func_prop_name = "function";
pmx->groups_prop_name = "groups";
pmx->pins_prop_name = "pins";
} else {
pmx->func_prop_name = "renesas,function";
pmx->groups_prop_name = "renesas,groups";
pmx->pins_prop_name = "renesas,pins";
}
}
/* Parse the function and configuration properties. At least a function /* Parse the function and configuration properties. At least a function
* or one configuration must be specified. * or one configuration must be specified.
*/ */
ret = of_property_read_string(np, "renesas,function", &function); ret = of_property_read_string(np, pmx->func_prop_name, &function);
if (ret < 0 && ret != -EINVAL) { if (ret < 0 && ret != -EINVAL) {
dev_err(dev, "Invalid function in DT\n"); dev_err(dev, "Invalid function in DT\n");
return ret; return ret;
@ -129,11 +153,12 @@ static int sh_pfc_dt_subnode_to_map(struct device *dev, struct device_node *np,
if (!function && num_configs == 0) { if (!function && num_configs == 0) {
dev_err(dev, dev_err(dev,
"DT node must contain at least a function or config\n"); "DT node must contain at least a function or config\n");
ret = -ENODEV;
goto done; goto done;
} }
/* Count the number of pins and groups and reallocate mappings. */ /* Count the number of pins and groups and reallocate mappings. */
ret = of_property_count_strings(np, "renesas,pins"); ret = of_property_count_strings(np, pmx->pins_prop_name);
if (ret == -EINVAL) { if (ret == -EINVAL) {
num_pins = 0; num_pins = 0;
} else if (ret < 0) { } else if (ret < 0) {
@ -143,7 +168,7 @@ static int sh_pfc_dt_subnode_to_map(struct device *dev, struct device_node *np,
num_pins = ret; num_pins = ret;
} }
ret = of_property_count_strings(np, "renesas,groups"); ret = of_property_count_strings(np, pmx->groups_prop_name);
if (ret == -EINVAL) { if (ret == -EINVAL) {
num_groups = 0; num_groups = 0;
} else if (ret < 0) { } else if (ret < 0) {
@ -174,7 +199,7 @@ static int sh_pfc_dt_subnode_to_map(struct device *dev, struct device_node *np,
*num_maps = nmaps; *num_maps = nmaps;
/* Iterate over pins and groups and create the mappings. */ /* Iterate over pins and groups and create the mappings. */
of_property_for_each_string(np, "renesas,groups", prop, group) { of_property_for_each_string(np, pmx->groups_prop_name, prop, group) {
if (function) { if (function) {
maps[idx].type = PIN_MAP_TYPE_MUX_GROUP; maps[idx].type = PIN_MAP_TYPE_MUX_GROUP;
maps[idx].data.mux.group = group; maps[idx].data.mux.group = group;
@ -198,7 +223,7 @@ static int sh_pfc_dt_subnode_to_map(struct device *dev, struct device_node *np,
goto done; goto done;
} }
of_property_for_each_string(np, "renesas,pins", prop, pin) { of_property_for_each_string(np, pmx->pins_prop_name, prop, pin) {
ret = sh_pfc_map_add_config(&maps[idx], pin, ret = sh_pfc_map_add_config(&maps[idx], pin,
PIN_MAP_TYPE_CONFIGS_PIN, PIN_MAP_TYPE_CONFIGS_PIN,
configs, num_configs); configs, num_configs);
@ -246,7 +271,7 @@ static int sh_pfc_dt_node_to_map(struct pinctrl_dev *pctldev,
index = 0; index = 0;
for_each_child_of_node(np, child) { for_each_child_of_node(np, child) {
ret = sh_pfc_dt_subnode_to_map(dev, child, map, num_maps, ret = sh_pfc_dt_subnode_to_map(pctldev, child, map, num_maps,
&index); &index);
if (ret < 0) if (ret < 0)
goto done; goto done;
@ -254,7 +279,8 @@ static int sh_pfc_dt_node_to_map(struct pinctrl_dev *pctldev,
/* If no mapping has been found in child nodes try the config node. */ /* If no mapping has been found in child nodes try the config node. */
if (*num_maps == 0) { if (*num_maps == 0) {
ret = sh_pfc_dt_subnode_to_map(dev, np, map, num_maps, &index); ret = sh_pfc_dt_subnode_to_map(pctldev, np, map, num_maps,
&index);
if (ret < 0) if (ret < 0)
goto done; goto done;
} }
@ -465,6 +491,9 @@ static bool sh_pfc_pinconf_validate(struct sh_pfc *pfc, unsigned int _pin,
case PIN_CONFIG_BIAS_PULL_DOWN: case PIN_CONFIG_BIAS_PULL_DOWN:
return pin->configs & SH_PFC_PIN_CFG_PULL_DOWN; return pin->configs & SH_PFC_PIN_CFG_PULL_DOWN;
case PIN_CONFIG_POWER_SOURCE:
return pin->configs & SH_PFC_PIN_CFG_IO_VOLTAGE;
default: default:
return false; return false;
} }
@ -477,7 +506,6 @@ static int sh_pfc_pinconf_get(struct pinctrl_dev *pctldev, unsigned _pin,
struct sh_pfc *pfc = pmx->pfc; struct sh_pfc *pfc = pmx->pfc;
enum pin_config_param param = pinconf_to_config_param(*config); enum pin_config_param param = pinconf_to_config_param(*config);
unsigned long flags; unsigned long flags;
unsigned int bias;
if (!sh_pfc_pinconf_validate(pfc, _pin, param)) if (!sh_pfc_pinconf_validate(pfc, _pin, param))
return -ENOTSUPP; return -ENOTSUPP;
@ -485,7 +513,9 @@ static int sh_pfc_pinconf_get(struct pinctrl_dev *pctldev, unsigned _pin,
switch (param) { switch (param) {
case PIN_CONFIG_BIAS_DISABLE: case PIN_CONFIG_BIAS_DISABLE:
case PIN_CONFIG_BIAS_PULL_UP: case PIN_CONFIG_BIAS_PULL_UP:
case PIN_CONFIG_BIAS_PULL_DOWN: case PIN_CONFIG_BIAS_PULL_DOWN: {
unsigned int bias;
if (!pfc->info->ops || !pfc->info->ops->get_bias) if (!pfc->info->ops || !pfc->info->ops->get_bias)
return -ENOTSUPP; return -ENOTSUPP;
@ -498,6 +528,24 @@ static int sh_pfc_pinconf_get(struct pinctrl_dev *pctldev, unsigned _pin,
*config = 0; *config = 0;
break; break;
}
case PIN_CONFIG_POWER_SOURCE: {
int ret;
if (!pfc->info->ops || !pfc->info->ops->get_io_voltage)
return -ENOTSUPP;
spin_lock_irqsave(&pfc->lock, flags);
ret = pfc->info->ops->get_io_voltage(pfc, _pin);
spin_unlock_irqrestore(&pfc->lock, flags);
if (ret < 0)
return ret;
*config = ret;
break;
}
default: default:
return -ENOTSUPP; return -ENOTSUPP;
@ -534,6 +582,24 @@ static int sh_pfc_pinconf_set(struct pinctrl_dev *pctldev, unsigned _pin,
break; break;
case PIN_CONFIG_POWER_SOURCE: {
unsigned int arg =
pinconf_to_config_argument(configs[i]);
int ret;
if (!pfc->info->ops || !pfc->info->ops->set_io_voltage)
return -ENOTSUPP;
spin_lock_irqsave(&pfc->lock, flags);
ret = pfc->info->ops->set_io_voltage(pfc, _pin, arg);
spin_unlock_irqrestore(&pfc->lock, flags);
if (ret)
return ret;
break;
}
default: default:
return -ENOTSUPP; return -ENOTSUPP;
} }

View File

@ -12,6 +12,7 @@
#define __SH_PFC_H #define __SH_PFC_H
#include <linux/bug.h> #include <linux/bug.h>
#include <linux/pinctrl/pinconf-generic.h>
#include <linux/stringify.h> #include <linux/stringify.h>
enum { enum {
@ -26,6 +27,7 @@ enum {
#define SH_PFC_PIN_CFG_OUTPUT (1 << 1) #define SH_PFC_PIN_CFG_OUTPUT (1 << 1)
#define SH_PFC_PIN_CFG_PULL_UP (1 << 2) #define SH_PFC_PIN_CFG_PULL_UP (1 << 2)
#define SH_PFC_PIN_CFG_PULL_DOWN (1 << 3) #define SH_PFC_PIN_CFG_PULL_DOWN (1 << 3)
#define SH_PFC_PIN_CFG_IO_VOLTAGE (1 << 4)
#define SH_PFC_PIN_CFG_NO_GPIO (1 << 31) #define SH_PFC_PIN_CFG_NO_GPIO (1 << 31)
struct sh_pfc_pin { struct sh_pfc_pin {
@ -121,6 +123,9 @@ struct sh_pfc_soc_operations {
unsigned int (*get_bias)(struct sh_pfc *pfc, unsigned int pin); unsigned int (*get_bias)(struct sh_pfc *pfc, unsigned int pin);
void (*set_bias)(struct sh_pfc *pfc, unsigned int pin, void (*set_bias)(struct sh_pfc *pfc, unsigned int pin,
unsigned int bias); unsigned int bias);
int (*get_io_voltage)(struct sh_pfc *pfc, unsigned int pin);
int (*set_io_voltage)(struct sh_pfc *pfc, unsigned int pin,
u16 voltage_mV);
}; };
struct sh_pfc_soc_info { struct sh_pfc_soc_info {

View File

@ -148,6 +148,19 @@ enum altas7_pad_type {
#define DIV_DISABLE 0x1 #define DIV_DISABLE 0x1
#define DIV_ENABLE 0x0 #define DIV_ENABLE 0x0
/* Number of Function input disable registers */
#define NUM_OF_IN_DISABLE_REG 0x2
/* Offset of Function input disable registers */
#define IN_DISABLE_0_REG_SET 0x0A00
#define IN_DISABLE_0_REG_CLR 0x0A04
#define IN_DISABLE_1_REG_SET 0x0A08
#define IN_DISABLE_1_REG_CLR 0x0A0C
#define IN_DISABLE_VAL_0_REG_SET 0x0A80
#define IN_DISABLE_VAL_0_REG_CLR 0x0A84
#define IN_DISABLE_VAL_1_REG_SET 0x0A88
#define IN_DISABLE_VAL_1_REG_CLR 0x0A8C
struct dt_params { struct dt_params {
const char *property; const char *property;
int value; int value;
@ -196,6 +209,16 @@ struct atlas7_pad_config {
.ad_ctrl_bit = adb, \ .ad_ctrl_bit = adb, \
} }
/**
* struct atlas7_pad_status - Atlas7 Pad status
*/
struct atlas7_pad_status {
u8 func;
u8 pull;
u8 dstr;
u8 reserved;
};
/** /**
* struct atlas7_pad_mux - Atlas7 mux * struct atlas7_pad_mux - Atlas7 mux
* @bank: The bank of this pad's registers on. * @bank: The bank of this pad's registers on.
@ -285,6 +308,9 @@ struct atlas7_pinctrl_data {
/* Platform info of atlas7 pinctrl */ /* Platform info of atlas7 pinctrl */
#define ATLAS7_PINCTRL_REG_BANKS 2 #define ATLAS7_PINCTRL_REG_BANKS 2
#define ATLAS7_PINCTRL_BANK_0_PINS 18 #define ATLAS7_PINCTRL_BANK_0_PINS 18
#define ATLAS7_PINCTRL_BANK_1_PINS 141
#define ATLAS7_PINCTRL_TOTAL_PINS \
(ATLAS7_PINCTRL_BANK_0_PINS + ATLAS7_PINCTRL_BANK_1_PINS)
/** /**
* Atlas7 GPIO Chip * Atlas7 GPIO Chip
@ -316,6 +342,7 @@ struct atlas7_gpio_bank {
unsigned int gpio_offset; unsigned int gpio_offset;
unsigned int ngpio; unsigned int ngpio;
const unsigned int *gpio_pins; const unsigned int *gpio_pins;
u32 sleep_data[NGPIO_OF_BANK];
}; };
struct atlas7_gpio_chip { struct atlas7_gpio_chip {
@ -343,6 +370,9 @@ struct atlas7_pmx {
struct pinctrl_desc pctl_desc; struct pinctrl_desc pctl_desc;
struct atlas7_pinctrl_data *pctl_data; struct atlas7_pinctrl_data *pctl_data;
void __iomem *regs[ATLAS7_PINCTRL_REG_BANKS]; void __iomem *regs[ATLAS7_PINCTRL_REG_BANKS];
u32 status_ds[NUM_OF_IN_DISABLE_REG];
u32 status_dsv[NUM_OF_IN_DISABLE_REG];
struct atlas7_pad_status sleep_data[ATLAS7_PINCTRL_TOTAL_PINS];
}; };
/* /*
@ -3480,6 +3510,160 @@ struct atlas7_pinctrl_data atlas7_ioc_data = {
.confs_cnt = ARRAY_SIZE(atlas7_ioc_pad_confs), .confs_cnt = ARRAY_SIZE(atlas7_ioc_pad_confs),
}; };
/* Simple map data structure */
struct map_data {
u8 idx;
u8 data;
};
/**
* struct atlas7_pull_info - Atlas7 Pad pull info
* @type:The type of this Pad.
* @mask:The mas value of this pin's pull bits.
* @v2s: The map of pull register value to pull status.
* @s2v: The map of pull status to pull register value.
*/
struct atlas7_pull_info {
u8 pad_type;
u8 mask;
const struct map_data *v2s;
const struct map_data *s2v;
};
/* Pull Register value map to status */
static const struct map_data p4we_pull_v2s[] = {
{ P4WE_PULL_UP, PULL_UP },
{ P4WE_HIGH_HYSTERESIS, HIGH_HYSTERESIS },
{ P4WE_HIGH_Z, HIGH_Z },
{ P4WE_PULL_DOWN, PULL_DOWN },
};
static const struct map_data p16st_pull_v2s[] = {
{ P16ST_PULL_UP, PULL_UP },
{ PD, PULL_UNKNOWN },
{ P16ST_HIGH_Z, HIGH_Z },
{ P16ST_PULL_DOWN, PULL_DOWN },
};
static const struct map_data pm31_pull_v2s[] = {
{ PM31_PULL_DISABLED, PULL_DOWN },
{ PM31_PULL_ENABLED, PULL_UP },
};
static const struct map_data pangd_pull_v2s[] = {
{ PANGD_PULL_UP, PULL_UP },
{ PD, PULL_UNKNOWN },
{ PANGD_HIGH_Z, HIGH_Z },
{ PANGD_PULL_DOWN, PULL_DOWN },
};
/* Pull status map to register value */
static const struct map_data p4we_pull_s2v[] = {
{ PULL_UP, P4WE_PULL_UP },
{ HIGH_HYSTERESIS, P4WE_HIGH_HYSTERESIS },
{ HIGH_Z, P4WE_HIGH_Z },
{ PULL_DOWN, P4WE_PULL_DOWN },
{ PULL_DISABLE, -1 },
{ PULL_ENABLE, -1 },
};
static const struct map_data p16st_pull_s2v[] = {
{ PULL_UP, P16ST_PULL_UP },
{ HIGH_HYSTERESIS, -1 },
{ HIGH_Z, P16ST_HIGH_Z },
{ PULL_DOWN, P16ST_PULL_DOWN },
{ PULL_DISABLE, -1 },
{ PULL_ENABLE, -1 },
};
static const struct map_data pm31_pull_s2v[] = {
{ PULL_UP, PM31_PULL_ENABLED },
{ HIGH_HYSTERESIS, -1 },
{ HIGH_Z, -1 },
{ PULL_DOWN, PM31_PULL_DISABLED },
{ PULL_DISABLE, -1 },
{ PULL_ENABLE, -1 },
};
static const struct map_data pangd_pull_s2v[] = {
{ PULL_UP, PANGD_PULL_UP },
{ HIGH_HYSTERESIS, -1 },
{ HIGH_Z, PANGD_HIGH_Z },
{ PULL_DOWN, PANGD_PULL_DOWN },
{ PULL_DISABLE, -1 },
{ PULL_ENABLE, -1 },
};
static const struct atlas7_pull_info atlas7_pull_map[] = {
{ PAD_T_4WE_PD, P4WE_PULL_MASK, p4we_pull_v2s, p4we_pull_s2v },
{ PAD_T_4WE_PU, P4WE_PULL_MASK, p4we_pull_v2s, p4we_pull_s2v },
{ PAD_T_16ST, P16ST_PULL_MASK, p16st_pull_v2s, p16st_pull_s2v },
{ PAD_T_M31_0204_PD, PM31_PULL_MASK, pm31_pull_v2s, pm31_pull_s2v },
{ PAD_T_M31_0204_PU, PM31_PULL_MASK, pm31_pull_v2s, pm31_pull_s2v },
{ PAD_T_M31_0610_PD, PM31_PULL_MASK, pm31_pull_v2s, pm31_pull_s2v },
{ PAD_T_M31_0610_PU, PM31_PULL_MASK, pm31_pull_v2s, pm31_pull_s2v },
{ PAD_T_AD, PANGD_PULL_MASK, pangd_pull_v2s, pangd_pull_s2v },
};
/**
* struct atlas7_ds_ma_info - Atlas7 Pad DriveStrength & currents info
* @ma: The Drive Strength in current value .
* @ds_16st: The correspond raw value of 16st pad.
* @ds_4we: The correspond raw value of 4we pad.
* @ds_0204m31: The correspond raw value of 0204m31 pad.
* @ds_0610m31: The correspond raw value of 0610m31 pad.
*/
struct atlas7_ds_ma_info {
u32 ma;
u32 ds_16st;
u32 ds_4we;
u32 ds_0204m31;
u32 ds_0610m31;
};
static const struct atlas7_ds_ma_info atlas7_ma2ds_map[] = {
{ 2, DS_16ST_0, DS_4WE_0, DS_M31_0, DS_NULL },
{ 4, DS_16ST_1, DS_NULL, DS_M31_1, DS_NULL },
{ 6, DS_16ST_2, DS_NULL, DS_NULL, DS_M31_0 },
{ 8, DS_16ST_3, DS_4WE_1, DS_NULL, DS_NULL },
{ 10, DS_16ST_4, DS_NULL, DS_NULL, DS_M31_1 },
{ 12, DS_16ST_5, DS_NULL, DS_NULL, DS_NULL },
{ 14, DS_16ST_6, DS_NULL, DS_NULL, DS_NULL },
{ 16, DS_16ST_7, DS_4WE_2, DS_NULL, DS_NULL },
{ 18, DS_16ST_8, DS_NULL, DS_NULL, DS_NULL },
{ 20, DS_16ST_9, DS_NULL, DS_NULL, DS_NULL },
{ 22, DS_16ST_10, DS_NULL, DS_NULL, DS_NULL },
{ 24, DS_16ST_11, DS_NULL, DS_NULL, DS_NULL },
{ 26, DS_16ST_12, DS_NULL, DS_NULL, DS_NULL },
{ 28, DS_16ST_13, DS_4WE_3, DS_NULL, DS_NULL },
{ 30, DS_16ST_14, DS_NULL, DS_NULL, DS_NULL },
{ 32, DS_16ST_15, DS_NULL, DS_NULL, DS_NULL },
};
/**
* struct atlas7_ds_info - Atlas7 Pad DriveStrength info
* @type: The type of this Pad.
* @mask: The mask value of this pin's pull bits.
* @imval: The immediate value of drives trength register.
*/
struct atlas7_ds_info {
u8 type;
u8 mask;
u8 imval;
u8 reserved;
};
static const struct atlas7_ds_info atlas7_ds_map[] = {
{ PAD_T_4WE_PD, DS_2BIT_MASK, DS_2BIT_IM_VAL },
{ PAD_T_4WE_PU, DS_2BIT_MASK, DS_2BIT_IM_VAL },
{ PAD_T_16ST, DS_4BIT_MASK, DS_4BIT_IM_VAL },
{ PAD_T_M31_0204_PD, DS_1BIT_MASK, DS_1BIT_IM_VAL },
{ PAD_T_M31_0204_PU, DS_1BIT_MASK, DS_1BIT_IM_VAL },
{ PAD_T_M31_0610_PD, DS_1BIT_MASK, DS_1BIT_IM_VAL },
{ PAD_T_M31_0610_PU, DS_1BIT_MASK, DS_1BIT_IM_VAL },
{ PAD_T_AD, DS_NULL, DS_NULL },
};
static inline u32 atlas7_pin_to_bank(u32 pin) static inline u32 atlas7_pin_to_bank(u32 pin)
{ {
return (pin >= ATLAS7_PINCTRL_BANK_0_PINS) ? 1 : 0; return (pin >= ATLAS7_PINCTRL_BANK_0_PINS) ? 1 : 0;
@ -3682,49 +3866,22 @@ static int atlas7_pmx_set_mux(struct pinctrl_dev *pctldev,
return 0; return 0;
} }
struct atlas7_ds_info {
u32 ma;
u32 ds_16st;
u32 ds_4we;
u32 ds_0204m31;
u32 ds_0610m31;
};
const struct atlas7_ds_info atlas7_ds_map[] = {
{ 2, DS_16ST_0, DS_4WE_0, DS_M31_0, DS_NULL},
{ 4, DS_16ST_1, DS_NULL, DS_M31_1, DS_NULL},
{ 6, DS_16ST_2, DS_NULL, DS_NULL, DS_M31_0},
{ 8, DS_16ST_3, DS_4WE_1, DS_NULL, DS_NULL},
{ 10, DS_16ST_4, DS_NULL, DS_NULL, DS_M31_1},
{ 12, DS_16ST_5, DS_NULL, DS_NULL, DS_NULL},
{ 14, DS_16ST_6, DS_NULL, DS_NULL, DS_NULL},
{ 16, DS_16ST_7, DS_4WE_2, DS_NULL, DS_NULL},
{ 18, DS_16ST_8, DS_NULL, DS_NULL, DS_NULL},
{ 20, DS_16ST_9, DS_NULL, DS_NULL, DS_NULL},
{ 22, DS_16ST_10, DS_NULL, DS_NULL, DS_NULL},
{ 24, DS_16ST_11, DS_NULL, DS_NULL, DS_NULL},
{ 26, DS_16ST_12, DS_NULL, DS_NULL, DS_NULL},
{ 28, DS_16ST_13, DS_4WE_3, DS_NULL, DS_NULL},
{ 30, DS_16ST_14, DS_NULL, DS_NULL, DS_NULL},
{ 32, DS_16ST_15, DS_NULL, DS_NULL, DS_NULL},
};
static u32 convert_current_to_drive_strength(u32 type, u32 ma) static u32 convert_current_to_drive_strength(u32 type, u32 ma)
{ {
int idx; int idx;
for (idx = 0; idx < ARRAY_SIZE(atlas7_ds_map); idx++) { for (idx = 0; idx < ARRAY_SIZE(atlas7_ma2ds_map); idx++) {
if (atlas7_ds_map[idx].ma != ma) if (atlas7_ma2ds_map[idx].ma != ma)
continue; continue;
if (type == PAD_T_4WE_PD || type == PAD_T_4WE_PU) if (type == PAD_T_4WE_PD || type == PAD_T_4WE_PU)
return atlas7_ds_map[idx].ds_4we; return atlas7_ma2ds_map[idx].ds_4we;
else if (type == PAD_T_16ST) else if (type == PAD_T_16ST)
return atlas7_ds_map[idx].ds_16st; return atlas7_ma2ds_map[idx].ds_16st;
else if (type == PAD_T_M31_0204_PD || type == PAD_T_M31_0204_PU) else if (type == PAD_T_M31_0204_PD || type == PAD_T_M31_0204_PU)
return atlas7_ds_map[idx].ds_0204m31; return atlas7_ma2ds_map[idx].ds_0204m31;
else if (type == PAD_T_M31_0610_PD || type == PAD_T_M31_0610_PU) else if (type == PAD_T_M31_0610_PD || type == PAD_T_M31_0610_PU)
return atlas7_ds_map[idx].ds_0610m31; return atlas7_ma2ds_map[idx].ds_0610m31;
} }
return DS_NULL; return DS_NULL;
@ -3735,78 +3892,21 @@ static int altas7_pinctrl_set_pull_sel(struct pinctrl_dev *pctldev,
{ {
struct atlas7_pmx *pmx = pinctrl_dev_get_drvdata(pctldev); struct atlas7_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
struct atlas7_pad_config *conf = &pmx->pctl_data->confs[pin]; struct atlas7_pad_config *conf = &pmx->pctl_data->confs[pin];
u32 type = conf->type; const struct atlas7_pull_info *pull_info;
u32 shift = conf->pupd_bit; u32 bank;
u32 bank = atlas7_pin_to_bank(pin); unsigned long regv;
void __iomem *pull_sel_reg, *pull_clr_reg; void __iomem *pull_sel_reg;
bank = atlas7_pin_to_bank(pin);
pull_info = &atlas7_pull_map[conf->type];
pull_sel_reg = pmx->regs[bank] + conf->pupd_reg; pull_sel_reg = pmx->regs[bank] + conf->pupd_reg;
pull_clr_reg = CLR_REG(pull_sel_reg);
if (type == PAD_T_4WE_PD || type == PAD_T_4WE_PU) { /* Retrieve correspond register value from table by sel */
writel(P4WE_PULL_MASK << shift, pull_clr_reg); regv = pull_info->s2v[sel].data & pull_info->mask;
if (sel == PULL_UP) /* Clear & Set new value to pull register */
writel(P4WE_PULL_UP << shift, pull_sel_reg); writel(pull_info->mask << conf->pupd_bit, CLR_REG(pull_sel_reg));
else if (sel == HIGH_HYSTERESIS) writel(regv << conf->pupd_bit, pull_sel_reg);
writel(P4WE_HIGH_HYSTERESIS << shift, pull_sel_reg);
else if (sel == HIGH_Z)
writel(P4WE_HIGH_Z << shift, pull_sel_reg);
else if (sel == PULL_DOWN)
writel(P4WE_PULL_DOWN << shift, pull_sel_reg);
else {
pr_err("Unknown Pull select type for 4WEPAD#%d\n",
pin);
return -ENOTSUPP;
}
} else if (type == PAD_T_16ST) {
writel(P16ST_PULL_MASK << shift, pull_clr_reg);
if (sel == PULL_UP)
writel(P16ST_PULL_UP << shift, pull_sel_reg);
else if (sel == HIGH_Z)
writel(P16ST_HIGH_Z << shift, pull_sel_reg);
else if (sel == PULL_DOWN)
writel(P16ST_PULL_DOWN << shift, pull_sel_reg);
else {
pr_err("Unknown Pull select type for 16STPAD#%d\n",
pin);
return -ENOTSUPP;
}
} else if (type == PAD_T_M31_0204_PD ||
type == PAD_T_M31_0204_PU ||
type == PAD_T_M31_0610_PD ||
type == PAD_T_M31_0610_PU) {
writel(PM31_PULL_MASK << shift, pull_clr_reg);
if (sel == PULL_UP)
writel(PM31_PULL_ENABLED << shift, pull_sel_reg);
else if (sel == PULL_DOWN)
writel(PM31_PULL_DISABLED << shift, pull_sel_reg);
else {
pr_err("Unknown Pull select type for M31PAD#%d\n",
pin);
return -ENOTSUPP;
}
} else if (type == PAD_T_AD) {
writel(PANGD_PULL_MASK << shift, pull_clr_reg);
if (sel == PULL_UP)
writel(PANGD_PULL_UP << shift, pull_sel_reg);
else if (sel == HIGH_Z)
writel(PANGD_HIGH_Z << shift, pull_sel_reg);
else if (sel == PULL_DOWN)
writel(PANGD_PULL_DOWN << shift, pull_sel_reg);
else {
pr_err("Unknown Pull select type for A/D PAD#%d\n",
pin);
return -ENOTSUPP;
}
} else {
pr_err("Unknown Pad type[%d] for pull select PAD#%d\n",
type, pin);
return -ENOTSUPP;
}
pr_debug("PIN_CFG ### SET PIN#%d PULL SELECTOR:%d == OK ####\n", pr_debug("PIN_CFG ### SET PIN#%d PULL SELECTOR:%d == OK ####\n",
pin, sel); pin, sel);
@ -3818,43 +3918,25 @@ static int __altas7_pinctrl_set_drive_strength_sel(struct pinctrl_dev *pctldev,
{ {
struct atlas7_pmx *pmx = pinctrl_dev_get_drvdata(pctldev); struct atlas7_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
struct atlas7_pad_config *conf = &pmx->pctl_data->confs[pin]; struct atlas7_pad_config *conf = &pmx->pctl_data->confs[pin];
u32 type = conf->type; const struct atlas7_ds_info *ds_info;
u32 shift = conf->drvstr_bit; u32 bank;
u32 bank = atlas7_pin_to_bank(pin); void __iomem *ds_sel_reg;
void __iomem *ds_sel_reg, *ds_clr_reg;
ds_info = &atlas7_ds_map[conf->type];
if (sel & (~(ds_info->mask)))
goto unsupport;
bank = atlas7_pin_to_bank(pin);
ds_sel_reg = pmx->regs[bank] + conf->drvstr_reg; ds_sel_reg = pmx->regs[bank] + conf->drvstr_reg;
ds_clr_reg = CLR_REG(ds_sel_reg);
if (type == PAD_T_4WE_PD || type == PAD_T_4WE_PU) {
if (sel & (~DS_2BIT_MASK))
goto unsupport;
writel(DS_2BIT_IM_VAL << shift, ds_clr_reg); writel(ds_info->imval << conf->drvstr_bit, CLR_REG(ds_sel_reg));
writel(sel << shift, ds_sel_reg); writel(sel << conf->drvstr_bit, ds_sel_reg);
return 0; return 0;
} else if (type == PAD_T_16ST) {
if (sel & (~DS_4BIT_MASK))
goto unsupport;
writel(DS_4BIT_IM_VAL << shift, ds_clr_reg);
writel(sel << shift, ds_sel_reg);
return 0;
} else if (type == PAD_T_M31_0204_PD || type == PAD_T_M31_0204_PU ||
type == PAD_T_M31_0610_PD || type == PAD_T_M31_0610_PU) {
if (sel & (~DS_1BIT_MASK))
goto unsupport;
writel(DS_1BIT_IM_VAL << shift, ds_clr_reg);
writel(sel << shift, ds_sel_reg);
return 0;
}
unsupport: unsupport:
pr_err("Pad#%d type[%d] doesn't support ds code[%d]!\n", pr_err("Pad#%d type[%d] doesn't support ds code[%d]!\n",
pin, type, sel); pin, conf->type, sel);
return -ENOTSUPP; return -ENOTSUPP;
} }
@ -4101,14 +4183,135 @@ unmap_io:
return ret; return ret;
} }
#ifdef CONFIG_PM_SLEEP
static int atlas7_pinmux_suspend_noirq(struct device *dev)
{
struct atlas7_pmx *pmx = dev_get_drvdata(dev);
struct atlas7_pad_status *status;
struct atlas7_pad_config *conf;
const struct atlas7_ds_info *ds_info;
const struct atlas7_pull_info *pull_info;
int idx;
u32 bank;
unsigned long regv;
for (idx = 0; idx < pmx->pctl_desc.npins; idx++) {
/* Get this Pad's descriptor from PINCTRL */
conf = &pmx->pctl_data->confs[idx];
bank = atlas7_pin_to_bank(idx);
status = &pmx->sleep_data[idx];
/* Save Function selector */
regv = readl(pmx->regs[bank] + conf->mux_reg);
status->func = (regv >> conf->mux_bit) & FUNC_CLEAR_MASK;
/* Check if Pad is in Analogue selector */
if (conf->ad_ctrl_reg == -1)
goto save_ds_sel;
regv = readl(pmx->regs[bank] + conf->ad_ctrl_reg);
if (!(regv & (conf->ad_ctrl_bit << ANA_CLEAR_MASK)))
status->func = FUNC_ANALOGUE;
save_ds_sel:
if (conf->drvstr_reg == -1)
goto save_pull_sel;
/* Save Drive Strength selector */
ds_info = &atlas7_ds_map[conf->type];
regv = readl(pmx->regs[bank] + conf->drvstr_reg);
status->dstr = (regv >> conf->drvstr_bit) & ds_info->mask;
save_pull_sel:
/* Save Pull selector */
pull_info = &atlas7_pull_map[conf->type];
regv = readl(pmx->regs[bank] + conf->pupd_reg);
regv = (regv >> conf->pupd_bit) & pull_info->mask;
status->pull = pull_info->v2s[regv].data;
}
/*
* Save disable input selector, this selector is not for Pin,
* but for Mux function.
*/
for (idx = 0; idx < NUM_OF_IN_DISABLE_REG; idx++) {
pmx->status_ds[idx] = readl(pmx->regs[BANK_DS] +
IN_DISABLE_0_REG_SET + 0x8 * idx);
pmx->status_dsv[idx] = readl(pmx->regs[BANK_DS] +
IN_DISABLE_VAL_0_REG_SET + 0x8 * idx);
}
return 0;
}
static int atlas7_pinmux_resume_noirq(struct device *dev)
{
struct atlas7_pmx *pmx = dev_get_drvdata(dev);
struct atlas7_pad_status *status;
struct atlas7_pad_config *conf;
int idx;
u32 bank;
for (idx = 0; idx < pmx->pctl_desc.npins; idx++) {
/* Get this Pad's descriptor from PINCTRL */
conf = &pmx->pctl_data->confs[idx];
bank = atlas7_pin_to_bank(idx);
status = &pmx->sleep_data[idx];
/* Restore Function selector */
__atlas7_pmx_pin_enable(pmx, idx, (u32)status->func & 0xff);
if (FUNC_ANALOGUE == status->func)
goto restore_pull_sel;
/* Restore Drive Strength selector */
__altas7_pinctrl_set_drive_strength_sel(pmx->pctl, idx,
(u32)status->dstr & 0xff);
restore_pull_sel:
/* Restore Pull selector */
altas7_pinctrl_set_pull_sel(pmx->pctl, idx,
(u32)status->pull & 0xff);
}
/*
* Restore disable input selector, this selector is not for Pin,
* but for Mux function
*/
for (idx = 0; idx < NUM_OF_IN_DISABLE_REG; idx++) {
writel(~0, pmx->regs[BANK_DS] +
IN_DISABLE_0_REG_CLR + 0x8 * idx);
writel(pmx->status_ds[idx], pmx->regs[BANK_DS] +
IN_DISABLE_0_REG_SET + 0x8 * idx);
writel(~0, pmx->regs[BANK_DS] +
IN_DISABLE_VAL_0_REG_CLR + 0x8 * idx);
writel(pmx->status_dsv[idx], pmx->regs[BANK_DS] +
IN_DISABLE_VAL_0_REG_SET + 0x8 * idx);
}
return 0;
}
static const struct dev_pm_ops atlas7_pinmux_pm_ops = {
.suspend_noirq = atlas7_pinmux_suspend_noirq,
.resume_noirq = atlas7_pinmux_resume_noirq,
.freeze_noirq = atlas7_pinmux_suspend_noirq,
.restore_noirq = atlas7_pinmux_resume_noirq,
};
#endif
static const struct of_device_id atlas7_pinmux_ids[] = { static const struct of_device_id atlas7_pinmux_ids[] = {
{ .compatible = "sirf,atlas7-ioc",}, { .compatible = "sirf,atlas7-ioc",},
{},
}; };
static struct platform_driver atlas7_pinmux_driver = { static struct platform_driver atlas7_pinmux_driver = {
.driver = { .driver = {
.name = "atlas7-ioc", .name = "atlas7-ioc",
.of_match_table = atlas7_pinmux_ids, .of_match_table = atlas7_pinmux_ids,
#ifdef CONFIG_PM_SLEEP
.pm = &atlas7_pinmux_pm_ops,
#endif
}, },
.probe = atlas7_pinmux_probe, .probe = atlas7_pinmux_probe,
}; };
@ -4286,14 +4489,15 @@ static struct irq_chip atlas7_gpio_irq_chip = {
.irq_set_type = atlas7_gpio_irq_type, .irq_set_type = atlas7_gpio_irq_type,
}; };
static void atlas7_gpio_handle_irq(unsigned int irq, struct irq_desc *desc) static void atlas7_gpio_handle_irq(unsigned int __irq, struct irq_desc *desc)
{ {
struct gpio_chip *gc = irq_desc_get_handler_data(desc); struct gpio_chip *gc = irq_desc_get_handler_data(desc);
struct atlas7_gpio_chip *a7gc = to_atlas7_gpio(gc); struct atlas7_gpio_chip *a7gc = to_atlas7_gpio(gc);
struct atlas7_gpio_bank *bank = NULL; struct atlas7_gpio_bank *bank = NULL;
u32 status, ctrl; u32 status, ctrl;
int pin_in_bank = 0, idx; int pin_in_bank = 0, idx;
struct irq_chip *chip = irq_get_chip(irq); struct irq_chip *chip = irq_desc_get_chip(desc);
unsigned int irq = irq_desc_get_irq(desc);
for (idx = 0; idx < a7gc->nbank; idx++) { for (idx = 0; idx < a7gc->nbank; idx++) {
bank = &a7gc->banks[idx]; bank = &a7gc->banks[idx];
@ -4496,6 +4700,7 @@ static void atlas7_gpio_set_value(struct gpio_chip *chip,
static const struct of_device_id atlas7_gpio_ids[] = { static const struct of_device_id atlas7_gpio_ids[] = {
{ .compatible = "sirf,atlas7-gpio", }, { .compatible = "sirf,atlas7-gpio", },
{},
}; };
static int atlas7_gpio_probe(struct platform_device *pdev) static int atlas7_gpio_probe(struct platform_device *pdev)
@ -4612,17 +4817,65 @@ static int atlas7_gpio_probe(struct platform_device *pdev)
BUG_ON(!bank->pctldev); BUG_ON(!bank->pctldev);
} }
platform_set_drvdata(pdev, a7gc);
dev_info(&pdev->dev, "add to system.\n"); dev_info(&pdev->dev, "add to system.\n");
return 0; return 0;
failed: failed:
return ret; return ret;
} }
#ifdef CONFIG_PM_SLEEP
static int atlas7_gpio_suspend_noirq(struct device *dev)
{
struct atlas7_gpio_chip *a7gc = dev_get_drvdata(dev);
struct atlas7_gpio_bank *bank;
void __iomem *ctrl_reg;
u32 idx, pin;
for (idx = 0; idx < a7gc->nbank; idx++) {
bank = &a7gc->banks[idx];
for (pin = 0; pin < bank->ngpio; pin++) {
ctrl_reg = ATLAS7_GPIO_CTRL(bank, pin);
bank->sleep_data[pin] = readl(ctrl_reg);
}
}
return 0;
}
static int atlas7_gpio_resume_noirq(struct device *dev)
{
struct atlas7_gpio_chip *a7gc = dev_get_drvdata(dev);
struct atlas7_gpio_bank *bank;
void __iomem *ctrl_reg;
u32 idx, pin;
for (idx = 0; idx < a7gc->nbank; idx++) {
bank = &a7gc->banks[idx];
for (pin = 0; pin < bank->ngpio; pin++) {
ctrl_reg = ATLAS7_GPIO_CTRL(bank, pin);
writel(bank->sleep_data[pin], ctrl_reg);
}
}
return 0;
}
static const struct dev_pm_ops atlas7_gpio_pm_ops = {
.suspend_noirq = atlas7_gpio_suspend_noirq,
.resume_noirq = atlas7_gpio_resume_noirq,
.freeze_noirq = atlas7_gpio_suspend_noirq,
.restore_noirq = atlas7_gpio_resume_noirq,
};
#endif
static struct platform_driver atlas7_gpio_driver = { static struct platform_driver atlas7_gpio_driver = {
.driver = { .driver = {
.name = "atlas7-gpio", .name = "atlas7-gpio",
.owner = THIS_MODULE,
.of_match_table = atlas7_gpio_ids, .of_match_table = atlas7_gpio_ids,
#ifdef CONFIG_PM_SLEEP
.pm = &atlas7_gpio_pm_ops,
#endif
}, },
.probe = atlas7_gpio_probe, .probe = atlas7_gpio_probe,
}; };

View File

@ -545,14 +545,15 @@ static struct irq_chip sirfsoc_irq_chip = {
.irq_set_type = sirfsoc_gpio_irq_type, .irq_set_type = sirfsoc_gpio_irq_type,
}; };
static void sirfsoc_gpio_handle_irq(unsigned int irq, struct irq_desc *desc) static void sirfsoc_gpio_handle_irq(unsigned int __irq, struct irq_desc *desc)
{ {
unsigned int irq = irq_desc_get_irq(desc);
struct gpio_chip *gc = irq_desc_get_handler_data(desc); struct gpio_chip *gc = irq_desc_get_handler_data(desc);
struct sirfsoc_gpio_chip *sgpio = to_sirfsoc_gpio(gc); struct sirfsoc_gpio_chip *sgpio = to_sirfsoc_gpio(gc);
struct sirfsoc_gpio_bank *bank; struct sirfsoc_gpio_bank *bank;
u32 status, ctrl; u32 status, ctrl;
int idx = 0; int idx = 0;
struct irq_chip *chip = irq_get_chip(irq); struct irq_chip *chip = irq_desc_get_chip(desc);
int i; int i;
for (i = 0; i < SIRFSOC_GPIO_NO_OF_BANKS; i++) { for (i = 0; i < SIRFSOC_GPIO_NO_OF_BANKS; i++) {

View File

@ -135,7 +135,14 @@ static const struct sunxi_desc_pin sun4i_a10_pins[] = {
SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 3), SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 3),
SUNXI_FUNCTION(0x0, "gpio_in"), SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"), SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "ir0")), /* TX */ SUNXI_FUNCTION(0x2, "ir0"), /* TX */
/*
* The SPDIF block is not referenced at all in the A10 user
* manual. However it is described in the code leaked and the
* pin descriptions are declared in the A20 user manual which
* is pin compatible with this device.
*/
SUNXI_FUNCTION(0x4, "spdif")), /* SPDIF MCLK */
SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 4), SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 4),
SUNXI_FUNCTION(0x0, "gpio_in"), SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"), SUNXI_FUNCTION(0x1, "gpio_out"),
@ -176,11 +183,15 @@ static const struct sunxi_desc_pin sun4i_a10_pins[] = {
SUNXI_FUNCTION(0x0, "gpio_in"), SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"), SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "i2s"), /* DI */ SUNXI_FUNCTION(0x2, "i2s"), /* DI */
SUNXI_FUNCTION(0x3, "ac97")), /* DI */ SUNXI_FUNCTION(0x3, "ac97"), /* DI */
/* Undocumented mux function - See SPDIF MCLK above */
SUNXI_FUNCTION(0x4, "spdif")), /* SPDIF IN */
SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 13), SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 13),
SUNXI_FUNCTION(0x0, "gpio_in"), SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"), SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "spi2")), /* CS1 */ SUNXI_FUNCTION(0x2, "spi2"), /* CS1 */
/* Undocumented mux function - See SPDIF MCLK above */
SUNXI_FUNCTION(0x4, "spdif")), /* SPDIF OUT */
SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 14), SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 14),
SUNXI_FUNCTION(0x0, "gpio_in"), SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"), SUNXI_FUNCTION(0x1, "gpio_out"),

View File

@ -588,7 +588,6 @@ static void sunxi_pinctrl_irq_release_resources(struct irq_data *d)
static int sunxi_pinctrl_irq_set_type(struct irq_data *d, unsigned int type) static int sunxi_pinctrl_irq_set_type(struct irq_data *d, unsigned int type)
{ {
struct sunxi_pinctrl *pctl = irq_data_get_irq_chip_data(d); struct sunxi_pinctrl *pctl = irq_data_get_irq_chip_data(d);
struct irq_desc *desc = container_of(d, struct irq_desc, irq_data);
u32 reg = sunxi_irq_cfg_reg(d->hwirq); u32 reg = sunxi_irq_cfg_reg(d->hwirq);
u8 index = sunxi_irq_cfg_offset(d->hwirq); u8 index = sunxi_irq_cfg_offset(d->hwirq);
unsigned long flags; unsigned long flags;
@ -615,16 +614,17 @@ static int sunxi_pinctrl_irq_set_type(struct irq_data *d, unsigned int type)
return -EINVAL; return -EINVAL;
} }
if (type & IRQ_TYPE_LEVEL_MASK) {
d->chip = &sunxi_pinctrl_level_irq_chip;
desc->handle_irq = handle_fasteoi_irq;
} else {
d->chip = &sunxi_pinctrl_edge_irq_chip;
desc->handle_irq = handle_edge_irq;
}
spin_lock_irqsave(&pctl->lock, flags); spin_lock_irqsave(&pctl->lock, flags);
if (type & IRQ_TYPE_LEVEL_MASK)
__irq_set_chip_handler_name_locked(d->irq,
&sunxi_pinctrl_level_irq_chip,
handle_fasteoi_irq, NULL);
else
__irq_set_chip_handler_name_locked(d->irq,
&sunxi_pinctrl_edge_irq_chip,
handle_edge_irq, NULL);
regval = readl(pctl->membase + reg); regval = readl(pctl->membase + reg);
regval &= ~(IRQ_CFG_IRQ_MASK << index); regval &= ~(IRQ_CFG_IRQ_MASK << index);
writel(regval | (mode << index), pctl->membase + reg); writel(regval | (mode << index), pctl->membase + reg);
@ -685,6 +685,7 @@ static void sunxi_pinctrl_irq_ack_unmask(struct irq_data *d)
} }
static struct irq_chip sunxi_pinctrl_edge_irq_chip = { static struct irq_chip sunxi_pinctrl_edge_irq_chip = {
.name = "sunxi_pio_edge",
.irq_ack = sunxi_pinctrl_irq_ack, .irq_ack = sunxi_pinctrl_irq_ack,
.irq_mask = sunxi_pinctrl_irq_mask, .irq_mask = sunxi_pinctrl_irq_mask,
.irq_unmask = sunxi_pinctrl_irq_unmask, .irq_unmask = sunxi_pinctrl_irq_unmask,
@ -695,6 +696,7 @@ static struct irq_chip sunxi_pinctrl_edge_irq_chip = {
}; };
static struct irq_chip sunxi_pinctrl_level_irq_chip = { static struct irq_chip sunxi_pinctrl_level_irq_chip = {
.name = "sunxi_pio_level",
.irq_eoi = sunxi_pinctrl_irq_ack, .irq_eoi = sunxi_pinctrl_irq_ack,
.irq_mask = sunxi_pinctrl_irq_mask, .irq_mask = sunxi_pinctrl_irq_mask,
.irq_unmask = sunxi_pinctrl_irq_unmask, .irq_unmask = sunxi_pinctrl_irq_unmask,
@ -709,10 +711,42 @@ static struct irq_chip sunxi_pinctrl_level_irq_chip = {
IRQCHIP_EOI_IF_HANDLED, IRQCHIP_EOI_IF_HANDLED,
}; };
static void sunxi_pinctrl_irq_handler(unsigned irq, struct irq_desc *desc) static int sunxi_pinctrl_irq_of_xlate(struct irq_domain *d,
struct device_node *node,
const u32 *intspec,
unsigned int intsize,
unsigned long *out_hwirq,
unsigned int *out_type)
{ {
struct irq_chip *chip = irq_get_chip(irq); struct sunxi_desc_function *desc;
struct sunxi_pinctrl *pctl = irq_get_handler_data(irq); int pin, base;
if (intsize < 3)
return -EINVAL;
base = PINS_PER_BANK * intspec[0];
pin = base + intspec[1];
desc = sunxi_pinctrl_desc_find_function_by_pin(d->host_data,
pin, "irq");
if (!desc)
return -EINVAL;
*out_hwirq = desc->irqbank * PINS_PER_BANK + desc->irqnum;
*out_type = intspec[2];
return 0;
}
static struct irq_domain_ops sunxi_pinctrl_irq_domain_ops = {
.xlate = sunxi_pinctrl_irq_of_xlate,
};
static void sunxi_pinctrl_irq_handler(unsigned __irq, struct irq_desc *desc)
{
unsigned int irq = irq_desc_get_irq(desc);
struct irq_chip *chip = irq_desc_get_chip(desc);
struct sunxi_pinctrl *pctl = irq_desc_get_handler_data(desc);
unsigned long bank, reg, val; unsigned long bank, reg, val;
for (bank = 0; bank < pctl->desc->irq_banks; bank++) for (bank = 0; bank < pctl->desc->irq_banks; bank++)
@ -983,8 +1017,8 @@ int sunxi_pinctrl_init(struct platform_device *pdev,
pctl->domain = irq_domain_add_linear(node, pctl->domain = irq_domain_add_linear(node,
pctl->desc->irq_banks * IRQ_PER_BANK, pctl->desc->irq_banks * IRQ_PER_BANK,
&irq_domain_simple_ops, &sunxi_pinctrl_irq_domain_ops,
NULL); pctl);
if (!pctl->domain) { if (!pctl->domain) {
dev_err(&pdev->dev, "Couldn't register IRQ domain\n"); dev_err(&pdev->dev, "Couldn't register IRQ domain\n");
ret = -ENOMEM; ret = -ENOMEM;

View File

@ -0,0 +1,32 @@
if ARCH_UNIPHIER
config PINCTRL_UNIPHIER_CORE
bool
select PINMUX
select GENERIC_PINCONF
config PINCTRL_UNIPHIER_PH1_LD4
tristate "UniPhier PH1-LD4 SoC pinctrl driver"
select PINCTRL_UNIPHIER_CORE
config PINCTRL_UNIPHIER_PH1_PRO4
tristate "UniPhier PH1-Pro4 SoC pinctrl driver"
select PINCTRL_UNIPHIER_CORE
config PINCTRL_UNIPHIER_PH1_SLD8
tristate "UniPhier PH1-sLD8 SoC pinctrl driver"
select PINCTRL_UNIPHIER_CORE
config PINCTRL_UNIPHIER_PH1_PRO5
tristate "UniPhier PH1-Pro5 SoC pinctrl driver"
select PINCTRL_UNIPHIER_CORE
config PINCTRL_UNIPHIER_PROXSTREAM2
tristate "UniPhier ProXstream2 SoC pinctrl driver"
select PINCTRL_UNIPHIER_CORE
config PINCTRL_UNIPHIER_PH1_LD6B
tristate "UniPhier PH1-LD6b SoC pinctrl driver"
select PINCTRL_UNIPHIER_CORE
endif

View File

@ -0,0 +1,8 @@
obj-$(CONFIG_PINCTRL_UNIPHIER_CORE) += pinctrl-uniphier-core.o
obj-$(CONFIG_PINCTRL_UNIPHIER_PH1_LD4) += pinctrl-ph1-ld4.o
obj-$(CONFIG_PINCTRL_UNIPHIER_PH1_PRO4) += pinctrl-ph1-pro4.o
obj-$(CONFIG_PINCTRL_UNIPHIER_PH1_SLD8) += pinctrl-ph1-sld8.o
obj-$(CONFIG_PINCTRL_UNIPHIER_PH1_PRO5) += pinctrl-ph1-pro5.o
obj-$(CONFIG_PINCTRL_UNIPHIER_PROXSTREAM2) += pinctrl-proxstream2.o
obj-$(CONFIG_PINCTRL_UNIPHIER_PH1_LD6B) += pinctrl-ph1-ld6b.o

View File

@ -0,0 +1,886 @@
/*
* Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/pinctrl/pinctrl.h>
#include <linux/platform_device.h>
#include "pinctrl-uniphier.h"
#define DRIVER_NAME "ph1-ld4-pinctrl"
static const struct pinctrl_pin_desc ph1_ld4_pins[] = {
UNIPHIER_PINCTRL_PIN(0, "EA1", UNIPHIER_PIN_IECTRL_NONE,
8, UNIPHIER_PIN_DRV_4_8,
8, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(1, "EA2", UNIPHIER_PIN_IECTRL_NONE,
9, UNIPHIER_PIN_DRV_4_8,
9, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(2, "EA3", UNIPHIER_PIN_IECTRL_NONE,
10, UNIPHIER_PIN_DRV_4_8,
10, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(3, "EA4", UNIPHIER_PIN_IECTRL_NONE,
11, UNIPHIER_PIN_DRV_4_8,
11, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(4, "EA5", UNIPHIER_PIN_IECTRL_NONE,
12, UNIPHIER_PIN_DRV_4_8,
12, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(5, "EA6", UNIPHIER_PIN_IECTRL_NONE,
13, UNIPHIER_PIN_DRV_4_8,
13, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(6, "EA7", UNIPHIER_PIN_IECTRL_NONE,
14, UNIPHIER_PIN_DRV_4_8,
14, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(7, "EA8", 0,
15, UNIPHIER_PIN_DRV_4_8,
15, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(8, "EA9", 0,
16, UNIPHIER_PIN_DRV_4_8,
16, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(9, "EA10", 0,
17, UNIPHIER_PIN_DRV_4_8,
17, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(10, "EA11", 0,
18, UNIPHIER_PIN_DRV_4_8,
18, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(11, "EA12", 0,
19, UNIPHIER_PIN_DRV_4_8,
19, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(12, "EA13", 0,
20, UNIPHIER_PIN_DRV_4_8,
20, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(13, "EA14", 0,
21, UNIPHIER_PIN_DRV_4_8,
21, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(14, "EA15", 0,
22, UNIPHIER_PIN_DRV_4_8,
22, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(15, "ECLK", UNIPHIER_PIN_IECTRL_NONE,
23, UNIPHIER_PIN_DRV_4_8,
23, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(16, "XERWE0", UNIPHIER_PIN_IECTRL_NONE,
24, UNIPHIER_PIN_DRV_4_8,
24, UNIPHIER_PIN_PULL_UP),
UNIPHIER_PINCTRL_PIN(17, "XERWE1", UNIPHIER_PIN_IECTRL_NONE,
25, UNIPHIER_PIN_DRV_4_8,
25, UNIPHIER_PIN_PULL_UP),
UNIPHIER_PINCTRL_PIN(18, "ES0", UNIPHIER_PIN_IECTRL_NONE,
27, UNIPHIER_PIN_DRV_4_8,
27, UNIPHIER_PIN_PULL_UP),
UNIPHIER_PINCTRL_PIN(19, "ES1", UNIPHIER_PIN_IECTRL_NONE,
28, UNIPHIER_PIN_DRV_4_8,
28, UNIPHIER_PIN_PULL_UP),
UNIPHIER_PINCTRL_PIN(20, "ES2", UNIPHIER_PIN_IECTRL_NONE,
29, UNIPHIER_PIN_DRV_4_8,
29, UNIPHIER_PIN_PULL_UP),
UNIPHIER_PINCTRL_PIN(21, "XERST", UNIPHIER_PIN_IECTRL_NONE,
38, UNIPHIER_PIN_DRV_4_8,
38, UNIPHIER_PIN_PULL_UP),
UNIPHIER_PINCTRL_PIN(22, "MMCCLK", UNIPHIER_PIN_IECTRL_NONE,
0, UNIPHIER_PIN_DRV_8_12_16_20,
146, UNIPHIER_PIN_PULL_UP),
UNIPHIER_PINCTRL_PIN(23, "MMCCMD", UNIPHIER_PIN_IECTRL_NONE,
4, UNIPHIER_PIN_DRV_8_12_16_20,
147, UNIPHIER_PIN_PULL_UP),
UNIPHIER_PINCTRL_PIN(24, "MMCDAT0", UNIPHIER_PIN_IECTRL_NONE,
8, UNIPHIER_PIN_DRV_8_12_16_20,
148, UNIPHIER_PIN_PULL_UP),
UNIPHIER_PINCTRL_PIN(25, "MMCDAT1", UNIPHIER_PIN_IECTRL_NONE,
12, UNIPHIER_PIN_DRV_8_12_16_20,
149, UNIPHIER_PIN_PULL_UP),
UNIPHIER_PINCTRL_PIN(26, "MMCDAT2", UNIPHIER_PIN_IECTRL_NONE,
16, UNIPHIER_PIN_DRV_8_12_16_20,
150, UNIPHIER_PIN_PULL_UP),
UNIPHIER_PINCTRL_PIN(27, "MMCDAT3", UNIPHIER_PIN_IECTRL_NONE,
20, UNIPHIER_PIN_DRV_8_12_16_20,
151, UNIPHIER_PIN_PULL_UP),
UNIPHIER_PINCTRL_PIN(28, "MMCDAT4", UNIPHIER_PIN_IECTRL_NONE,
24, UNIPHIER_PIN_DRV_8_12_16_20,
152, UNIPHIER_PIN_PULL_UP),
UNIPHIER_PINCTRL_PIN(29, "MMCDAT5", UNIPHIER_PIN_IECTRL_NONE,
28, UNIPHIER_PIN_DRV_8_12_16_20,
153, UNIPHIER_PIN_PULL_UP),
UNIPHIER_PINCTRL_PIN(30, "MMCDAT6", UNIPHIER_PIN_IECTRL_NONE,
32, UNIPHIER_PIN_DRV_8_12_16_20,
154, UNIPHIER_PIN_PULL_UP),
UNIPHIER_PINCTRL_PIN(31, "MMCDAT7", UNIPHIER_PIN_IECTRL_NONE,
36, UNIPHIER_PIN_DRV_8_12_16_20,
155, UNIPHIER_PIN_PULL_UP),
UNIPHIER_PINCTRL_PIN(32, "RMII_RXD0", 6,
39, UNIPHIER_PIN_DRV_4_8,
39, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(33, "RMII_RXD1", 6,
40, UNIPHIER_PIN_DRV_4_8,
40, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(34, "RMII_CRS_DV", 6,
41, UNIPHIER_PIN_DRV_4_8,
41, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(35, "RMII_RXER", 6,
42, UNIPHIER_PIN_DRV_4_8,
42, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(36, "RMII_REFCLK", 6,
43, UNIPHIER_PIN_DRV_4_8,
43, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(37, "RMII_TXD0", 6,
44, UNIPHIER_PIN_DRV_4_8,
44, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(38, "RMII_TXD1", 6,
45, UNIPHIER_PIN_DRV_4_8,
45, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(39, "RMII_TXEN", 6,
46, UNIPHIER_PIN_DRV_4_8,
46, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(40, "MDC", 6,
47, UNIPHIER_PIN_DRV_4_8,
47, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(41, "MDIO", 6,
48, UNIPHIER_PIN_DRV_4_8,
48, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(42, "MDIO_INTL", 6,
49, UNIPHIER_PIN_DRV_4_8,
49, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(43, "PHYRSTL", 6,
50, UNIPHIER_PIN_DRV_4_8,
50, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(44, "SDCLK", UNIPHIER_PIN_IECTRL_NONE,
40, UNIPHIER_PIN_DRV_8_12_16_20,
156, UNIPHIER_PIN_PULL_UP),
UNIPHIER_PINCTRL_PIN(45, "SDCMD", UNIPHIER_PIN_IECTRL_NONE,
44, UNIPHIER_PIN_DRV_8_12_16_20,
157, UNIPHIER_PIN_PULL_UP),
UNIPHIER_PINCTRL_PIN(46, "SDDAT0", UNIPHIER_PIN_IECTRL_NONE,
48, UNIPHIER_PIN_DRV_8_12_16_20,
158, UNIPHIER_PIN_PULL_UP),
UNIPHIER_PINCTRL_PIN(47, "SDDAT1", UNIPHIER_PIN_IECTRL_NONE,
52, UNIPHIER_PIN_DRV_8_12_16_20,
159, UNIPHIER_PIN_PULL_UP),
UNIPHIER_PINCTRL_PIN(48, "SDDAT2", UNIPHIER_PIN_IECTRL_NONE,
56, UNIPHIER_PIN_DRV_8_12_16_20,
160, UNIPHIER_PIN_PULL_UP),
UNIPHIER_PINCTRL_PIN(49, "SDDAT3", UNIPHIER_PIN_IECTRL_NONE,
60, UNIPHIER_PIN_DRV_8_12_16_20,
161, UNIPHIER_PIN_PULL_UP),
UNIPHIER_PINCTRL_PIN(50, "SDCD", UNIPHIER_PIN_IECTRL_NONE,
51, UNIPHIER_PIN_DRV_4_8,
51, UNIPHIER_PIN_PULL_UP),
UNIPHIER_PINCTRL_PIN(51, "SDWP", UNIPHIER_PIN_IECTRL_NONE,
52, UNIPHIER_PIN_DRV_4_8,
52, UNIPHIER_PIN_PULL_UP),
UNIPHIER_PINCTRL_PIN(52, "SDVOLC", UNIPHIER_PIN_IECTRL_NONE,
53, UNIPHIER_PIN_DRV_4_8,
53, UNIPHIER_PIN_PULL_UP),
UNIPHIER_PINCTRL_PIN(53, "USB0VBUS", 0,
54, UNIPHIER_PIN_DRV_4_8,
54, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(54, "USB0OD", 0,
55, UNIPHIER_PIN_DRV_4_8,
55, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(55, "USB1VBUS", 0,
56, UNIPHIER_PIN_DRV_4_8,
56, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(56, "USB1OD", 0,
57, UNIPHIER_PIN_DRV_4_8,
57, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(57, "PCRESET", 0,
58, UNIPHIER_PIN_DRV_4_8,
58, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(58, "PCREG", 0,
59, UNIPHIER_PIN_DRV_4_8,
59, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(59, "PCCE2", 0,
60, UNIPHIER_PIN_DRV_4_8,
60, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(60, "PCVS1", 0,
61, UNIPHIER_PIN_DRV_4_8,
61, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(61, "PCCD2", 0,
62, UNIPHIER_PIN_DRV_4_8,
62, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(62, "PCCD1", 0,
63, UNIPHIER_PIN_DRV_4_8,
63, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(63, "PCREADY", 0,
64, UNIPHIER_PIN_DRV_4_8,
64, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(64, "PCDOE", 0,
65, UNIPHIER_PIN_DRV_4_8,
65, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(65, "PCCE1", 0,
66, UNIPHIER_PIN_DRV_4_8,
66, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(66, "PCWE", 0,
67, UNIPHIER_PIN_DRV_4_8,
67, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(67, "PCOE", 0,
68, UNIPHIER_PIN_DRV_4_8,
68, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(68, "PCWAIT", 0,
69, UNIPHIER_PIN_DRV_4_8,
69, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(69, "PCIOWR", 0,
70, UNIPHIER_PIN_DRV_4_8,
70, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(70, "PCIORD", 0,
71, UNIPHIER_PIN_DRV_4_8,
71, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(71, "HS0DIN0", 0,
72, UNIPHIER_PIN_DRV_4_8,
72, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(72, "HS0DIN1", 0,
73, UNIPHIER_PIN_DRV_4_8,
73, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(73, "HS0DIN2", 0,
74, UNIPHIER_PIN_DRV_4_8,
74, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(74, "HS0DIN3", 0,
75, UNIPHIER_PIN_DRV_4_8,
75, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(75, "HS0DIN4", 0,
76, UNIPHIER_PIN_DRV_4_8,
76, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(76, "HS0DIN5", 0,
77, UNIPHIER_PIN_DRV_4_8,
77, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(77, "HS0DIN6", 0,
78, UNIPHIER_PIN_DRV_4_8,
78, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(78, "HS0DIN7", 0,
79, UNIPHIER_PIN_DRV_4_8,
79, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(79, "HS0BCLKIN", 0,
80, UNIPHIER_PIN_DRV_4_8,
80, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(80, "HS0VALIN", 0,
81, UNIPHIER_PIN_DRV_4_8,
81, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(81, "HS0SYNCIN", 0,
82, UNIPHIER_PIN_DRV_4_8,
82, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(82, "HSDOUT0", 0,
83, UNIPHIER_PIN_DRV_4_8,
83, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(83, "HSDOUT1", 0,
84, UNIPHIER_PIN_DRV_4_8,
84, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(84, "HSDOUT2", 0,
85, UNIPHIER_PIN_DRV_4_8,
85, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(85, "HSDOUT3", 0,
86, UNIPHIER_PIN_DRV_4_8,
86, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(86, "HSDOUT4", 0,
87, UNIPHIER_PIN_DRV_4_8,
87, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(87, "HSDOUT5", 0,
88, UNIPHIER_PIN_DRV_4_8,
88, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(88, "HSDOUT6", 0,
89, UNIPHIER_PIN_DRV_4_8,
89, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(89, "HSDOUT7", 0,
90, UNIPHIER_PIN_DRV_4_8,
90, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(90, "HSBCLKOUT", 0,
91, UNIPHIER_PIN_DRV_4_8,
91, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(91, "HSVALOUT", 0,
92, UNIPHIER_PIN_DRV_4_8,
92, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(92, "HSSYNCOUT", 0,
93, UNIPHIER_PIN_DRV_4_8,
93, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(93, "AGCI", 3,
-1, UNIPHIER_PIN_DRV_FIXED_4,
162, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(94, "AGCR", 4,
-1, UNIPHIER_PIN_DRV_FIXED_4,
163, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(95, "AGCBS", 5,
-1, UNIPHIER_PIN_DRV_FIXED_4,
164, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(96, "IECOUT", 0,
94, UNIPHIER_PIN_DRV_4_8,
94, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(97, "ASMCK", 0,
95, UNIPHIER_PIN_DRV_4_8,
95, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(98, "ABCKO", UNIPHIER_PIN_IECTRL_NONE,
96, UNIPHIER_PIN_DRV_4_8,
96, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(99, "ALRCKO", UNIPHIER_PIN_IECTRL_NONE,
97, UNIPHIER_PIN_DRV_4_8,
97, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(100, "ASDOUT0", UNIPHIER_PIN_IECTRL_NONE,
98, UNIPHIER_PIN_DRV_4_8,
98, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(101, "ARCOUT", 0,
99, UNIPHIER_PIN_DRV_4_8,
99, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(102, "SDA0", UNIPHIER_PIN_IECTRL_NONE,
-1, UNIPHIER_PIN_DRV_FIXED_4,
-1, UNIPHIER_PIN_PULL_NONE),
UNIPHIER_PINCTRL_PIN(103, "SCL0", UNIPHIER_PIN_IECTRL_NONE,
-1, UNIPHIER_PIN_DRV_FIXED_4,
-1, UNIPHIER_PIN_PULL_NONE),
UNIPHIER_PINCTRL_PIN(104, "SDA1", UNIPHIER_PIN_IECTRL_NONE,
-1, UNIPHIER_PIN_DRV_FIXED_4,
-1, UNIPHIER_PIN_PULL_NONE),
UNIPHIER_PINCTRL_PIN(105, "SCL1", UNIPHIER_PIN_IECTRL_NONE,
-1, UNIPHIER_PIN_DRV_FIXED_4,
-1, UNIPHIER_PIN_PULL_NONE),
UNIPHIER_PINCTRL_PIN(106, "DMDSDA0", UNIPHIER_PIN_IECTRL_NONE,
-1, UNIPHIER_PIN_DRV_FIXED_4,
-1, UNIPHIER_PIN_PULL_NONE),
UNIPHIER_PINCTRL_PIN(107, "DMDSCL0", UNIPHIER_PIN_IECTRL_NONE,
-1, UNIPHIER_PIN_DRV_FIXED_4,
-1, UNIPHIER_PIN_PULL_NONE),
UNIPHIER_PINCTRL_PIN(108, "DMDSDA1", UNIPHIER_PIN_IECTRL_NONE,
-1, UNIPHIER_PIN_DRV_FIXED_4,
-1, UNIPHIER_PIN_PULL_NONE),
UNIPHIER_PINCTRL_PIN(109, "DMDSCL1", UNIPHIER_PIN_IECTRL_NONE,
-1, UNIPHIER_PIN_DRV_FIXED_4,
-1, UNIPHIER_PIN_PULL_NONE),
UNIPHIER_PINCTRL_PIN(110, "SBO0", UNIPHIER_PIN_IECTRL_NONE,
100, UNIPHIER_PIN_DRV_4_8,
100, UNIPHIER_PIN_PULL_UP),
UNIPHIER_PINCTRL_PIN(111, "SBI0", UNIPHIER_PIN_IECTRL_NONE,
101, UNIPHIER_PIN_DRV_4_8,
101, UNIPHIER_PIN_PULL_UP),
UNIPHIER_PINCTRL_PIN(112, "HIN", 1,
-1, UNIPHIER_PIN_DRV_FIXED_5,
-1, UNIPHIER_PIN_PULL_NONE),
UNIPHIER_PINCTRL_PIN(113, "VIN", 2,
-1, UNIPHIER_PIN_DRV_FIXED_5,
-1, UNIPHIER_PIN_PULL_NONE),
UNIPHIER_PINCTRL_PIN(114, "TCON0", UNIPHIER_PIN_IECTRL_NONE,
102, UNIPHIER_PIN_DRV_4_8,
102, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(115, "TCON1", UNIPHIER_PIN_IECTRL_NONE,
103, UNIPHIER_PIN_DRV_4_8,
103, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(116, "TCON2", UNIPHIER_PIN_IECTRL_NONE,
104, UNIPHIER_PIN_DRV_4_8,
104, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(117, "TCON3", UNIPHIER_PIN_IECTRL_NONE,
105, UNIPHIER_PIN_DRV_4_8,
105, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(118, "TCON4", UNIPHIER_PIN_IECTRL_NONE,
106, UNIPHIER_PIN_DRV_4_8,
106, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(119, "TCON5", UNIPHIER_PIN_IECTRL_NONE,
107, UNIPHIER_PIN_DRV_4_8,
107, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(120, "TCON6", 0,
108, UNIPHIER_PIN_DRV_4_8,
108, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(121, "TCON7", 0,
109, UNIPHIER_PIN_DRV_4_8,
109, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(122, "PWMA", 0,
110, UNIPHIER_PIN_DRV_4_8,
110, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(123, "XIRQ1", 0,
111, UNIPHIER_PIN_DRV_4_8,
111, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(124, "XIRQ2", 0,
112, UNIPHIER_PIN_DRV_4_8,
112, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(125, "XIRQ3", 0,
113, UNIPHIER_PIN_DRV_4_8,
113, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(126, "XIRQ4", 0,
114, UNIPHIER_PIN_DRV_4_8,
114, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(127, "XIRQ5", 0,
115, UNIPHIER_PIN_DRV_4_8,
115, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(128, "XIRQ6", 0,
116, UNIPHIER_PIN_DRV_4_8,
116, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(129, "XIRQ7", 0,
117, UNIPHIER_PIN_DRV_4_8,
117, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(130, "XIRQ8", 0,
118, UNIPHIER_PIN_DRV_4_8,
118, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(131, "XIRQ9", 0,
119, UNIPHIER_PIN_DRV_4_8,
119, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(132, "XIRQ10", 0,
120, UNIPHIER_PIN_DRV_4_8,
120, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(133, "XIRQ11", 0,
121, UNIPHIER_PIN_DRV_4_8,
121, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(134, "XIRQ14", 0,
122, UNIPHIER_PIN_DRV_4_8,
122, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(135, "PORT00", 0,
123, UNIPHIER_PIN_DRV_4_8,
123, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(136, "PORT01", 0,
124, UNIPHIER_PIN_DRV_4_8,
124, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(137, "PORT02", 0,
125, UNIPHIER_PIN_DRV_4_8,
125, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(138, "PORT03", 0,
126, UNIPHIER_PIN_DRV_4_8,
126, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(139, "PORT04", 0,
127, UNIPHIER_PIN_DRV_4_8,
127, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(140, "PORT05", 0,
128, UNIPHIER_PIN_DRV_4_8,
128, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(141, "PORT06", 0,
129, UNIPHIER_PIN_DRV_4_8,
129, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(142, "PORT07", 0,
130, UNIPHIER_PIN_DRV_4_8,
130, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(143, "PORT10", 0,
131, UNIPHIER_PIN_DRV_4_8,
131, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(144, "PORT11", 0,
132, UNIPHIER_PIN_DRV_4_8,
132, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(145, "PORT12", 0,
133, UNIPHIER_PIN_DRV_4_8,
133, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(146, "PORT13", 0,
134, UNIPHIER_PIN_DRV_4_8,
134, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(147, "PORT14", 0,
135, UNIPHIER_PIN_DRV_4_8,
135, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(148, "PORT15", 0,
136, UNIPHIER_PIN_DRV_4_8,
136, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(149, "PORT16", 0,
137, UNIPHIER_PIN_DRV_4_8,
137, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(150, "PORT17", UNIPHIER_PIN_IECTRL_NONE,
138, UNIPHIER_PIN_DRV_4_8,
138, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(151, "PORT20", 0,
139, UNIPHIER_PIN_DRV_4_8,
139, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(152, "PORT21", 0,
140, UNIPHIER_PIN_DRV_4_8,
140, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(153, "PORT22", 0,
141, UNIPHIER_PIN_DRV_4_8,
141, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(154, "PORT23", 0,
142, UNIPHIER_PIN_DRV_4_8,
142, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(155, "PORT24", UNIPHIER_PIN_IECTRL_NONE,
143, UNIPHIER_PIN_DRV_4_8,
143, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(156, "PORT25", 0,
144, UNIPHIER_PIN_DRV_4_8,
144, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(157, "PORT26", 0,
145, UNIPHIER_PIN_DRV_4_8,
145, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(158, "XNFRE", UNIPHIER_PIN_IECTRL_NONE,
31, UNIPHIER_PIN_DRV_4_8,
31, UNIPHIER_PIN_PULL_UP),
UNIPHIER_PINCTRL_PIN(159, "XNFWE", UNIPHIER_PIN_IECTRL_NONE,
32, UNIPHIER_PIN_DRV_4_8,
32, UNIPHIER_PIN_PULL_UP),
UNIPHIER_PINCTRL_PIN(160, "NFALE", UNIPHIER_PIN_IECTRL_NONE,
33, UNIPHIER_PIN_DRV_4_8,
33, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(161, "NFCLE", UNIPHIER_PIN_IECTRL_NONE,
34, UNIPHIER_PIN_DRV_4_8,
34, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(162, "XNFWP", UNIPHIER_PIN_IECTRL_NONE,
35, UNIPHIER_PIN_DRV_4_8,
35, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(163, "XNFCE0", UNIPHIER_PIN_IECTRL_NONE,
36, UNIPHIER_PIN_DRV_4_8,
36, UNIPHIER_PIN_PULL_UP),
UNIPHIER_PINCTRL_PIN(164, "NANDRYBY0", UNIPHIER_PIN_IECTRL_NONE,
37, UNIPHIER_PIN_DRV_4_8,
37, UNIPHIER_PIN_PULL_UP),
};
static const unsigned emmc_pins[] = {21, 22, 23, 24, 25, 26, 27};
static const unsigned emmc_muxvals[] = {0, 1, 1, 1, 1, 1, 1};
static const unsigned emmc_dat8_pins[] = {28, 29, 30, 31};
static const unsigned emmc_dat8_muxvals[] = {1, 1, 1, 1};
static const unsigned i2c0_pins[] = {102, 103};
static const unsigned i2c0_muxvals[] = {0, 0};
static const unsigned i2c1_pins[] = {104, 105};
static const unsigned i2c1_muxvals[] = {0, 0};
static const unsigned i2c2_pins[] = {108, 109};
static const unsigned i2c2_muxvals[] = {2, 2};
static const unsigned i2c3_pins[] = {108, 109};
static const unsigned i2c3_muxvals[] = {3, 3};
static const unsigned nand_pins[] = {24, 25, 26, 27, 28, 29, 30, 31, 158, 159,
160, 161, 162, 163, 164};
static const unsigned nand_muxvals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0};
static const unsigned nand_cs1_pins[] = {22, 23};
static const unsigned nand_cs1_muxvals[] = {0, 0};
static const unsigned uart0_pins[] = {85, 88};
static const unsigned uart0_muxvals[] = {1, 1};
static const unsigned uart1_pins[] = {155, 156};
static const unsigned uart1_muxvals[] = {13, 13};
static const unsigned uart1b_pins[] = {69, 70};
static const unsigned uart1b_muxvals[] = {23, 23};
static const unsigned uart2_pins[] = {128, 129};
static const unsigned uart2_muxvals[] = {13, 13};
static const unsigned uart3_pins[] = {110, 111};
static const unsigned uart3_muxvals[] = {1, 1};
static const unsigned usb0_pins[] = {53, 54};
static const unsigned usb0_muxvals[] = {0, 0};
static const unsigned usb1_pins[] = {55, 56};
static const unsigned usb1_muxvals[] = {0, 0};
static const unsigned usb2_pins[] = {155, 156};
static const unsigned usb2_muxvals[] = {4, 4};
static const unsigned usb2b_pins[] = {67, 68};
static const unsigned usb2b_muxvals[] = {23, 23};
static const unsigned port_range0_pins[] = {
135, 136, 137, 138, 139, 140, 141, 142, /* PORT0x */
143, 144, 145, 146, 147, 148, 149, 150, /* PORT1x */
151, 152, 153, 154, 155, 156, 157, 0, /* PORT2x */
1, 2, 3, 4, 5, 120, 121, 122, /* PORT3x */
24, 25, 26, 27, 28, 29, 30, 31, /* PORT4x */
40, 41, 42, 43, 44, 45, 46, 47, /* PORT5x */
48, 49, 50, 51, 52, 53, 54, 55, /* PORT6x */
56, 85, 84, 59, 82, 61, 64, 65, /* PORT7x */
8, 9, 10, 11, 12, 13, 14, 15, /* PORT8x */
66, 67, 68, 69, 70, 71, 72, 73, /* PORT9x */
74, 75, 89, 86, 78, 79, 80, 81, /* PORT10x */
60, 83, 58, 57, 88, 87, 77, 76, /* PORT11x */
90, 91, 92, 93, 94, 95, 96, 97, /* PORT12x */
98, 99, 100, 6, 101, 114, 115, 116, /* PORT13x */
103, 108, 21, 22, 23, 117, 118, 119, /* PORT14x */
};
static const unsigned port_range0_muxvals[] = {
0, 0, 0, 0, 0, 0, 0, 0, /* PORT0x */
0, 0, 0, 0, 0, 0, 0, 0, /* PORT1x */
0, 0, 0, 0, 0, 0, 0, 15, /* PORT2x */
15, 15, 15, 15, 15, 15, 15, 15, /* PORT3x */
15, 15, 15, 15, 15, 15, 15, 15, /* PORT4x */
15, 15, 15, 15, 15, 15, 15, 15, /* PORT5x */
15, 15, 15, 15, 15, 15, 15, 15, /* PORT6x */
15, 15, 15, 15, 15, 15, 15, 15, /* PORT7x */
15, 15, 15, 15, 15, 15, 15, 15, /* PORT8x */
15, 15, 15, 15, 15, 15, 15, 15, /* PORT9x */
15, 15, 15, 15, 15, 15, 15, 15, /* PORT10x */
15, 15, 15, 15, 15, 15, 15, 15, /* PORT11x */
15, 15, 15, 15, 15, 15, 15, 15, /* PORT12x */
15, 15, 15, 15, 15, 15, 15, 15, /* PORT13x */
15, 15, 15, 15, 15, 15, 15, 15, /* PORT14x */
};
static const unsigned port_range1_pins[] = {
7, /* PORT166 */
};
static const unsigned port_range1_muxvals[] = {
15, /* PORT166 */
};
static const unsigned xirq_range0_pins[] = {
151, 123, 124, 125, 126, 127, 128, 129, /* XIRQ0-7 */
130, 131, 132, 133, 62, /* XIRQ8-12 */
};
static const unsigned xirq_range0_muxvals[] = {
14, 0, 0, 0, 0, 0, 0, 0, /* XIRQ0-7 */
0, 0, 0, 0, 14, /* XIRQ8-12 */
};
static const unsigned xirq_range1_pins[] = {
134, 63, /* XIRQ14-15 */
};
static const unsigned xirq_range1_muxvals[] = {
0, 14, /* XIRQ14-15 */
};
static const struct uniphier_pinctrl_group ph1_ld4_groups[] = {
UNIPHIER_PINCTRL_GROUP(emmc),
UNIPHIER_PINCTRL_GROUP(emmc_dat8),
UNIPHIER_PINCTRL_GROUP(i2c0),
UNIPHIER_PINCTRL_GROUP(i2c1),
UNIPHIER_PINCTRL_GROUP(i2c2),
UNIPHIER_PINCTRL_GROUP(i2c3),
UNIPHIER_PINCTRL_GROUP(nand),
UNIPHIER_PINCTRL_GROUP(nand_cs1),
UNIPHIER_PINCTRL_GROUP(uart0),
UNIPHIER_PINCTRL_GROUP(uart1),
UNIPHIER_PINCTRL_GROUP(uart1b),
UNIPHIER_PINCTRL_GROUP(uart2),
UNIPHIER_PINCTRL_GROUP(uart3),
UNIPHIER_PINCTRL_GROUP(usb0),
UNIPHIER_PINCTRL_GROUP(usb1),
UNIPHIER_PINCTRL_GROUP(usb2),
UNIPHIER_PINCTRL_GROUP(usb2b),
UNIPHIER_PINCTRL_GROUP_GPIO_RANGE_PORT(port_range0),
UNIPHIER_PINCTRL_GROUP_GPIO_RANGE_PORT(port_range1),
UNIPHIER_PINCTRL_GROUP_GPIO_RANGE_IRQ(xirq_range0),
UNIPHIER_PINCTRL_GROUP_GPIO_RANGE_IRQ(xirq_range1),
UNIPHIER_PINCTRL_GROUP_SINGLE(port00, port_range0, 0),
UNIPHIER_PINCTRL_GROUP_SINGLE(port01, port_range0, 1),
UNIPHIER_PINCTRL_GROUP_SINGLE(port02, port_range0, 2),
UNIPHIER_PINCTRL_GROUP_SINGLE(port03, port_range0, 3),
UNIPHIER_PINCTRL_GROUP_SINGLE(port04, port_range0, 4),
UNIPHIER_PINCTRL_GROUP_SINGLE(port05, port_range0, 5),
UNIPHIER_PINCTRL_GROUP_SINGLE(port06, port_range0, 6),
UNIPHIER_PINCTRL_GROUP_SINGLE(port07, port_range0, 7),
UNIPHIER_PINCTRL_GROUP_SINGLE(port10, port_range0, 8),
UNIPHIER_PINCTRL_GROUP_SINGLE(port11, port_range0, 9),
UNIPHIER_PINCTRL_GROUP_SINGLE(port12, port_range0, 10),
UNIPHIER_PINCTRL_GROUP_SINGLE(port13, port_range0, 11),
UNIPHIER_PINCTRL_GROUP_SINGLE(port14, port_range0, 12),
UNIPHIER_PINCTRL_GROUP_SINGLE(port15, port_range0, 13),
UNIPHIER_PINCTRL_GROUP_SINGLE(port16, port_range0, 14),
UNIPHIER_PINCTRL_GROUP_SINGLE(port17, port_range0, 15),
UNIPHIER_PINCTRL_GROUP_SINGLE(port20, port_range0, 16),
UNIPHIER_PINCTRL_GROUP_SINGLE(port21, port_range0, 17),
UNIPHIER_PINCTRL_GROUP_SINGLE(port22, port_range0, 18),
UNIPHIER_PINCTRL_GROUP_SINGLE(port23, port_range0, 19),
UNIPHIER_PINCTRL_GROUP_SINGLE(port24, port_range0, 20),
UNIPHIER_PINCTRL_GROUP_SINGLE(port25, port_range0, 21),
UNIPHIER_PINCTRL_GROUP_SINGLE(port26, port_range0, 22),
UNIPHIER_PINCTRL_GROUP_SINGLE(port27, port_range0, 23),
UNIPHIER_PINCTRL_GROUP_SINGLE(port30, port_range0, 24),
UNIPHIER_PINCTRL_GROUP_SINGLE(port31, port_range0, 25),
UNIPHIER_PINCTRL_GROUP_SINGLE(port32, port_range0, 26),
UNIPHIER_PINCTRL_GROUP_SINGLE(port33, port_range0, 27),
UNIPHIER_PINCTRL_GROUP_SINGLE(port34, port_range0, 28),
UNIPHIER_PINCTRL_GROUP_SINGLE(port35, port_range0, 29),
UNIPHIER_PINCTRL_GROUP_SINGLE(port36, port_range0, 30),
UNIPHIER_PINCTRL_GROUP_SINGLE(port37, port_range0, 31),
UNIPHIER_PINCTRL_GROUP_SINGLE(port40, port_range0, 32),
UNIPHIER_PINCTRL_GROUP_SINGLE(port41, port_range0, 33),
UNIPHIER_PINCTRL_GROUP_SINGLE(port42, port_range0, 34),
UNIPHIER_PINCTRL_GROUP_SINGLE(port43, port_range0, 35),
UNIPHIER_PINCTRL_GROUP_SINGLE(port44, port_range0, 36),
UNIPHIER_PINCTRL_GROUP_SINGLE(port45, port_range0, 37),
UNIPHIER_PINCTRL_GROUP_SINGLE(port46, port_range0, 38),
UNIPHIER_PINCTRL_GROUP_SINGLE(port47, port_range0, 39),
UNIPHIER_PINCTRL_GROUP_SINGLE(port50, port_range0, 40),
UNIPHIER_PINCTRL_GROUP_SINGLE(port51, port_range0, 41),
UNIPHIER_PINCTRL_GROUP_SINGLE(port52, port_range0, 42),
UNIPHIER_PINCTRL_GROUP_SINGLE(port53, port_range0, 43),
UNIPHIER_PINCTRL_GROUP_SINGLE(port54, port_range0, 44),
UNIPHIER_PINCTRL_GROUP_SINGLE(port55, port_range0, 45),
UNIPHIER_PINCTRL_GROUP_SINGLE(port56, port_range0, 46),
UNIPHIER_PINCTRL_GROUP_SINGLE(port57, port_range0, 47),
UNIPHIER_PINCTRL_GROUP_SINGLE(port60, port_range0, 48),
UNIPHIER_PINCTRL_GROUP_SINGLE(port61, port_range0, 49),
UNIPHIER_PINCTRL_GROUP_SINGLE(port62, port_range0, 50),
UNIPHIER_PINCTRL_GROUP_SINGLE(port63, port_range0, 51),
UNIPHIER_PINCTRL_GROUP_SINGLE(port64, port_range0, 52),
UNIPHIER_PINCTRL_GROUP_SINGLE(port65, port_range0, 53),
UNIPHIER_PINCTRL_GROUP_SINGLE(port66, port_range0, 54),
UNIPHIER_PINCTRL_GROUP_SINGLE(port67, port_range0, 55),
UNIPHIER_PINCTRL_GROUP_SINGLE(port70, port_range0, 56),
UNIPHIER_PINCTRL_GROUP_SINGLE(port71, port_range0, 57),
UNIPHIER_PINCTRL_GROUP_SINGLE(port72, port_range0, 58),
UNIPHIER_PINCTRL_GROUP_SINGLE(port73, port_range0, 59),
UNIPHIER_PINCTRL_GROUP_SINGLE(port74, port_range0, 60),
UNIPHIER_PINCTRL_GROUP_SINGLE(port75, port_range0, 61),
UNIPHIER_PINCTRL_GROUP_SINGLE(port76, port_range0, 62),
UNIPHIER_PINCTRL_GROUP_SINGLE(port77, port_range0, 63),
UNIPHIER_PINCTRL_GROUP_SINGLE(port80, port_range0, 64),
UNIPHIER_PINCTRL_GROUP_SINGLE(port81, port_range0, 65),
UNIPHIER_PINCTRL_GROUP_SINGLE(port82, port_range0, 66),
UNIPHIER_PINCTRL_GROUP_SINGLE(port83, port_range0, 67),
UNIPHIER_PINCTRL_GROUP_SINGLE(port84, port_range0, 68),
UNIPHIER_PINCTRL_GROUP_SINGLE(port85, port_range0, 69),
UNIPHIER_PINCTRL_GROUP_SINGLE(port86, port_range0, 70),
UNIPHIER_PINCTRL_GROUP_SINGLE(port87, port_range0, 71),
UNIPHIER_PINCTRL_GROUP_SINGLE(port90, port_range0, 72),
UNIPHIER_PINCTRL_GROUP_SINGLE(port91, port_range0, 73),
UNIPHIER_PINCTRL_GROUP_SINGLE(port92, port_range0, 74),
UNIPHIER_PINCTRL_GROUP_SINGLE(port93, port_range0, 75),
UNIPHIER_PINCTRL_GROUP_SINGLE(port94, port_range0, 76),
UNIPHIER_PINCTRL_GROUP_SINGLE(port95, port_range0, 77),
UNIPHIER_PINCTRL_GROUP_SINGLE(port96, port_range0, 78),
UNIPHIER_PINCTRL_GROUP_SINGLE(port97, port_range0, 79),
UNIPHIER_PINCTRL_GROUP_SINGLE(port100, port_range0, 80),
UNIPHIER_PINCTRL_GROUP_SINGLE(port101, port_range0, 81),
UNIPHIER_PINCTRL_GROUP_SINGLE(port102, port_range0, 82),
UNIPHIER_PINCTRL_GROUP_SINGLE(port103, port_range0, 83),
UNIPHIER_PINCTRL_GROUP_SINGLE(port104, port_range0, 84),
UNIPHIER_PINCTRL_GROUP_SINGLE(port105, port_range0, 85),
UNIPHIER_PINCTRL_GROUP_SINGLE(port106, port_range0, 86),
UNIPHIER_PINCTRL_GROUP_SINGLE(port107, port_range0, 87),
UNIPHIER_PINCTRL_GROUP_SINGLE(port110, port_range0, 88),
UNIPHIER_PINCTRL_GROUP_SINGLE(port111, port_range0, 89),
UNIPHIER_PINCTRL_GROUP_SINGLE(port112, port_range0, 90),
UNIPHIER_PINCTRL_GROUP_SINGLE(port113, port_range0, 91),
UNIPHIER_PINCTRL_GROUP_SINGLE(port114, port_range0, 92),
UNIPHIER_PINCTRL_GROUP_SINGLE(port115, port_range0, 93),
UNIPHIER_PINCTRL_GROUP_SINGLE(port116, port_range0, 94),
UNIPHIER_PINCTRL_GROUP_SINGLE(port117, port_range0, 95),
UNIPHIER_PINCTRL_GROUP_SINGLE(port120, port_range0, 96),
UNIPHIER_PINCTRL_GROUP_SINGLE(port121, port_range0, 97),
UNIPHIER_PINCTRL_GROUP_SINGLE(port122, port_range0, 98),
UNIPHIER_PINCTRL_GROUP_SINGLE(port123, port_range0, 99),
UNIPHIER_PINCTRL_GROUP_SINGLE(port124, port_range0, 100),
UNIPHIER_PINCTRL_GROUP_SINGLE(port125, port_range0, 101),
UNIPHIER_PINCTRL_GROUP_SINGLE(port126, port_range0, 102),
UNIPHIER_PINCTRL_GROUP_SINGLE(port127, port_range0, 103),
UNIPHIER_PINCTRL_GROUP_SINGLE(port130, port_range0, 104),
UNIPHIER_PINCTRL_GROUP_SINGLE(port131, port_range0, 105),
UNIPHIER_PINCTRL_GROUP_SINGLE(port132, port_range0, 106),
UNIPHIER_PINCTRL_GROUP_SINGLE(port133, port_range0, 107),
UNIPHIER_PINCTRL_GROUP_SINGLE(port134, port_range0, 108),
UNIPHIER_PINCTRL_GROUP_SINGLE(port135, port_range0, 109),
UNIPHIER_PINCTRL_GROUP_SINGLE(port136, port_range0, 110),
UNIPHIER_PINCTRL_GROUP_SINGLE(port137, port_range0, 111),
UNIPHIER_PINCTRL_GROUP_SINGLE(port140, port_range0, 112),
UNIPHIER_PINCTRL_GROUP_SINGLE(port141, port_range0, 113),
UNIPHIER_PINCTRL_GROUP_SINGLE(port142, port_range0, 114),
UNIPHIER_PINCTRL_GROUP_SINGLE(port143, port_range0, 115),
UNIPHIER_PINCTRL_GROUP_SINGLE(port144, port_range0, 116),
UNIPHIER_PINCTRL_GROUP_SINGLE(port145, port_range0, 117),
UNIPHIER_PINCTRL_GROUP_SINGLE(port146, port_range0, 118),
UNIPHIER_PINCTRL_GROUP_SINGLE(port147, port_range0, 119),
UNIPHIER_PINCTRL_GROUP_SINGLE(port165, port_range1, 0),
UNIPHIER_PINCTRL_GROUP_SINGLE(xirq0, xirq_range0, 0),
UNIPHIER_PINCTRL_GROUP_SINGLE(xirq1, xirq_range0, 1),
UNIPHIER_PINCTRL_GROUP_SINGLE(xirq2, xirq_range0, 2),
UNIPHIER_PINCTRL_GROUP_SINGLE(xirq3, xirq_range0, 3),
UNIPHIER_PINCTRL_GROUP_SINGLE(xirq4, xirq_range0, 4),
UNIPHIER_PINCTRL_GROUP_SINGLE(xirq5, xirq_range0, 5),
UNIPHIER_PINCTRL_GROUP_SINGLE(xirq6, xirq_range0, 6),
UNIPHIER_PINCTRL_GROUP_SINGLE(xirq7, xirq_range0, 7),
UNIPHIER_PINCTRL_GROUP_SINGLE(xirq8, xirq_range0, 8),
UNIPHIER_PINCTRL_GROUP_SINGLE(xirq9, xirq_range0, 9),
UNIPHIER_PINCTRL_GROUP_SINGLE(xirq10, xirq_range0, 10),
UNIPHIER_PINCTRL_GROUP_SINGLE(xirq11, xirq_range0, 11),
UNIPHIER_PINCTRL_GROUP_SINGLE(xirq12, xirq_range0, 12),
UNIPHIER_PINCTRL_GROUP_SINGLE(xirq14, xirq_range1, 0),
UNIPHIER_PINCTRL_GROUP_SINGLE(xirq15, xirq_range1, 1),
};
static const char * const emmc_groups[] = {"emmc", "emmc_dat8"};
static const char * const i2c0_groups[] = {"i2c0"};
static const char * const i2c1_groups[] = {"i2c1"};
static const char * const i2c2_groups[] = {"i2c2"};
static const char * const i2c3_groups[] = {"i2c3"};
static const char * const nand_groups[] = {"nand", "nand_cs1"};
static const char * const uart0_groups[] = {"uart0"};
static const char * const uart1_groups[] = {"uart1", "uart1b"};
static const char * const uart2_groups[] = {"uart2"};
static const char * const uart3_groups[] = {"uart3"};
static const char * const usb0_groups[] = {"usb0"};
static const char * const usb1_groups[] = {"usb1"};
static const char * const usb2_groups[] = {"usb2", "usb2b"};
static const char * const port_groups[] = {
"port00", "port01", "port02", "port03",
"port04", "port05", "port06", "port07",
"port10", "port11", "port12", "port13",
"port14", "port15", "port16", "port17",
"port20", "port21", "port22", "port23",
"port24", "port25", "port26", "port27",
"port30", "port31", "port32", "port33",
"port34", "port35", "port36", "port37",
"port40", "port41", "port42", "port43",
"port44", "port45", "port46", "port47",
"port50", "port51", "port52", "port53",
"port54", "port55", "port56", "port57",
"port60", "port61", "port62", "port63",
"port64", "port65", "port66", "port67",
"port70", "port71", "port72", "port73",
"port74", "port75", "port76", "port77",
"port80", "port81", "port82", "port83",
"port84", "port85", "port86", "port87",
"port90", "port91", "port92", "port93",
"port94", "port95", "port96", "port97",
"port100", "port101", "port102", "port103",
"port104", "port105", "port106", "port107",
"port110", "port111", "port112", "port113",
"port114", "port115", "port116", "port117",
"port120", "port121", "port122", "port123",
"port124", "port125", "port126", "port127",
"port130", "port131", "port132", "port133",
"port134", "port135", "port136", "port137",
"port140", "port141", "port142", "port143",
"port144", "port145", "port146", "port147",
/* port150-164 missing */
/* none */ "port165",
};
static const char * const xirq_groups[] = {
"xirq0", "xirq1", "xirq2", "xirq3",
"xirq4", "xirq5", "xirq6", "xirq7",
"xirq8", "xirq9", "xirq10", "xirq11",
"xirq12", /* none*/ "xirq14", "xirq15",
};
static const struct uniphier_pinmux_function ph1_ld4_functions[] = {
UNIPHIER_PINMUX_FUNCTION(emmc),
UNIPHIER_PINMUX_FUNCTION(i2c0),
UNIPHIER_PINMUX_FUNCTION(i2c1),
UNIPHIER_PINMUX_FUNCTION(i2c2),
UNIPHIER_PINMUX_FUNCTION(i2c3),
UNIPHIER_PINMUX_FUNCTION(nand),
UNIPHIER_PINMUX_FUNCTION(uart0),
UNIPHIER_PINMUX_FUNCTION(uart1),
UNIPHIER_PINMUX_FUNCTION(uart2),
UNIPHIER_PINMUX_FUNCTION(uart3),
UNIPHIER_PINMUX_FUNCTION(usb0),
UNIPHIER_PINMUX_FUNCTION(usb1),
UNIPHIER_PINMUX_FUNCTION(usb2),
UNIPHIER_PINMUX_FUNCTION(port),
UNIPHIER_PINMUX_FUNCTION(xirq),
};
static struct uniphier_pinctrl_socdata ph1_ld4_pindata = {
.groups = ph1_ld4_groups,
.groups_count = ARRAY_SIZE(ph1_ld4_groups),
.functions = ph1_ld4_functions,
.functions_count = ARRAY_SIZE(ph1_ld4_functions),
.mux_bits = 8,
.reg_stride = 4,
.load_pinctrl = false,
};
static struct pinctrl_desc ph1_ld4_pinctrl_desc = {
.name = DRIVER_NAME,
.pins = ph1_ld4_pins,
.npins = ARRAY_SIZE(ph1_ld4_pins),
.owner = THIS_MODULE,
};
static int ph1_ld4_pinctrl_probe(struct platform_device *pdev)
{
return uniphier_pinctrl_probe(pdev, &ph1_ld4_pinctrl_desc,
&ph1_ld4_pindata);
}
static const struct of_device_id ph1_ld4_pinctrl_match[] = {
{ .compatible = "socionext,ph1-ld4-pinctrl" },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, ph1_ld4_pinctrl_match);
static struct platform_driver ph1_ld4_pinctrl_driver = {
.probe = ph1_ld4_pinctrl_probe,
.remove = uniphier_pinctrl_remove,
.driver = {
.name = DRIVER_NAME,
.of_match_table = ph1_ld4_pinctrl_match,
},
};
module_platform_driver(ph1_ld4_pinctrl_driver);
MODULE_AUTHOR("Masahiro Yamada <yamada.masahiro@socionext.com>");
MODULE_DESCRIPTION("UniPhier PH1-LD4 pinctrl driver");
MODULE_LICENSE("GPL");

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,794 @@
/*
* Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/pinctrl/pinctrl.h>
#include <linux/platform_device.h>
#include "pinctrl-uniphier.h"
#define DRIVER_NAME "ph1-sld8-pinctrl"
static const struct pinctrl_pin_desc ph1_sld8_pins[] = {
UNIPHIER_PINCTRL_PIN(0, "PCA00", UNIPHIER_PIN_IECTRL_NONE,
15, UNIPHIER_PIN_DRV_4_8,
15, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(1, "PCA01", UNIPHIER_PIN_IECTRL_NONE,
16, UNIPHIER_PIN_DRV_4_8,
16, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(2, "PCA02", UNIPHIER_PIN_IECTRL_NONE,
17, UNIPHIER_PIN_DRV_4_8,
17, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(3, "PCA03", UNIPHIER_PIN_IECTRL_NONE,
18, UNIPHIER_PIN_DRV_4_8,
18, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(4, "PCA04", UNIPHIER_PIN_IECTRL_NONE,
19, UNIPHIER_PIN_DRV_4_8,
19, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(5, "PCA05", UNIPHIER_PIN_IECTRL_NONE,
20, UNIPHIER_PIN_DRV_4_8,
20, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(6, "PCA06", UNIPHIER_PIN_IECTRL_NONE,
21, UNIPHIER_PIN_DRV_4_8,
21, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(7, "PCA07", UNIPHIER_PIN_IECTRL_NONE,
22, UNIPHIER_PIN_DRV_4_8,
22, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(8, "PCA08", UNIPHIER_PIN_IECTRL_NONE,
23, UNIPHIER_PIN_DRV_4_8,
23, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(9, "PCA09", UNIPHIER_PIN_IECTRL_NONE,
24, UNIPHIER_PIN_DRV_4_8,
24, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(10, "PCA10", UNIPHIER_PIN_IECTRL_NONE,
25, UNIPHIER_PIN_DRV_4_8,
25, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(11, "PCA11", UNIPHIER_PIN_IECTRL_NONE,
26, UNIPHIER_PIN_DRV_4_8,
26, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(12, "PCA12", UNIPHIER_PIN_IECTRL_NONE,
27, UNIPHIER_PIN_DRV_4_8,
27, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(13, "PCA13", UNIPHIER_PIN_IECTRL_NONE,
28, UNIPHIER_PIN_DRV_4_8,
28, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(14, "PCA14", UNIPHIER_PIN_IECTRL_NONE,
29, UNIPHIER_PIN_DRV_4_8,
29, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(15, "XNFRE_GB", UNIPHIER_PIN_IECTRL_NONE,
30, UNIPHIER_PIN_DRV_4_8,
30, UNIPHIER_PIN_PULL_UP),
UNIPHIER_PINCTRL_PIN(16, "XNFWE_GB", UNIPHIER_PIN_IECTRL_NONE,
31, UNIPHIER_PIN_DRV_4_8,
31, UNIPHIER_PIN_PULL_UP),
UNIPHIER_PINCTRL_PIN(17, "NFALE_GB", UNIPHIER_PIN_IECTRL_NONE,
32, UNIPHIER_PIN_DRV_4_8,
32, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(18, "NFCLE_GB", UNIPHIER_PIN_IECTRL_NONE,
33, UNIPHIER_PIN_DRV_4_8,
33, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(19, "XNFWP_GB", UNIPHIER_PIN_IECTRL_NONE,
34, UNIPHIER_PIN_DRV_4_8,
34, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(20, "XNFCE0_GB", UNIPHIER_PIN_IECTRL_NONE,
35, UNIPHIER_PIN_DRV_4_8,
35, UNIPHIER_PIN_PULL_UP),
UNIPHIER_PINCTRL_PIN(21, "NANDRYBY0_GB", UNIPHIER_PIN_IECTRL_NONE,
36, UNIPHIER_PIN_DRV_4_8,
36, UNIPHIER_PIN_PULL_UP),
UNIPHIER_PINCTRL_PIN(22, "XNFCE1_GB", UNIPHIER_PIN_IECTRL_NONE,
0, UNIPHIER_PIN_DRV_8_12_16_20,
119, UNIPHIER_PIN_PULL_UP),
UNIPHIER_PINCTRL_PIN(23, "NANDRYBY1_GB", UNIPHIER_PIN_IECTRL_NONE,
4, UNIPHIER_PIN_DRV_8_12_16_20,
120, UNIPHIER_PIN_PULL_UP),
UNIPHIER_PINCTRL_PIN(24, "NFD0_GB", UNIPHIER_PIN_IECTRL_NONE,
8, UNIPHIER_PIN_DRV_8_12_16_20,
121, UNIPHIER_PIN_PULL_UP),
UNIPHIER_PINCTRL_PIN(25, "NFD1_GB", UNIPHIER_PIN_IECTRL_NONE,
12, UNIPHIER_PIN_DRV_8_12_16_20,
122, UNIPHIER_PIN_PULL_UP),
UNIPHIER_PINCTRL_PIN(26, "NFD2_GB", UNIPHIER_PIN_IECTRL_NONE,
16, UNIPHIER_PIN_DRV_8_12_16_20,
123, UNIPHIER_PIN_PULL_UP),
UNIPHIER_PINCTRL_PIN(27, "NFD3_GB", UNIPHIER_PIN_IECTRL_NONE,
20, UNIPHIER_PIN_DRV_8_12_16_20,
124, UNIPHIER_PIN_PULL_UP),
UNIPHIER_PINCTRL_PIN(28, "NFD4_GB", UNIPHIER_PIN_IECTRL_NONE,
24, UNIPHIER_PIN_DRV_8_12_16_20,
125, UNIPHIER_PIN_PULL_UP),
UNIPHIER_PINCTRL_PIN(29, "NFD5_GB", UNIPHIER_PIN_IECTRL_NONE,
28, UNIPHIER_PIN_DRV_8_12_16_20,
126, UNIPHIER_PIN_PULL_UP),
UNIPHIER_PINCTRL_PIN(30, "NFD6_GB", UNIPHIER_PIN_IECTRL_NONE,
32, UNIPHIER_PIN_DRV_8_12_16_20,
127, UNIPHIER_PIN_PULL_UP),
UNIPHIER_PINCTRL_PIN(31, "NFD7_GB", UNIPHIER_PIN_IECTRL_NONE,
36, UNIPHIER_PIN_DRV_8_12_16_20,
128, UNIPHIER_PIN_PULL_UP),
UNIPHIER_PINCTRL_PIN(32, "SDCLK", UNIPHIER_PIN_IECTRL_NONE,
40, UNIPHIER_PIN_DRV_8_12_16_20,
-1, UNIPHIER_PIN_PULL_NONE),
UNIPHIER_PINCTRL_PIN(33, "SDCMD", UNIPHIER_PIN_IECTRL_NONE,
44, UNIPHIER_PIN_DRV_8_12_16_20,
-1, UNIPHIER_PIN_PULL_NONE),
UNIPHIER_PINCTRL_PIN(34, "SDDAT0", UNIPHIER_PIN_IECTRL_NONE,
48, UNIPHIER_PIN_DRV_8_12_16_20,
-1, UNIPHIER_PIN_PULL_NONE),
UNIPHIER_PINCTRL_PIN(35, "SDDAT1", UNIPHIER_PIN_IECTRL_NONE,
52, UNIPHIER_PIN_DRV_8_12_16_20,
-1, UNIPHIER_PIN_PULL_NONE),
UNIPHIER_PINCTRL_PIN(36, "SDDAT2", UNIPHIER_PIN_IECTRL_NONE,
56, UNIPHIER_PIN_DRV_8_12_16_20,
-1, UNIPHIER_PIN_PULL_NONE),
UNIPHIER_PINCTRL_PIN(37, "SDDAT3", UNIPHIER_PIN_IECTRL_NONE,
60, UNIPHIER_PIN_DRV_8_12_16_20,
-1, UNIPHIER_PIN_PULL_NONE),
UNIPHIER_PINCTRL_PIN(38, "SDCD", UNIPHIER_PIN_IECTRL_NONE,
-1, UNIPHIER_PIN_DRV_FIXED_4,
129, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(39, "SDWP", UNIPHIER_PIN_IECTRL_NONE,
-1, UNIPHIER_PIN_DRV_FIXED_4,
130, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(40, "SDVOLC", UNIPHIER_PIN_IECTRL_NONE,
-1, UNIPHIER_PIN_DRV_FIXED_4,
131, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(41, "USB0VBUS", UNIPHIER_PIN_IECTRL_NONE,
37, UNIPHIER_PIN_DRV_4_8,
37, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(42, "USB0OD", UNIPHIER_PIN_IECTRL_NONE,
38, UNIPHIER_PIN_DRV_4_8,
38, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(43, "USB1VBUS", UNIPHIER_PIN_IECTRL_NONE,
39, UNIPHIER_PIN_DRV_4_8,
39, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(44, "USB1OD", UNIPHIER_PIN_IECTRL_NONE,
40, UNIPHIER_PIN_DRV_4_8,
40, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(45, "PCRESET", UNIPHIER_PIN_IECTRL_NONE,
41, UNIPHIER_PIN_DRV_4_8,
41, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(46, "PCREG", UNIPHIER_PIN_IECTRL_NONE,
42, UNIPHIER_PIN_DRV_4_8,
42, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(47, "PCCE2", UNIPHIER_PIN_IECTRL_NONE,
43, UNIPHIER_PIN_DRV_4_8,
43, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(48, "PCVS1", UNIPHIER_PIN_IECTRL_NONE,
44, UNIPHIER_PIN_DRV_4_8,
44, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(49, "PCCD2", UNIPHIER_PIN_IECTRL_NONE,
45, UNIPHIER_PIN_DRV_4_8,
45, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(50, "PCCD1", UNIPHIER_PIN_IECTRL_NONE,
46, UNIPHIER_PIN_DRV_4_8,
46, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(51, "PCREADY", UNIPHIER_PIN_IECTRL_NONE,
47, UNIPHIER_PIN_DRV_4_8,
47, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(52, "PCDOE", UNIPHIER_PIN_IECTRL_NONE,
48, UNIPHIER_PIN_DRV_4_8,
48, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(53, "PCCE1", UNIPHIER_PIN_IECTRL_NONE,
49, UNIPHIER_PIN_DRV_4_8,
49, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(54, "PCWE", UNIPHIER_PIN_IECTRL_NONE,
50, UNIPHIER_PIN_DRV_4_8,
50, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(55, "PCOE", UNIPHIER_PIN_IECTRL_NONE,
51, UNIPHIER_PIN_DRV_4_8,
51, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(56, "PCWAIT", UNIPHIER_PIN_IECTRL_NONE,
52, UNIPHIER_PIN_DRV_4_8,
52, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(57, "PCIOWR", UNIPHIER_PIN_IECTRL_NONE,
53, UNIPHIER_PIN_DRV_4_8,
53, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(58, "PCIORD", UNIPHIER_PIN_IECTRL_NONE,
54, UNIPHIER_PIN_DRV_4_8,
54, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(59, "HS0DIN0", UNIPHIER_PIN_IECTRL_NONE,
55, UNIPHIER_PIN_DRV_4_8,
55, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(60, "HS0DIN1", UNIPHIER_PIN_IECTRL_NONE,
56, UNIPHIER_PIN_DRV_4_8,
56, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(61, "HS0DIN2", UNIPHIER_PIN_IECTRL_NONE,
57, UNIPHIER_PIN_DRV_4_8,
57, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(62, "HS0DIN3", UNIPHIER_PIN_IECTRL_NONE,
58, UNIPHIER_PIN_DRV_4_8,
58, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(63, "HS0DIN4", UNIPHIER_PIN_IECTRL_NONE,
59, UNIPHIER_PIN_DRV_4_8,
59, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(64, "HS0DIN5", UNIPHIER_PIN_IECTRL_NONE,
60, UNIPHIER_PIN_DRV_4_8,
60, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(65, "HS0DIN6", UNIPHIER_PIN_IECTRL_NONE,
61, UNIPHIER_PIN_DRV_4_8,
61, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(66, "HS0DIN7", UNIPHIER_PIN_IECTRL_NONE,
62, UNIPHIER_PIN_DRV_4_8,
62, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(67, "HS0BCLKIN", UNIPHIER_PIN_IECTRL_NONE,
63, UNIPHIER_PIN_DRV_4_8,
63, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(68, "HS0VALIN", UNIPHIER_PIN_IECTRL_NONE,
64, UNIPHIER_PIN_DRV_4_8,
64, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(69, "HS0SYNCIN", UNIPHIER_PIN_IECTRL_NONE,
65, UNIPHIER_PIN_DRV_4_8,
65, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(70, "HSDOUT0", UNIPHIER_PIN_IECTRL_NONE,
66, UNIPHIER_PIN_DRV_4_8,
66, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(71, "HSDOUT1", UNIPHIER_PIN_IECTRL_NONE,
67, UNIPHIER_PIN_DRV_4_8,
67, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(72, "HSDOUT2", UNIPHIER_PIN_IECTRL_NONE,
68, UNIPHIER_PIN_DRV_4_8,
68, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(73, "HSDOUT3", UNIPHIER_PIN_IECTRL_NONE,
69, UNIPHIER_PIN_DRV_4_8,
69, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(74, "HSDOUT4", UNIPHIER_PIN_IECTRL_NONE,
70, UNIPHIER_PIN_DRV_4_8,
70, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(75, "HSDOUT5", UNIPHIER_PIN_IECTRL_NONE,
71, UNIPHIER_PIN_DRV_4_8,
71, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(76, "HSDOUT6", UNIPHIER_PIN_IECTRL_NONE,
72, UNIPHIER_PIN_DRV_4_8,
72, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(77, "HSDOUT7", UNIPHIER_PIN_IECTRL_NONE,
73, UNIPHIER_PIN_DRV_4_8,
73, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(78, "HSBCLKOUT", UNIPHIER_PIN_IECTRL_NONE,
74, UNIPHIER_PIN_DRV_4_8,
74, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(79, "HSVALOUT", UNIPHIER_PIN_IECTRL_NONE,
75, UNIPHIER_PIN_DRV_4_8,
75, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(80, "HSSYNCOUT", UNIPHIER_PIN_IECTRL_NONE,
76, UNIPHIER_PIN_DRV_4_8,
76, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(81, "HS1DIN0", UNIPHIER_PIN_IECTRL_NONE,
77, UNIPHIER_PIN_DRV_4_8,
77, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(82, "HS1DIN1", UNIPHIER_PIN_IECTRL_NONE,
78, UNIPHIER_PIN_DRV_4_8,
78, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(83, "HS1DIN2", UNIPHIER_PIN_IECTRL_NONE,
79, UNIPHIER_PIN_DRV_4_8,
79, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(84, "HS1DIN3", UNIPHIER_PIN_IECTRL_NONE,
80, UNIPHIER_PIN_DRV_4_8,
80, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(85, "HS1DIN4", UNIPHIER_PIN_IECTRL_NONE,
81, UNIPHIER_PIN_DRV_4_8,
81, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(86, "HS1DIN5", UNIPHIER_PIN_IECTRL_NONE,
82, UNIPHIER_PIN_DRV_4_8,
82, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(87, "HS1DIN6", UNIPHIER_PIN_IECTRL_NONE,
83, UNIPHIER_PIN_DRV_4_8,
83, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(88, "HS1DIN7", UNIPHIER_PIN_IECTRL_NONE,
84, UNIPHIER_PIN_DRV_4_8,
84, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(89, "HS1BCLKIN", UNIPHIER_PIN_IECTRL_NONE,
85, UNIPHIER_PIN_DRV_4_8,
85, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(90, "HS1VALIN", UNIPHIER_PIN_IECTRL_NONE,
86, UNIPHIER_PIN_DRV_4_8,
86, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(91, "HS1SYNCIN", UNIPHIER_PIN_IECTRL_NONE,
87, UNIPHIER_PIN_DRV_4_8,
87, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(92, "AGCI", UNIPHIER_PIN_IECTRL_NONE,
-1, UNIPHIER_PIN_DRV_FIXED_4,
132, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(93, "AGCR", UNIPHIER_PIN_IECTRL_NONE,
-1, UNIPHIER_PIN_DRV_FIXED_4,
133, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(94, "AGCBS", UNIPHIER_PIN_IECTRL_NONE,
-1, UNIPHIER_PIN_DRV_FIXED_4,
134, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(95, "IECOUT", UNIPHIER_PIN_IECTRL_NONE,
88, UNIPHIER_PIN_DRV_4_8,
88, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(96, "ASMCK", UNIPHIER_PIN_IECTRL_NONE,
89, UNIPHIER_PIN_DRV_4_8,
89, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(97, "ABCKO", UNIPHIER_PIN_IECTRL_NONE,
90, UNIPHIER_PIN_DRV_4_8,
90, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(98, "ALRCKO", UNIPHIER_PIN_IECTRL_NONE,
91, UNIPHIER_PIN_DRV_4_8,
91, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(99, "ASDOUT0", UNIPHIER_PIN_IECTRL_NONE,
92, UNIPHIER_PIN_DRV_4_8,
92, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(100, "ASDOUT1", UNIPHIER_PIN_IECTRL_NONE,
93, UNIPHIER_PIN_DRV_4_8,
93, UNIPHIER_PIN_PULL_UP),
UNIPHIER_PINCTRL_PIN(101, "ARCOUT", UNIPHIER_PIN_IECTRL_NONE,
94, UNIPHIER_PIN_DRV_4_8,
94, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(102, "SDA0", UNIPHIER_PIN_IECTRL_NONE,
-1, UNIPHIER_PIN_DRV_FIXED_4,
-1, UNIPHIER_PIN_PULL_NONE),
UNIPHIER_PINCTRL_PIN(103, "SCL0", UNIPHIER_PIN_IECTRL_NONE,
-1, UNIPHIER_PIN_DRV_FIXED_4,
-1, UNIPHIER_PIN_PULL_NONE),
UNIPHIER_PINCTRL_PIN(104, "SDA1", UNIPHIER_PIN_IECTRL_NONE,
-1, UNIPHIER_PIN_DRV_FIXED_4,
-1, UNIPHIER_PIN_PULL_NONE),
UNIPHIER_PINCTRL_PIN(105, "SCL1", UNIPHIER_PIN_IECTRL_NONE,
-1, UNIPHIER_PIN_DRV_FIXED_4,
-1, UNIPHIER_PIN_PULL_NONE),
UNIPHIER_PINCTRL_PIN(106, "DMDSDA0", UNIPHIER_PIN_IECTRL_NONE,
-1, UNIPHIER_PIN_DRV_FIXED_4,
-1, UNIPHIER_PIN_PULL_NONE),
UNIPHIER_PINCTRL_PIN(107, "DMDSCL0", UNIPHIER_PIN_IECTRL_NONE,
-1, UNIPHIER_PIN_DRV_FIXED_4,
-1, UNIPHIER_PIN_PULL_NONE),
UNIPHIER_PINCTRL_PIN(108, "DMDSDA1", UNIPHIER_PIN_IECTRL_NONE,
-1, UNIPHIER_PIN_DRV_FIXED_4,
-1, UNIPHIER_PIN_PULL_NONE),
UNIPHIER_PINCTRL_PIN(109, "DMDSCL1", UNIPHIER_PIN_IECTRL_NONE,
-1, UNIPHIER_PIN_DRV_FIXED_4,
-1, UNIPHIER_PIN_PULL_NONE),
UNIPHIER_PINCTRL_PIN(110, "SBO0", UNIPHIER_PIN_IECTRL_NONE,
95, UNIPHIER_PIN_DRV_4_8,
95, UNIPHIER_PIN_PULL_UP),
UNIPHIER_PINCTRL_PIN(111, "SBI0", UNIPHIER_PIN_IECTRL_NONE,
96, UNIPHIER_PIN_DRV_4_8,
96, UNIPHIER_PIN_PULL_UP),
UNIPHIER_PINCTRL_PIN(112, "SBO1", UNIPHIER_PIN_IECTRL_NONE,
97, UNIPHIER_PIN_DRV_4_8,
97, UNIPHIER_PIN_PULL_UP),
UNIPHIER_PINCTRL_PIN(113, "SBI1", UNIPHIER_PIN_IECTRL_NONE,
98, UNIPHIER_PIN_DRV_4_8,
98, UNIPHIER_PIN_PULL_UP),
UNIPHIER_PINCTRL_PIN(114, "TXD1", UNIPHIER_PIN_IECTRL_NONE,
99, UNIPHIER_PIN_DRV_4_8,
99, UNIPHIER_PIN_PULL_UP),
UNIPHIER_PINCTRL_PIN(115, "RXD1", UNIPHIER_PIN_IECTRL_NONE,
100, UNIPHIER_PIN_DRV_4_8,
100, UNIPHIER_PIN_PULL_UP),
UNIPHIER_PINCTRL_PIN(116, "HIN", UNIPHIER_PIN_IECTRL_NONE,
-1, UNIPHIER_PIN_DRV_FIXED_5,
-1, UNIPHIER_PIN_PULL_NONE),
UNIPHIER_PINCTRL_PIN(117, "VIN", UNIPHIER_PIN_IECTRL_NONE,
-1, UNIPHIER_PIN_DRV_FIXED_5,
-1, UNIPHIER_PIN_PULL_NONE),
UNIPHIER_PINCTRL_PIN(118, "TCON0", UNIPHIER_PIN_IECTRL_NONE,
101, UNIPHIER_PIN_DRV_4_8,
101, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(119, "TCON1", UNIPHIER_PIN_IECTRL_NONE,
102, UNIPHIER_PIN_DRV_4_8,
102, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(120, "TCON2", UNIPHIER_PIN_IECTRL_NONE,
103, UNIPHIER_PIN_DRV_4_8,
103, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(121, "TCON3", UNIPHIER_PIN_IECTRL_NONE,
104, UNIPHIER_PIN_DRV_4_8,
104, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(122, "TCON4", UNIPHIER_PIN_IECTRL_NONE,
105, UNIPHIER_PIN_DRV_4_8,
105, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(123, "TCON5", UNIPHIER_PIN_IECTRL_NONE,
106, UNIPHIER_PIN_DRV_4_8,
106, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(124, "TCON6", UNIPHIER_PIN_IECTRL_NONE,
107, UNIPHIER_PIN_DRV_4_8,
107, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(125, "TCON7", UNIPHIER_PIN_IECTRL_NONE,
108, UNIPHIER_PIN_DRV_4_8,
108, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(126, "TCON8", UNIPHIER_PIN_IECTRL_NONE,
109, UNIPHIER_PIN_DRV_4_8,
109, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(127, "PWMA", UNIPHIER_PIN_IECTRL_NONE,
110, UNIPHIER_PIN_DRV_4_8,
110, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(128, "XIRQ0", UNIPHIER_PIN_IECTRL_NONE,
111, UNIPHIER_PIN_DRV_4_8,
111, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(129, "XIRQ1", UNIPHIER_PIN_IECTRL_NONE,
112, UNIPHIER_PIN_DRV_4_8,
112, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(130, "XIRQ2", UNIPHIER_PIN_IECTRL_NONE,
113, UNIPHIER_PIN_DRV_4_8,
113, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(131, "XIRQ3", UNIPHIER_PIN_IECTRL_NONE,
114, UNIPHIER_PIN_DRV_4_8,
114, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(132, "XIRQ4", UNIPHIER_PIN_IECTRL_NONE,
115, UNIPHIER_PIN_DRV_4_8,
115, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(133, "XIRQ5", UNIPHIER_PIN_IECTRL_NONE,
116, UNIPHIER_PIN_DRV_4_8,
116, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(134, "XIRQ6", UNIPHIER_PIN_IECTRL_NONE,
117, UNIPHIER_PIN_DRV_4_8,
117, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(135, "XIRQ7", UNIPHIER_PIN_IECTRL_NONE,
118, UNIPHIER_PIN_DRV_4_8,
118, UNIPHIER_PIN_PULL_DOWN),
};
static const unsigned emmc_pins[] = {21, 22, 23, 24, 25, 26, 27};
static const unsigned emmc_muxvals[] = {1, 1, 1, 1, 1, 1, 1};
static const unsigned emmc_dat8_pins[] = {28, 29, 30, 31};
static const unsigned emmc_dat8_muxvals[] = {1, 1, 1, 1};
static const unsigned i2c0_pins[] = {102, 103};
static const unsigned i2c0_muxvals[] = {0, 0};
static const unsigned i2c1_pins[] = {104, 105};
static const unsigned i2c1_muxvals[] = {0, 0};
static const unsigned i2c2_pins[] = {108, 109};
static const unsigned i2c2_muxvals[] = {2, 2};
static const unsigned i2c3_pins[] = {108, 109};
static const unsigned i2c3_muxvals[] = {3, 3};
static const unsigned nand_pins[] = {15, 16, 17, 18, 19, 20, 21, 24, 25, 26,
27, 28, 29, 30, 31};
static const unsigned nand_muxvals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0};
static const unsigned nand_cs1_pins[] = {22, 23};
static const unsigned nand_cs1_muxvals[] = {0, 0};
static const unsigned uart0_pins[] = {70, 71};
static const unsigned uart0_muxvals[] = {3, 3};
static const unsigned uart1_pins[] = {114, 115};
static const unsigned uart1_muxvals[] = {0, 0};
static const unsigned uart2_pins[] = {112, 113};
static const unsigned uart2_muxvals[] = {1, 1};
static const unsigned uart3_pins[] = {110, 111};
static const unsigned uart3_muxvals[] = {1, 1};
static const unsigned usb0_pins[] = {41, 42};
static const unsigned usb0_muxvals[] = {0, 0};
static const unsigned usb1_pins[] = {43, 44};
static const unsigned usb1_muxvals[] = {0, 0};
static const unsigned usb2_pins[] = {114, 115};
static const unsigned usb2_muxvals[] = {1, 1};
static const unsigned port_range0_pins[] = {
0, 1, 2, 3, 4, 5, 6, 7, /* PORT0x */
8, 9, 10, 11, 12, 13, 14, 15, /* PORT1x */
32, 33, 34, 35, 36, 37, 38, 39, /* PORT2x */
59, 60, 61, 62, 63, 64, 65, 66, /* PORT3x */
95, 96, 97, 98, 99, 100, 101, 57, /* PORT4x */
70, 71, 72, 73, 74, 75, 76, 77, /* PORT5x */
81, 83, 84, 85, 86, 89, 90, 91, /* PORT6x */
118, 119, 120, 121, 122, 53, 54, 55, /* PORT7x */
41, 42, 43, 44, 79, 80, 18, 19, /* PORT8x */
110, 111, 112, 113, 114, 115, 16, 17, /* PORT9x */
40, 67, 68, 69, 78, 92, 93, 94, /* PORT10x */
48, 49, 46, 45, 123, 124, 125, 126, /* PORT11x */
47, 127, 20, 56, 22, /* PORT120-124 */
};
static const unsigned port_range0_muxvals[] = {
15, 15, 15, 15, 15, 15, 15, 15, /* PORT0x */
15, 15, 15, 15, 15, 15, 15, 15, /* PORT1x */
15, 15, 15, 15, 15, 15, 15, 15, /* PORT2x */
15, 15, 15, 15, 15, 15, 15, 15, /* PORT3x */
15, 15, 15, 15, 15, 15, 15, 15, /* PORT4x */
15, 15, 15, 15, 15, 15, 15, 15, /* PORT5x */
15, 15, 15, 15, 15, 15, 15, 15, /* PORT6x */
15, 15, 15, 15, 15, 15, 15, 15, /* PORT7x */
15, 15, 15, 15, 15, 15, 15, 15, /* PORT8x */
15, 15, 15, 15, 15, 15, 15, 15, /* PORT9x */
15, 15, 15, 15, 15, 15, 15, 15, /* PORT10x */
15, 15, 15, 15, 15, 15, 15, 15, /* PORT11x */
15, 15, 15, 15, 15, /* PORT120-124 */
};
static const unsigned port_range1_pins[] = {
116, 117, /* PORT130-131 */
};
static const unsigned port_range1_muxvals[] = {
15, 15, /* PORT130-131 */
};
static const unsigned port_range2_pins[] = {
102, 103, 104, 105, 106, 107, 108, 109, /* PORT14x */
};
static const unsigned port_range2_muxvals[] = {
15, 15, 15, 15, 15, 15, 15, 15, /* PORT14x */
};
static const unsigned port_range3_pins[] = {
23, /* PORT166 */
};
static const unsigned port_range3_muxvals[] = {
15, /* PORT166 */
};
static const unsigned xirq_range0_pins[] = {
128, 129, 130, 131, 132, 133, 134, 135, /* XIRQ0-7 */
82, 87, 88, 50, 51, /* XIRQ8-12 */
};
static const unsigned xirq_range0_muxvals[] = {
0, 0, 0, 0, 0, 0, 0, 0, /* XIRQ0-7 */
14, 14, 14, 14, 14, /* XIRQ8-12 */
};
static const unsigned xirq_range1_pins[] = {
52, 58, /* XIRQ14-15 */
};
static const unsigned xirq_range1_muxvals[] = {
14, 14, /* XIRQ14-15 */
};
static const struct uniphier_pinctrl_group ph1_sld8_groups[] = {
UNIPHIER_PINCTRL_GROUP(emmc),
UNIPHIER_PINCTRL_GROUP(emmc_dat8),
UNIPHIER_PINCTRL_GROUP(i2c0),
UNIPHIER_PINCTRL_GROUP(i2c1),
UNIPHIER_PINCTRL_GROUP(i2c2),
UNIPHIER_PINCTRL_GROUP(i2c3),
UNIPHIER_PINCTRL_GROUP(nand),
UNIPHIER_PINCTRL_GROUP(nand_cs1),
UNIPHIER_PINCTRL_GROUP(uart0),
UNIPHIER_PINCTRL_GROUP(uart1),
UNIPHIER_PINCTRL_GROUP(uart2),
UNIPHIER_PINCTRL_GROUP(uart3),
UNIPHIER_PINCTRL_GROUP(usb0),
UNIPHIER_PINCTRL_GROUP(usb1),
UNIPHIER_PINCTRL_GROUP(usb2),
UNIPHIER_PINCTRL_GROUP_GPIO_RANGE_PORT(port_range0),
UNIPHIER_PINCTRL_GROUP_GPIO_RANGE_PORT(port_range1),
UNIPHIER_PINCTRL_GROUP_GPIO_RANGE_PORT(port_range2),
UNIPHIER_PINCTRL_GROUP_GPIO_RANGE_PORT(port_range3),
UNIPHIER_PINCTRL_GROUP_GPIO_RANGE_IRQ(xirq_range0),
UNIPHIER_PINCTRL_GROUP_GPIO_RANGE_IRQ(xirq_range1),
UNIPHIER_PINCTRL_GROUP_SINGLE(port00, port_range0, 0),
UNIPHIER_PINCTRL_GROUP_SINGLE(port01, port_range0, 1),
UNIPHIER_PINCTRL_GROUP_SINGLE(port02, port_range0, 2),
UNIPHIER_PINCTRL_GROUP_SINGLE(port03, port_range0, 3),
UNIPHIER_PINCTRL_GROUP_SINGLE(port04, port_range0, 4),
UNIPHIER_PINCTRL_GROUP_SINGLE(port05, port_range0, 5),
UNIPHIER_PINCTRL_GROUP_SINGLE(port06, port_range0, 6),
UNIPHIER_PINCTRL_GROUP_SINGLE(port07, port_range0, 7),
UNIPHIER_PINCTRL_GROUP_SINGLE(port10, port_range0, 8),
UNIPHIER_PINCTRL_GROUP_SINGLE(port11, port_range0, 9),
UNIPHIER_PINCTRL_GROUP_SINGLE(port12, port_range0, 10),
UNIPHIER_PINCTRL_GROUP_SINGLE(port13, port_range0, 11),
UNIPHIER_PINCTRL_GROUP_SINGLE(port14, port_range0, 12),
UNIPHIER_PINCTRL_GROUP_SINGLE(port15, port_range0, 13),
UNIPHIER_PINCTRL_GROUP_SINGLE(port16, port_range0, 14),
UNIPHIER_PINCTRL_GROUP_SINGLE(port17, port_range0, 15),
UNIPHIER_PINCTRL_GROUP_SINGLE(port20, port_range0, 16),
UNIPHIER_PINCTRL_GROUP_SINGLE(port21, port_range0, 17),
UNIPHIER_PINCTRL_GROUP_SINGLE(port22, port_range0, 18),
UNIPHIER_PINCTRL_GROUP_SINGLE(port23, port_range0, 19),
UNIPHIER_PINCTRL_GROUP_SINGLE(port24, port_range0, 20),
UNIPHIER_PINCTRL_GROUP_SINGLE(port25, port_range0, 21),
UNIPHIER_PINCTRL_GROUP_SINGLE(port26, port_range0, 22),
UNIPHIER_PINCTRL_GROUP_SINGLE(port27, port_range0, 23),
UNIPHIER_PINCTRL_GROUP_SINGLE(port30, port_range0, 24),
UNIPHIER_PINCTRL_GROUP_SINGLE(port31, port_range0, 25),
UNIPHIER_PINCTRL_GROUP_SINGLE(port32, port_range0, 26),
UNIPHIER_PINCTRL_GROUP_SINGLE(port33, port_range0, 27),
UNIPHIER_PINCTRL_GROUP_SINGLE(port34, port_range0, 28),
UNIPHIER_PINCTRL_GROUP_SINGLE(port35, port_range0, 29),
UNIPHIER_PINCTRL_GROUP_SINGLE(port36, port_range0, 30),
UNIPHIER_PINCTRL_GROUP_SINGLE(port37, port_range0, 31),
UNIPHIER_PINCTRL_GROUP_SINGLE(port40, port_range0, 32),
UNIPHIER_PINCTRL_GROUP_SINGLE(port41, port_range0, 33),
UNIPHIER_PINCTRL_GROUP_SINGLE(port42, port_range0, 34),
UNIPHIER_PINCTRL_GROUP_SINGLE(port43, port_range0, 35),
UNIPHIER_PINCTRL_GROUP_SINGLE(port44, port_range0, 36),
UNIPHIER_PINCTRL_GROUP_SINGLE(port45, port_range0, 37),
UNIPHIER_PINCTRL_GROUP_SINGLE(port46, port_range0, 38),
UNIPHIER_PINCTRL_GROUP_SINGLE(port47, port_range0, 39),
UNIPHIER_PINCTRL_GROUP_SINGLE(port50, port_range0, 40),
UNIPHIER_PINCTRL_GROUP_SINGLE(port51, port_range0, 41),
UNIPHIER_PINCTRL_GROUP_SINGLE(port52, port_range0, 42),
UNIPHIER_PINCTRL_GROUP_SINGLE(port53, port_range0, 43),
UNIPHIER_PINCTRL_GROUP_SINGLE(port54, port_range0, 44),
UNIPHIER_PINCTRL_GROUP_SINGLE(port55, port_range0, 45),
UNIPHIER_PINCTRL_GROUP_SINGLE(port56, port_range0, 46),
UNIPHIER_PINCTRL_GROUP_SINGLE(port57, port_range0, 47),
UNIPHIER_PINCTRL_GROUP_SINGLE(port60, port_range0, 48),
UNIPHIER_PINCTRL_GROUP_SINGLE(port61, port_range0, 49),
UNIPHIER_PINCTRL_GROUP_SINGLE(port62, port_range0, 50),
UNIPHIER_PINCTRL_GROUP_SINGLE(port63, port_range0, 51),
UNIPHIER_PINCTRL_GROUP_SINGLE(port64, port_range0, 52),
UNIPHIER_PINCTRL_GROUP_SINGLE(port65, port_range0, 53),
UNIPHIER_PINCTRL_GROUP_SINGLE(port66, port_range0, 54),
UNIPHIER_PINCTRL_GROUP_SINGLE(port67, port_range0, 55),
UNIPHIER_PINCTRL_GROUP_SINGLE(port70, port_range0, 56),
UNIPHIER_PINCTRL_GROUP_SINGLE(port71, port_range0, 57),
UNIPHIER_PINCTRL_GROUP_SINGLE(port72, port_range0, 58),
UNIPHIER_PINCTRL_GROUP_SINGLE(port73, port_range0, 59),
UNIPHIER_PINCTRL_GROUP_SINGLE(port74, port_range0, 60),
UNIPHIER_PINCTRL_GROUP_SINGLE(port75, port_range0, 61),
UNIPHIER_PINCTRL_GROUP_SINGLE(port76, port_range0, 62),
UNIPHIER_PINCTRL_GROUP_SINGLE(port77, port_range0, 63),
UNIPHIER_PINCTRL_GROUP_SINGLE(port80, port_range0, 64),
UNIPHIER_PINCTRL_GROUP_SINGLE(port81, port_range0, 65),
UNIPHIER_PINCTRL_GROUP_SINGLE(port82, port_range0, 66),
UNIPHIER_PINCTRL_GROUP_SINGLE(port83, port_range0, 67),
UNIPHIER_PINCTRL_GROUP_SINGLE(port84, port_range0, 68),
UNIPHIER_PINCTRL_GROUP_SINGLE(port85, port_range0, 69),
UNIPHIER_PINCTRL_GROUP_SINGLE(port86, port_range0, 70),
UNIPHIER_PINCTRL_GROUP_SINGLE(port87, port_range0, 71),
UNIPHIER_PINCTRL_GROUP_SINGLE(port90, port_range0, 72),
UNIPHIER_PINCTRL_GROUP_SINGLE(port91, port_range0, 73),
UNIPHIER_PINCTRL_GROUP_SINGLE(port92, port_range0, 74),
UNIPHIER_PINCTRL_GROUP_SINGLE(port93, port_range0, 75),
UNIPHIER_PINCTRL_GROUP_SINGLE(port94, port_range0, 76),
UNIPHIER_PINCTRL_GROUP_SINGLE(port95, port_range0, 77),
UNIPHIER_PINCTRL_GROUP_SINGLE(port96, port_range0, 78),
UNIPHIER_PINCTRL_GROUP_SINGLE(port97, port_range0, 79),
UNIPHIER_PINCTRL_GROUP_SINGLE(port100, port_range0, 80),
UNIPHIER_PINCTRL_GROUP_SINGLE(port101, port_range0, 81),
UNIPHIER_PINCTRL_GROUP_SINGLE(port102, port_range0, 82),
UNIPHIER_PINCTRL_GROUP_SINGLE(port103, port_range0, 83),
UNIPHIER_PINCTRL_GROUP_SINGLE(port104, port_range0, 84),
UNIPHIER_PINCTRL_GROUP_SINGLE(port105, port_range0, 85),
UNIPHIER_PINCTRL_GROUP_SINGLE(port106, port_range0, 86),
UNIPHIER_PINCTRL_GROUP_SINGLE(port107, port_range0, 87),
UNIPHIER_PINCTRL_GROUP_SINGLE(port110, port_range0, 88),
UNIPHIER_PINCTRL_GROUP_SINGLE(port111, port_range0, 89),
UNIPHIER_PINCTRL_GROUP_SINGLE(port112, port_range0, 90),
UNIPHIER_PINCTRL_GROUP_SINGLE(port113, port_range0, 91),
UNIPHIER_PINCTRL_GROUP_SINGLE(port114, port_range0, 92),
UNIPHIER_PINCTRL_GROUP_SINGLE(port115, port_range0, 93),
UNIPHIER_PINCTRL_GROUP_SINGLE(port116, port_range0, 94),
UNIPHIER_PINCTRL_GROUP_SINGLE(port117, port_range0, 95),
UNIPHIER_PINCTRL_GROUP_SINGLE(port120, port_range0, 96),
UNIPHIER_PINCTRL_GROUP_SINGLE(port121, port_range0, 97),
UNIPHIER_PINCTRL_GROUP_SINGLE(port122, port_range0, 98),
UNIPHIER_PINCTRL_GROUP_SINGLE(port123, port_range0, 99),
UNIPHIER_PINCTRL_GROUP_SINGLE(port124, port_range0, 100),
UNIPHIER_PINCTRL_GROUP_SINGLE(port130, port_range1, 0),
UNIPHIER_PINCTRL_GROUP_SINGLE(port131, port_range1, 1),
UNIPHIER_PINCTRL_GROUP_SINGLE(port140, port_range2, 0),
UNIPHIER_PINCTRL_GROUP_SINGLE(port141, port_range2, 1),
UNIPHIER_PINCTRL_GROUP_SINGLE(port142, port_range2, 2),
UNIPHIER_PINCTRL_GROUP_SINGLE(port143, port_range2, 3),
UNIPHIER_PINCTRL_GROUP_SINGLE(port144, port_range2, 4),
UNIPHIER_PINCTRL_GROUP_SINGLE(port145, port_range2, 5),
UNIPHIER_PINCTRL_GROUP_SINGLE(port146, port_range2, 6),
UNIPHIER_PINCTRL_GROUP_SINGLE(port147, port_range2, 7),
UNIPHIER_PINCTRL_GROUP_SINGLE(port166, port_range3, 0),
UNIPHIER_PINCTRL_GROUP_SINGLE(xirq0, xirq_range0, 0),
UNIPHIER_PINCTRL_GROUP_SINGLE(xirq1, xirq_range0, 1),
UNIPHIER_PINCTRL_GROUP_SINGLE(xirq2, xirq_range0, 2),
UNIPHIER_PINCTRL_GROUP_SINGLE(xirq3, xirq_range0, 3),
UNIPHIER_PINCTRL_GROUP_SINGLE(xirq4, xirq_range0, 4),
UNIPHIER_PINCTRL_GROUP_SINGLE(xirq5, xirq_range0, 5),
UNIPHIER_PINCTRL_GROUP_SINGLE(xirq6, xirq_range0, 6),
UNIPHIER_PINCTRL_GROUP_SINGLE(xirq7, xirq_range0, 7),
UNIPHIER_PINCTRL_GROUP_SINGLE(xirq8, xirq_range0, 8),
UNIPHIER_PINCTRL_GROUP_SINGLE(xirq9, xirq_range0, 9),
UNIPHIER_PINCTRL_GROUP_SINGLE(xirq10, xirq_range0, 10),
UNIPHIER_PINCTRL_GROUP_SINGLE(xirq11, xirq_range0, 11),
UNIPHIER_PINCTRL_GROUP_SINGLE(xirq12, xirq_range0, 12),
UNIPHIER_PINCTRL_GROUP_SINGLE(xirq14, xirq_range1, 0),
UNIPHIER_PINCTRL_GROUP_SINGLE(xirq15, xirq_range1, 1),
};
static const char * const emmc_groups[] = {"emmc", "emmc_dat8"};
static const char * const i2c0_groups[] = {"i2c0"};
static const char * const i2c1_groups[] = {"i2c1"};
static const char * const i2c2_groups[] = {"i2c2"};
static const char * const i2c3_groups[] = {"i2c3"};
static const char * const nand_groups[] = {"nand", "nand_cs1"};
static const char * const uart0_groups[] = {"uart0"};
static const char * const uart1_groups[] = {"uart1"};
static const char * const uart2_groups[] = {"uart2"};
static const char * const uart3_groups[] = {"uart3"};
static const char * const usb0_groups[] = {"usb0"};
static const char * const usb1_groups[] = {"usb1"};
static const char * const usb2_groups[] = {"usb2"};
static const char * const port_groups[] = {
"port00", "port01", "port02", "port03",
"port04", "port05", "port06", "port07",
"port10", "port11", "port12", "port13",
"port14", "port15", "port16", "port17",
"port20", "port21", "port22", "port23",
"port24", "port25", "port26", "port27",
"port30", "port31", "port32", "port33",
"port34", "port35", "port36", "port37",
"port40", "port41", "port42", "port43",
"port44", "port45", "port46", "port47",
"port50", "port51", "port52", "port53",
"port54", "port55", "port56", "port57",
"port60", "port61", "port62", "port63",
"port64", "port65", "port66", "port67",
"port70", "port71", "port72", "port73",
"port74", "port75", "port76", "port77",
"port80", "port81", "port82", "port83",
"port84", "port85", "port86", "port87",
"port90", "port91", "port92", "port93",
"port94", "port95", "port96", "port97",
"port100", "port101", "port102", "port103",
"port104", "port105", "port106", "port107",
"port110", "port111", "port112", "port113",
"port114", "port115", "port116", "port117",
"port120", "port121", "port122", "port123",
"port124", "port125", "port126", "port127",
"port130", "port131", "port132", "port133",
"port134", "port135", "port136", "port137",
"port140", "port141", "port142", "port143",
"port144", "port145", "port146", "port147",
/* port150-164 missing */
/* none */ "port165",
};
static const char * const xirq_groups[] = {
"xirq0", "xirq1", "xirq2", "xirq3",
"xirq4", "xirq5", "xirq6", "xirq7",
"xirq8", "xirq9", "xirq10", "xirq11",
"xirq12", /* none*/ "xirq14", "xirq15",
};
static const struct uniphier_pinmux_function ph1_sld8_functions[] = {
UNIPHIER_PINMUX_FUNCTION(emmc),
UNIPHIER_PINMUX_FUNCTION(i2c0),
UNIPHIER_PINMUX_FUNCTION(i2c1),
UNIPHIER_PINMUX_FUNCTION(i2c2),
UNIPHIER_PINMUX_FUNCTION(i2c3),
UNIPHIER_PINMUX_FUNCTION(nand),
UNIPHIER_PINMUX_FUNCTION(uart0),
UNIPHIER_PINMUX_FUNCTION(uart1),
UNIPHIER_PINMUX_FUNCTION(uart2),
UNIPHIER_PINMUX_FUNCTION(uart3),
UNIPHIER_PINMUX_FUNCTION(usb0),
UNIPHIER_PINMUX_FUNCTION(usb1),
UNIPHIER_PINMUX_FUNCTION(usb2),
UNIPHIER_PINMUX_FUNCTION(port),
UNIPHIER_PINMUX_FUNCTION(xirq),
};
static struct uniphier_pinctrl_socdata ph1_sld8_pindata = {
.groups = ph1_sld8_groups,
.groups_count = ARRAY_SIZE(ph1_sld8_groups),
.functions = ph1_sld8_functions,
.functions_count = ARRAY_SIZE(ph1_sld8_functions),
.mux_bits = 8,
.reg_stride = 4,
.load_pinctrl = false,
};
static struct pinctrl_desc ph1_sld8_pinctrl_desc = {
.name = DRIVER_NAME,
.pins = ph1_sld8_pins,
.npins = ARRAY_SIZE(ph1_sld8_pins),
.owner = THIS_MODULE,
};
static int ph1_sld8_pinctrl_probe(struct platform_device *pdev)
{
return uniphier_pinctrl_probe(pdev, &ph1_sld8_pinctrl_desc,
&ph1_sld8_pindata);
}
static const struct of_device_id ph1_sld8_pinctrl_match[] = {
{ .compatible = "socionext,ph1-sld8-pinctrl" },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, ph1_sld8_pinctrl_match);
static struct platform_driver ph1_sld8_pinctrl_driver = {
.probe = ph1_sld8_pinctrl_probe,
.remove = uniphier_pinctrl_remove,
.driver = {
.name = DRIVER_NAME,
.of_match_table = ph1_sld8_pinctrl_match,
},
};
module_platform_driver(ph1_sld8_pinctrl_driver);
MODULE_AUTHOR("Masahiro Yamada <yamada.masahiro@socionext.com>");
MODULE_DESCRIPTION("UniPhier PH1-sLD8 pinctrl driver");
MODULE_LICENSE("GPL");

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,684 @@
/*
* Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/export.h>
#include <linux/mfd/syscon.h>
#include <linux/pinctrl/pinconf.h>
#include <linux/pinctrl/pinconf-generic.h>
#include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/pinmux.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include "../core.h"
#include "../pinctrl-utils.h"
#include "pinctrl-uniphier.h"
struct uniphier_pinctrl_priv {
struct pinctrl_dev *pctldev;
struct regmap *regmap;
struct uniphier_pinctrl_socdata *socdata;
};
static int uniphier_pctl_get_groups_count(struct pinctrl_dev *pctldev)
{
struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
return priv->socdata->groups_count;
}
static const char *uniphier_pctl_get_group_name(struct pinctrl_dev *pctldev,
unsigned selector)
{
struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
return priv->socdata->groups[selector].name;
}
static int uniphier_pctl_get_group_pins(struct pinctrl_dev *pctldev,
unsigned selector,
const unsigned **pins,
unsigned *num_pins)
{
struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
*pins = priv->socdata->groups[selector].pins;
*num_pins = priv->socdata->groups[selector].num_pins;
return 0;
}
#ifdef CONFIG_DEBUG_FS
static void uniphier_pctl_pin_dbg_show(struct pinctrl_dev *pctldev,
struct seq_file *s, unsigned offset)
{
const struct pinctrl_pin_desc *pin = &pctldev->desc->pins[offset];
const char *pull_dir, *drv_str;
switch (uniphier_pin_get_pull_dir(pin->drv_data)) {
case UNIPHIER_PIN_PULL_UP:
pull_dir = "UP";
break;
case UNIPHIER_PIN_PULL_DOWN:
pull_dir = "DOWN";
break;
case UNIPHIER_PIN_PULL_NONE:
pull_dir = "NONE";
break;
default:
BUG();
}
switch (uniphier_pin_get_drv_str(pin->drv_data)) {
case UNIPHIER_PIN_DRV_4_8:
drv_str = "4/8(mA)";
break;
case UNIPHIER_PIN_DRV_8_12_16_20:
drv_str = "8/12/16/20(mA)";
break;
case UNIPHIER_PIN_DRV_FIXED_4:
drv_str = "4(mA)";
break;
case UNIPHIER_PIN_DRV_FIXED_5:
drv_str = "5(mA)";
break;
case UNIPHIER_PIN_DRV_FIXED_8:
drv_str = "8(mA)";
break;
case UNIPHIER_PIN_DRV_NONE:
drv_str = "NONE";
break;
default:
BUG();
}
seq_printf(s, " PULL_DIR=%s DRV_STR=%s", pull_dir, drv_str);
}
#endif
static const struct pinctrl_ops uniphier_pctlops = {
.get_groups_count = uniphier_pctl_get_groups_count,
.get_group_name = uniphier_pctl_get_group_name,
.get_group_pins = uniphier_pctl_get_group_pins,
#ifdef CONFIG_DEBUG_FS
.pin_dbg_show = uniphier_pctl_pin_dbg_show,
#endif
.dt_node_to_map = pinconf_generic_dt_node_to_map_all,
.dt_free_map = pinctrl_utils_dt_free_map,
};
static int uniphier_conf_pin_bias_get(struct pinctrl_dev *pctldev,
const struct pinctrl_pin_desc *pin,
enum pin_config_param param)
{
struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
enum uniphier_pin_pull_dir pull_dir =
uniphier_pin_get_pull_dir(pin->drv_data);
unsigned int pupdctrl, reg, shift, val;
unsigned int expected = 1;
int ret;
switch (param) {
case PIN_CONFIG_BIAS_DISABLE:
if (pull_dir == UNIPHIER_PIN_PULL_NONE)
return 0;
if (pull_dir == UNIPHIER_PIN_PULL_UP_FIXED ||
pull_dir == UNIPHIER_PIN_PULL_DOWN_FIXED)
return -EINVAL;
expected = 0;
break;
case PIN_CONFIG_BIAS_PULL_UP:
if (pull_dir == UNIPHIER_PIN_PULL_UP_FIXED)
return 0;
if (pull_dir != UNIPHIER_PIN_PULL_UP)
return -EINVAL;
break;
case PIN_CONFIG_BIAS_PULL_DOWN:
if (pull_dir == UNIPHIER_PIN_PULL_DOWN_FIXED)
return 0;
if (pull_dir != UNIPHIER_PIN_PULL_DOWN)
return -EINVAL;
break;
default:
BUG();
}
pupdctrl = uniphier_pin_get_pupdctrl(pin->drv_data);
reg = UNIPHIER_PINCTRL_PUPDCTRL_BASE + pupdctrl / 32 * 4;
shift = pupdctrl % 32;
ret = regmap_read(priv->regmap, reg, &val);
if (ret)
return ret;
val = (val >> shift) & 1;
return (val == expected) ? 0 : -EINVAL;
}
static int uniphier_conf_pin_drive_get(struct pinctrl_dev *pctldev,
const struct pinctrl_pin_desc *pin,
u16 *strength)
{
struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
enum uniphier_pin_drv_str drv_str =
uniphier_pin_get_drv_str(pin->drv_data);
const unsigned int strength_4_8[] = {4, 8};
const unsigned int strength_8_12_16_20[] = {8, 12, 16, 20};
const unsigned int *supported_strength;
unsigned int drvctrl, reg, shift, mask, width, val;
int ret;
switch (drv_str) {
case UNIPHIER_PIN_DRV_4_8:
supported_strength = strength_4_8;
width = 1;
break;
case UNIPHIER_PIN_DRV_8_12_16_20:
supported_strength = strength_8_12_16_20;
width = 2;
break;
case UNIPHIER_PIN_DRV_FIXED_4:
*strength = 4;
return 0;
case UNIPHIER_PIN_DRV_FIXED_5:
*strength = 5;
return 0;
case UNIPHIER_PIN_DRV_FIXED_8:
*strength = 8;
return 0;
default:
/* drive strength control is not supported for this pin */
return -EINVAL;
}
drvctrl = uniphier_pin_get_drvctrl(pin->drv_data);
drvctrl *= width;
reg = (width == 2) ? UNIPHIER_PINCTRL_DRV2CTRL_BASE :
UNIPHIER_PINCTRL_DRVCTRL_BASE;
reg += drvctrl / 32 * 4;
shift = drvctrl % 32;
mask = (1U << width) - 1;
ret = regmap_read(priv->regmap, reg, &val);
if (ret)
return ret;
*strength = supported_strength[(val >> shift) & mask];
return 0;
}
static int uniphier_conf_pin_input_enable_get(struct pinctrl_dev *pctldev,
const struct pinctrl_pin_desc *pin)
{
struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
unsigned int iectrl = uniphier_pin_get_iectrl(pin->drv_data);
unsigned int val;
int ret;
if (iectrl == UNIPHIER_PIN_IECTRL_NONE)
/* This pin is always input-enabled. */
return 0;
ret = regmap_read(priv->regmap, UNIPHIER_PINCTRL_IECTRL, &val);
if (ret)
return ret;
return val & BIT(iectrl) ? 0 : -EINVAL;
}
static int uniphier_conf_pin_config_get(struct pinctrl_dev *pctldev,
unsigned pin,
unsigned long *configs)
{
const struct pinctrl_pin_desc *pin_desc = &pctldev->desc->pins[pin];
enum pin_config_param param = pinconf_to_config_param(*configs);
bool has_arg = false;
u16 arg;
int ret;
switch (param) {
case PIN_CONFIG_BIAS_DISABLE:
case PIN_CONFIG_BIAS_PULL_UP:
case PIN_CONFIG_BIAS_PULL_DOWN:
ret = uniphier_conf_pin_bias_get(pctldev, pin_desc, param);
break;
case PIN_CONFIG_DRIVE_STRENGTH:
ret = uniphier_conf_pin_drive_get(pctldev, pin_desc, &arg);
has_arg = true;
break;
case PIN_CONFIG_INPUT_ENABLE:
ret = uniphier_conf_pin_input_enable_get(pctldev, pin_desc);
break;
default:
/* unsupported parameter */
ret = -EINVAL;
break;
}
if (ret == 0 && has_arg)
*configs = pinconf_to_config_packed(param, arg);
return ret;
}
static int uniphier_conf_pin_bias_set(struct pinctrl_dev *pctldev,
const struct pinctrl_pin_desc *pin,
enum pin_config_param param,
u16 arg)
{
struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
enum uniphier_pin_pull_dir pull_dir =
uniphier_pin_get_pull_dir(pin->drv_data);
unsigned int pupdctrl, reg, shift;
unsigned int val = 1;
switch (param) {
case PIN_CONFIG_BIAS_DISABLE:
if (pull_dir == UNIPHIER_PIN_PULL_NONE)
return 0;
if (pull_dir == UNIPHIER_PIN_PULL_UP_FIXED ||
pull_dir == UNIPHIER_PIN_PULL_DOWN_FIXED) {
dev_err(pctldev->dev,
"can not disable pull register for pin %u (%s)\n",
pin->number, pin->name);
return -EINVAL;
}
val = 0;
break;
case PIN_CONFIG_BIAS_PULL_UP:
if (pull_dir == UNIPHIER_PIN_PULL_UP_FIXED && arg != 0)
return 0;
if (pull_dir != UNIPHIER_PIN_PULL_UP) {
dev_err(pctldev->dev,
"pull-up is unsupported for pin %u (%s)\n",
pin->number, pin->name);
return -EINVAL;
}
if (arg == 0) {
dev_err(pctldev->dev, "pull-up can not be total\n");
return -EINVAL;
}
break;
case PIN_CONFIG_BIAS_PULL_DOWN:
if (pull_dir == UNIPHIER_PIN_PULL_DOWN_FIXED && arg != 0)
return 0;
if (pull_dir != UNIPHIER_PIN_PULL_DOWN) {
dev_err(pctldev->dev,
"pull-down is unsupported for pin %u (%s)\n",
pin->number, pin->name);
return -EINVAL;
}
if (arg == 0) {
dev_err(pctldev->dev, "pull-down can not be total\n");
return -EINVAL;
}
break;
case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT:
if (pull_dir == UNIPHIER_PIN_PULL_NONE) {
dev_err(pctldev->dev,
"pull-up/down is unsupported for pin %u (%s)\n",
pin->number, pin->name);
return -EINVAL;
}
if (arg == 0)
return 0; /* configuration ingored */
break;
default:
BUG();
}
pupdctrl = uniphier_pin_get_pupdctrl(pin->drv_data);
reg = UNIPHIER_PINCTRL_PUPDCTRL_BASE + pupdctrl / 32 * 4;
shift = pupdctrl % 32;
return regmap_update_bits(priv->regmap, reg, 1 << shift, val << shift);
}
static int uniphier_conf_pin_drive_set(struct pinctrl_dev *pctldev,
const struct pinctrl_pin_desc *pin,
u16 strength)
{
struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
enum uniphier_pin_drv_str drv_str =
uniphier_pin_get_drv_str(pin->drv_data);
const unsigned int strength_4_8[] = {4, 8, -1};
const unsigned int strength_8_12_16_20[] = {8, 12, 16, 20, -1};
const unsigned int *supported_strength;
unsigned int drvctrl, reg, shift, mask, width, val;
switch (drv_str) {
case UNIPHIER_PIN_DRV_4_8:
supported_strength = strength_4_8;
width = 1;
break;
case UNIPHIER_PIN_DRV_8_12_16_20:
supported_strength = strength_8_12_16_20;
width = 2;
break;
default:
dev_err(pctldev->dev,
"cannot change drive strength for pin %u (%s)\n",
pin->number, pin->name);
return -EINVAL;
}
for (val = 0; supported_strength[val] > 0; val++) {
if (supported_strength[val] > strength)
break;
}
if (val == 0) {
dev_err(pctldev->dev,
"unsupported drive strength %u mA for pin %u (%s)\n",
strength, pin->number, pin->name);
return -EINVAL;
}
val--;
drvctrl = uniphier_pin_get_drvctrl(pin->drv_data);
drvctrl *= width;
reg = (width == 2) ? UNIPHIER_PINCTRL_DRV2CTRL_BASE :
UNIPHIER_PINCTRL_DRVCTRL_BASE;
reg += drvctrl / 32 * 4;
shift = drvctrl % 32;
mask = (1U << width) - 1;
return regmap_update_bits(priv->regmap, reg,
mask << shift, val << shift);
}
static int uniphier_conf_pin_input_enable(struct pinctrl_dev *pctldev,
const struct pinctrl_pin_desc *pin,
u16 enable)
{
struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
unsigned int iectrl = uniphier_pin_get_iectrl(pin->drv_data);
if (enable == 0) {
/*
* Multiple pins share one input enable, so per-pin disabling
* is impossible.
*/
dev_err(pctldev->dev, "unable to disable input\n");
return -EINVAL;
}
if (iectrl == UNIPHIER_PIN_IECTRL_NONE)
/* This pin is always input-enabled. nothing to do. */
return 0;
return regmap_update_bits(priv->regmap, UNIPHIER_PINCTRL_IECTRL,
BIT(iectrl), BIT(iectrl));
}
static int uniphier_conf_pin_config_set(struct pinctrl_dev *pctldev,
unsigned pin,
unsigned long *configs,
unsigned num_configs)
{
const struct pinctrl_pin_desc *pin_desc = &pctldev->desc->pins[pin];
int i, ret;
for (i = 0; i < num_configs; i++) {
enum pin_config_param param =
pinconf_to_config_param(configs[i]);
u16 arg = pinconf_to_config_argument(configs[i]);
switch (param) {
case PIN_CONFIG_BIAS_DISABLE:
case PIN_CONFIG_BIAS_PULL_UP:
case PIN_CONFIG_BIAS_PULL_DOWN:
case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT:
ret = uniphier_conf_pin_bias_set(pctldev, pin_desc,
param, arg);
break;
case PIN_CONFIG_DRIVE_STRENGTH:
ret = uniphier_conf_pin_drive_set(pctldev, pin_desc,
arg);
break;
case PIN_CONFIG_INPUT_ENABLE:
ret = uniphier_conf_pin_input_enable(pctldev,
pin_desc, arg);
break;
default:
dev_err(pctldev->dev,
"unsupported configuration parameter %u\n",
param);
return -EINVAL;
}
if (ret)
return ret;
}
return 0;
}
static int uniphier_conf_pin_config_group_set(struct pinctrl_dev *pctldev,
unsigned selector,
unsigned long *configs,
unsigned num_configs)
{
struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
const unsigned *pins = priv->socdata->groups[selector].pins;
unsigned num_pins = priv->socdata->groups[selector].num_pins;
int i, ret;
for (i = 0; i < num_pins; i++) {
ret = uniphier_conf_pin_config_set(pctldev, pins[i],
configs, num_configs);
if (ret)
return ret;
}
return 0;
}
static const struct pinconf_ops uniphier_confops = {
.is_generic = true,
.pin_config_get = uniphier_conf_pin_config_get,
.pin_config_set = uniphier_conf_pin_config_set,
.pin_config_group_set = uniphier_conf_pin_config_group_set,
};
static int uniphier_pmx_get_functions_count(struct pinctrl_dev *pctldev)
{
struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
return priv->socdata->functions_count;
}
static const char *uniphier_pmx_get_function_name(struct pinctrl_dev *pctldev,
unsigned selector)
{
struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
return priv->socdata->functions[selector].name;
}
static int uniphier_pmx_get_function_groups(struct pinctrl_dev *pctldev,
unsigned selector,
const char * const **groups,
unsigned *num_groups)
{
struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
*groups = priv->socdata->functions[selector].groups;
*num_groups = priv->socdata->functions[selector].num_groups;
return 0;
}
static int uniphier_pmx_set_one_mux(struct pinctrl_dev *pctldev, unsigned pin,
unsigned muxval)
{
struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
unsigned mux_bits = priv->socdata->mux_bits;
unsigned reg_stride = priv->socdata->reg_stride;
unsigned reg, reg_end, shift, mask;
int ret;
reg = UNIPHIER_PINCTRL_PINMUX_BASE + pin * mux_bits / 32 * reg_stride;
reg_end = reg + reg_stride;
shift = pin * mux_bits % 32;
mask = (1U << mux_bits) - 1;
/*
* If reg_stride is greater than 4, the MSB of each pinsel shall be
* stored in the offset+4.
*/
for (; reg < reg_end; reg += 4) {
ret = regmap_update_bits(priv->regmap, reg,
mask << shift, muxval << shift);
if (ret)
return ret;
muxval >>= mux_bits;
}
if (priv->socdata->load_pinctrl) {
ret = regmap_write(priv->regmap,
UNIPHIER_PINCTRL_LOAD_PINMUX, 1);
if (ret)
return ret;
}
/* some pins need input-enabling */
return uniphier_conf_pin_input_enable(pctldev,
&pctldev->desc->pins[pin], 1);
}
static int uniphier_pmx_set_mux(struct pinctrl_dev *pctldev,
unsigned func_selector,
unsigned group_selector)
{
struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
const struct uniphier_pinctrl_group *grp =
&priv->socdata->groups[group_selector];
int i;
int ret;
for (i = 0; i < grp->num_pins; i++) {
ret = uniphier_pmx_set_one_mux(pctldev, grp->pins[i],
grp->muxvals[i]);
if (ret)
return ret;
}
return 0;
}
static int uniphier_pmx_gpio_request_enable(struct pinctrl_dev *pctldev,
struct pinctrl_gpio_range *range,
unsigned offset)
{
struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
const struct uniphier_pinctrl_group *groups = priv->socdata->groups;
int groups_count = priv->socdata->groups_count;
enum uniphier_pinmux_gpio_range_type range_type;
int i, j;
if (strstr(range->name, "irq"))
range_type = UNIPHIER_PINMUX_GPIO_RANGE_IRQ;
else
range_type = UNIPHIER_PINMUX_GPIO_RANGE_PORT;
for (i = 0; i < groups_count; i++) {
if (groups[i].range_type != range_type)
continue;
for (j = 0; j < groups[i].num_pins; j++)
if (groups[i].pins[j] == offset)
goto found;
}
dev_err(pctldev->dev, "pin %u does not support GPIO\n", offset);
return -EINVAL;
found:
return uniphier_pmx_set_one_mux(pctldev, offset, groups[i].muxvals[j]);
}
static const struct pinmux_ops uniphier_pmxops = {
.get_functions_count = uniphier_pmx_get_functions_count,
.get_function_name = uniphier_pmx_get_function_name,
.get_function_groups = uniphier_pmx_get_function_groups,
.set_mux = uniphier_pmx_set_mux,
.gpio_request_enable = uniphier_pmx_gpio_request_enable,
.strict = true,
};
int uniphier_pinctrl_probe(struct platform_device *pdev,
struct pinctrl_desc *desc,
struct uniphier_pinctrl_socdata *socdata)
{
struct device *dev = &pdev->dev;
struct uniphier_pinctrl_priv *priv;
if (!socdata ||
!socdata->groups ||
!socdata->groups_count ||
!socdata->functions ||
!socdata->functions_count ||
!socdata->mux_bits ||
!socdata->reg_stride) {
dev_err(dev, "pinctrl socdata lacks necessary members\n");
return -EINVAL;
}
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
priv->regmap = syscon_node_to_regmap(dev->of_node);
if (IS_ERR(priv->regmap)) {
dev_err(dev, "failed to get regmap\n");
return PTR_ERR(priv->regmap);
}
priv->socdata = socdata;
desc->pctlops = &uniphier_pctlops;
desc->pmxops = &uniphier_pmxops;
desc->confops = &uniphier_confops;
priv->pctldev = pinctrl_register(desc, dev, priv);
if (IS_ERR(priv->pctldev)) {
dev_err(dev, "failed to register UniPhier pinctrl driver\n");
return PTR_ERR(priv->pctldev);
}
platform_set_drvdata(pdev, priv);
return 0;
}
EXPORT_SYMBOL_GPL(uniphier_pinctrl_probe);
int uniphier_pinctrl_remove(struct platform_device *pdev)
{
struct uniphier_pinctrl_priv *priv = platform_get_drvdata(pdev);
pinctrl_unregister(priv->pctldev);
return 0;
}
EXPORT_SYMBOL_GPL(uniphier_pinctrl_remove);

View File

@ -0,0 +1,217 @@
/*
* Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef __PINCTRL_UNIPHIER_H__
#define __PINCTRL_UNIPHIER_H__
#include <linux/bug.h>
#include <linux/kernel.h>
#include <linux/types.h>
#define UNIPHIER_PINCTRL_PINMUX_BASE 0x0
#define UNIPHIER_PINCTRL_LOAD_PINMUX 0x700
#define UNIPHIER_PINCTRL_DRVCTRL_BASE 0x800
#define UNIPHIER_PINCTRL_DRV2CTRL_BASE 0x900
#define UNIPHIER_PINCTRL_PUPDCTRL_BASE 0xa00
#define UNIPHIER_PINCTRL_IECTRL 0xd00
/* input enable control register bit */
#define UNIPHIER_PIN_IECTRL_SHIFT 0
#define UNIPHIER_PIN_IECTRL_BITS 8
#define UNIPHIER_PIN_IECTRL_MASK ((1UL << (UNIPHIER_PIN_IECTRL_BITS)) \
- 1)
/* drive strength control register number */
#define UNIPHIER_PIN_DRVCTRL_SHIFT ((UNIPHIER_PIN_IECTRL_SHIFT) + \
(UNIPHIER_PIN_IECTRL_BITS))
#define UNIPHIER_PIN_DRVCTRL_BITS 9
#define UNIPHIER_PIN_DRVCTRL_MASK ((1UL << (UNIPHIER_PIN_DRVCTRL_BITS)) \
- 1)
/* supported drive strength (mA) */
#define UNIPHIER_PIN_DRV_STR_SHIFT ((UNIPHIER_PIN_DRVCTRL_SHIFT) + \
(UNIPHIER_PIN_DRVCTRL_BITS))
#define UNIPHIER_PIN_DRV_STR_BITS 3
#define UNIPHIER_PIN_DRV_STR_MASK ((1UL << (UNIPHIER_PIN_DRV_STR_BITS)) \
- 1)
/* pull-up / pull-down register number */
#define UNIPHIER_PIN_PUPDCTRL_SHIFT ((UNIPHIER_PIN_DRV_STR_SHIFT) + \
(UNIPHIER_PIN_DRV_STR_BITS))
#define UNIPHIER_PIN_PUPDCTRL_BITS 9
#define UNIPHIER_PIN_PUPDCTRL_MASK ((1UL << (UNIPHIER_PIN_PUPDCTRL_BITS))\
- 1)
/* direction of pull register */
#define UNIPHIER_PIN_PULL_DIR_SHIFT ((UNIPHIER_PIN_PUPDCTRL_SHIFT) + \
(UNIPHIER_PIN_PUPDCTRL_BITS))
#define UNIPHIER_PIN_PULL_DIR_BITS 3
#define UNIPHIER_PIN_PULL_DIR_MASK ((1UL << (UNIPHIER_PIN_PULL_DIR_BITS))\
- 1)
#if UNIPHIER_PIN_PULL_DIR_SHIFT + UNIPHIER_PIN_PULL_DIR_BITS > BITS_PER_LONG
#error "unable to pack pin attributes."
#endif
#define UNIPHIER_PIN_IECTRL_NONE (UNIPHIER_PIN_IECTRL_MASK)
/* selectable drive strength */
enum uniphier_pin_drv_str {
UNIPHIER_PIN_DRV_4_8, /* 2 level control: 4/8 mA */
UNIPHIER_PIN_DRV_8_12_16_20, /* 4 level control: 8/12/16/20 mA */
UNIPHIER_PIN_DRV_FIXED_4, /* fixed to 4mA */
UNIPHIER_PIN_DRV_FIXED_5, /* fixed to 5mA */
UNIPHIER_PIN_DRV_FIXED_8, /* fixed to 8mA */
UNIPHIER_PIN_DRV_NONE, /* no support (input only pin) */
};
/* direction of pull register (no pin supports bi-directional pull biasing) */
enum uniphier_pin_pull_dir {
UNIPHIER_PIN_PULL_UP, /* pull-up or disabled */
UNIPHIER_PIN_PULL_DOWN, /* pull-down or disabled */
UNIPHIER_PIN_PULL_UP_FIXED, /* always pull-up */
UNIPHIER_PIN_PULL_DOWN_FIXED, /* always pull-down */
UNIPHIER_PIN_PULL_NONE, /* no pull register */
};
#define UNIPHIER_PIN_IECTRL(x) \
(((x) & (UNIPHIER_PIN_IECTRL_MASK)) << (UNIPHIER_PIN_IECTRL_SHIFT))
#define UNIPHIER_PIN_DRVCTRL(x) \
(((x) & (UNIPHIER_PIN_DRVCTRL_MASK)) << (UNIPHIER_PIN_DRVCTRL_SHIFT))
#define UNIPHIER_PIN_DRV_STR(x) \
(((x) & (UNIPHIER_PIN_DRV_STR_MASK)) << (UNIPHIER_PIN_DRV_STR_SHIFT))
#define UNIPHIER_PIN_PUPDCTRL(x) \
(((x) & (UNIPHIER_PIN_PUPDCTRL_MASK)) << (UNIPHIER_PIN_PUPDCTRL_SHIFT))
#define UNIPHIER_PIN_PULL_DIR(x) \
(((x) & (UNIPHIER_PIN_PULL_DIR_MASK)) << (UNIPHIER_PIN_PULL_DIR_SHIFT))
#define UNIPHIER_PIN_ATTR_PACKED(iectrl, drvctrl, drv_str, pupdctrl, pull_dir)\
(UNIPHIER_PIN_IECTRL(iectrl) | \
UNIPHIER_PIN_DRVCTRL(drvctrl) | \
UNIPHIER_PIN_DRV_STR(drv_str) | \
UNIPHIER_PIN_PUPDCTRL(pupdctrl) | \
UNIPHIER_PIN_PULL_DIR(pull_dir))
static inline unsigned int uniphier_pin_get_iectrl(void *drv_data)
{
return ((unsigned long)drv_data >> UNIPHIER_PIN_IECTRL_SHIFT) &
UNIPHIER_PIN_IECTRL_MASK;
}
static inline unsigned int uniphier_pin_get_drvctrl(void *drv_data)
{
return ((unsigned long)drv_data >> UNIPHIER_PIN_DRVCTRL_SHIFT) &
UNIPHIER_PIN_DRVCTRL_MASK;
}
static inline unsigned int uniphier_pin_get_drv_str(void *drv_data)
{
return ((unsigned long)drv_data >> UNIPHIER_PIN_DRV_STR_SHIFT) &
UNIPHIER_PIN_DRV_STR_MASK;
}
static inline unsigned int uniphier_pin_get_pupdctrl(void *drv_data)
{
return ((unsigned long)drv_data >> UNIPHIER_PIN_PUPDCTRL_SHIFT) &
UNIPHIER_PIN_PUPDCTRL_MASK;
}
static inline unsigned int uniphier_pin_get_pull_dir(void *drv_data)
{
return ((unsigned long)drv_data >> UNIPHIER_PIN_PULL_DIR_SHIFT) &
UNIPHIER_PIN_PULL_DIR_MASK;
}
enum uniphier_pinmux_gpio_range_type {
UNIPHIER_PINMUX_GPIO_RANGE_PORT,
UNIPHIER_PINMUX_GPIO_RANGE_IRQ,
UNIPHIER_PINMUX_GPIO_RANGE_NONE,
};
struct uniphier_pinctrl_group {
const char *name;
const unsigned *pins;
unsigned num_pins;
const unsigned *muxvals;
enum uniphier_pinmux_gpio_range_type range_type;
};
struct uniphier_pinmux_function {
const char *name;
const char * const *groups;
unsigned num_groups;
};
struct uniphier_pinctrl_socdata {
const struct uniphier_pinctrl_group *groups;
int groups_count;
const struct uniphier_pinmux_function *functions;
int functions_count;
unsigned mux_bits;
unsigned reg_stride;
bool load_pinctrl;
};
#define UNIPHIER_PINCTRL_PIN(a, b, c, d, e, f, g) \
{ \
.number = a, \
.name = b, \
.drv_data = (void *)UNIPHIER_PIN_ATTR_PACKED(c, d, e, f, g), \
}
#define __UNIPHIER_PINCTRL_GROUP(grp, type) \
{ \
.name = #grp, \
.pins = grp##_pins, \
.num_pins = ARRAY_SIZE(grp##_pins), \
.muxvals = grp##_muxvals + \
BUILD_BUG_ON_ZERO(ARRAY_SIZE(grp##_pins) != \
ARRAY_SIZE(grp##_muxvals)), \
.range_type = type, \
}
#define UNIPHIER_PINCTRL_GROUP(grp) \
__UNIPHIER_PINCTRL_GROUP(grp, UNIPHIER_PINMUX_GPIO_RANGE_NONE)
#define UNIPHIER_PINCTRL_GROUP_GPIO_RANGE_PORT(grp) \
__UNIPHIER_PINCTRL_GROUP(grp, UNIPHIER_PINMUX_GPIO_RANGE_PORT)
#define UNIPHIER_PINCTRL_GROUP_GPIO_RANGE_IRQ(grp) \
__UNIPHIER_PINCTRL_GROUP(grp, UNIPHIER_PINMUX_GPIO_RANGE_IRQ)
#define UNIPHIER_PINCTRL_GROUP_SINGLE(grp, array, ofst) \
{ \
.name = #grp, \
.pins = array##_pins + ofst, \
.num_pins = 1, \
.muxvals = array##_muxvals + ofst, \
}
#define UNIPHIER_PINMUX_FUNCTION(func) \
{ \
.name = #func, \
.groups = func##_groups, \
.num_groups = ARRAY_SIZE(func##_groups), \
}
struct platform_device;
struct pinctrl_desc;
int uniphier_pinctrl_probe(struct platform_device *pdev,
struct pinctrl_desc *desc,
struct uniphier_pinctrl_socdata *socdata);
int uniphier_pinctrl_remove(struct platform_device *pdev);
#endif /* __PINCTRL_UNIPHIER_H__ */

View File

@ -7,6 +7,47 @@
#define _DT_BINDINGS_PINCTRL_QCOM_PMIC_MPP_H #define _DT_BINDINGS_PINCTRL_QCOM_PMIC_MPP_H
/* power-source */ /* power-source */
/* Digital Input/Output: level [PM8058] */
#define PM8058_MPP_VPH 0
#define PM8058_MPP_S3 1
#define PM8058_MPP_L2 2
#define PM8058_MPP_L3 3
/* Digital Input/Output: level [PM8901] */
#define PM8901_MPP_MSMIO 0
#define PM8901_MPP_DIG 1
#define PM8901_MPP_L5 2
#define PM8901_MPP_S4 3
#define PM8901_MPP_VPH 4
/* Digital Input/Output: level [PM8921] */
#define PM8921_MPP_S4 1
#define PM8921_MPP_L15 3
#define PM8921_MPP_L17 4
#define PM8921_MPP_VPH 7
/* Digital Input/Output: level [PM8821] */
#define PM8821_MPP_1P8 0
#define PM8821_MPP_VPH 7
/* Digital Input/Output: level [PM8018] */
#define PM8018_MPP_L4 0
#define PM8018_MPP_L14 1
#define PM8018_MPP_S3 2
#define PM8018_MPP_L6 3
#define PM8018_MPP_L2 4
#define PM8018_MPP_L5 5
#define PM8018_MPP_VPH 7
/* Digital Input/Output: level [PM8038] */
#define PM8038_MPP_L20 0
#define PM8038_MPP_L11 1
#define PM8038_MPP_L5 2
#define PM8038_MPP_L15 3
#define PM8038_MPP_L17 4
#define PM8038_MPP_VPH 7
#define PM8841_MPP_VPH 0 #define PM8841_MPP_VPH 0
#define PM8841_MPP_S3 2 #define PM8841_MPP_S3 2
@ -37,6 +78,16 @@
#define PMIC_MPP_AMUX_ROUTE_ABUS3 6 #define PMIC_MPP_AMUX_ROUTE_ABUS3 6
#define PMIC_MPP_AMUX_ROUTE_ABUS4 7 #define PMIC_MPP_AMUX_ROUTE_ABUS4 7
/* Analog Output: level */
#define PMIC_MPP_AOUT_LVL_1V25 0
#define PMIC_MPP_AOUT_LVL_1V25_2 1
#define PMIC_MPP_AOUT_LVL_0V625 2
#define PMIC_MPP_AOUT_LVL_0V3125 3
#define PMIC_MPP_AOUT_LVL_MPP 4
#define PMIC_MPP_AOUT_LVL_ABUS1 5
#define PMIC_MPP_AOUT_LVL_ABUS2 6
#define PMIC_MPP_AOUT_LVL_ABUS3 7
/* To be used with "function" */ /* To be used with "function" */
#define PMIC_MPP_FUNC_NORMAL "normal" #define PMIC_MPP_FUNC_NORMAL "normal"
#define PMIC_MPP_FUNC_PAIRED "paired" #define PMIC_MPP_FUNC_PAIRED "paired"