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:
commit
88a99886c2
4
CREDITS
4
CREDITS
|
@ -20,6 +20,10 @@ D: One of assisting postmasters for vger.kernel.org's lists
|
|||
S: (ask for current address)
|
||||
S: Finland
|
||||
|
||||
N: Thomas Abraham
|
||||
E: thomas.ab@samsung.com
|
||||
D: Samsung pin controller driver
|
||||
|
||||
N: Dragos Acostachioaie
|
||||
E: dragos@iname.com
|
||||
W: http://www.arbornet.org/~dragos
|
||||
|
|
|
@ -48,7 +48,7 @@ Optional subnode-properties:
|
|||
|
||||
Examples:
|
||||
|
||||
pinctrl@01c20800 {
|
||||
pio: pinctrl@01c20800 {
|
||||
compatible = "allwinner,sun5i-a13-pinctrl";
|
||||
reg = <0x01c20800 0x400>;
|
||||
#address-cells = <1>;
|
||||
|
@ -68,3 +68,38 @@ pinctrl@01c20800 {
|
|||
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>;
|
||||
};
|
||||
|
|
|
@ -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.
|
|
@ -7,8 +7,13 @@ of PMIC's from Qualcomm.
|
|||
Usage: required
|
||||
Value type: <string>
|
||||
Definition: Should contain one of:
|
||||
"qcom,pm8018-mpp",
|
||||
"qcom,pm8038-mpp",
|
||||
"qcom,pm8821-mpp",
|
||||
"qcom,pm8841-mpp",
|
||||
"qcom,pm8916-mpp",
|
||||
"qcom,pm8917-mpp",
|
||||
"qcom,pm8921-mpp",
|
||||
"qcom,pm8941-mpp",
|
||||
"qcom,pma8084-mpp",
|
||||
|
||||
|
@ -77,12 +82,9 @@ to specify in a pin configuration subnode:
|
|||
Value type: <string>
|
||||
Definition: Specify the alternative function to be configured for the
|
||||
specified pins. Valid values are:
|
||||
"normal",
|
||||
"paired",
|
||||
"dtest1",
|
||||
"dtest2",
|
||||
"dtest3",
|
||||
"dtest4"
|
||||
"digital",
|
||||
"analog",
|
||||
"sink"
|
||||
|
||||
- bias-disable:
|
||||
Usage: optional
|
||||
|
@ -127,12 +129,18 @@ to specify in a pin configuration subnode:
|
|||
Definition: Selects the power source for the specified pins. Valid power
|
||||
sources are defined in <dt-bindings/pinctrl/qcom,pmic-mpp.h>
|
||||
|
||||
- qcom,analog-mode:
|
||||
- qcom,analog-level:
|
||||
Usage: optional
|
||||
Value type: <none>
|
||||
Definition: Selects Analog mode of operation: combined with input-enable
|
||||
and/or output-high, output-low MPP could operate as
|
||||
Bidirectional Logic, Analog Input, Analog Output.
|
||||
Value type: <u32>
|
||||
Definition: Selects the source for analog output. Valued values are
|
||||
defined in <dt-binding/pinctrl/qcom,pmic-mpp.h>
|
||||
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:
|
||||
Usage: optional
|
||||
|
@ -140,6 +148,10 @@ to specify in a pin configuration subnode:
|
|||
Definition: Selects the source for analog input. Valid values are
|
||||
defined in <dt-bindings/pinctrl/qcom,pmic-mpp.h>
|
||||
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:
|
||||
|
||||
|
@ -156,7 +168,7 @@ Example:
|
|||
pm8841_default: default {
|
||||
gpio {
|
||||
pins = "mpp1", "mpp2", "mpp3", "mpp4";
|
||||
function = "normal";
|
||||
function = "digital";
|
||||
input-enable;
|
||||
power-source = <PM8841_MPP_S3>;
|
||||
};
|
||||
|
|
|
@ -58,12 +58,12 @@ are parsed through phandles and processed purely based on their content.
|
|||
|
||||
Pin Configuration Node Properties:
|
||||
|
||||
- renesas,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
|
||||
- pins : 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.
|
||||
|
||||
- renesas,function: A string containing the name of the function to mux to the
|
||||
pin group(s) specified by the renesas,groups property
|
||||
- function: A string containing the name of the function to mux to the pin
|
||||
group(s) specified by the groups property.
|
||||
|
||||
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
|
||||
|
@ -71,7 +71,9 @@ Pin Configuration Node Properties:
|
|||
|
||||
The pin configuration parameters use the generic pinconf bindings defined in
|
||||
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
|
||||
|
@ -141,19 +143,19 @@ Example 3: KZM-A9-GT (SH-Mobile AG5) default pin state hog and pin control maps
|
|||
|
||||
mmcif_pins: mmcif {
|
||||
mux {
|
||||
renesas,groups = "mmc0_data8_0", "mmc0_ctrl_0";
|
||||
renesas,function = "mmc0";
|
||||
groups = "mmc0_data8_0", "mmc0_ctrl_0";
|
||||
function = "mmc0";
|
||||
};
|
||||
cfg {
|
||||
renesas,groups = "mmc0_data8_0";
|
||||
renesas,pins = "PORT279";
|
||||
groups = "mmc0_data8_0";
|
||||
pins = "PORT279";
|
||||
bias-pull-up;
|
||||
};
|
||||
};
|
||||
|
||||
scifa4_pins: scifa4 {
|
||||
renesas,groups = "scifa4_data", "scifa4_ctrl";
|
||||
renesas,function = "scifa4";
|
||||
groups = "scifa4_data", "scifa4_ctrl";
|
||||
function = "scifa4";
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -3,7 +3,9 @@ ST Ericsson Nomadik pinmux controller
|
|||
Required properties:
|
||||
- compatible: "stericsson,db8500-pinctrl", "stericsson,db8540-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
|
||||
common pinctrl bindings used by client devices, including the meaning of the
|
||||
|
@ -74,7 +76,8 @@ Example board file extract:
|
|||
|
||||
pinctrl@80157000 {
|
||||
compatible = "stericsson,db8500-pinctrl";
|
||||
reg = <0x80157000 0x2000>;
|
||||
nomadik-gpio-chips = <&gpio0>, <&gpio1>, <&gpio2>, <&gpio3>;
|
||||
prcm = <&prcmu>;
|
||||
|
||||
pinctrl-names = "default";
|
||||
|
||||
|
|
|
@ -8045,7 +8045,6 @@ F: drivers/pinctrl/sh-pfc/
|
|||
|
||||
PIN CONTROLLER - SAMSUNG
|
||||
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-samsung-soc@vger.kernel.org (moderated for non-subscribers)
|
||||
S: Maintained
|
||||
|
|
|
@ -294,7 +294,7 @@
|
|||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
gpio-bank = <0>;
|
||||
|
||||
gpio-ranges = <&pinctrl 0 0 32>;
|
||||
clocks = <&prcc_pclk 1 9>;
|
||||
};
|
||||
|
||||
|
@ -309,7 +309,7 @@
|
|||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
gpio-bank = <1>;
|
||||
|
||||
gpio-ranges = <&pinctrl 0 32 5>;
|
||||
clocks = <&prcc_pclk 1 9>;
|
||||
};
|
||||
|
||||
|
@ -324,7 +324,7 @@
|
|||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
gpio-bank = <2>;
|
||||
|
||||
gpio-ranges = <&pinctrl 0 64 32>;
|
||||
clocks = <&prcc_pclk 3 8>;
|
||||
};
|
||||
|
||||
|
@ -339,7 +339,7 @@
|
|||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
gpio-bank = <3>;
|
||||
|
||||
gpio-ranges = <&pinctrl 0 96 2>;
|
||||
clocks = <&prcc_pclk 3 8>;
|
||||
};
|
||||
|
||||
|
@ -354,7 +354,7 @@
|
|||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
gpio-bank = <4>;
|
||||
|
||||
gpio-ranges = <&pinctrl 0 128 32>;
|
||||
clocks = <&prcc_pclk 3 8>;
|
||||
};
|
||||
|
||||
|
@ -369,7 +369,7 @@
|
|||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
gpio-bank = <5>;
|
||||
|
||||
gpio-ranges = <&pinctrl 0 160 12>;
|
||||
clocks = <&prcc_pclk 3 8>;
|
||||
};
|
||||
|
||||
|
@ -384,7 +384,7 @@
|
|||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
gpio-bank = <6>;
|
||||
|
||||
gpio-ranges = <&pinctrl 0 192 32>;
|
||||
clocks = <&prcc_pclk 2 11>;
|
||||
};
|
||||
|
||||
|
@ -399,7 +399,7 @@
|
|||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
gpio-bank = <7>;
|
||||
|
||||
gpio-ranges = <&pinctrl 0 224 7>;
|
||||
clocks = <&prcc_pclk 2 11>;
|
||||
};
|
||||
|
||||
|
@ -414,12 +414,15 @@
|
|||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
gpio-bank = <8>;
|
||||
|
||||
gpio-ranges = <&pinctrl 0 256 12>;
|
||||
clocks = <&prcc_pclk 5 1>;
|
||||
};
|
||||
|
||||
pinctrl {
|
||||
pinctrl: pinctrl {
|
||||
compatible = "stericsson,db8500-pinctrl";
|
||||
nomadik-gpio-chips = <&gpio0>, <&gpio1>, <&gpio2>, <&gpio3>,
|
||||
<&gpio4>, <&gpio5>, <&gpio6>, <&gpio7>,
|
||||
<&gpio8>;
|
||||
prcm = <&prcmu>;
|
||||
};
|
||||
|
||||
|
|
|
@ -59,6 +59,7 @@
|
|||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
gpio-bank = <0>;
|
||||
gpio-ranges = <&pinctrl 0 0 32>;
|
||||
clocks = <&pclk>;
|
||||
};
|
||||
|
||||
|
@ -72,6 +73,7 @@
|
|||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
gpio-bank = <1>;
|
||||
gpio-ranges = <&pinctrl 0 32 32>;
|
||||
clocks = <&pclk>;
|
||||
};
|
||||
|
||||
|
@ -85,12 +87,14 @@
|
|||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
gpio-bank = <2>;
|
||||
gpio-ranges = <&pinctrl 0 64 32>;
|
||||
clocks = <&pclk>;
|
||||
};
|
||||
|
||||
gpio3: gpio@101e7000 {
|
||||
compatible = "st,nomadik-gpio";
|
||||
reg = <0x101e7000 0x80>;
|
||||
ngpio = <28>;
|
||||
interrupt-parent = <&vica>;
|
||||
interrupts = <9>;
|
||||
interrupt-controller;
|
||||
|
@ -98,11 +102,13 @@
|
|||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
gpio-bank = <3>;
|
||||
gpio-ranges = <&pinctrl 0 96 28>;
|
||||
clocks = <&pclk>;
|
||||
};
|
||||
|
||||
pinctrl {
|
||||
pinctrl: pinctrl {
|
||||
compatible = "stericsson,stn8815-pinctrl";
|
||||
nomadik-gpio-chips = <&gpio0>, <&gpio1>, <&gpio2>, <&gpio3>;
|
||||
/* Pin configurations */
|
||||
uart1 {
|
||||
uart1_default_mux: uart1_mux {
|
||||
|
|
|
@ -11,7 +11,7 @@ obj-y += bus/
|
|||
obj-$(CONFIG_GENERIC_PHY) += phy/
|
||||
|
||||
# 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 += pwm/
|
||||
obj-$(CONFIG_PCI) += pci/
|
||||
|
|
|
@ -780,6 +780,7 @@ static const char *const rk3288_critical_clocks[] __initconst = {
|
|||
"aclk_cpu",
|
||||
"aclk_peri",
|
||||
"hclk_peri",
|
||||
"pclk_pd_pmu",
|
||||
};
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
|
|
|
@ -82,6 +82,12 @@ config PINCTRL_AMD
|
|||
Requires ACPI/FDT device enumeration code to set up a platform
|
||||
device.
|
||||
|
||||
config PINCTRL_DIGICOLOR
|
||||
bool
|
||||
depends on OF && (ARCH_DIGICOLOR || COMPILE_TEST)
|
||||
select PINMUX
|
||||
select GENERIC_PINCONF
|
||||
|
||||
config PINCTRL_LANTIQ
|
||||
bool
|
||||
depends on LANTIQ
|
||||
|
@ -240,6 +246,7 @@ source "drivers/pinctrl/samsung/Kconfig"
|
|||
source "drivers/pinctrl/sh-pfc/Kconfig"
|
||||
source "drivers/pinctrl/spear/Kconfig"
|
||||
source "drivers/pinctrl/sunxi/Kconfig"
|
||||
source "drivers/pinctrl/uniphier/Kconfig"
|
||||
source "drivers/pinctrl/vt8500/Kconfig"
|
||||
source "drivers/pinctrl/mediatek/Kconfig"
|
||||
|
||||
|
|
|
@ -2,12 +2,10 @@
|
|||
|
||||
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_PINCONF) += pinconf.o
|
||||
ifeq ($(CONFIG_OF),y)
|
||||
obj-$(CONFIG_PINCTRL) += devicetree.o
|
||||
endif
|
||||
obj-$(CONFIG_OF) += devicetree.o
|
||||
obj-$(CONFIG_GENERIC_PINCONF) += pinconf-generic.o
|
||||
obj-$(CONFIG_PINCTRL_ADI2) += pinctrl-adi2.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_AT91) += pinctrl-at91.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_MESON) += meson/
|
||||
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_PLAT_SPEAR) += spear/
|
||||
obj-$(CONFIG_ARCH_SUNXI) += sunxi/
|
||||
obj-$(CONFIG_ARCH_UNIPHIER) += uniphier/
|
||||
obj-$(CONFIG_ARCH_VT8500) += vt8500/
|
||||
obj-$(CONFIG_ARCH_MEDIATEK) += mediatek/
|
||||
|
|
|
@ -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);
|
||||
|
||||
if (type & IRQ_TYPE_EDGE_BOTH)
|
||||
__irq_set_handler_locked(data->irq, handle_edge_irq);
|
||||
irq_set_handler_locked(data, handle_edge_irq);
|
||||
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);
|
||||
|
||||
|
@ -989,7 +989,6 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev)
|
|||
irq_set_chip_and_handler(irq, &bcm2835_gpio_irq_chip,
|
||||
handle_level_irq);
|
||||
irq_set_chip_data(irq, pc);
|
||||
set_irq_flags(irq, IRQF_VALID);
|
||||
}
|
||||
|
||||
for (i = 0; i < BCM2835_NUM_BANKS; i++) {
|
||||
|
|
|
@ -231,8 +231,7 @@ static int pinctrl_register_one_pin(struct pinctrl_dev *pctldev,
|
|||
|
||||
pindesc = pin_desc_get(pctldev, number);
|
||||
if (pindesc != NULL) {
|
||||
pr_err("pin %d already registered on %s\n", number,
|
||||
pctldev->desc->name);
|
||||
dev_err(pctldev->dev, "pin %d already registered\n", number);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 *pctldev;
|
||||
|
||||
pctldev = get_pinctrl_dev_from_of_node(np);
|
||||
if (!pctldev)
|
||||
return NULL;
|
||||
|
||||
return pctldev;
|
||||
return get_pinctrl_dev_from_of_node(np);
|
||||
}
|
||||
|
||||
static int dt_to_map_one_config(struct pinctrl *p, const char *statename,
|
||||
|
|
|
@ -87,6 +87,13 @@ config PINCTRL_IMX6SX
|
|||
help
|
||||
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
|
||||
bool "IMX7D pinctrl driver"
|
||||
depends on SOC_IMX7D
|
||||
|
|
|
@ -12,6 +12,7 @@ obj-$(CONFIG_PINCTRL_IMX6Q) += pinctrl-imx6q.o
|
|||
obj-$(CONFIG_PINCTRL_IMX6Q) += pinctrl-imx6dl.o
|
||||
obj-$(CONFIG_PINCTRL_IMX6SL) += pinctrl-imx6sl.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_VF610) += pinctrl-vf610.o
|
||||
obj-$(CONFIG_PINCTRL_MXS) += pinctrl-mxs.o
|
||||
|
|
|
@ -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");
|
|
@ -12,11 +12,6 @@
|
|||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* 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>
|
||||
|
@ -146,7 +141,7 @@ struct byt_gpio_pin_context {
|
|||
struct byt_gpio {
|
||||
struct gpio_chip chip;
|
||||
struct platform_device *pdev;
|
||||
spinlock_t lock;
|
||||
raw_spinlock_t lock;
|
||||
void __iomem *reg_base;
|
||||
struct pinctrl_gpio_range *range;
|
||||
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;
|
||||
u32 value;
|
||||
|
||||
spin_lock_irqsave(&vg->lock, flags);
|
||||
raw_spin_lock_irqsave(&vg->lock, flags);
|
||||
value = readl(reg);
|
||||
value &= ~(BYT_TRIG_POS | BYT_TRIG_NEG | BYT_TRIG_LVL);
|
||||
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)
|
||||
|
@ -201,6 +196,9 @@ static int byt_gpio_request(struct gpio_chip *chip, unsigned offset)
|
|||
struct byt_gpio *vg = to_byt_gpio(chip);
|
||||
void __iomem *reg = byt_gpio_reg(chip, offset, BYT_CONF0_REG);
|
||||
u32 value, gpio_mux;
|
||||
unsigned long flags;
|
||||
|
||||
raw_spin_lock_irqsave(&vg->lock, flags);
|
||||
|
||||
/*
|
||||
* 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;
|
||||
gpio_mux = byt_get_gpio_mux(vg, offset);
|
||||
if (WARN_ON(gpio_mux != value)) {
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&vg->lock, flags);
|
||||
value = readl(reg) & ~BYT_PIN_MUX;
|
||||
value |= gpio_mux;
|
||||
writel(value, reg);
|
||||
spin_unlock_irqrestore(&vg->lock, flags);
|
||||
|
||||
dev_warn(&vg->pdev->dev,
|
||||
"pin %u forcibly re-configured as GPIO\n", offset);
|
||||
}
|
||||
|
||||
raw_spin_unlock_irqrestore(&vg->lock, flags);
|
||||
|
||||
pm_runtime_get(&vg->pdev->dev);
|
||||
|
||||
return 0;
|
||||
|
@ -250,7 +246,7 @@ static int byt_irq_type(struct irq_data *d, unsigned type)
|
|||
if (offset >= vg->chip.ngpio)
|
||||
return -EINVAL;
|
||||
|
||||
spin_lock_irqsave(&vg->lock, flags);
|
||||
raw_spin_lock_irqsave(&vg->lock, flags);
|
||||
value = readl(reg);
|
||||
|
||||
WARN(value & BYT_DIRECT_IRQ_EN,
|
||||
|
@ -265,11 +261,11 @@ static int byt_irq_type(struct irq_data *d, unsigned type)
|
|||
writel(value, reg);
|
||||
|
||||
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)
|
||||
__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;
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
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)
|
||||
|
@ -287,7 +291,7 @@ static void byt_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
|
|||
unsigned long flags;
|
||||
u32 old_val;
|
||||
|
||||
spin_lock_irqsave(&vg->lock, flags);
|
||||
raw_spin_lock_irqsave(&vg->lock, flags);
|
||||
|
||||
old_val = readl(reg);
|
||||
|
||||
|
@ -296,7 +300,7 @@ static void byt_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
|
|||
else
|
||||
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)
|
||||
|
@ -306,13 +310,13 @@ static int byt_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
|
|||
unsigned long flags;
|
||||
u32 value;
|
||||
|
||||
spin_lock_irqsave(&vg->lock, flags);
|
||||
raw_spin_lock_irqsave(&vg->lock, flags);
|
||||
|
||||
value = readl(reg) | BYT_DIR_MASK;
|
||||
value &= ~BYT_INPUT_EN; /* active low */
|
||||
writel(value, reg);
|
||||
|
||||
spin_unlock_irqrestore(&vg->lock, flags);
|
||||
raw_spin_unlock_irqrestore(&vg->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -326,7 +330,7 @@ static int byt_gpio_direction_output(struct gpio_chip *chip,
|
|||
unsigned long flags;
|
||||
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
|
||||
|
@ -345,7 +349,7 @@ static int byt_gpio_direction_output(struct gpio_chip *chip,
|
|||
else
|
||||
writel(reg_val & ~BYT_LEVEL, reg);
|
||||
|
||||
spin_unlock_irqrestore(&vg->lock, flags);
|
||||
raw_spin_unlock_irqrestore(&vg->lock, flags);
|
||||
|
||||
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);
|
||||
int i;
|
||||
unsigned long flags;
|
||||
u32 conf0, val, offs;
|
||||
|
||||
spin_lock_irqsave(&vg->lock, flags);
|
||||
|
||||
for (i = 0; i < vg->chip.ngpio; i++) {
|
||||
const char *pull_str = NULL;
|
||||
const char *pull = NULL;
|
||||
unsigned long flags;
|
||||
const char *label;
|
||||
offs = vg->range->pins[i] * 16;
|
||||
|
||||
raw_spin_lock_irqsave(&vg->lock, flags);
|
||||
conf0 = readl(vg->reg_base + offs + BYT_CONF0_REG);
|
||||
val = readl(vg->reg_base + offs + BYT_VAL_REG);
|
||||
raw_spin_unlock_irqrestore(&vg->lock, flags);
|
||||
|
||||
label = gpiochip_is_requested(chip, i);
|
||||
if (!label)
|
||||
|
@ -418,7 +423,6 @@ static void byt_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
|
|||
|
||||
seq_puts(s, "\n");
|
||||
}
|
||||
spin_unlock_irqrestore(&vg->lock, flags);
|
||||
}
|
||||
|
||||
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);
|
||||
void __iomem *reg;
|
||||
|
||||
raw_spin_lock(&vg->lock);
|
||||
reg = byt_gpio_reg(&vg->chip, offset, BYT_INT_STAT_REG);
|
||||
writel(BIT(offset % 32), reg);
|
||||
raw_spin_unlock(&vg->lock);
|
||||
}
|
||||
|
||||
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;
|
||||
u32 value;
|
||||
|
||||
spin_lock_irqsave(&vg->lock, flags);
|
||||
|
||||
reg = byt_gpio_reg(&vg->chip, offset, BYT_CONF0_REG);
|
||||
|
||||
raw_spin_lock_irqsave(&vg->lock, flags);
|
||||
value = readl(reg);
|
||||
|
||||
switch (irqd_get_trigger_type(d)) {
|
||||
|
@ -486,7 +492,7 @@ static void byt_irq_unmask(struct irq_data *d)
|
|||
|
||||
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)
|
||||
|
@ -578,7 +584,7 @@ static int byt_gpio_probe(struct platform_device *pdev)
|
|||
if (IS_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->label = dev_name(&pdev->dev);
|
||||
|
|
|
@ -174,7 +174,7 @@ struct chv_pinctrl {
|
|||
struct pinctrl_dev *pctldev;
|
||||
struct gpio_chip chip;
|
||||
void __iomem *regs;
|
||||
spinlock_t lock;
|
||||
raw_spinlock_t lock;
|
||||
unsigned intr_lines[16];
|
||||
const struct chv_community *community;
|
||||
u32 saved_intmask;
|
||||
|
@ -720,13 +720,13 @@ static void chv_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
|
|||
u32 ctrl0, ctrl1;
|
||||
bool locked;
|
||||
|
||||
spin_lock_irqsave(&pctrl->lock, flags);
|
||||
raw_spin_lock_irqsave(&pctrl->lock, flags);
|
||||
|
||||
ctrl0 = readl(chv_padreg(pctrl, offset, CHV_PADCTRL0));
|
||||
ctrl1 = readl(chv_padreg(pctrl, offset, CHV_PADCTRL1));
|
||||
locked = chv_pad_locked(pctrl, offset);
|
||||
|
||||
spin_unlock_irqrestore(&pctrl->lock, flags);
|
||||
raw_spin_unlock_irqrestore(&pctrl->lock, flags);
|
||||
|
||||
if (ctrl0 & CHV_PADCTRL0_GPIOEN) {
|
||||
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];
|
||||
|
||||
spin_lock_irqsave(&pctrl->lock, flags);
|
||||
raw_spin_lock_irqsave(&pctrl->lock, flags);
|
||||
|
||||
/* Check first that the pad is not locked */
|
||||
for (i = 0; i < grp->npins; i++) {
|
||||
if (chv_pad_locked(pctrl, grp->pins[i])) {
|
||||
dev_warn(pctrl->dev, "unable to set mode for locked pin %u\n",
|
||||
grp->pins[i]);
|
||||
spin_unlock_irqrestore(&pctrl->lock, flags);
|
||||
raw_spin_unlock_irqrestore(&pctrl->lock, flags);
|
||||
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 ");
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&pctrl->lock, flags);
|
||||
raw_spin_unlock_irqrestore(&pctrl->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -853,13 +853,13 @@ static int chv_gpio_request_enable(struct pinctrl_dev *pctldev,
|
|||
void __iomem *reg;
|
||||
u32 value;
|
||||
|
||||
spin_lock_irqsave(&pctrl->lock, flags);
|
||||
raw_spin_lock_irqsave(&pctrl->lock, flags);
|
||||
|
||||
if (chv_pad_locked(pctrl, offset)) {
|
||||
value = readl(chv_padreg(pctrl, offset, CHV_PADCTRL0));
|
||||
if (!(value & CHV_PADCTRL0_GPIOEN)) {
|
||||
/* Locked so cannot enable */
|
||||
spin_unlock_irqrestore(&pctrl->lock, flags);
|
||||
raw_spin_unlock_irqrestore(&pctrl->lock, flags);
|
||||
return -EBUSY;
|
||||
}
|
||||
} else {
|
||||
|
@ -899,7 +899,7 @@ static int chv_gpio_request_enable(struct pinctrl_dev *pctldev,
|
|||
chv_writel(value, reg);
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&pctrl->lock, flags);
|
||||
raw_spin_unlock_irqrestore(&pctrl->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -913,13 +913,13 @@ static void chv_gpio_disable_free(struct pinctrl_dev *pctldev,
|
|||
void __iomem *reg;
|
||||
u32 value;
|
||||
|
||||
spin_lock_irqsave(&pctrl->lock, flags);
|
||||
raw_spin_lock_irqsave(&pctrl->lock, flags);
|
||||
|
||||
reg = chv_padreg(pctrl, offset, CHV_PADCTRL0);
|
||||
value = readl(reg) & ~CHV_PADCTRL0_GPIOEN;
|
||||
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,
|
||||
|
@ -931,7 +931,7 @@ static int chv_gpio_set_direction(struct pinctrl_dev *pctldev,
|
|||
unsigned long flags;
|
||||
u32 ctrl0;
|
||||
|
||||
spin_lock_irqsave(&pctrl->lock, flags);
|
||||
raw_spin_lock_irqsave(&pctrl->lock, flags);
|
||||
|
||||
ctrl0 = readl(reg) & ~CHV_PADCTRL0_GPIOCFG_MASK;
|
||||
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;
|
||||
chv_writel(ctrl0, reg);
|
||||
|
||||
spin_unlock_irqrestore(&pctrl->lock, flags);
|
||||
raw_spin_unlock_irqrestore(&pctrl->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -965,10 +965,10 @@ static int chv_config_get(struct pinctrl_dev *pctldev, unsigned pin,
|
|||
u16 arg = 0;
|
||||
u32 term;
|
||||
|
||||
spin_lock_irqsave(&pctrl->lock, flags);
|
||||
raw_spin_lock_irqsave(&pctrl->lock, flags);
|
||||
ctrl0 = readl(chv_padreg(pctrl, pin, CHV_PADCTRL0));
|
||||
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;
|
||||
|
||||
|
@ -1042,7 +1042,7 @@ static int chv_config_set_pull(struct chv_pinctrl *pctrl, unsigned pin,
|
|||
unsigned long flags;
|
||||
u32 ctrl0, pull;
|
||||
|
||||
spin_lock_irqsave(&pctrl->lock, flags);
|
||||
raw_spin_lock_irqsave(&pctrl->lock, flags);
|
||||
ctrl0 = readl(reg);
|
||||
|
||||
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;
|
||||
break;
|
||||
default:
|
||||
spin_unlock_irqrestore(&pctrl->lock, flags);
|
||||
raw_spin_unlock_irqrestore(&pctrl->lock, flags);
|
||||
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;
|
||||
break;
|
||||
default:
|
||||
spin_unlock_irqrestore(&pctrl->lock, flags);
|
||||
raw_spin_unlock_irqrestore(&pctrl->lock, flags);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -1091,12 +1091,12 @@ static int chv_config_set_pull(struct chv_pinctrl *pctrl, unsigned pin,
|
|||
break;
|
||||
|
||||
default:
|
||||
spin_unlock_irqrestore(&pctrl->lock, flags);
|
||||
raw_spin_unlock_irqrestore(&pctrl->lock, flags);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
chv_writel(ctrl0, reg);
|
||||
spin_unlock_irqrestore(&pctrl->lock, flags);
|
||||
raw_spin_unlock_irqrestore(&pctrl->lock, flags);
|
||||
|
||||
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);
|
||||
int pin = chv_gpio_offset_to_pin(pctrl, offset);
|
||||
unsigned long flags;
|
||||
u32 ctrl0, cfg;
|
||||
|
||||
raw_spin_lock_irqsave(&pctrl->lock, flags);
|
||||
ctrl0 = readl(chv_padreg(pctrl, pin, CHV_PADCTRL0));
|
||||
raw_spin_unlock_irqrestore(&pctrl->lock, flags);
|
||||
|
||||
cfg = ctrl0 & CHV_PADCTRL0_GPIOCFG_MASK;
|
||||
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;
|
||||
u32 ctrl0;
|
||||
|
||||
spin_lock_irqsave(&pctrl->lock, flags);
|
||||
raw_spin_lock_irqsave(&pctrl->lock, flags);
|
||||
|
||||
reg = chv_padreg(pctrl, pin, CHV_PADCTRL0);
|
||||
ctrl0 = readl(reg);
|
||||
|
@ -1201,7 +1204,7 @@ static void chv_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
|
|||
|
||||
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)
|
||||
|
@ -1209,8 +1212,11 @@ static int chv_gpio_get_direction(struct gpio_chip *chip, unsigned offset)
|
|||
struct chv_pinctrl *pctrl = gpiochip_to_pinctrl(chip);
|
||||
unsigned pin = chv_gpio_offset_to_pin(pctrl, offset);
|
||||
u32 ctrl0, direction;
|
||||
unsigned long flags;
|
||||
|
||||
raw_spin_lock_irqsave(&pctrl->lock, flags);
|
||||
ctrl0 = readl(chv_padreg(pctrl, pin, CHV_PADCTRL0));
|
||||
raw_spin_unlock_irqrestore(&pctrl->lock, flags);
|
||||
|
||||
direction = ctrl0 & CHV_PADCTRL0_GPIOCFG_MASK;
|
||||
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));
|
||||
u32 intr_line;
|
||||
|
||||
spin_lock(&pctrl->lock);
|
||||
raw_spin_lock(&pctrl->lock);
|
||||
|
||||
intr_line = readl(chv_padreg(pctrl, pin, CHV_PADCTRL0));
|
||||
intr_line &= CHV_PADCTRL0_INTSEL_MASK;
|
||||
intr_line >>= CHV_PADCTRL0_INTSEL_SHIFT;
|
||||
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)
|
||||
|
@ -1266,7 +1272,7 @@ static void chv_gpio_irq_mask_unmask(struct irq_data *d, bool mask)
|
|||
u32 value, intr_line;
|
||||
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 &= 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);
|
||||
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)
|
||||
|
@ -1313,6 +1319,7 @@ static unsigned chv_gpio_irq_startup(struct irq_data *d)
|
|||
unsigned long flags;
|
||||
u32 intsel, value;
|
||||
|
||||
raw_spin_lock_irqsave(&pctrl->lock, flags);
|
||||
intsel = readl(chv_padreg(pctrl, pin, CHV_PADCTRL0));
|
||||
intsel &= CHV_PADCTRL0_INTSEL_MASK;
|
||||
intsel >>= CHV_PADCTRL0_INTSEL_SHIFT;
|
||||
|
@ -1323,12 +1330,11 @@ static unsigned chv_gpio_irq_startup(struct irq_data *d)
|
|||
else
|
||||
handler = handle_edge_irq;
|
||||
|
||||
spin_lock_irqsave(&pctrl->lock, flags);
|
||||
if (!pctrl->intr_lines[intsel]) {
|
||||
__irq_set_handler_locked(d->irq, handler);
|
||||
irq_set_handler_locked(d, handler);
|
||||
pctrl->intr_lines[intsel] = offset;
|
||||
}
|
||||
spin_unlock_irqrestore(&pctrl->lock, flags);
|
||||
raw_spin_unlock_irqrestore(&pctrl->lock, flags);
|
||||
}
|
||||
|
||||
chv_gpio_irq_unmask(d);
|
||||
|
@ -1344,7 +1350,7 @@ static int chv_gpio_irq_type(struct irq_data *d, unsigned type)
|
|||
unsigned long flags;
|
||||
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
|
||||
|
@ -1389,11 +1395,11 @@ static int chv_gpio_irq_type(struct irq_data *d, unsigned type)
|
|||
pctrl->intr_lines[value] = offset;
|
||||
|
||||
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)
|
||||
__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;
|
||||
}
|
||||
|
@ -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 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;
|
||||
u32 intr_line;
|
||||
|
||||
|
@ -1505,7 +1511,7 @@ static int chv_pinctrl_probe(struct platform_device *pdev)
|
|||
if (i == ARRAY_SIZE(chv_communities))
|
||||
return -ENODEV;
|
||||
|
||||
spin_lock_init(&pctrl->lock);
|
||||
raw_spin_lock_init(&pctrl->lock);
|
||||
pctrl->dev = &pdev->dev;
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
|
|
|
@ -758,9 +758,9 @@ static int intel_gpio_irq_type(struct irq_data *d, unsigned type)
|
|||
writel(value, reg);
|
||||
|
||||
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)
|
||||
__irq_set_handler_locked(d->irq, handle_level_irq);
|
||||
irq_set_handler_locked(d, handle_level_irq);
|
||||
|
||||
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 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;
|
||||
|
||||
chained_irq_enter(chip, desc);
|
||||
|
|
|
@ -385,6 +385,7 @@ static struct platform_driver mtk_pinctrl_driver = {
|
|||
.driver = {
|
||||
.name = "mediatek-mt8173-pinctrl",
|
||||
.of_match_table = mt8173_pctrl_match,
|
||||
.pm = &mtk_eint_pm_ops,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include <linux/mfd/syscon.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/pm.h>
|
||||
#include <dt-bindings/pinctrl/mt65xx.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);
|
||||
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);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -1062,6 +1063,77 @@ static int mtk_eint_set_type(struct irq_data *d,
|
|||
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)
|
||||
{
|
||||
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 = {
|
||||
.name = "mt-eint",
|
||||
.irq_disable = mtk_eint_mask,
|
||||
.irq_mask = mtk_eint_mask,
|
||||
.irq_unmask = mtk_eint_unmask,
|
||||
.irq_ack = mtk_eint_ack,
|
||||
.irq_set_type = mtk_eint_set_type,
|
||||
.irq_set_wake = mtk_eint_irq_set_wake,
|
||||
.irq_request_resources = mtk_pinctrl_irq_request_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)
|
||||
{
|
||||
struct irq_chip *chip = irq_get_chip(irq);
|
||||
struct mtk_pinctrl *pctl = irq_get_handler_data(irq);
|
||||
struct irq_chip *chip = irq_desc_get_chip(desc);
|
||||
struct mtk_pinctrl *pctl = irq_desc_get_handler_data(desc);
|
||||
unsigned int status, eint_num;
|
||||
int offset, index, virq;
|
||||
const struct mtk_eint_offsets *eint_offsets =
|
||||
|
@ -1202,12 +1276,6 @@ static int mtk_pctrl_build_state(struct platform_device *pdev)
|
|||
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,
|
||||
const struct mtk_pinctrl_devdata *data,
|
||||
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 property *prop;
|
||||
struct resource *res;
|
||||
int i, ret, irq;
|
||||
int i, ret, irq, ports_buf;
|
||||
|
||||
pctl = devm_kzalloc(&pdev->dev, sizeof(*pctl), GFP_KERNEL);
|
||||
if (!pctl)
|
||||
|
@ -1265,12 +1333,17 @@ int mtk_pctrl_init(struct platform_device *pdev,
|
|||
|
||||
for (i = 0; i < pctl->devdata->npins; i++)
|
||||
pins[i] = pctl->devdata->pins[i].pin;
|
||||
mtk_pctrl_desc.name = dev_name(&pdev->dev);
|
||||
mtk_pctrl_desc.owner = THIS_MODULE;
|
||||
mtk_pctrl_desc.pins = pins;
|
||||
mtk_pctrl_desc.npins = pctl->devdata->npins;
|
||||
|
||||
pctl->pctl_desc.name = dev_name(&pdev->dev);
|
||||
pctl->pctl_desc.owner = THIS_MODULE;
|
||||
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->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)) {
|
||||
dev_err(&pdev->dev, "couldn't register pinctrl driver\n");
|
||||
return PTR_ERR(pctl->pctl_dev);
|
||||
|
@ -1319,6 +1392,21 @@ int mtk_pctrl_init(struct platform_device *pdev,
|
|||
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,
|
||||
sizeof(int), GFP_KERNEL);
|
||||
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,
|
||||
handle_level_irq);
|
||||
irq_set_chip_data(virq, pctl);
|
||||
set_irq_flags(virq, IRQF_VALID);
|
||||
};
|
||||
|
||||
irq_set_chained_handler_and_data(irq, mtk_eint_irq_handler, pctl);
|
||||
set_irq_flags(irq, IRQF_VALID);
|
||||
return 0;
|
||||
|
||||
chip_error:
|
||||
|
|
|
@ -256,6 +256,7 @@ struct mtk_pinctrl_devdata {
|
|||
struct mtk_pinctrl {
|
||||
struct regmap *regmap1;
|
||||
struct regmap *regmap2;
|
||||
struct pinctrl_desc pctl_desc;
|
||||
struct device *dev;
|
||||
struct gpio_chip *chip;
|
||||
struct mtk_pinctrl_group *groups;
|
||||
|
@ -266,6 +267,8 @@ struct mtk_pinctrl {
|
|||
void __iomem *eint_reg_base;
|
||||
struct irq_domain *domain;
|
||||
int *eint_dual_edges;
|
||||
u32 *wake_mask;
|
||||
u32 *cur_mask;
|
||||
};
|
||||
|
||||
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,
|
||||
unsigned int pin, unsigned char align, int value);
|
||||
|
||||
extern const struct dev_pm_ops mtk_eint_pm_ops;
|
||||
|
||||
#endif /* __PINCTRL_MTK_COMMON_H */
|
||||
|
|
|
@ -355,25 +355,6 @@ static const struct pinctrl_pin_desc nmk_db8500_pins[] = {
|
|||
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:
|
||||
* 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 = {
|
||||
.gpio_ranges = nmk_db8500_ranges,
|
||||
.gpio_num_ranges = ARRAY_SIZE(nmk_db8500_ranges),
|
||||
.pins = nmk_db8500_pins,
|
||||
.npins = ARRAY_SIZE(nmk_db8500_pins),
|
||||
.functions = nmk_db8500_functions,
|
||||
|
|
|
@ -341,28 +341,6 @@ static const struct pinctrl_pin_desc nmk_db8540_pins[] = {
|
|||
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:
|
||||
* 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 = {
|
||||
.gpio_ranges = nmk_db8540_ranges,
|
||||
.gpio_num_ranges = ARRAY_SIZE(nmk_db8540_ranges),
|
||||
.pins = nmk_db8540_pins,
|
||||
.npins = ARRAY_SIZE(nmk_db8540_pins),
|
||||
.functions = nmk_db8540_functions,
|
||||
|
|
|
@ -264,20 +264,6 @@ static const struct pinctrl_pin_desc nmk_stn8815_pins[] = {
|
|||
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:
|
||||
* 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 */
|
||||
static const unsigned u0_a_1_pins[] = { STN8815_PIN_B4, STN8815_PIN_D5,
|
||||
STN8815_PIN_C5, STN8815_PIN_A4, STN8815_PIN_B5, STN8815_PIN_D6,
|
||||
STN8815_PIN_C6, STN8815_PIN_B6 };
|
||||
static const unsigned u0txrx_a_1_pins[] = { STN8815_PIN_B4, STN8815_PIN_D5 };
|
||||
static const unsigned u0ctsrts_a_1_pins[] = { STN8815_PIN_C5, 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,
|
||||
STN8815_PIN_C11, STN8815_PIN_B11, STN8815_PIN_A11, STN8815_PIN_C12,
|
||||
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 }
|
||||
|
||||
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_b_1, NMK_GPIO_ALT_B),
|
||||
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...) \
|
||||
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(u1, "u1_a_1", "u1_b_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 = {
|
||||
.gpio_ranges = nmk_stn8815_ranges,
|
||||
.gpio_num_ranges = ARRAY_SIZE(nmk_stn8815_ranges),
|
||||
.pins = nmk_stn8815_pins,
|
||||
.npins = ARRAY_SIZE(nmk_stn8815_pins),
|
||||
.functions = nmk_stn8815_functions,
|
||||
|
|
|
@ -203,6 +203,7 @@ typedef unsigned long pin_cfg_t;
|
|||
|
||||
#define GPIO_BLOCK_SHIFT 5
|
||||
#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 */
|
||||
#define NMK_GPIO_DAT 0x00
|
||||
|
@ -282,8 +283,7 @@ struct nmk_pinctrl {
|
|||
void __iomem *prcm_base;
|
||||
};
|
||||
|
||||
static struct nmk_gpio_chip *
|
||||
nmk_gpio_chips[DIV_ROUND_UP(ARCH_NR_GPIOS, NMK_GPIO_PER_CHIP)];
|
||||
static struct nmk_gpio_chip *nmk_gpio_chips[NMK_MAX_BANKS];
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
static void __nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc,
|
||||
u32 status)
|
||||
static void __nmk_gpio_irq_handler(struct irq_desc *desc, 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);
|
||||
|
||||
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);
|
||||
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,
|
||||
struct irq_desc *desc)
|
||||
static void nmk_gpio_latent_irq_handler(unsigned int irq, struct irq_desc *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);
|
||||
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 */
|
||||
|
@ -1012,6 +1010,7 @@ static void nmk_gpio_dbg_show_one(struct seq_file *s,
|
|||
int irq = gpio_to_irq(gpio);
|
||||
struct irq_desc *desc = irq_to_desc(irq);
|
||||
int pullidx = 0;
|
||||
int val;
|
||||
|
||||
if (pull)
|
||||
pullidx = data_out ? 1 : 2;
|
||||
|
@ -1021,6 +1020,10 @@ static void nmk_gpio_dbg_show_one(struct seq_file *s,
|
|||
label ?: "(none)",
|
||||
pulls[pullidx],
|
||||
(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(),
|
||||
* 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)
|
||||
{
|
||||
struct device_node *np = dev->dev.of_node;
|
||||
struct nmk_gpio_chip *nmk_chip;
|
||||
struct gpio_chip *chip;
|
||||
struct irq_chip *irqchip;
|
||||
struct resource *res;
|
||||
struct clk *clk;
|
||||
int latent_irq;
|
||||
bool supports_sleepmode;
|
||||
void __iomem *base;
|
||||
int irq;
|
||||
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))
|
||||
supports_sleepmode = true;
|
||||
else
|
||||
supports_sleepmode = false;
|
||||
|
||||
if (of_property_read_u32(np, "gpio-bank", &dev->id)) {
|
||||
dev_err(&dev->dev, "gpio-bank property not found\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
/* Correct platform device ID */
|
||||
dev->id = nmk_chip->bank;
|
||||
|
||||
irq = platform_get_irq(dev, 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 */
|
||||
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,
|
||||
* 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->latent_parent_irq = latent_irq;
|
||||
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->dbg_show = nmk_gpio_dbg_show;
|
||||
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;
|
||||
|
||||
irqchip = &nmk_chip->irqchip;
|
||||
|
@ -1253,14 +1296,10 @@ static int nmk_gpio_probe(struct platform_device *dev)
|
|||
clk_disable(nmk_chip->clk);
|
||||
chip->of_node = np;
|
||||
|
||||
ret = gpiochip_add(&nmk_chip->chip);
|
||||
ret = gpiochip_add(chip);
|
||||
if (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);
|
||||
|
||||
/*
|
||||
|
@ -1320,35 +1359,40 @@ static int nmk_get_group_pins(struct pinctrl_dev *pctldev, unsigned selector,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct pinctrl_gpio_range *
|
||||
nmk_match_gpio_range(struct pinctrl_dev *pctldev, unsigned offset)
|
||||
static struct nmk_gpio_chip *find_nmk_gpio_from_pin(unsigned pin)
|
||||
{
|
||||
struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev);
|
||||
int i;
|
||||
struct nmk_gpio_chip *nmk_gpio;
|
||||
|
||||
for (i = 0; i < npct->soc->gpio_num_ranges; i++) {
|
||||
struct pinctrl_gpio_range *range;
|
||||
|
||||
range = &npct->soc->gpio_ranges[i];
|
||||
if (offset >= range->pin_base &&
|
||||
offset <= (range->pin_base + range->npins - 1))
|
||||
return range;
|
||||
for(i = 0; i < NMK_MAX_BANKS; i++) {
|
||||
nmk_gpio = nmk_gpio_chips[i];
|
||||
if (!nmk_gpio)
|
||||
continue;
|
||||
if (pin >= nmk_gpio->chip.base &&
|
||||
pin < nmk_gpio->chip.base + nmk_gpio->chip.ngpio)
|
||||
return nmk_gpio;
|
||||
}
|
||||
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,
|
||||
unsigned offset)
|
||||
{
|
||||
struct pinctrl_gpio_range *range;
|
||||
struct gpio_chip *chip;
|
||||
struct gpio_chip *chip = find_gc_from_pin(offset);
|
||||
|
||||
range = nmk_match_gpio_range(pctldev, offset);
|
||||
if (!range || !range->gc) {
|
||||
if (!chip) {
|
||||
seq_printf(s, "invalid pin offset");
|
||||
return;
|
||||
}
|
||||
chip = range->gc;
|
||||
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++) {
|
||||
struct pinctrl_gpio_range *range;
|
||||
struct nmk_gpio_chip *nmk_chip;
|
||||
struct gpio_chip *chip;
|
||||
unsigned bit;
|
||||
|
||||
range = nmk_match_gpio_range(pctldev, g->pins[i]);
|
||||
if (!range) {
|
||||
nmk_chip = find_nmk_gpio_from_pin(g->pins[i]);
|
||||
if (!nmk_chip) {
|
||||
dev_err(npct->dev,
|
||||
"invalid pin offset %d in group %s at index %d\n",
|
||||
g->pins[i], g->name, i);
|
||||
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);
|
||||
|
||||
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_gpio_chip *nmk_chip;
|
||||
struct pinctrl_gpio_range *range;
|
||||
struct gpio_chip *chip;
|
||||
unsigned bit;
|
||||
pin_cfg_t cfg;
|
||||
int pull, slpm, output, val, i;
|
||||
bool lowemi, gpiomode, sleep;
|
||||
|
||||
range = nmk_match_gpio_range(pctldev, pin);
|
||||
if (!range) {
|
||||
dev_err(npct->dev, "invalid pin offset %d\n", pin);
|
||||
nmk_chip = find_nmk_gpio_from_pin(pin);
|
||||
if (!nmk_chip) {
|
||||
dev_err(npct->dev,
|
||||
"invalid pin offset %d\n", pin);
|
||||
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++) {
|
||||
/*
|
||||
|
@ -1997,6 +2024,31 @@ static int nmk_pinctrl_probe(struct platform_device *pdev)
|
|||
if (version == PINCTRL_NMK_DB8540)
|
||||
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);
|
||||
if (prcm_np)
|
||||
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.npins = npct->soc->npins;
|
||||
npct->dev = &pdev->dev;
|
||||
|
@ -2034,10 +2073,6 @@ static int nmk_pinctrl_probe(struct platform_device *pdev)
|
|||
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);
|
||||
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)
|
||||
{
|
||||
int ret;
|
||||
return platform_driver_register(&nmk_gpio_driver);
|
||||
}
|
||||
subsys_initcall(nmk_gpio_init);
|
||||
|
||||
ret = platform_driver_register(&nmk_gpio_driver);
|
||||
if (ret)
|
||||
return ret;
|
||||
static int __init nmk_pinctrl_init(void)
|
||||
{
|
||||
return platform_driver_register(&nmk_pinctrl_driver);
|
||||
}
|
||||
|
||||
core_initcall(nmk_gpio_init);
|
||||
core_initcall(nmk_pinctrl_init);
|
||||
|
||||
MODULE_AUTHOR("Prafulla WADASKAR and Alessandro Rubini");
|
||||
MODULE_DESCRIPTION("Nomadik GPIO Driver");
|
||||
|
|
|
@ -121,8 +121,6 @@ struct nmk_pingroup {
|
|||
|
||||
/**
|
||||
* 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.
|
||||
* All pins which are also GPIOs must be listed first within the
|
||||
* 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
|
||||
*/
|
||||
struct nmk_pinctrl_soc_data {
|
||||
struct pinctrl_gpio_range *gpio_ranges;
|
||||
unsigned gpio_num_ranges;
|
||||
const struct pinctrl_pin_desc *pins;
|
||||
unsigned npins;
|
||||
const struct nmk_function *functions;
|
||||
|
|
|
@ -61,8 +61,8 @@ int pin_config_get_for_pin(struct pinctrl_dev *pctldev, unsigned pin,
|
|||
const struct pinconf_ops *ops = pctldev->desc->confops;
|
||||
|
||||
if (!ops || !ops->pin_config_get) {
|
||||
dev_dbg(pctldev->dev, "cannot get pin configuration, missing "
|
||||
"pin_config_get() function in driver\n");
|
||||
dev_dbg(pctldev->dev,
|
||||
"cannot get pin configuration, .pin_config_get missing in driver\n");
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
|
@ -202,18 +202,34 @@ int pinconf_apply_setting(struct pinctrl_setting const *setting)
|
|||
|
||||
#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;
|
||||
int i;
|
||||
|
||||
pctldev = get_pinctrl_dev_from_devname(map->ctrl_dev_name);
|
||||
if (pctldev)
|
||||
confops = pctldev->desc->confops;
|
||||
else
|
||||
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) {
|
||||
case PIN_MAP_TYPE_CONFIGS_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);
|
||||
|
||||
for (i = 0; i < map->data.configs.num_configs; i++) {
|
||||
seq_printf(s, "config ");
|
||||
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");
|
||||
}
|
||||
pinconf_show_config(s, pctldev, map->data.configs.configs,
|
||||
map->data.configs.num_configs);
|
||||
}
|
||||
|
||||
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;
|
||||
const struct pinctrl_ops *pctlops = pctldev->desc->pctlops;
|
||||
const struct pinconf_ops *confops = pctldev->desc->confops;
|
||||
struct pin_desc *desc;
|
||||
int i;
|
||||
|
||||
switch (setting->type) {
|
||||
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
|
||||
* values, so they can be decoded to something meaningful.
|
||||
*/
|
||||
for (i = 0; i < setting->data.configs.num_configs; i++) {
|
||||
seq_printf(s, " ");
|
||||
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");
|
||||
pinconf_show_config(s, pctldev, setting->data.configs.configs,
|
||||
setting->data.configs.num_configs);
|
||||
}
|
||||
|
||||
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 *found = NULL;
|
||||
struct pinctrl_dev *pctldev;
|
||||
const struct pinconf_ops *confops = NULL;
|
||||
struct dbg_cfg *dbg = &pinconf_dbg_conf;
|
||||
int i, j;
|
||||
unsigned long config;
|
||||
|
||||
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);
|
||||
config = *found->data.configs.configs;
|
||||
seq_printf(s, "Dev %s has config of %s in state %s: 0x%08lX\n",
|
||||
dbg->dev_name, dbg->pin_name,
|
||||
dbg->state_name, config);
|
||||
|
||||
if (pctldev)
|
||||
confops = pctldev->desc->confops;
|
||||
|
||||
if (confops && confops->pin_config_config_dbg_show)
|
||||
confops->pin_config_config_dbg_show(pctldev, s, config);
|
||||
seq_printf(s, "Dev %s has config of %s in state %s:\n",
|
||||
dbg->dev_name, dbg->pin_name, dbg->state_name);
|
||||
pinconf_show_config(s, pctldev, found->data.configs.configs,
|
||||
found->data.configs.num_configs);
|
||||
|
||||
exit:
|
||||
mutex_unlock(&pinctrl_maps_mutex);
|
||||
|
@ -470,10 +460,12 @@ exit:
|
|||
* 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
|
||||
* @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
|
||||
* config_pin is literal, alternatives like config_mux not supported yet
|
||||
* <devicename> <state> <pinname> are values that should match the pinctrl-maps
|
||||
* <config> is the configuration to be changed. Supported configs are
|
||||
* "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
|
||||
*/
|
||||
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"))
|
||||
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, " ");
|
||||
if (!token)
|
||||
return -EINVAL;
|
||||
if (strcmp(token, "config_pin"))
|
||||
return -EINVAL;
|
||||
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;
|
||||
|
||||
/* get arg 'device_name' */
|
||||
token = strsep(&b, " ");
|
||||
|
|
|
@ -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)) {
|
||||
writel(pintmask, &pint_regs->edge_set);
|
||||
__irq_set_handler_locked(irq, handle_edge_irq);
|
||||
irq_set_handler_locked(d, handle_edge_irq);
|
||||
} else {
|
||||
writel(pintmask, &pint_regs->edge_clear);
|
||||
__irq_set_handler_locked(irq, handle_level_irq);
|
||||
irq_set_handler_locked(d, handle_level_irq);
|
||||
}
|
||||
|
||||
out:
|
||||
|
|
|
@ -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_HIGH << ACTIVE_LEVEL_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;
|
||||
|
||||
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_LOW << ACTIVE_LEVEL_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;
|
||||
|
||||
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 |= BOTH_EADGE << ACTIVE_LEVEL_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;
|
||||
|
||||
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 &= ~(DB_CNTRl_MASK << 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;
|
||||
|
||||
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 &= ~(DB_CNTRl_MASK << 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;
|
||||
|
||||
case IRQ_TYPE_NONE:
|
||||
|
@ -492,8 +492,9 @@ static struct irq_chip amd_gpio_irqchip = {
|
|||
.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 off;
|
||||
u32 reg;
|
||||
|
@ -501,7 +502,7 @@ static void amd_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
|
|||
u64 reg64;
|
||||
int handled = 0;
|
||||
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 amd_gpio *gpio_dev = to_amd_gpio(gc);
|
||||
|
||||
|
|
|
@ -320,6 +320,9 @@ static const struct pinctrl_ops at91_pctrl_ops = {
|
|||
static void __iomem *pin_to_controller(struct at91_pinctrl *info,
|
||||
unsigned int bank)
|
||||
{
|
||||
if (!gpio_chips[bank])
|
||||
return NULL;
|
||||
|
||||
return gpio_chips[bank]->regbase;
|
||||
}
|
||||
|
||||
|
@ -729,6 +732,10 @@ static int at91_pmx_set(struct pinctrl_dev *pctldev, unsigned selector,
|
|||
pin = &pins_conf[i];
|
||||
at91_pin_dbg(info->dev, pin);
|
||||
pio = pin_to_controller(info, pin->bank);
|
||||
|
||||
if (!pio)
|
||||
continue;
|
||||
|
||||
mask = pin_to_mask(pin->pin);
|
||||
at91_mux_disable_interrupt(pio, mask);
|
||||
switch (pin->mux) {
|
||||
|
@ -848,6 +855,10 @@ static int at91_pinconf_get(struct pinctrl_dev *pctldev,
|
|||
*config = 0;
|
||||
dev_dbg(info->dev, "%s:%d, pin_id=%d", __func__, __LINE__, pin_id);
|
||||
pio = pin_to_controller(info, pin_to_bank(pin_id));
|
||||
|
||||
if (!pio)
|
||||
return -EINVAL;
|
||||
|
||||
pin = pin_id % MAX_NB_GPIO_PER_BANK;
|
||||
|
||||
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",
|
||||
__func__, __LINE__, pin_id, config);
|
||||
pio = pin_to_controller(info, pin_to_bank(pin_id));
|
||||
|
||||
if (!pio)
|
||||
return -EINVAL;
|
||||
|
||||
pin = pin_id % MAX_NB_GPIO_PER_BANK;
|
||||
mask = pin_to_mask(pin);
|
||||
|
||||
|
@ -1444,22 +1459,22 @@ static int alt_gpio_irq_type(struct irq_data *d, unsigned type)
|
|||
|
||||
switch (type) {
|
||||
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_REHLSR);
|
||||
break;
|
||||
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_FELLSR);
|
||||
break;
|
||||
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_FELLSR);
|
||||
break;
|
||||
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_REHLSR);
|
||||
break;
|
||||
|
@ -1468,7 +1483,7 @@ static int alt_gpio_irq_type(struct irq_data *d, unsigned type)
|
|||
* disable additional interrupt modes:
|
||||
* 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);
|
||||
return 0;
|
||||
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 */
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
static u32 wakeups[MAX_GPIO_BANKS];
|
||||
|
@ -1585,8 +1578,6 @@ void at91_pinctrl_gpio_resume(void)
|
|||
static struct irq_chip gpio_irqchip = {
|
||||
.name = "GPIO",
|
||||
.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_mask = gpio_irq_mask,
|
||||
.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)
|
||||
{
|
||||
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 at91_gpio_chip *at91_gpio = container_of(gpio_chip,
|
||||
struct at91_gpio_chip, chip);
|
||||
|
|
|
@ -519,10 +519,11 @@ static struct irq_chip u300_gpio_irqchip = {
|
|||
.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);
|
||||
struct gpio_chip *chip = irq_get_handler_data(irq);
|
||||
unsigned int irq = irq_desc_get_irq(desc);
|
||||
struct irq_chip *parent_chip = irq_desc_get_chip(desc);
|
||||
struct gpio_chip *chip = irq_desc_get_handler_data(desc);
|
||||
struct u300_gpio *gpio = to_u300_gpio(chip);
|
||||
struct u300_gpio_port *port = &gpio->ports[irq - chip->base];
|
||||
int pinoffset = port->number << 3; /* get the right stride */
|
||||
|
|
|
@ -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, ®_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, ®_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);
|
|
@ -37,6 +37,9 @@
|
|||
#define LPC18XX_SCU_PIN_EHD_MASK 0x300
|
||||
#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_EHD BIT(2)
|
||||
#define LPC18XX_SCU_I2C0_EZI BIT(3)
|
||||
|
@ -617,10 +620,33 @@ static const struct pinctrl_pin_desc lpc18xx_pins[] = {
|
|||
|
||||
static int lpc18xx_pconf_get_usb1(enum pin_config_param param, int *arg, u32 reg)
|
||||
{
|
||||
/* TODO */
|
||||
switch (param) {
|
||||
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,
|
||||
unsigned pin)
|
||||
{
|
||||
|
@ -782,10 +808,30 @@ static int lpc18xx_pconf_set_usb1(struct pinctrl_dev *pctldev,
|
|||
enum pin_config_param param,
|
||||
u16 param_val, u32 *reg)
|
||||
{
|
||||
/* TODO */
|
||||
switch (param) {
|
||||
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,
|
||||
enum pin_config_param param,
|
||||
u16 param_val, u32 *reg,
|
||||
|
|
|
@ -1310,9 +1310,11 @@ static int pistachio_gpio_irq_set_type(struct irq_data *data, unsigned int type)
|
|||
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 irq_chip *chip = irq_get_chip(irq);
|
||||
unsigned long pending;
|
||||
|
|
|
@ -945,6 +945,7 @@ static int _rockchip_pmx_gpio_set_direction(struct gpio_chip *chip,
|
|||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
clk_enable(bank->clk);
|
||||
spin_lock_irqsave(&bank->slock, flags);
|
||||
|
||||
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);
|
||||
|
||||
spin_unlock_irqrestore(&bank->slock, flags);
|
||||
clk_disable(bank->clk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1389,6 +1391,7 @@ static void rockchip_gpio_set(struct gpio_chip *gc, unsigned offset, int value)
|
|||
unsigned long flags;
|
||||
u32 data;
|
||||
|
||||
clk_enable(bank->clk);
|
||||
spin_lock_irqsave(&bank->slock, flags);
|
||||
|
||||
data = readl(reg);
|
||||
|
@ -1398,6 +1401,7 @@ static void rockchip_gpio_set(struct gpio_chip *gc, unsigned offset, int value)
|
|||
writel(data, reg);
|
||||
|
||||
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);
|
||||
u32 data;
|
||||
|
||||
clk_enable(bank->clk);
|
||||
data = readl(bank->reg_base + GPIO_EXT_PORT);
|
||||
clk_disable(bank->clk);
|
||||
data >>= offset;
|
||||
data &= 1;
|
||||
return data;
|
||||
|
@ -1469,10 +1475,10 @@ static const struct gpio_chip rockchip_gpiolib_chip = {
|
|||
* 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 rockchip_pin_bank *bank = irq_get_handler_data(irq);
|
||||
struct irq_chip *chip = irq_desc_get_chip(desc);
|
||||
struct rockchip_pin_bank *bank = irq_desc_get_handler_data(desc);
|
||||
u32 pend;
|
||||
|
||||
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);
|
||||
|
||||
while (pend) {
|
||||
unsigned int virq;
|
||||
unsigned int irq, virq;
|
||||
|
||||
irq = __ffs(pend);
|
||||
pend &= ~BIT(irq);
|
||||
|
@ -1546,6 +1552,7 @@ static int rockchip_irq_set_type(struct irq_data *d, unsigned int type)
|
|||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
clk_enable(bank->clk);
|
||||
spin_lock_irqsave(&bank->slock, flags);
|
||||
|
||||
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);
|
||||
|
||||
if (type & IRQ_TYPE_EDGE_BOTH)
|
||||
__irq_set_handler_locked(d->irq, handle_edge_irq);
|
||||
irq_set_handler_locked(d, handle_edge_irq);
|
||||
else
|
||||
__irq_set_handler_locked(d->irq, handle_level_irq);
|
||||
irq_set_handler_locked(d, handle_level_irq);
|
||||
|
||||
spin_lock_irqsave(&bank->slock, flags);
|
||||
irq_gc_lock(gc);
|
||||
|
@ -1603,6 +1610,7 @@ static int rockchip_irq_set_type(struct irq_data *d, unsigned int type)
|
|||
default:
|
||||
irq_gc_unlock(gc);
|
||||
spin_unlock_irqrestore(&bank->slock, flags);
|
||||
clk_disable(bank->clk);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -1611,6 +1619,7 @@ static int rockchip_irq_set_type(struct irq_data *d, unsigned int type)
|
|||
|
||||
irq_gc_unlock(gc);
|
||||
spin_unlock_irqrestore(&bank->slock, flags);
|
||||
clk_disable(bank->clk);
|
||||
|
||||
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 rockchip_pin_bank *bank = gc->private;
|
||||
|
||||
clk_enable(bank->clk);
|
||||
bank->saved_masks = irq_reg_readl(gc, GPIO_INTMASK);
|
||||
irq_reg_writel(gc, ~gc->wake_active, GPIO_INTMASK);
|
||||
clk_disable(bank->clk);
|
||||
}
|
||||
|
||||
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 rockchip_pin_bank *bank = gc->private;
|
||||
|
||||
clk_enable(bank->clk);
|
||||
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,
|
||||
|
@ -1640,7 +1671,7 @@ static int rockchip_interrupts_register(struct platform_device *pdev,
|
|||
unsigned int clr = IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN;
|
||||
struct irq_chip_generic *gc;
|
||||
int ret;
|
||||
int i;
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < ctrl->nr_banks; ++i, ++bank) {
|
||||
if (!bank->valid) {
|
||||
|
@ -1649,11 +1680,19 @@ static int rockchip_interrupts_register(struct platform_device *pdev,
|
|||
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,
|
||||
&irq_generic_chip_ops, NULL);
|
||||
if (!bank->domain) {
|
||||
dev_warn(&pdev->dev, "could not initialize irq domain for bank %s\n",
|
||||
bank->name);
|
||||
clk_disable(bank->clk);
|
||||
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",
|
||||
bank->name);
|
||||
irq_domain_remove(bank->domain);
|
||||
clk_disable(bank->clk);
|
||||
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.ack = GPIO_PORTS_EOI;
|
||||
gc->chip_types[0].chip.irq_ack = irq_gc_ack_set_bit;
|
||||
gc->chip_types[0].chip.irq_mask = irq_gc_mask_set_bit;
|
||||
gc->chip_types[0].chip.irq_unmask = irq_gc_mask_clr_bit;
|
||||
gc->chip_types[0].chip.irq_mask = rockchip_irq_gc_mask_set_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_suspend = rockchip_irq_suspend;
|
||||
gc->chip_types[0].chip.irq_resume = rockchip_irq_resume;
|
||||
gc->chip_types[0].chip.irq_set_type = rockchip_irq_set_type;
|
||||
gc->wake_enabled = IRQ_MSK(bank->nr_pins);
|
||||
|
||||
irq_set_handler_data(bank->irq, bank);
|
||||
irq_set_chained_handler(bank->irq, rockchip_irq_demux);
|
||||
irq_set_chained_handler_and_data(bank->irq,
|
||||
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;
|
||||
|
@ -1808,7 +1855,7 @@ static int rockchip_get_bank_data(struct rockchip_pin_bank *bank,
|
|||
if (IS_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[];
|
||||
|
|
|
@ -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 irq_chip *chip;
|
||||
|
||||
chip = irq_get_chip(irq);
|
||||
chip = irq_desc_get_chip(desc);
|
||||
chained_irq_enter(chip, desc);
|
||||
pcs_irq_handle(pcs_soc);
|
||||
/* 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_and_handler(irq, &pcs->chip,
|
||||
handle_level_irq);
|
||||
|
||||
#ifdef CONFIG_ARM
|
||||
set_irq_flags(irq, IRQF_VALID);
|
||||
#else
|
||||
irq_set_noprobe(irq);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1768,9 +1763,9 @@ static int pcs_irq_init_chained_handler(struct pcs_device *pcs,
|
|||
return res;
|
||||
}
|
||||
} else {
|
||||
irq_set_handler_data(pcs_soc->irq, pcs_soc);
|
||||
irq_set_chained_handler(pcs_soc->irq,
|
||||
pcs_irq_chain_handler);
|
||||
irq_set_chained_handler_and_data(pcs_soc->irq,
|
||||
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 = {
|
||||
.flags = PCS_QUIRK_SHARED_IRQ,
|
||||
.irq_enable_mask = (1 << 24), /* WAKEUPENABLE */
|
||||
.irq_status_mask = (1 << 25), /* WAKEUPEVENT */
|
||||
};
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
/* 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 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)
|
||||
{
|
||||
struct irq_chip *chip = irq_get_chip(irq);
|
||||
struct st_pinctrl *info = irq_get_handler_data(irq);
|
||||
struct irq_chip *chip = irq_desc_get_chip(desc);
|
||||
struct st_pinctrl *info = irq_desc_get_handler_data(desc);
|
||||
unsigned long status;
|
||||
int n;
|
||||
|
||||
|
|
|
@ -706,10 +706,10 @@ static const char * const sdio1_wp_groups[] = {"gpio0_0_grp",
|
|||
"gpio0_39_grp", "gpio0_41_grp", "gpio0_43_grp",
|
||||
"gpio0_45_grp", "gpio0_47_grp", "gpio0_49_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_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",
|
||||
"can0_2_grp", "can0_3_grp", "can0_4_grp", "can0_5_grp",
|
||||
"can0_6_grp", "can0_7_grp", "can0_8_grp", "can0_9_grp",
|
||||
|
|
|
@ -322,8 +322,7 @@ static int pinmux_func_name_to_selector(struct pinctrl_dev *pctldev,
|
|||
selector++;
|
||||
}
|
||||
|
||||
pr_err("%s does not support function %s\n",
|
||||
pinctrl_dev_get_name(pctldev), function);
|
||||
dev_err(pctldev->dev, "function '%s' not supported\n", function);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
|
|
@ -63,6 +63,14 @@ config PINCTRL_MSM8916
|
|||
This is the pinctrl, pinmux, pinconf and gpiolib driver for the
|
||||
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
|
||||
tristate "Qualcomm SPMI PMIC pin controller driver"
|
||||
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
|
||||
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
|
||||
|
|
|
@ -7,5 +7,8 @@ obj-$(CONFIG_PINCTRL_MSM8660) += pinctrl-msm8660.o
|
|||
obj-$(CONFIG_PINCTRL_MSM8960) += pinctrl-msm8960.o
|
||||
obj-$(CONFIG_PINCTRL_MSM8X74) += pinctrl-msm8x74.o
|
||||
obj-$(CONFIG_PINCTRL_MSM8916) += pinctrl-msm8916.o
|
||||
obj-$(CONFIG_PINCTRL_QDF2XXX) += pinctrl-qdf2xxx.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_SSBI_PMIC) += pinctrl-ssbi-gpio.o
|
||||
obj-$(CONFIG_PINCTRL_QCOM_SSBI_PMIC) += pinctrl-ssbi-mpp.o
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include <linux/interrupt.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/reboot.h>
|
||||
#include <linux/pm.h>
|
||||
|
||||
#include "../core.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);
|
||||
|
||||
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))
|
||||
__irq_set_handler_locked(d->irq, handle_edge_irq);
|
||||
irq_set_handler_locked(d, handle_edge_irq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -764,12 +765,13 @@ static struct irq_chip msm_gpio_irq_chip = {
|
|||
.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);
|
||||
const struct msm_pingroup *g;
|
||||
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 handled = 0;
|
||||
u32 val;
|
||||
|
@ -855,6 +857,13 @@ static int msm_ps_hold_restart(struct notifier_block *nb, unsigned long action,
|
|||
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)
|
||||
{
|
||||
int i;
|
||||
|
@ -867,6 +876,8 @@ static void msm_pinctrl_setup_pm_reset(struct msm_pinctrl *pctrl)
|
|||
if (register_restart_handler(&pctrl->restart_nb))
|
||||
dev_err(pctrl->dev,
|
||||
"failed to setup restart handler.\n");
|
||||
poweroff_pctrl = pctrl;
|
||||
pm_power_off = msm_ps_hold_poweroff;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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");
|
|
@ -61,7 +61,9 @@
|
|||
#define PMIC_MPP_REG_DIG_PULL_CTL 0x42
|
||||
#define PMIC_MPP_REG_DIG_IN_CTL 0x43
|
||||
#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_SINK_CTL 0x4c
|
||||
|
||||
/* PMIC_MPP_REG_MODE_CTL */
|
||||
#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_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
|
||||
|
||||
/* Qualcomm specific pin configurations */
|
||||
#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
|
||||
|
@ -99,13 +115,15 @@
|
|||
* @out_value: Cached pin output value.
|
||||
* @output_enabled: Set to true if MPP output 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
|
||||
* Output or Bidirectional Analog mode.
|
||||
* @paired: Pin operates in paired mode
|
||||
* @num_sources: Number of power-sources supported by this MPP.
|
||||
* @power_source: Current power-source used.
|
||||
* @amux_input: Set the source for analog input.
|
||||
* @aout_level: Analog output level
|
||||
* @pullup: Pullup resistor value. Valid in Bidirectional mode only.
|
||||
* @function: See pmic_mpp_functions[].
|
||||
* @drive_strength: Amount of current in sink mode
|
||||
* @dtest: DTEST route selector
|
||||
*/
|
||||
struct pmic_mpp_pad {
|
||||
u16 base;
|
||||
|
@ -114,12 +132,15 @@ struct pmic_mpp_pad {
|
|||
bool out_value;
|
||||
bool output_enabled;
|
||||
bool input_enabled;
|
||||
bool analog_mode;
|
||||
bool paired;
|
||||
unsigned int num_sources;
|
||||
unsigned int power_source;
|
||||
unsigned int amux_input;
|
||||
unsigned int aout_level;
|
||||
unsigned int pullup;
|
||||
unsigned int function;
|
||||
unsigned int drive_strength;
|
||||
unsigned int dtest;
|
||||
};
|
||||
|
||||
struct pmic_mpp_state {
|
||||
|
@ -129,25 +150,32 @@ struct pmic_mpp_state {
|
|||
struct gpio_chip chip;
|
||||
};
|
||||
|
||||
struct pmic_mpp_bindings {
|
||||
const char *property;
|
||||
unsigned param;
|
||||
static const struct pinconf_generic_params pmic_mpp_bindings[] = {
|
||||
{"qcom,amux-route", PMIC_MPP_CONF_AMUX_ROUTE, 0},
|
||||
{"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[] = {
|
||||
{"qcom,amux-route", PMIC_MPP_CONF_AMUX_ROUTE},
|
||||
{"qcom,analog-mode", PMIC_MPP_CONF_ANALOG_MODE},
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
static const struct pin_config_item pmic_conf_items[] = {
|
||||
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[] = {
|
||||
"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[] = {
|
||||
PMIC_MPP_FUNC_NORMAL, PMIC_MPP_FUNC_PAIRED,
|
||||
"reserved1", "reserved2",
|
||||
PMIC_MPP_FUNC_DTEST1, PMIC_MPP_FUNC_DTEST2,
|
||||
PMIC_MPP_FUNC_DTEST3, PMIC_MPP_FUNC_DTEST4,
|
||||
"digital", "analog", "sink"
|
||||
};
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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 = {
|
||||
.get_groups_count = pmic_mpp_get_groups_count,
|
||||
.get_group_name = pmic_mpp_get_group_name,
|
||||
.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,
|
||||
};
|
||||
|
||||
|
@ -340,6 +261,53 @@ static int pmic_mpp_get_function_groups(struct pinctrl_dev *pctldev,
|
|||
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,
|
||||
unsigned pin)
|
||||
{
|
||||
|
@ -352,31 +320,7 @@ static int pmic_mpp_set_mux(struct pinctrl_dev *pctldev, unsigned function,
|
|||
|
||||
pad->function = function;
|
||||
|
||||
if (!pad->analog_mode) {
|
||||
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;
|
||||
ret = pmic_mpp_write_mode_ctl(state, pad);
|
||||
|
||||
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:
|
||||
arg = pad->out_value;
|
||||
break;
|
||||
case PMIC_MPP_CONF_DTEST_SELECTOR:
|
||||
arg = pad->dtest;
|
||||
break;
|
||||
case PMIC_MPP_CONF_AMUX_ROUTE:
|
||||
arg = pad->amux_input;
|
||||
break;
|
||||
case PMIC_MPP_CONF_ANALOG_MODE:
|
||||
arg = pad->analog_mode;
|
||||
case PMIC_MPP_CONF_PAIRED:
|
||||
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;
|
||||
default:
|
||||
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;
|
||||
|
||||
/* Make it possible to enable the pin, by not setting high impedance */
|
||||
pad->is_enabled = true;
|
||||
|
||||
for (i = 0; i < nconfs; i++) {
|
||||
param = pinconf_to_config_param(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->out_value = arg;
|
||||
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:
|
||||
if (arg >= PMIC_MPP_AMUX_ROUTE_ABUS4)
|
||||
return -EINVAL;
|
||||
pad->amux_input = arg;
|
||||
break;
|
||||
case PMIC_MPP_CONF_ANALOG_MODE:
|
||||
pad->analog_mode = true;
|
||||
case PMIC_MPP_CONF_ANALOG_LEVEL:
|
||||
pad->aout_level = arg;
|
||||
break;
|
||||
case PMIC_MPP_CONF_PAIRED:
|
||||
pad->paired = !!arg;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
|
@ -528,29 +493,17 @@ static int pmic_mpp_config_set(struct pinctrl_dev *pctldev, unsigned int pin,
|
|||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (!pad->analog_mode) {
|
||||
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 */
|
||||
}
|
||||
}
|
||||
ret = pmic_mpp_write(state, pad, PMIC_MPP_REG_AOUT_CTL, pad->aout_level);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
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_mode_ctl(state, pad);
|
||||
if (ret < 0)
|
||||
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,
|
||||
|
@ -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_pad *pad;
|
||||
int ret, val;
|
||||
int ret;
|
||||
|
||||
static const char *const biases[] = {
|
||||
"0.6kOhm", "10kOhm", "30kOhm", "Disabled"
|
||||
};
|
||||
|
||||
|
||||
pad = pctldev->desc->pins[pin].drv_data;
|
||||
|
||||
seq_printf(s, " mpp%-2d:", pin + PMIC_MPP_PHYSICAL_OFFSET);
|
||||
|
||||
val = pmic_mpp_read(state, pad, PMIC_MPP_REG_EN_CTL);
|
||||
|
||||
if (val < 0 || !(val >> PMIC_MPP_REG_MASTER_EN_SHIFT)) {
|
||||
if (!pad->is_enabled) {
|
||||
seq_puts(s, " ---");
|
||||
} 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->analog_mode ? "ana" : "dig");
|
||||
seq_printf(s, " %-7s", pmic_mpp_functions[pad->function]);
|
||||
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, " %-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 = {
|
||||
.is_generic = true,
|
||||
.pin_config_group_get = pmic_mpp_config_get,
|
||||
.pin_config_group_set = pmic_mpp_config_set,
|
||||
.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)
|
||||
{
|
||||
int type, subtype, val, dir;
|
||||
unsigned int sel;
|
||||
|
||||
type = pmic_mpp_read(state, pad, PMIC_MPP_REG_TYPE);
|
||||
if (type < 0)
|
||||
|
@ -751,43 +707,53 @@ static int pmic_mpp_populate(struct pmic_mpp_state *state,
|
|||
dir &= PMIC_MPP_REG_MODE_DIR_MASK;
|
||||
|
||||
switch (dir) {
|
||||
case 0:
|
||||
case PMIC_MPP_MODE_DIGITAL_INPUT:
|
||||
pad->input_enabled = true;
|
||||
pad->output_enabled = false;
|
||||
pad->analog_mode = false;
|
||||
pad->function = PMIC_MPP_DIGITAL;
|
||||
break;
|
||||
case 1:
|
||||
case PMIC_MPP_MODE_DIGITAL_OUTPUT:
|
||||
pad->input_enabled = false;
|
||||
pad->output_enabled = true;
|
||||
pad->analog_mode = false;
|
||||
pad->function = PMIC_MPP_DIGITAL;
|
||||
break;
|
||||
case 2:
|
||||
case PMIC_MPP_MODE_DIGITAL_BIDIR:
|
||||
pad->input_enabled = true;
|
||||
pad->output_enabled = true;
|
||||
pad->analog_mode = false;
|
||||
pad->function = PMIC_MPP_DIGITAL;
|
||||
break;
|
||||
case 3:
|
||||
case PMIC_MPP_MODE_ANALOG_BIDIR:
|
||||
pad->input_enabled = true;
|
||||
pad->output_enabled = true;
|
||||
pad->analog_mode = true;
|
||||
pad->function = PMIC_MPP_ANALOG;
|
||||
break;
|
||||
case 4:
|
||||
case PMIC_MPP_MODE_ANALOG_INPUT:
|
||||
pad->input_enabled = true;
|
||||
pad->output_enabled = false;
|
||||
pad->analog_mode = true;
|
||||
pad->function = PMIC_MPP_ANALOG;
|
||||
break;
|
||||
case 5:
|
||||
case PMIC_MPP_MODE_ANALOG_OUTPUT:
|
||||
pad->input_enabled = false;
|
||||
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;
|
||||
default:
|
||||
dev_err(state->dev, "unknown MPP direction\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
pad->function = val >> PMIC_MPP_REG_MODE_FUNCTION_SHIFT;
|
||||
pad->function &= PMIC_MPP_REG_MODE_FUNCTION_MASK;
|
||||
sel = val >> PMIC_MPP_REG_MODE_FUNCTION_SHIFT;
|
||||
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);
|
||||
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 &= PMIC_MPP_REG_AIN_ROUTE_MASK;
|
||||
|
||||
/* Pin could be disabled with PIN_CONFIG_BIAS_HIGH_IMPEDANCE */
|
||||
pad->is_enabled = true;
|
||||
val = pmic_mpp_read(state, pad, PMIC_MPP_REG_SINK_CTL);
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -866,6 +848,12 @@ static int pmic_mpp_probe(struct platform_device *pdev)
|
|||
pctrldesc->pins = pindesc;
|
||||
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++) {
|
||||
pad = &pads[i];
|
||||
pindesc->drv_data = pad;
|
||||
|
|
|
@ -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");
|
|
@ -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");
|
|
@ -148,9 +148,9 @@ static int exynos_irq_set_type(struct irq_data *irqd, unsigned int type)
|
|||
}
|
||||
|
||||
if (type & IRQ_TYPE_EDGE_BOTH)
|
||||
__irq_set_handler_locked(irqd->irq, handle_edge_irq);
|
||||
irq_set_handler_locked(irqd, handle_edge_irq);
|
||||
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 &= ~(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_and_handler(virq, &b->irq_chip->chip,
|
||||
handle_level_irq);
|
||||
set_irq_flags(virq, IRQF_VALID);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -422,9 +421,9 @@ static const struct of_device_id exynos_wkup_irq_ids[] = {
|
|||
/* interrupt handler for wakeup interrupts 0..15 */
|
||||
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 irq_chip *chip = irq_get_chip(irq);
|
||||
struct irq_chip *chip = irq_desc_get_chip(desc);
|
||||
int eint_irq;
|
||||
|
||||
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 */
|
||||
static void exynos_irq_demux_eint16_31(unsigned int irq, struct irq_desc *desc)
|
||||
{
|
||||
struct irq_chip *chip = irq_get_chip(irq);
|
||||
struct exynos_muxed_weint_data *eintd = irq_get_handler_data(irq);
|
||||
struct irq_chip *chip = irq_desc_get_chip(desc);
|
||||
struct exynos_muxed_weint_data *eintd = irq_desc_get_handler_data(desc);
|
||||
struct samsung_pinctrl_drv_data *d = eintd->banks[0]->drvdata;
|
||||
unsigned long pend;
|
||||
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].bank = bank;
|
||||
irq_set_handler_data(irq, &weint_data[idx]);
|
||||
irq_set_chained_handler(irq, exynos_irq_eint0_15);
|
||||
irq_set_chained_handler_and_data(irq,
|
||||
exynos_irq_eint0_15,
|
||||
&weint_data[idx]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -44,9 +44,7 @@
|
|||
#define PIN_NAME_LENGTH 10
|
||||
|
||||
#define GROUP_SUFFIX "-grp"
|
||||
#define GSUFFIX_LEN sizeof(GROUP_SUFFIX)
|
||||
#define FUNCTION_SUFFIX "-mux"
|
||||
#define FSUFFIX_LEN sizeof(FUNCTION_SUFFIX)
|
||||
|
||||
/*
|
||||
* 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 */
|
||||
map = kzalloc(sizeof(*map) * map_cnt, GFP_KERNEL);
|
||||
if (!map) {
|
||||
dev_err(dev, "could not alloc memory for pin-maps\n");
|
||||
if (!map)
|
||||
return -ENOMEM;
|
||||
}
|
||||
*nmaps = 0;
|
||||
|
||||
/*
|
||||
* Allocate memory for pin group name. The pin group name is derived
|
||||
* from the node name from which these map entries are be created.
|
||||
*/
|
||||
gname = kzalloc(strlen(np->name) + GSUFFIX_LEN, GFP_KERNEL);
|
||||
if (!gname) {
|
||||
dev_err(dev, "failed to alloc memory for group name\n");
|
||||
gname = kasprintf(GFP_KERNEL, "%s%s", np->name, GROUP_SUFFIX);
|
||||
if (!gname)
|
||||
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
|
||||
|
@ -231,10 +224,8 @@ static int exynos5440_dt_node_to_map(struct pinctrl_dev *pctldev,
|
|||
|
||||
/* Allocate memory for config entries */
|
||||
cfg = kzalloc(sizeof(*cfg) * cfg_cnt, GFP_KERNEL);
|
||||
if (!cfg) {
|
||||
dev_err(dev, "failed to alloc memory for configs\n");
|
||||
if (!cfg)
|
||||
goto free_gname;
|
||||
}
|
||||
|
||||
/* Prepare a list of config settings */
|
||||
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:
|
||||
/* create the function map entry */
|
||||
if (of_find_property(np, "samsung,exynos5440-pin-function", NULL)) {
|
||||
fname = kzalloc(strlen(np->name) + FSUFFIX_LEN, GFP_KERNEL);
|
||||
if (!fname) {
|
||||
dev_err(dev, "failed to alloc memory for func name\n");
|
||||
fname = kasprintf(GFP_KERNEL,
|
||||
"%s%s", np->name, FUNCTION_SUFFIX);
|
||||
if (!fname)
|
||||
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.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);
|
||||
if (!*pin_list) {
|
||||
dev_err(dev, "failed to allocate memory for pin list\n");
|
||||
if (!*pin_list)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
return of_property_read_u32_array(cfg_np, "samsung,exynos5440-pins",
|
||||
*pin_list, *npins);
|
||||
|
@ -682,17 +668,15 @@ static int exynos5440_pinctrl_parse_dt(struct platform_device *pdev,
|
|||
return -EINVAL;
|
||||
|
||||
groups = devm_kzalloc(dev, grp_cnt * sizeof(*groups), GFP_KERNEL);
|
||||
if (!groups) {
|
||||
dev_err(dev, "failed allocate memory for ping group list\n");
|
||||
if (!groups)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
grp = groups;
|
||||
|
||||
functions = devm_kzalloc(dev, grp_cnt * sizeof(*functions), GFP_KERNEL);
|
||||
if (!functions) {
|
||||
dev_err(dev, "failed to allocate memory for function list\n");
|
||||
if (!functions)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
func = functions;
|
||||
|
||||
/*
|
||||
|
@ -710,14 +694,10 @@ static int exynos5440_pinctrl_parse_dt(struct platform_device *pdev,
|
|||
}
|
||||
|
||||
/* derive pin group name from the node name */
|
||||
gname = devm_kzalloc(dev, strlen(cfg_np->name) + GSUFFIX_LEN,
|
||||
GFP_KERNEL);
|
||||
if (!gname) {
|
||||
dev_err(dev, "failed to alloc memory for group name\n");
|
||||
gname = devm_kasprintf(dev, GFP_KERNEL,
|
||||
"%s%s", cfg_np->name, GROUP_SUFFIX);
|
||||
if (!gname)
|
||||
return -ENOMEM;
|
||||
}
|
||||
snprintf(gname, strlen(cfg_np->name) + 4, "%s%s", cfg_np->name,
|
||||
GROUP_SUFFIX);
|
||||
|
||||
grp->name = gname;
|
||||
grp->pins = pin_list;
|
||||
|
@ -731,22 +711,15 @@ skip_to_pin_function:
|
|||
continue;
|
||||
|
||||
/* derive function name from the node name */
|
||||
fname = devm_kzalloc(dev, strlen(cfg_np->name) + FSUFFIX_LEN,
|
||||
GFP_KERNEL);
|
||||
if (!fname) {
|
||||
dev_err(dev, "failed to alloc memory for func name\n");
|
||||
fname = devm_kasprintf(dev, GFP_KERNEL,
|
||||
"%s%s", cfg_np->name, FUNCTION_SUFFIX);
|
||||
if (!fname)
|
||||
return -ENOMEM;
|
||||
}
|
||||
snprintf(fname, strlen(cfg_np->name) + 4, "%s%s", cfg_np->name,
|
||||
FUNCTION_SUFFIX);
|
||||
|
||||
func->name = fname;
|
||||
func->groups = devm_kzalloc(dev, sizeof(char *), GFP_KERNEL);
|
||||
if (!func->groups) {
|
||||
dev_err(dev, "failed to alloc memory for group list "
|
||||
"in pin function");
|
||||
if (!func->groups)
|
||||
return -ENOMEM;
|
||||
}
|
||||
func->groups[0] = gname;
|
||||
func->num_groups = gname ? 1 : 0;
|
||||
func->function = function;
|
||||
|
@ -774,10 +747,8 @@ static int exynos5440_pinctrl_register(struct platform_device *pdev,
|
|||
int pin, ret;
|
||||
|
||||
ctrldesc = devm_kzalloc(dev, sizeof(*ctrldesc), GFP_KERNEL);
|
||||
if (!ctrldesc) {
|
||||
dev_err(dev, "could not allocate memory for pinctrl desc\n");
|
||||
if (!ctrldesc)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ctrldesc->name = "exynos5440-pinctrl";
|
||||
ctrldesc->owner = THIS_MODULE;
|
||||
|
@ -787,10 +758,8 @@ static int exynos5440_pinctrl_register(struct platform_device *pdev,
|
|||
|
||||
pindesc = devm_kzalloc(&pdev->dev, sizeof(*pindesc) *
|
||||
EXYNOS5440_MAX_PINS, GFP_KERNEL);
|
||||
if (!pindesc) {
|
||||
dev_err(&pdev->dev, "mem alloc for pin descriptors failed\n");
|
||||
if (!pindesc)
|
||||
return -ENOMEM;
|
||||
}
|
||||
ctrldesc->pins = pindesc;
|
||||
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 *
|
||||
ctrldesc->npins, GFP_KERNEL);
|
||||
if (!pin_names) {
|
||||
dev_err(&pdev->dev, "mem alloc for pin names failed\n");
|
||||
if (!pin_names)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* for each pin, set the name of the pin */
|
||||
for (pin = 0; pin < ctrldesc->npins; pin++) {
|
||||
|
@ -844,10 +811,8 @@ static int exynos5440_gpiolib_register(struct platform_device *pdev,
|
|||
int ret;
|
||||
|
||||
gc = devm_kzalloc(&pdev->dev, sizeof(*gc), GFP_KERNEL);
|
||||
if (!gc) {
|
||||
dev_err(&pdev->dev, "mem alloc for gpio_chip failed\n");
|
||||
if (!gc)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
priv->gc = gc;
|
||||
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_and_handler(virq, &exynos5440_gpio_irq_chip,
|
||||
handle_level_irq);
|
||||
set_irq_flags(virq, IRQF_VALID);
|
||||
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,
|
||||
GFP_KERNEL);
|
||||
if (!intd) {
|
||||
dev_err(dev, "failed to allocate memory for gpio intr data\n");
|
||||
if (!intd)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
for (i = 0; i < EXYNOS5440_MAX_GPIO_INT; 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);
|
||||
if (!priv) {
|
||||
dev_err(dev, "could not allocate memory for private data\n");
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
priv->reg_base = devm_ioremap_resource(&pdev->dev, res);
|
||||
|
|
|
@ -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 */
|
||||
if (type & IRQ_TYPE_EDGE_BOTH)
|
||||
__irq_set_handler_locked(irq, handle_edge_irq);
|
||||
irq_set_handler_locked(d, handle_edge_irq);
|
||||
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,
|
||||
|
@ -181,7 +181,7 @@ static int s3c24xx_eint_type(struct irq_data *data, unsigned int type)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
s3c24xx_eint_set_handler(data->irq, type);
|
||||
s3c24xx_eint_set_handler(data, type);
|
||||
|
||||
/* Set up interrupt trigger */
|
||||
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)
|
||||
{
|
||||
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;
|
||||
|
||||
/* 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)
|
||||
{
|
||||
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 s3c24xx_eint_data *eint_data = irq_get_handler_data(irq);
|
||||
struct irq_chip *chip = irq_data_get_irq_chip(data);
|
||||
unsigned int virq;
|
||||
|
||||
chained_irq_enter(chip, desc);
|
||||
|
@ -357,11 +357,11 @@ static struct irq_chip s3c24xx_eint_chip = {
|
|||
.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)
|
||||
{
|
||||
struct irq_chip *chip = irq_get_chip(irq);
|
||||
struct s3c24xx_eint_data *data = irq_get_handler_data(irq);
|
||||
struct s3c24xx_eint_data *data = irq_desc_get_handler_data(desc);
|
||||
struct irq_chip *chip = irq_desc_get_irq_chip(desc);
|
||||
struct samsung_pinctrl_drv_data *d = data->drvdata;
|
||||
unsigned int pend, mask;
|
||||
|
||||
|
@ -374,7 +374,7 @@ static inline void s3c24xx_demux_eint(unsigned int irq, struct irq_desc *desc,
|
|||
pend &= range;
|
||||
|
||||
while (pend) {
|
||||
unsigned int virq;
|
||||
unsigned int virq, irq;
|
||||
|
||||
irq = __ffs(pend);
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
s3c24xx_demux_eint(irq, desc, 8, 0xffff00);
|
||||
s3c24xx_demux_eint(desc, 8, 0xffff00);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
irq_set_chip_data(virq, bank);
|
||||
set_irq_flags(virq, IRQF_VALID);
|
||||
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_data(virq, bank);
|
||||
set_irq_flags(virq, IRQF_VALID);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -260,13 +260,13 @@ static int s3c64xx_irq_get_trigger(unsigned int type)
|
|||
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 */
|
||||
if (type & IRQ_TYPE_EDGE_BOTH)
|
||||
__irq_set_handler_locked(irq, handle_edge_irq);
|
||||
irq_set_handler_locked(d, handle_edge_irq);
|
||||
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,
|
||||
|
@ -356,7 +356,7 @@ static int s3c64xx_gpio_irq_set_type(struct irq_data *irqd, unsigned int type)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
s3c64xx_irq_set_handler(irqd->irq, type);
|
||||
s3c64xx_irq_set_handler(irqd, type);
|
||||
|
||||
/* Set up interrupt trigger */
|
||||
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,
|
||||
&s3c64xx_gpio_irq_chip, handle_level_irq);
|
||||
irq_set_chip_data(virq, bank);
|
||||
set_irq_flags(virq, IRQF_VALID);
|
||||
|
||||
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)
|
||||
{
|
||||
struct irq_chip *chip = irq_get_chip(irq);
|
||||
struct s3c64xx_eint_gpio_data *data = irq_get_handler_data(irq);
|
||||
struct irq_chip *chip = irq_desc_get_chip(desc);
|
||||
struct s3c64xx_eint_gpio_data *data = irq_desc_get_handler_data(desc);
|
||||
struct samsung_pinctrl_drv_data *drvdata = data->drvdata;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
s3c64xx_irq_set_handler(irqd->irq, type);
|
||||
s3c64xx_irq_set_handler(irqd, type);
|
||||
|
||||
/* Set up interrupt trigger */
|
||||
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,
|
||||
};
|
||||
|
||||
static inline void s3c64xx_irq_demux_eint(unsigned int irq,
|
||||
struct irq_desc *desc, u32 range)
|
||||
static inline void s3c64xx_irq_demux_eint(struct irq_desc *desc, u32 range)
|
||||
{
|
||||
struct irq_chip *chip = irq_get_chip(irq);
|
||||
struct s3c64xx_eint0_data *data = irq_get_handler_data(irq);
|
||||
struct irq_chip *chip = irq_desc_get_chip(desc);
|
||||
struct s3c64xx_eint0_data *data = irq_desc_get_handler_data(desc);
|
||||
struct samsung_pinctrl_drv_data *drvdata = data->drvdata;
|
||||
unsigned int pend, mask;
|
||||
|
||||
|
@ -616,11 +614,10 @@ static inline void s3c64xx_irq_demux_eint(unsigned int irq,
|
|||
pend &= range;
|
||||
|
||||
while (pend) {
|
||||
unsigned int virq;
|
||||
unsigned int virq, irq;
|
||||
|
||||
irq = fls(pend) - 1;
|
||||
pend &= ~(1 << irq);
|
||||
|
||||
virq = irq_linear_revmap(data->domains[irq], data->pins[irq]);
|
||||
/*
|
||||
* 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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
s3c64xx_irq_demux_eint(irq, desc, 0xff00000);
|
||||
s3c64xx_irq_demux_eint(desc, 0xff00000);
|
||||
}
|
||||
|
||||
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,
|
||||
&s3c64xx_eint0_irq_chip, handle_level_irq);
|
||||
irq_set_chip_data(virq, ddata);
|
||||
set_irq_flags(virq, IRQF_VALID);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -29,24 +29,25 @@
|
|||
static int sh_pfc_map_resources(struct sh_pfc *pfc,
|
||||
struct platform_device *pdev)
|
||||
{
|
||||
unsigned int num_windows = 0;
|
||||
unsigned int num_irqs = 0;
|
||||
unsigned int num_windows, num_irqs;
|
||||
struct sh_pfc_window *windows;
|
||||
unsigned int *irqs = NULL;
|
||||
struct resource *res;
|
||||
unsigned int i;
|
||||
int irq;
|
||||
|
||||
/* Count the MEM and IRQ resources. */
|
||||
for (i = 0; i < pdev->num_resources; ++i) {
|
||||
switch (resource_type(&pdev->resource[i])) {
|
||||
case IORESOURCE_MEM:
|
||||
num_windows++;
|
||||
break;
|
||||
|
||||
case IORESOURCE_IRQ:
|
||||
num_irqs++;
|
||||
for (num_windows = 0;; num_windows++) {
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, num_windows);
|
||||
if (!res)
|
||||
break;
|
||||
}
|
||||
for (num_irqs = 0;; num_irqs++) {
|
||||
irq = platform_get_irq(pdev, num_irqs);
|
||||
if (irq == -EPROBE_DEFER)
|
||||
return irq;
|
||||
if (irq < 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (num_windows == 0)
|
||||
|
@ -72,22 +73,17 @@ static int sh_pfc_map_resources(struct sh_pfc *pfc,
|
|||
}
|
||||
|
||||
/* Fill them. */
|
||||
for (i = 0, res = pdev->resource; i < pdev->num_resources; i++, res++) {
|
||||
switch (resource_type(res)) {
|
||||
case IORESOURCE_MEM:
|
||||
for (i = 0; i < num_windows; i++) {
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, i);
|
||||
windows->phys = res->start;
|
||||
windows->size = resource_size(res);
|
||||
windows->virt = devm_ioremap_resource(pfc->dev, res);
|
||||
if (IS_ERR(windows->virt))
|
||||
return -ENOMEM;
|
||||
windows++;
|
||||
break;
|
||||
|
||||
case IORESOURCE_IRQ:
|
||||
*irqs++ = res->start;
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < num_irqs; i++)
|
||||
*irqs++ = platform_get_irq(pdev, i);
|
||||
|
||||
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[] = {
|
||||
#ifdef CONFIG_PINCTRL_PFC_R8A7740
|
||||
{ "pfc-r8a7740", (kernel_ulong_t)&r8a7740_pinmux_info },
|
||||
#endif
|
||||
#ifdef CONFIG_PINCTRL_PFC_R8A7778
|
||||
{ "pfc-r8a7778", (kernel_ulong_t)&r8a7778_pinmux_info },
|
||||
#endif
|
||||
|
@ -609,9 +602,6 @@ static const struct platform_device_id sh_pfc_id_table[] = {
|
|||
#ifdef CONFIG_PINCTRL_PFC_SH7269
|
||||
{ "pfc-sh7269", (kernel_ulong_t)&sh7269_pinmux_info },
|
||||
#endif
|
||||
#ifdef CONFIG_PINCTRL_PFC_SH73A0
|
||||
{ "pfc-sh73a0", (kernel_ulong_t)&sh73a0_pinmux_info },
|
||||
#endif
|
||||
#ifdef CONFIG_PINCTRL_PFC_SH7720
|
||||
{ "pfc-sh7720", (kernel_ulong_t)&sh7720_pinmux_info },
|
||||
#endif
|
||||
|
|
|
@ -22,10 +22,6 @@
|
|||
#include <linux/kernel.h>
|
||||
#include <linux/pinctrl/pinconf-generic.h>
|
||||
|
||||
#ifndef CONFIG_ARCH_MULTIPLATFORM
|
||||
#include <mach/irqs.h>
|
||||
#endif
|
||||
|
||||
#include "core.h"
|
||||
#include "sh_pfc.h"
|
||||
|
||||
|
|
|
@ -27,10 +27,27 @@
|
|||
#include "core.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) \
|
||||
PORT_GP_32(0, fn, sfx), \
|
||||
PORT_GP_32(1, fn, sfx), \
|
||||
PORT_GP_32(2, fn, sfx), \
|
||||
PORT_GP_30(1, fn, sfx), \
|
||||
PORT_GP_30(2, fn, sfx), \
|
||||
PORT_GP_32(3, fn, sfx), \
|
||||
PORT_GP_32(4, fn, sfx), \
|
||||
PORT_GP_32(5, fn, sfx)
|
||||
|
|
|
@ -14,15 +14,30 @@
|
|||
#include "core.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) \
|
||||
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(3, fn, sfx), \
|
||||
PORT_GP_32(4, fn, sfx), \
|
||||
PORT_GP_32(5, fn, sfx), \
|
||||
PORT_GP_32(6, fn, sfx), \
|
||||
PORT_GP_32(7, fn, sfx)
|
||||
PORT_GP_26(7, fn, sfx)
|
||||
|
||||
enum {
|
||||
PINMUX_RESERVED = 0,
|
||||
|
|
|
@ -2770,6 +2770,24 @@ static const unsigned int sdhi2_wp_pins[] = {
|
|||
static const unsigned int sdhi2_wp_mux[] = {
|
||||
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[] = {
|
||||
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_cd),
|
||||
SH_PFC_PIN_GROUP(sdhi2_wp),
|
||||
SH_PFC_PIN_GROUP(usb0),
|
||||
SH_PFC_PIN_GROUP(usb1),
|
||||
};
|
||||
|
||||
static const char * const eth_groups[] = {
|
||||
|
@ -3219,6 +3239,14 @@ static const char * const sdhi2_groups[] = {
|
|||
"sdhi2_wp",
|
||||
};
|
||||
|
||||
static const char * const usb0_groups[] = {
|
||||
"usb0",
|
||||
};
|
||||
|
||||
static const char * const usb1_groups[] = {
|
||||
"usb1",
|
||||
};
|
||||
|
||||
static const struct sh_pfc_function pinmux_functions[] = {
|
||||
SH_PFC_FUNCTION(eth),
|
||||
SH_PFC_FUNCTION(hscif0),
|
||||
|
@ -3253,6 +3281,8 @@ static const struct sh_pfc_function pinmux_functions[] = {
|
|||
SH_PFC_FUNCTION(sdhi0),
|
||||
SH_PFC_FUNCTION(sdhi1),
|
||||
SH_PFC_FUNCTION(sdhi2),
|
||||
SH_PFC_FUNCTION(usb0),
|
||||
SH_PFC_FUNCTION(usb1),
|
||||
};
|
||||
|
||||
static const struct pinmux_cfg_reg pinmux_config_regs[] = {
|
||||
|
|
|
@ -26,10 +26,6 @@
|
|||
#include <linux/regulator/machine.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#ifndef CONFIG_ARCH_MULTIPLATFORM
|
||||
#include <mach/irqs.h>
|
||||
#endif
|
||||
|
||||
#include "core.h"
|
||||
#include "sh_pfc.h"
|
||||
|
||||
|
|
|
@ -40,6 +40,10 @@ struct sh_pfc_pinctrl {
|
|||
|
||||
struct pinctrl_pin_desc *pins;
|
||||
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)
|
||||
|
@ -96,10 +100,13 @@ static int sh_pfc_map_add_config(struct pinctrl_map *map,
|
|||
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,
|
||||
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;
|
||||
unsigned int nmaps = *num_maps;
|
||||
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;
|
||||
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
|
||||
* 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) {
|
||||
dev_err(dev, "Invalid function in DT\n");
|
||||
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) {
|
||||
dev_err(dev,
|
||||
"DT node must contain at least a function or config\n");
|
||||
ret = -ENODEV;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* 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) {
|
||||
num_pins = 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;
|
||||
}
|
||||
|
||||
ret = of_property_count_strings(np, "renesas,groups");
|
||||
ret = of_property_count_strings(np, pmx->groups_prop_name);
|
||||
if (ret == -EINVAL) {
|
||||
num_groups = 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;
|
||||
|
||||
/* 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) {
|
||||
maps[idx].type = PIN_MAP_TYPE_MUX_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;
|
||||
}
|
||||
|
||||
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,
|
||||
PIN_MAP_TYPE_CONFIGS_PIN,
|
||||
configs, num_configs);
|
||||
|
@ -246,7 +271,7 @@ static int sh_pfc_dt_node_to_map(struct pinctrl_dev *pctldev,
|
|||
index = 0;
|
||||
|
||||
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);
|
||||
if (ret < 0)
|
||||
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 (*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)
|
||||
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:
|
||||
return pin->configs & SH_PFC_PIN_CFG_PULL_DOWN;
|
||||
|
||||
case PIN_CONFIG_POWER_SOURCE:
|
||||
return pin->configs & SH_PFC_PIN_CFG_IO_VOLTAGE;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
@ -477,7 +506,6 @@ static int sh_pfc_pinconf_get(struct pinctrl_dev *pctldev, unsigned _pin,
|
|||
struct sh_pfc *pfc = pmx->pfc;
|
||||
enum pin_config_param param = pinconf_to_config_param(*config);
|
||||
unsigned long flags;
|
||||
unsigned int bias;
|
||||
|
||||
if (!sh_pfc_pinconf_validate(pfc, _pin, param))
|
||||
return -ENOTSUPP;
|
||||
|
@ -485,7 +513,9 @@ static int sh_pfc_pinconf_get(struct pinctrl_dev *pctldev, unsigned _pin,
|
|||
switch (param) {
|
||||
case PIN_CONFIG_BIAS_DISABLE:
|
||||
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)
|
||||
return -ENOTSUPP;
|
||||
|
||||
|
@ -498,6 +528,24 @@ static int sh_pfc_pinconf_get(struct pinctrl_dev *pctldev, unsigned _pin,
|
|||
|
||||
*config = 0;
|
||||
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:
|
||||
return -ENOTSUPP;
|
||||
|
@ -534,6 +582,24 @@ static int sh_pfc_pinconf_set(struct pinctrl_dev *pctldev, unsigned _pin,
|
|||
|
||||
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:
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#define __SH_PFC_H
|
||||
|
||||
#include <linux/bug.h>
|
||||
#include <linux/pinctrl/pinconf-generic.h>
|
||||
#include <linux/stringify.h>
|
||||
|
||||
enum {
|
||||
|
@ -26,6 +27,7 @@ enum {
|
|||
#define SH_PFC_PIN_CFG_OUTPUT (1 << 1)
|
||||
#define SH_PFC_PIN_CFG_PULL_UP (1 << 2)
|
||||
#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)
|
||||
|
||||
struct sh_pfc_pin {
|
||||
|
@ -121,6 +123,9 @@ struct sh_pfc_soc_operations {
|
|||
unsigned int (*get_bias)(struct sh_pfc *pfc, unsigned int pin);
|
||||
void (*set_bias)(struct sh_pfc *pfc, unsigned int pin,
|
||||
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 {
|
||||
|
|
|
@ -148,6 +148,19 @@ enum altas7_pad_type {
|
|||
#define DIV_DISABLE 0x1
|
||||
#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 {
|
||||
const char *property;
|
||||
int value;
|
||||
|
@ -196,6 +209,16 @@ struct atlas7_pad_config {
|
|||
.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
|
||||
* @bank: The bank of this pad's registers on.
|
||||
|
@ -285,6 +308,9 @@ struct atlas7_pinctrl_data {
|
|||
/* Platform info of atlas7 pinctrl */
|
||||
#define ATLAS7_PINCTRL_REG_BANKS 2
|
||||
#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
|
||||
|
@ -316,6 +342,7 @@ struct atlas7_gpio_bank {
|
|||
unsigned int gpio_offset;
|
||||
unsigned int ngpio;
|
||||
const unsigned int *gpio_pins;
|
||||
u32 sleep_data[NGPIO_OF_BANK];
|
||||
};
|
||||
|
||||
struct atlas7_gpio_chip {
|
||||
|
@ -343,6 +370,9 @@ struct atlas7_pmx {
|
|||
struct pinctrl_desc pctl_desc;
|
||||
struct atlas7_pinctrl_data *pctl_data;
|
||||
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),
|
||||
};
|
||||
|
||||
/* 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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
int idx;
|
||||
|
||||
for (idx = 0; idx < ARRAY_SIZE(atlas7_ds_map); idx++) {
|
||||
if (atlas7_ds_map[idx].ma != ma)
|
||||
for (idx = 0; idx < ARRAY_SIZE(atlas7_ma2ds_map); idx++) {
|
||||
if (atlas7_ma2ds_map[idx].ma != ma)
|
||||
continue;
|
||||
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
return atlas7_ds_map[idx].ds_0610m31;
|
||||
return atlas7_ma2ds_map[idx].ds_0610m31;
|
||||
}
|
||||
|
||||
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_pad_config *conf = &pmx->pctl_data->confs[pin];
|
||||
u32 type = conf->type;
|
||||
u32 shift = conf->pupd_bit;
|
||||
u32 bank = atlas7_pin_to_bank(pin);
|
||||
void __iomem *pull_sel_reg, *pull_clr_reg;
|
||||
const struct atlas7_pull_info *pull_info;
|
||||
u32 bank;
|
||||
unsigned long regv;
|
||||
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_clr_reg = CLR_REG(pull_sel_reg);
|
||||
|
||||
if (type == PAD_T_4WE_PD || type == PAD_T_4WE_PU) {
|
||||
writel(P4WE_PULL_MASK << shift, pull_clr_reg);
|
||||
/* Retrieve correspond register value from table by sel */
|
||||
regv = pull_info->s2v[sel].data & pull_info->mask;
|
||||
|
||||
if (sel == PULL_UP)
|
||||
writel(P4WE_PULL_UP << shift, pull_sel_reg);
|
||||
else if (sel == HIGH_HYSTERESIS)
|
||||
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;
|
||||
}
|
||||
/* Clear & Set new value to pull register */
|
||||
writel(pull_info->mask << conf->pupd_bit, CLR_REG(pull_sel_reg));
|
||||
writel(regv << conf->pupd_bit, pull_sel_reg);
|
||||
|
||||
pr_debug("PIN_CFG ### SET PIN#%d PULL SELECTOR:%d == OK ####\n",
|
||||
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_pad_config *conf = &pmx->pctl_data->confs[pin];
|
||||
u32 type = conf->type;
|
||||
u32 shift = conf->drvstr_bit;
|
||||
u32 bank = atlas7_pin_to_bank(pin);
|
||||
void __iomem *ds_sel_reg, *ds_clr_reg;
|
||||
const struct atlas7_ds_info *ds_info;
|
||||
u32 bank;
|
||||
void __iomem *ds_sel_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_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(sel << shift, ds_sel_reg);
|
||||
writel(ds_info->imval << conf->drvstr_bit, CLR_REG(ds_sel_reg));
|
||||
writel(sel << conf->drvstr_bit, ds_sel_reg);
|
||||
|
||||
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:
|
||||
pr_err("Pad#%d type[%d] doesn't support ds code[%d]!\n",
|
||||
pin, type, sel);
|
||||
pin, conf->type, sel);
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
|
@ -4101,14 +4183,135 @@ unmap_io:
|
|||
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[] = {
|
||||
{ .compatible = "sirf,atlas7-ioc",},
|
||||
{},
|
||||
};
|
||||
|
||||
static struct platform_driver atlas7_pinmux_driver = {
|
||||
.driver = {
|
||||
.name = "atlas7-ioc",
|
||||
.of_match_table = atlas7_pinmux_ids,
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
.pm = &atlas7_pinmux_pm_ops,
|
||||
#endif
|
||||
},
|
||||
.probe = atlas7_pinmux_probe,
|
||||
};
|
||||
|
@ -4286,14 +4489,15 @@ static struct irq_chip atlas7_gpio_irq_chip = {
|
|||
.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 atlas7_gpio_chip *a7gc = to_atlas7_gpio(gc);
|
||||
struct atlas7_gpio_bank *bank = NULL;
|
||||
u32 status, ctrl;
|
||||
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++) {
|
||||
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[] = {
|
||||
{ .compatible = "sirf,atlas7-gpio", },
|
||||
{},
|
||||
};
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, a7gc);
|
||||
dev_info(&pdev->dev, "add to system.\n");
|
||||
return 0;
|
||||
failed:
|
||||
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 = {
|
||||
.driver = {
|
||||
.name = "atlas7-gpio",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = atlas7_gpio_ids,
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
.pm = &atlas7_gpio_pm_ops,
|
||||
#endif
|
||||
},
|
||||
.probe = atlas7_gpio_probe,
|
||||
};
|
||||
|
|
|
@ -545,14 +545,15 @@ static struct irq_chip sirfsoc_irq_chip = {
|
|||
.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 sirfsoc_gpio_chip *sgpio = to_sirfsoc_gpio(gc);
|
||||
struct sirfsoc_gpio_bank *bank;
|
||||
u32 status, ctrl;
|
||||
int idx = 0;
|
||||
struct irq_chip *chip = irq_get_chip(irq);
|
||||
struct irq_chip *chip = irq_desc_get_chip(desc);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < SIRFSOC_GPIO_NO_OF_BANKS; i++) {
|
||||
|
|
|
@ -135,7 +135,14 @@ static const struct sunxi_desc_pin sun4i_a10_pins[] = {
|
|||
SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 3),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
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_FUNCTION(0x0, "gpio_in"),
|
||||
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(0x1, "gpio_out"),
|
||||
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_FUNCTION(0x0, "gpio_in"),
|
||||
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_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
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);
|
||||
u8 index = sunxi_irq_cfg_offset(d->hwirq);
|
||||
unsigned long flags;
|
||||
|
@ -615,16 +614,17 @@ static int sunxi_pinctrl_irq_set_type(struct irq_data *d, unsigned int type)
|
|||
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);
|
||||
|
||||
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 &= ~(IRQ_CFG_IRQ_MASK << index);
|
||||
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 = {
|
||||
.name = "sunxi_pio_edge",
|
||||
.irq_ack = sunxi_pinctrl_irq_ack,
|
||||
.irq_mask = sunxi_pinctrl_irq_mask,
|
||||
.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 = {
|
||||
.name = "sunxi_pio_level",
|
||||
.irq_eoi = sunxi_pinctrl_irq_ack,
|
||||
.irq_mask = sunxi_pinctrl_irq_mask,
|
||||
.irq_unmask = sunxi_pinctrl_irq_unmask,
|
||||
|
@ -709,10 +711,42 @@ static struct irq_chip sunxi_pinctrl_level_irq_chip = {
|
|||
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_pinctrl *pctl = irq_get_handler_data(irq);
|
||||
struct sunxi_desc_function *desc;
|
||||
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;
|
||||
|
||||
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->desc->irq_banks * IRQ_PER_BANK,
|
||||
&irq_domain_simple_ops,
|
||||
NULL);
|
||||
&sunxi_pinctrl_irq_domain_ops,
|
||||
pctl);
|
||||
if (!pctl->domain) {
|
||||
dev_err(&pdev->dev, "Couldn't register IRQ domain\n");
|
||||
ret = -ENOMEM;
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
@ -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
|
@ -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);
|
|
@ -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__ */
|
|
@ -7,6 +7,47 @@
|
|||
#define _DT_BINDINGS_PINCTRL_QCOM_PMIC_MPP_H
|
||||
|
||||
/* 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_S3 2
|
||||
|
||||
|
@ -37,6 +78,16 @@
|
|||
#define PMIC_MPP_AMUX_ROUTE_ABUS3 6
|
||||
#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" */
|
||||
#define PMIC_MPP_FUNC_NORMAL "normal"
|
||||
#define PMIC_MPP_FUNC_PAIRED "paired"
|
||||
|
|
Loading…
Reference in New Issue