Commit ac7b7596 authored by Linus Torvalds's avatar Linus Torvalds

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

Pull pin control updates from Linus Walleij:
 "This is the big bulk of pin control changes for the v4.13 series:

  Core:
   - The documentation is moved over to RST.
   - We now have agreed bindings for enabling input and output buffers
     without actually enabling input and/or output on a pin. We are
     chiseling out some details of pin control electronics.

  New drivers:
   - ZTE ZX
   - Renesas RZA1
   - MIPS Ingenic JZ47xx: also switch over existing drivers in the tree
     to use this pin controller and consolidate earlier spread out code.
   - Microschip MCP23S08: this driver is migrated from the GPIO
     subsystem and totally rewritten to use proper pin control. All
     users are switched over.

  New subdrivers:
   - Renesas R8A7743 and R8A7745.
   - Allwinner Sunxi A83T R_PIO.
   - Marvell MVEBU Armada CP110 and AP806.
   - Intel Cannon Lake PCH.
   - Qualcomm IPQ8074.

  Notable improvements:
   - IRQ support on the Marvell MVEBU Armada 37xx.
   - Meson driver supports HDMI CEC, AO, I2S, SPDIF and PWM.
   - Rockchip driver now supports iomux-route switching for RK3228,
     RK3328 and RK3399.
   - Rockchip A10 and A20 are merged into a single driver.
   - STM32 has improved GPIO support.
   - Samsung Exynos drivers are split per ARMv7 and ARMv8.
   - Marvell MVEBU is converted to use regmap for register access.

  Maintenance:
   - Several Renesas SH-PFC refactorings and updates.
   - Serious code size cut for Mediatek MT7623.
   - Misc janitorial and MAINTAINERS fixes"

* tag 'pinctrl-v4.13-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl: (137 commits)
  pinctrl: samsung: Remove bogus irq_[un]mask from resource management
  pinctrl: rza1: make structures rza1_gpiochip_template and rza1_pinmux_ops static
  pinctrl: rza1: Remove unneeded wrong check for wrong variable
  pinctrl: qcom: Add ipq8074 pinctrl driver
  pinctrl: freescale: imx7d: make of_device_ids const.
  pinctrl: DT: extend the pinmux property to support integers array
  pinctrl: generic: Add output-enable property
  pinctrl: armada-37xx: Fix number of pin in sdio_sb
  pinctrl: armada-37xx: Fix uart2 group selection register mask
  pinctrl: bcm2835: Avoid warning from __irq_do_set_handler
  pinctrl: sh-pfc: r8a7795: Add PWM support
  MAINTAINERS: Add Qualcomm pinctrl drivers section
  arm: dts: dt-bindings: Add Renesas RZ/A1 pinctrl header
  dt-bindings: pinctrl: Add RZ/A1 bindings doc
  pinctrl: Renesas RZ/A1 pin and gpio controller
  pinctrl: sh-pfc: r8a7792: Add SCIF1 and SCIF2 pin groups
  pinctrl.txt: move it to the driver-api book
  pinctrl: ingenic: checking for NULL instead of IS_ERR()
  pinctrl: uniphier: fix WARN_ON() of pingroups dump on LD20
  pinctrl: uniphier: fix WARN_ON() of pingroups dump on LD11
  ...
parents 4f5dfdd2 3fa53ec2
Ingenic jz47xx GPIO controller
That the Ingenic GPIO driver node must be a sub-node of the Ingenic pinctrl
driver node.
Required properties:
--------------------
- compatible: Must contain one of:
- "ingenic,jz4740-gpio"
- "ingenic,jz4770-gpio"
- "ingenic,jz4780-gpio"
- reg: The GPIO bank number.
- interrupt-controller: Marks the device node as an interrupt controller.
- interrupts: Interrupt specifier for the controllers interrupt.
- #interrupt-cells: Should be 2. Refer to
../interrupt-controller/interrupts.txt for more details.
- gpio-controller: Marks the device node as a GPIO controller.
- #gpio-cells: Should be 2. The first cell is the GPIO number and the second
cell specifies GPIO flags, as defined in <dt-bindings/gpio/gpio.h>. Only the
GPIO_ACTIVE_HIGH and GPIO_ACTIVE_LOW flags are supported.
- gpio-ranges: Range of pins managed by the GPIO controller. Refer to
'gpio.txt' in this directory for more details.
Example:
--------
&pinctrl {
#address-cells = <1>;
#size-cells = <0>;
gpa: gpio@0 {
compatible = "ingenic,jz4740-gpio";
reg = <0>;
gpio-controller;
gpio-ranges = <&pinctrl 0 0 32>;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
interrupt-parent = <&intc>;
interrupts = <28>;
};
};
...@@ -20,8 +20,10 @@ Required properties: ...@@ -20,8 +20,10 @@ Required properties:
"allwinner,sun9i-a80-pinctrl" "allwinner,sun9i-a80-pinctrl"
"allwinner,sun9i-a80-r-pinctrl" "allwinner,sun9i-a80-r-pinctrl"
"allwinner,sun8i-a83t-pinctrl" "allwinner,sun8i-a83t-pinctrl"
"allwinner,sun8i-a83t-r-pinctrl"
"allwinner,sun8i-h3-pinctrl" "allwinner,sun8i-h3-pinctrl"
"allwinner,sun8i-h3-r-pinctrl" "allwinner,sun8i-h3-r-pinctrl"
"allwinner,sun8i-r40-pinctrl"
"allwinner,sun50i-a64-pinctrl" "allwinner,sun50i-a64-pinctrl"
"allwinner,sun50i-a64-r-pinctrl" "allwinner,sun50i-a64-r-pinctrl"
"allwinner,sun50i-h5-pinctrl" "allwinner,sun50i-h5-pinctrl"
......
Ingenic jz47xx 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
phrase "pin configuration node".
For the jz47xx SoCs, pin control is tightly bound with GPIO ports. All pins may
be used as GPIOs, multiplexed device functions are configured within the
GPIO port configuration registers and it is typical to refer to pins using the
naming scheme "PxN" where x is a character identifying the GPIO port with
which the pin is associated and N is an integer from 0 to 31 identifying the
pin within that GPIO port. For example PA0 is the first pin in GPIO port A, and
PB31 is the last pin in GPIO port B. The jz4740 contains 4 GPIO ports, PA to
PD, for a total of 128 pins. The jz4780 contains 6 GPIO ports, PA to PF, for a
total of 192 pins.
Required properties:
--------------------
- compatible: One of:
- "ingenic,jz4740-pinctrl"
- "ingenic,jz4770-pinctrl"
- "ingenic,jz4780-pinctrl"
- reg: Address range of the pinctrl registers.
GPIO sub-nodes
--------------
The pinctrl node can have optional sub-nodes for the Ingenic GPIO driver;
please refer to ../gpio/ingenic,gpio.txt.
Example:
--------
pinctrl: pin-controller@10010000 {
compatible = "ingenic,jz4740-pinctrl";
reg = <0x10010000 0x400>;
};
...@@ -204,21 +204,22 @@ each single pin the number of required sub-nodes containing "pin" and ...@@ -204,21 +204,22 @@ each single pin the number of required sub-nodes containing "pin" and
maintain. maintain.
For cases like this, the pin controller driver may use the pinmux helper For cases like this, the pin controller driver may use the pinmux helper
property, where the pin identifier is packed with mux configuration settings property, where the pin identifier is provided with mux configuration settings
in a single integer. in a pinmux group. A pinmux group consists of the pin identifier and mux
settings represented as a single integer or an array of integers.
The pinmux property accepts an array of integers, each of them describing The pinmux property accepts an array of pinmux groups, each of them describing
a single pin multiplexing configuration. a single pin multiplexing configuration.
pincontroller { pincontroller {
state_0_node_a { state_0_node_a {
pinmux = <PIN_ID_AND_MUX>, <PIN_ID_AND_MUX>, ...; pinmux = <PINMUX_GROUP>, <PINMUX_GROUP>, ...;
}; };
}; };
Each individual pin controller driver bindings documentation shall specify Each individual pin controller driver bindings documentation shall specify
how those values (pin IDs and pin multiplexing configuration) are defined and how pin IDs and pin multiplexing configuration are defined and assembled
assembled together. together in a pinmux group.
== Generic pin configuration node content == == Generic pin configuration node content ==
...@@ -251,14 +252,20 @@ drive-push-pull - drive actively high and low ...@@ -251,14 +252,20 @@ drive-push-pull - drive actively high and low
drive-open-drain - drive with open drain drive-open-drain - drive with open drain
drive-open-source - drive with open source drive-open-source - drive with open source
drive-strength - sink or source at most X mA drive-strength - sink or source at most X mA
input-enable - enable input on pin (no effect on output) input-enable - enable input on pin (no effect on output, such as
input-disable - disable input on pin (no effect on output) enabling an input buffer)
input-disable - disable input on pin (no effect on output, such as
disabling an input buffer)
input-schmitt-enable - enable schmitt-trigger mode input-schmitt-enable - enable schmitt-trigger mode
input-schmitt-disable - disable schmitt-trigger mode input-schmitt-disable - disable schmitt-trigger mode
input-debounce - debounce mode with debound time X input-debounce - debounce mode with debound time X
power-source - select between different power supplies power-source - select between different power supplies
low-power-enable - enable low power mode low-power-enable - enable low power mode
low-power-disable - disable low power mode low-power-disable - disable low power mode
output-disable - disable output on a pin (such as disable an output
buffer)
output-enable - enable output on a pin without actively driving it
(such as enabling an output buffer)
output-low - set the pin to output mode with low level output-low - set the pin to output mode with low level
output-high - set the pin to output mode with high level output-high - set the pin to output mode with high level
slew-rate - set the slew rate slew-rate - set the slew rate
...@@ -300,7 +307,7 @@ arguments are described below. ...@@ -300,7 +307,7 @@ arguments are described below.
- pinmux takes a list of pin IDs and mux settings as required argument. The - pinmux takes a list of pin IDs and mux settings as required argument. The
specific bindings for the hardware defines: specific bindings for the hardware defines:
- How pin IDs and mux settings are defined and assembled together in a single - How pin IDs and mux settings are defined and assembled together in a single
integer. integer or an array of integers.
- bias-pull-up, -down and -pin-default take as optional argument on hardware - bias-pull-up, -down and -pin-default take as optional argument on hardware
supporting it the pull strength in Ohm. bias-disable will disable the pull. supporting it the pull strength in Ohm. bias-disable will disable the pull.
......
* ZTE ZX Pin Controller
The pin controller on ZTE ZX platforms is kinda of hybrid. It consists of
a main controller and an auxiliary one. For example, on ZX296718 SoC, the
main controller is TOP_PMM and the auxiliary one is AON_IOCFG. Both
controllers work together to control pin multiplexing and configuration in
the way illustrated as below.
GMII_RXD3 ---+
|
DVI1_HS ---+----------------------------- GMII_RXD3 (TOP pin)
|
BGPIO16 ---+ ^
| pinconf
^ |
| pinmux |
| |
TOP_PMM (main) AON_IOCFG (aux)
| | |
| pinmux | |
| pinmux v |
v | pinconf
KEY_ROW2 ---+ v
PORT1_LCD_TE ---+ |
| AGPIO10 ---+------ KEY_ROW2 (AON pin)
I2S0_DOUT3 ---+ |
|-----------------------+
PWM_OUT3 ---+
|
VGA_VS1 ---+
For most of pins like GMII_RXD3 in the figure, the pinmux function is
controlled by TOP_PMM block only, and this type of pins are meant by term
'TOP pins'. For pins like KEY_ROW2, the pinmux is controlled by both
TOP_PMM and AON_IOCFG blocks, as the available multiplexing functions for
the pin spread in both controllers. This type of pins are called 'AON pins'.
Though pinmux implementation is quite different, pinconf is same for both
types of pins. Both are controlled by auxiliary controller, i.e. AON_IOCFG
on ZX296718.
Required properties:
- compatible: should be "zte,zx296718-pmm".
- reg: the register physical address and length.
- zte,auxiliary-controller: phandle to the auxiliary pin controller which
implements pinmux for AON pins and pinconf for all pins.
The following pin configuration are supported. Please refer to
pinctrl-bindings.txt in this directory for more details of the common
pinctrl bindings used by client devices.
- bias-pull-up
- bias-pull-down
- drive-strength
- input-enable
- slew-rate
Examples:
iocfg: pin-controller@119000 {
compatible = "zte,zx296718-iocfg";
reg = <0x119000 0x1000>;
};
pmm: pin-controller@1462000 {
compatible = "zte,zx296718-pmm";
reg = <0x1462000 0x1000>;
zte,auxiliary-controller = <&iocfg>;
};
&pmm {
vga_pins: vga {
pins = "KEY_COL1", "KEY_COL2", "KEY_ROW1", "KEY_ROW2";
function = "VGA";
};
};
&vga {
pinctrl-names = "default";
pinctrl-0 = <&vga_pins>;
status = "okay";
};
Qualcomm Technologies, Inc. IPQ8074 TLMM block
This binding describes the Top Level Mode Multiplexer block found in the
IPQ8074 platform.
- compatible:
Usage: required
Value type: <string>
Definition: must be "qcom,ipq8074-pinctrl"
- reg:
Usage: required
Value type: <prop-encoded-array>
Definition: the base address and size of the TLMM register space.
- interrupts:
Usage: required
Value type: <prop-encoded-array>
Definition: should specify the TLMM summary IRQ.
- interrupt-controller:
Usage: required
Value type: <none>
Definition: identifies this node as an interrupt controller
- #interrupt-cells:
Usage: required
Value type: <u32>
Definition: must be 2. Specifying the pin number and flags, as defined
in <dt-bindings/interrupt-controller/irq.h>
- gpio-controller:
Usage: required
Value type: <none>
Definition: identifies this node as a gpio controller
- #gpio-cells:
Usage: required
Value type: <u32>
Definition: must be 2. Specifying the pin number and flags, as defined
in <dt-bindings/gpio/gpio.h>
Please refer to ../gpio/gpio.txt and ../interrupt-controller/interrupts.txt for
a general description of GPIO and interrupt bindings.
Please refer to pinctrl-bindings.txt in this directory for details of the
common pinctrl bindings used by client devices, including the meaning of the
phrase "pin configuration node".
The pin configuration nodes act as a container for an arbitrary number of
subnodes. Each of these subnodes represents some desired configuration for a
pin, a group, or a list of pins or groups. This configuration can include the
mux function to select on those pin(s)/group(s), and various pin configuration
parameters, such as pull-up, drive strength, etc.
PIN CONFIGURATION NODES:
The name of each subnode is not important; all subnodes should be enumerated
and processed purely based on their content.
Each subnode only affects those parameters that are explicitly listed. In
other words, a subnode that lists a mux function but no pin configuration
parameters implies no information about any pin configuration parameters.
Similarly, a pin subnode that describes a pullup parameter implies no
information about e.g. the mux function.
The following generic properties as defined in pinctrl-bindings.txt are valid
to specify in a pin configuration subnode:
- pins:
Usage: required
Value type: <string-array>
Definition: List of gpio pins affected by the properties specified in
this subnode. Valid pins are:
gpio0-gpio69
- function:
Usage: required
Value type: <string>
Definition: Specify the alternative function to be configured for the
specified pins. Functions are only valid for gpio pins.
Valid values are:
atest_char, atest_char0, atest_char1, atest_char2,
atest_char3, audio_rxbclk, audio_rxd, audio_rxfsync,
audio_rxmclk, audio_txbclk, audio_txd, audio_txfsync,
audio_txmclk, blsp0_i2c, blsp0_spi, blsp0_uart, blsp1_i2c,
blsp1_spi, blsp1_uart, blsp2_i2c, blsp2_spi, blsp2_uart,
blsp3_i2c, blsp3_spi, blsp3_spi0, blsp3_spi1, blsp3_spi2,
blsp3_spi3, blsp3_uart, blsp4_i2c0, blsp4_i2c1, blsp4_spi0,
blsp4_spi1, blsp4_uart0, blsp4_uart1, blsp5_i2c, blsp5_spi,
blsp5_uart, burn0, burn1, cri_trng, cri_trng0, cri_trng1,
cxc0, cxc1, dbg_out, gcc_plltest, gcc_tlmm, gpio, ldo_en,
ldo_update, led0, led1, led2, mac0_sa0, mac0_sa1, mac1_sa0,
mac1_sa1, mac1_sa2, mac1_sa3, mac2_sa0, mac2_sa1, mdc,
mdio, pcie0_clk, pcie0_rst, pcie0_wake, pcie1_clk,
pcie1_rst, pcie1_wake, pcm_drx, pcm_dtx, pcm_fsync,
pcm_pclk, pcm_zsi0, pcm_zsi1, prng_rosc, pta1_0, pta1_1,
pta1_2, pta2_0, pta2_1, pta2_2, pwm0, pwm1, pwm2, pwm3,
qdss_cti_trig_in_a0, qdss_cti_trig_in_a1,
qdss_cti_trig_in_b0, qdss_cti_trig_in_b1,
qdss_cti_trig_out_a0, qdss_cti_trig_out_a1,
qdss_cti_trig_out_b0, qdss_cti_trig_out_b1,
qdss_traceclk_a, qdss_traceclk_b, qdss_tracectl_a,
qdss_tracectl_b, qdss_tracedata_a, qdss_tracedata_b,
qpic, rx0, rx1, rx2, sd_card, sd_write, tsens_max, wci2a,
wci2b, wci2c, wci2d
- bias-disable:
Usage: optional
Value type: <none>
Definition: The specified pins should be configued as no pull.
- bias-pull-down:
Usage: optional
Value type: <none>
Definition: The specified pins should be configued as pull down.
- bias-pull-up:
Usage: optional
Value type: <none>
Definition: The specified pins should be configued as pull up.
- output-high:
Usage: optional
Value type: <none>
Definition: The specified pins are configured in output mode, driven
high.
- output-low:
Usage: optional
Value type: <none>
Definition: The specified pins are configured in output mode, driven
low.
- drive-strength:
Usage: optional
Value type: <u32>
Definition: Selects the drive strength for the specified pins, in mA.
Valid values are: 2, 4, 6, 8, 10, 12, 14 and 16
Example:
tlmm: pinctrl@1000000 {
compatible = "qcom,ipq8074-pinctrl";
reg = <0x1000000 0x300000>;
interrupts = <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>;
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
uart2: uart2-default {
mux {
pins = "gpio23", "gpio24";
function = "blsp4_uart1";
};
rx {
pins = "gpio23";
drive-strength = <4>;
bias-disable;
};
tx {
pins = "gpio24";
drive-strength = <2>;
bias-pull-up;
};
};
};
...@@ -13,6 +13,8 @@ Required Properties: ...@@ -13,6 +13,8 @@ Required Properties:
- "renesas,pfc-emev2": for EMEV2 (EMMA Mobile EV2) compatible pin-controller. - "renesas,pfc-emev2": for EMEV2 (EMMA Mobile EV2) compatible pin-controller.
- "renesas,pfc-r8a73a4": for R8A73A4 (R-Mobile APE6) compatible pin-controller. - "renesas,pfc-r8a73a4": for R8A73A4 (R-Mobile APE6) compatible pin-controller.
- "renesas,pfc-r8a7740": for R8A7740 (R-Mobile A1) compatible pin-controller. - "renesas,pfc-r8a7740": for R8A7740 (R-Mobile A1) compatible pin-controller.
- "renesas,pfc-r8a7743": for R8A7743 (RZ/G1M) compatible pin-controller.
- "renesas,pfc-r8a7745": for R8A7745 (RZ/G1E) compatible pin-controller.
- "renesas,pfc-r8a7778": for R8A7778 (R-Mobile M1) compatible pin-controller. - "renesas,pfc-r8a7778": for R8A7778 (R-Mobile M1) compatible pin-controller.
- "renesas,pfc-r8a7779": for R8A7779 (R-Car H1) compatible pin-controller. - "renesas,pfc-r8a7779": for R8A7779 (R-Car H1) compatible pin-controller.
- "renesas,pfc-r8a7790": for R8A7790 (R-Car H2) compatible pin-controller. - "renesas,pfc-r8a7790": for R8A7790 (R-Car H2) compatible pin-controller.
......
Renesas RZ/A1 combined Pin and GPIO controller
The Renesas SoCs of the RZ/A1 family feature a combined Pin and GPIO controller,
named "Ports" in the hardware reference manual.
Pin multiplexing and GPIO configuration is performed on a per-pin basis
writing configuration values to per-port register sets.
Each "port" features up to 16 pins, each of them configurable for GPIO
function (port mode) or in alternate function mode.
Up to 8 different alternate function modes exist for each single pin.
Pin controller node
-------------------
Required properties:
- compatible
this shall be "renesas,r7s72100-ports".
- reg
address base and length of the memory area where the pin controller
hardware is mapped to.
Example:
Pin controller node for RZ/A1H SoC (r7s72100)
pinctrl: pin-controller@fcfe3000 {
compatible = "renesas,r7s72100-ports";
reg = <0xfcfe3000 0x4230>;
};
Sub-nodes
---------
The child nodes of the pin controller node describe a pin multiplexing
function or a GPIO controller alternatively.
- Pin multiplexing sub-nodes:
A pin multiplexing sub-node describes how to configure a set of
(or a single) pin in some desired alternate function mode.
A single sub-node may define several pin configurations.
A few alternate function require special pin configuration flags to be
supplied along with the alternate function configuration number.
The hardware reference manual specifies when a pin function requires
"software IO driven" mode to be specified. To do so use the generic
properties from the <include/linux/pinctrl/pinconf_generic.h> header file
to instruct the pin controller to perform the desired pin configuration
operation.
Please refer to pinctrl-bindings.txt to get to know more on generic
pin properties usage.
The allowed generic formats for a pin multiplexing sub-node are the
following ones:
node-1 {
pinmux = <PIN_ID_AND_MUX>, <PIN_ID_AND_MUX>, ... ;
GENERIC_PINCONFIG;
};
node-2 {
sub-node-1 {
pinmux = <PIN_ID_AND_MUX>, <PIN_ID_AND_MUX>, ... ;
GENERIC_PINCONFIG;
};
sub-node-2 {
pinmux = <PIN_ID_AND_MUX>, <PIN_ID_AND_MUX>, ... ;
GENERIC_PINCONFIG;
};
...
sub-node-n {
pinmux = <PIN_ID_AND_MUX>, <PIN_ID_AND_MUX>, ... ;
GENERIC_PINCONFIG;
};
};
Use the second format when pins part of the same logical group need to have
different generic pin configuration flags applied.
Client sub-nodes shall refer to pin multiplexing sub-nodes using the phandle
of the most external one.
Eg.
client-1 {
...
pinctrl-0 = <&node-1>;
...
};
client-2 {
...
pinctrl-0 = <&node-2>;
...
};
Required properties:
- pinmux:
integer array representing pin number and pin multiplexing configuration.
When a pin has to be configured in alternate function mode, use this
property to identify the pin by its global index, and provide its
alternate function configuration number along with it.
When multiple pins are required to be configured as part of the same
alternate function they shall be specified as members of the same
argument list of a single "pinmux" property.
Helper macros to ease assembling the pin index from its position
(port where it sits on and pin number) and alternate function identifier
are provided by the pin controller header file at:
<include/dt-bindings/pinctrl/r7s72100-pinctrl.h>
Integers values in "pinmux" argument list are assembled as:
((PORT * 16 + PIN) | MUX_FUNC << 16)
Optional generic properties:
- input-enable:
enable input bufer for pins requiring software driven IO input
operations.
- output-high:
enable output buffer for pins requiring software driven IO output
operations. output-low can be used alternatively, as line value is
ignored by the driver.
The hardware reference manual specifies when a pin has to be configured to
work in bi-directional mode and when the IO direction has to be specified
by software. Bi-directional pins are managed by the pin controller driver
internally, while software driven IO direction has to be explicitly
selected when multiple options are available.
Example:
A serial communication interface with a TX output pin and an RX input pin.
&pinctrl {
scif2_pins: serial2 {
pinmux = <RZA1_PINMUX(3, 0, 6)>, <RZA1_PINMUX(3, 2, 4)>;
};
};
Pin #0 on port #3 is configured as alternate function #6.
Pin #2 on port #3 is configured as alternate function #4.
Example 2:
I2c master: both SDA and SCL pins need bi-directional operations
&pinctrl {
i2c2_pins: i2c2 {
pinmux = <RZA1_PINMUX(1, 4, 1)>, <RZA1_PINMUX(1, 5, 1)>;
};
};
Pin #4 on port #1 is configured as alternate function #1.
Pin #5 on port #1 is configured as alternate function #1.
Both need to work in bi-directional mode, the driver manages this internally.
Example 3:
Multi-function timer input and output compare pins.
Configure TIOC0A as software driven input and TIOC0B as software driven
output.
&pinctrl {
tioc0_pins: tioc0 {
tioc0_input_pins {
pinumx = <RZA1_PINMUX(4, 0, 2)>;
input-enable;
};
tioc0_output_pins {
pinmux = <RZA1_PINMUX(4, 1, 1)>;
output-enable;
};
};
};
&tioc0 {
...
pinctrl-0 = <&tioc0_pins>;
...
};
Pin #0 on port #4 is configured as alternate function #2 with IO direction
specified by software as input.
Pin #1 on port #4 is configured as alternate function #1 with IO direction
specified by software as output.
- GPIO controller sub-nodes:
Each port of the r7s72100 pin controller hardware is itself a GPIO controller.
Different SoCs have different numbers of available pins per port, but
generally speaking, each of them can be configured in GPIO ("port") mode
on this hardware.
Describe GPIO controllers using sub-nodes with the following properties.
Required properties:
- gpio-controller
empty property as defined by the GPIO bindings documentation.
- #gpio-cells
number of cells required to identify and configure a GPIO.
Shall be 2.
- gpio-ranges
Describes a GPIO controller specifying its specific pin base, the pin
base in the global pin numbering space, and the number of controlled
pins, as defined by the GPIO bindings documentation. Refer to
Documentation/devicetree/bindings/gpio/gpio.txt file for a more detailed
description.
Example:
A GPIO controller node, controlling 16 pins indexed from 0.
The GPIO controller base in the global pin indexing space is pin 48, thus
pins [0 - 15] on this controller map to pins [48 - 63] in the global pin
indexing space.
port3: gpio-3 {
gpio-controller;
#gpio-cells = <2>;
gpio-ranges = <&pinctrl 0 48 16>;
};
A device node willing to use pins controlled by this GPIO controller, shall
refer to it as follows:
led1 {
gpios = <&port3 10 GPIO_ACTIVE_LOW>;
};
...@@ -43,6 +43,7 @@ available subsections can be seen below. ...@@ -43,6 +43,7 @@ available subsections can be seen below.
80211/index 80211/index
uio-howto uio-howto
firmware/index firmware/index
pinctl
misc_devices misc_devices
.. only:: subproject and html .. only:: subproject and html
......
...@@ -1515,6 +1515,7 @@ F: arch/arm64/boot/dts/marvell/armada* ...@@ -1515,6 +1515,7 @@ F: arch/arm64/boot/dts/marvell/armada*
F: drivers/cpufreq/mvebu-cpufreq.c F: drivers/cpufreq/mvebu-cpufreq.c
F: drivers/irqchip/irq-armada-370-xp.c F: drivers/irqchip/irq-armada-370-xp.c
F: drivers/irqchip/irq-mvebu-* F: drivers/irqchip/irq-mvebu-*
F: drivers/pinctrl/mvebu/
F: drivers/rtc/rtc-armada38x.c F: drivers/rtc/rtc-armada38x.c
ARM/Marvell Berlin SoC support ARM/Marvell Berlin SoC support
...@@ -1681,7 +1682,6 @@ F: arch/arm/mach-qcom/ ...@@ -1681,7 +1682,6 @@ F: arch/arm/mach-qcom/
F: arch/arm64/boot/dts/qcom/* F: arch/arm64/boot/dts/qcom/*
F: drivers/i2c/busses/i2c-qup.c F: drivers/i2c/busses/i2c-qup.c
F: drivers/clk/qcom/ F: drivers/clk/qcom/
F: drivers/pinctrl/qcom/
F: drivers/dma/qcom/ F: drivers/dma/qcom/
F: drivers/soc/qcom/ F: drivers/soc/qcom/
F: drivers/spi/spi-qup.c F: drivers/spi/spi-qup.c
...@@ -10267,6 +10267,13 @@ M: Heikki Krogerus <heikki.krogerus@linux.intel.com> ...@@ -10267,6 +10267,13 @@ M: Heikki Krogerus <heikki.krogerus@linux.intel.com>
S: Maintained S: Maintained
F: drivers/pinctrl/intel/ F: drivers/pinctrl/intel/
PIN CONTROLLER - QUALCOMM
M: Bjorn Andersson <bjorn.andersson@linaro.org>
S: Maintained
L: linux-arm-msm@vger.kernel.org
F: Documentation/devicetree/bindings/pinctrl/qcom,*.txt
F: drivers/pinctrl/qcom/
PIN CONTROLLER - RENESAS PIN CONTROLLER - RENESAS
M: Laurent Pinchart <laurent.pinchart@ideasonboard.com> M: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
M: Geert Uytterhoeven <geert+renesas@glider.be> M: Geert Uytterhoeven <geert+renesas@glider.be>
......
...@@ -112,7 +112,7 @@ CONFIG_GPIO_SX150X=y ...@@ -112,7 +112,7 @@ CONFIG_GPIO_SX150X=y
CONFIG_GPIO_74X164=y CONFIG_GPIO_74X164=y
CONFIG_GPIO_MAX7301=y CONFIG_GPIO_MAX7301=y
CONFIG_GPIO_MC33880=y CONFIG_GPIO_MC33880=y
CONFIG_GPIO_MCP23S08=y CONFIG_PINCTRL_MCP23S08=y
CONFIG_SENSORS_DS620=y CONFIG_SENSORS_DS620=y
CONFIG_SENSORS_MAX6639=y CONFIG_SENSORS_MAX6639=y
CONFIG_WATCHDOG=y CONFIG_WATCHDOG=y
......
...@@ -105,7 +105,7 @@ CONFIG_SPI=y ...@@ -105,7 +105,7 @@ CONFIG_SPI=y
CONFIG_SPI_ADI_V3=y CONFIG_SPI_ADI_V3=y
CONFIG_GPIOLIB=y CONFIG_GPIOLIB=y
CONFIG_GPIO_SYSFS=y CONFIG_GPIO_SYSFS=y
CONFIG_GPIO_MCP23S08=y CONFIG_PINCTRL_MCP23S08=y
# CONFIG_HWMON is not set # CONFIG_HWMON is not set
CONFIG_WATCHDOG=y CONFIG_WATCHDOG=y
CONFIG_BFIN_WDT=y CONFIG_BFIN_WDT=y
......
...@@ -348,14 +348,14 @@ static struct platform_device bfin_i2s = { ...@@ -348,14 +348,14 @@ static struct platform_device bfin_i2s = {
}; };
#endif #endif
#if IS_ENABLED(CONFIG_GPIO_MCP23S08) #if IS_ENABLED(CONFIG_PINCTRL_MCP23S08)
#include <linux/spi/mcp23s08.h> #include <linux/spi/mcp23s08.h>
static const struct mcp23s08_platform_data bfin_mcp23s08_sys_gpio_info = { static const struct mcp23s08_platform_data bfin_mcp23s08_sys_gpio_info = {
.chip[0].is_present = true, .spi_present_mask = BIT(0),
.base = 0x30, .base = 0x30,
}; };
static const struct mcp23s08_platform_data bfin_mcp23s08_usr_gpio_info = { static const struct mcp23s08_platform_data bfin_mcp23s08_usr_gpio_info = {
.chip[2].is_present = true, .spi_present_mask = BIT(2),
.base = 0x38, .base = 0x38,
}; };
#endif #endif
...@@ -423,7 +423,7 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = { ...@@ -423,7 +423,7 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
.mode = SPI_CPHA | SPI_CPOL, .mode = SPI_CPHA | SPI_CPOL,
}, },
#endif #endif
#if IS_ENABLED(CONFIG_GPIO_MCP23S08) #if IS_ENABLED(CONFIG_PINCTRL_MCP23S08)
{ {
.modalias = "mcp23s08", .modalias = "mcp23s08",
.platform_data = &bfin_mcp23s08_sys_gpio_info, .platform_data = &bfin_mcp23s08_sys_gpio_info,
......
...@@ -1887,7 +1887,7 @@ static struct platform_device i2c_bfin_twi1_device = { ...@@ -1887,7 +1887,7 @@ static struct platform_device i2c_bfin_twi1_device = {
}; };
#endif #endif
#if IS_ENABLED(CONFIG_GPIO_MCP23S08) #if IS_ENABLED(CONFIG_PINCTRL_MCP23S08)
#include <linux/spi/mcp23s08.h> #include <linux/spi/mcp23s08.h>
static const struct mcp23s08_platform_data bfin_mcp23s08_soft_switch0 = { static const struct mcp23s08_platform_data bfin_mcp23s08_soft_switch0 = {
.base = 120, .base = 120,
...@@ -1929,7 +1929,7 @@ static struct i2c_board_info __initdata bfin_i2c_board_info0[] = { ...@@ -1929,7 +1929,7 @@ static struct i2c_board_info __initdata bfin_i2c_board_info0[] = {
I2C_BOARD_INFO("ssm2602", 0x1b), I2C_BOARD_INFO("ssm2602", 0x1b),
}, },
#endif #endif
#if IS_ENABLED(CONFIG_GPIO_MCP23S08) #if IS_ENABLED(CONFIG_PINCTRL_MCP23S08)
{ {
I2C_BOARD_INFO("mcp23017", 0x21), I2C_BOARD_INFO("mcp23017", 0x21),
.platform_data = (void *)&bfin_mcp23s08_soft_switch0 .platform_data = (void *)&bfin_mcp23s08_soft_switch0
......
...@@ -364,6 +364,7 @@ config MACH_INGENIC ...@@ -364,6 +364,7 @@ config MACH_INGENIC
select SYS_SUPPORTS_ZBOOT_UART16550 select SYS_SUPPORTS_ZBOOT_UART16550
select DMA_NONCOHERENT select DMA_NONCOHERENT
select IRQ_MIPS_CPU select IRQ_MIPS_CPU
select PINCTRL
select GPIOLIB select GPIOLIB
select COMMON_CLK select COMMON_CLK
select GENERIC_IRQ_CHIP select GENERIC_IRQ_CHIP
......
...@@ -29,18 +29,30 @@ &ext { ...@@ -29,18 +29,30 @@ &ext {
&uart0 { &uart0 {
status = "okay"; status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&pins_uart0>;
}; };
&uart1 { &uart1 {
status = "okay"; status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&pins_uart1>;
}; };
&uart3 { &uart3 {
status = "okay"; status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&pins_uart2>;
}; };
&uart4 { &uart4 {
status = "okay"; status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&pins_uart4>;
}; };
&nemc { &nemc {
...@@ -61,6 +73,13 @@ nandc: nand-controller@1 { ...@@ -61,6 +73,13 @@ nandc: nand-controller@1 {
ingenic,nemc-tAW = <15>; ingenic,nemc-tAW = <15>;
ingenic,nemc-tSTRV = <100>; ingenic,nemc-tSTRV = <100>;
/*
* Only CLE/ALE are needed for the devices that are connected, rather
* than the full address line set.
*/
pinctrl-names = "default";
pinctrl-0 = <&pins_nemc>;
nand@1 { nand@1 {
reg = <1>; reg = <1>;
...@@ -69,6 +88,9 @@ nand@1 { ...@@ -69,6 +88,9 @@ nand@1 {
nand-ecc-mode = "hw"; nand-ecc-mode = "hw";
nand-on-flash-bbt; nand-on-flash-bbt;
pinctrl-names = "default";
pinctrl-0 = <&pins_nemc_cs1>;
partitions { partitions {
compatible = "fixed-partitions"; compatible = "fixed-partitions";
#address-cells = <2>; #address-cells = <2>;
...@@ -106,3 +128,41 @@ partition@0x8c00000 { ...@@ -106,3 +128,41 @@ partition@0x8c00000 {
&bch { &bch {
status = "okay"; status = "okay";
}; };
&pinctrl {
pins_uart0: uart0 {
function = "uart0";
groups = "uart0-data";
bias-disable;
};
pins_uart1: uart1 {
function = "uart1";
groups = "uart1-data";
bias-disable;
};
pins_uart2: uart2 {
function = "uart2";
groups = "uart2-data", "uart2-hwflow";
bias-disable;
};
pins_uart4: uart4 {
function = "uart4";
groups = "uart4-data";
bias-disable;
};
pins_nemc: nemc {
function = "nemc";
groups = "nemc-data", "nemc-cle-ale", "nemc-rd-we", "nemc-frd-fwe";
bias-disable;
};
pins_nemc_cs1: nemc-cs1 {
function = "nemc-cs1";
groups = "nemc-cs1";
bias-disable;
};
};
...@@ -55,6 +55,74 @@ rtc_dev: rtc@10003000 { ...@@ -55,6 +55,74 @@ rtc_dev: rtc@10003000 {
clock-names = "rtc"; clock-names = "rtc";
}; };
pinctrl: pin-controller@10010000 {
compatible = "ingenic,jz4740-pinctrl";
reg = <0x10010000 0x400>;
#address-cells = <1>;
#size-cells = <0>;
gpa: gpio@0 {
compatible = "ingenic,jz4740-gpio";
reg = <0>;
gpio-controller;
gpio-ranges = <&pinctrl 0 0 32>;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
interrupt-parent = <&intc>;
interrupts = <28>;
};
gpb: gpio@1 {
compatible = "ingenic,jz4740-gpio";
reg = <1>;
gpio-controller;
gpio-ranges = <&pinctrl 0 32 32>;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
interrupt-parent = <&intc>;
interrupts = <27>;
};
gpc: gpio@2 {
compatible = "ingenic,jz4740-gpio";
reg = <2>;
gpio-controller;
gpio-ranges = <&pinctrl 0 64 32>;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
interrupt-parent = <&intc>;
interrupts = <26>;
};
gpd: gpio@3 {
compatible = "ingenic,jz4740-gpio";
reg = <3>;
gpio-controller;
gpio-ranges = <&pinctrl 0 96 32>;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
interrupt-parent = <&intc>;
interrupts = <25>;
};
};
uart0: serial@10030000 { uart0: serial@10030000 {
compatible = "ingenic,jz4740-uart"; compatible = "ingenic,jz4740-uart";
reg = <0x10030000 0x100>; reg = <0x10030000 0x100>;
......
...@@ -44,6 +44,104 @@ cgu: jz4780-cgu@10000000 { ...@@ -44,6 +44,104 @@ cgu: jz4780-cgu@10000000 {
#clock-cells = <1>; #clock-cells = <1>;
}; };
pinctrl: pin-controller@10010000 {
compatible = "ingenic,jz4780-pinctrl";
reg = <0x10010000 0x600>;
#address-cells = <1>;
#size-cells = <0>;
gpa: gpio@0 {
compatible = "ingenic,jz4780-gpio";
reg = <0>;
gpio-controller;
gpio-ranges = <&pinctrl 0 0 32>;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
interrupt-parent = <&intc>;
interrupts = <17>;
};
gpb: gpio@1 {
compatible = "ingenic,jz4780-gpio";
reg = <1>;
gpio-controller;
gpio-ranges = <&pinctrl 0 32 32>;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
interrupt-parent = <&intc>;
interrupts = <16>;
};
gpc: gpio@2 {
compatible = "ingenic,jz4780-gpio";
reg = <2>;
gpio-controller;
gpio-ranges = <&pinctrl 0 64 32>;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
interrupt-parent = <&intc>;
interrupts = <15>;
};
gpd: gpio@3 {
compatible = "ingenic,jz4780-gpio";
reg = <3>;
gpio-controller;
gpio-ranges = <&pinctrl 0 96 32>;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
interrupt-parent = <&intc>;
interrupts = <14>;
};
gpe: gpio@4 {
compatible = "ingenic,jz4780-gpio";
reg = <4>;
gpio-controller;
gpio-ranges = <&pinctrl 0 128 32>;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
interrupt-parent = <&intc>;
interrupts = <13>;
};
gpf: gpio@5 {
compatible = "ingenic,jz4780-gpio";
reg = <5>;
gpio-controller;
gpio-ranges = <&pinctrl 0 160 32>;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
interrupt-parent = <&intc>;
interrupts = <12>;
};
};
uart0: serial@10030000 { uart0: serial@10030000 {
compatible = "ingenic,jz4780-uart"; compatible = "ingenic,jz4780-uart";
reg = <0x10030000 0x100>; reg = <0x10030000 0x100>;
......
...@@ -17,3 +17,16 @@ &ext { ...@@ -17,3 +17,16 @@ &ext {
&rtc_dev { &rtc_dev {
system-power-controller; system-power-controller;
}; };
&uart0 {
pinctrl-names = "default";
pinctrl-0 = <&pins_uart0>;
};
&pinctrl {
pins_uart0: uart0 {
function = "uart0";
groups = "uart0-data";
bias-disable;
};
};
This diff is collapsed.
...@@ -7,8 +7,6 @@ ...@@ -7,8 +7,6 @@
obj-y += prom.o time.o reset.o setup.o \ obj-y += prom.o time.o reset.o setup.o \
platform.o timer.o platform.o timer.o
obj-$(CONFIG_MACH_JZ4740) += gpio.o
CFLAGS_setup.o = -I$(src)/../../../scripts/dtc/libfdt CFLAGS_setup.o = -I$(src)/../../../scripts/dtc/libfdt
# board specific support # board specific support
......
...@@ -22,6 +22,8 @@ ...@@ -22,6 +22,8 @@
#include <linux/input/matrix_keypad.h> #include <linux/input/matrix_keypad.h>
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
#include <linux/spi/spi_gpio.h> #include <linux/spi/spi_gpio.h>
#include <linux/pinctrl/machine.h>
#include <linux/pinctrl/pinconf-generic.h>
#include <linux/power_supply.h> #include <linux/power_supply.h>
#include <linux/power/jz4740-battery.h> #include <linux/power/jz4740-battery.h>
#include <linux/power/gpio-charger.h> #include <linux/power/gpio-charger.h>
...@@ -159,7 +161,7 @@ static struct jz_nand_platform_data qi_lb60_nand_pdata = { ...@@ -159,7 +161,7 @@ static struct jz_nand_platform_data qi_lb60_nand_pdata = {
static struct gpiod_lookup_table qi_lb60_nand_gpio_table = { static struct gpiod_lookup_table qi_lb60_nand_gpio_table = {
.dev_id = "jz4740-nand.0", .dev_id = "jz4740-nand.0",
.table = { .table = {
GPIO_LOOKUP("Bank C", 30, "busy", 0), GPIO_LOOKUP("GPIOC", 30, "busy", 0),
{ }, { },
}, },
}; };
...@@ -421,8 +423,8 @@ static struct platform_device qi_lb60_audio_device = { ...@@ -421,8 +423,8 @@ static struct platform_device qi_lb60_audio_device = {
static struct gpiod_lookup_table qi_lb60_audio_gpio_table = { static struct gpiod_lookup_table qi_lb60_audio_gpio_table = {
.dev_id = "qi-lb60-audio", .dev_id = "qi-lb60-audio",
.table = { .table = {
GPIO_LOOKUP("Bank B", 29, "snd", 0), GPIO_LOOKUP("GPIOB", 29, "snd", 0),
GPIO_LOOKUP("Bank D", 4, "amp", 0), GPIO_LOOKUP("GPIOD", 4, "amp", 0),
{ }, { },
}, },
}; };
...@@ -447,13 +449,36 @@ static struct platform_device *jz_platform_devices[] __initdata = { ...@@ -447,13 +449,36 @@ static struct platform_device *jz_platform_devices[] __initdata = {
&qi_lb60_audio_device, &qi_lb60_audio_device,
}; };
static void __init board_gpio_setup(void) static unsigned long pin_cfg_bias_disable[] = {
{ PIN_CONFIG_BIAS_DISABLE,
/* We only need to enable/disable pullup here for pins used in generic };
* drivers. Everything else is done by the drivers themselves. */
jz_gpio_disable_pullup(QI_LB60_GPIO_SD_VCC_EN_N); static struct pinctrl_map pin_map[] __initdata = {
jz_gpio_disable_pullup(QI_LB60_GPIO_SD_CD); /* NAND pin configuration */
} PIN_MAP_MUX_GROUP_DEFAULT("jz4740-nand",
"10010000.jz4740-pinctrl", "nand", "nand-cs1"),
/* fbdev pin configuration */
PIN_MAP_MUX_GROUP("jz4740-fb", PINCTRL_STATE_DEFAULT,
"10010000.jz4740-pinctrl", "lcd", "lcd-8bit"),
PIN_MAP_MUX_GROUP("jz4740-fb", PINCTRL_STATE_SLEEP,
"10010000.jz4740-pinctrl", "lcd", "lcd-no-pins"),
/* MMC pin configuration */
PIN_MAP_MUX_GROUP_DEFAULT("jz4740-mmc.0",
"10010000.jz4740-pinctrl", "mmc", "mmc-1bit"),
PIN_MAP_MUX_GROUP_DEFAULT("jz4740-mmc.0",
"10010000.jz4740-pinctrl", "mmc", "mmc-4bit"),
PIN_MAP_CONFIGS_PIN_DEFAULT("jz4740-mmc.0",
"10010000.jz4740-pinctrl", "PD0", pin_cfg_bias_disable),
PIN_MAP_CONFIGS_PIN_DEFAULT("jz4740-mmc.0",
"10010000.jz4740-pinctrl", "PD2", pin_cfg_bias_disable),
/* PWM pin configuration */
PIN_MAP_MUX_GROUP_DEFAULT("jz4740-pwm",
"10010000.jz4740-pinctrl", "pwm4", "pwm4"),
};
static int __init qi_lb60_init_platform_devices(void) static int __init qi_lb60_init_platform_devices(void)
{ {
...@@ -469,6 +494,7 @@ static int __init qi_lb60_init_platform_devices(void) ...@@ -469,6 +494,7 @@ static int __init qi_lb60_init_platform_devices(void)
ARRAY_SIZE(qi_lb60_spi_board_info)); ARRAY_SIZE(qi_lb60_spi_board_info));
pwm_add_table(qi_lb60_pwm_lookup, ARRAY_SIZE(qi_lb60_pwm_lookup)); pwm_add_table(qi_lb60_pwm_lookup, ARRAY_SIZE(qi_lb60_pwm_lookup));
pinctrl_register_mappings(pin_map, ARRAY_SIZE(pin_map));
return platform_add_devices(jz_platform_devices, return platform_add_devices(jz_platform_devices,
ARRAY_SIZE(jz_platform_devices)); ARRAY_SIZE(jz_platform_devices));
...@@ -479,8 +505,6 @@ static int __init qi_lb60_board_setup(void) ...@@ -479,8 +505,6 @@ static int __init qi_lb60_board_setup(void)
{ {
printk(KERN_INFO "Qi Hardware JZ4740 QI LB60 setup\n"); printk(KERN_INFO "Qi Hardware JZ4740 QI LB60 setup\n");
board_gpio_setup();
if (qi_lb60_init_platform_devices()) if (qi_lb60_init_platform_devices())
panic("Failed to initialize platform devices"); panic("Failed to initialize platform devices");
......
This diff is collapsed.
...@@ -242,6 +242,17 @@ config GPIO_ICH ...@@ -242,6 +242,17 @@ config GPIO_ICH
If unsure, say N. If unsure, say N.
config GPIO_INGENIC
tristate "Ingenic JZ47xx SoCs GPIO support"
depends on OF
depends on MACH_INGENIC || COMPILE_TEST
select GPIOLIB_IRQCHIP
help
Say yes here to support the GPIO functionality present on the
JZ4740 and JZ4780 SoCs from Ingenic.
If unsure, say N.
config GPIO_IOP config GPIO_IOP
tristate "Intel IOP GPIO" tristate "Intel IOP GPIO"
depends on ARCH_IOP32X || ARCH_IOP33X || COMPILE_TEST depends on ARCH_IOP32X || ARCH_IOP33X || COMPILE_TEST
...@@ -1227,23 +1238,6 @@ config GPIO_PISOSR ...@@ -1227,23 +1238,6 @@ config GPIO_PISOSR
endmenu endmenu
menu "SPI or I2C GPIO expanders"
depends on (SPI_MASTER && !I2C) || I2C
config GPIO_MCP23S08
tristate "Microchip MCP23xxx I/O expander"
depends on OF_GPIO
select GPIOLIB_IRQCHIP
select REGMAP_I2C if I2C
select REGMAP if SPI_MASTER
help
SPI/I2C driver for Microchip MCP23S08/MCP23S17/MCP23008/MCP23017
I/O expanders.
This provides a GPIO interface supporting inputs and outputs.
The I2C versions of the chips can be used as interrupt-controller.
endmenu
menu "USB GPIO expanders" menu "USB GPIO expanders"
depends on USB depends on USB
......
...@@ -55,6 +55,7 @@ obj-$(CONFIG_GPIO_GPIO_MM) += gpio-gpio-mm.o ...@@ -55,6 +55,7 @@ obj-$(CONFIG_GPIO_GPIO_MM) += gpio-gpio-mm.o
obj-$(CONFIG_GPIO_GRGPIO) += gpio-grgpio.o obj-$(CONFIG_GPIO_GRGPIO) += gpio-grgpio.o
obj-$(CONFIG_HTC_EGPIO) += gpio-htc-egpio.o obj-$(CONFIG_HTC_EGPIO) += gpio-htc-egpio.o
obj-$(CONFIG_GPIO_ICH) += gpio-ich.o obj-$(CONFIG_GPIO_ICH) += gpio-ich.o
obj-$(CONFIG_GPIO_INGENIC) += gpio-ingenic.o
obj-$(CONFIG_GPIO_IOP) += gpio-iop.o obj-$(CONFIG_GPIO_IOP) += gpio-iop.o
obj-$(CONFIG_GPIO_IT87) += gpio-it87.o obj-$(CONFIG_GPIO_IT87) += gpio-it87.o
obj-$(CONFIG_GPIO_JANZ_TTL) += gpio-janz-ttl.o obj-$(CONFIG_GPIO_JANZ_TTL) += gpio-janz-ttl.o
...@@ -77,7 +78,6 @@ obj-$(CONFIG_GPIO_MENZ127) += gpio-menz127.o ...@@ -77,7 +78,6 @@ obj-$(CONFIG_GPIO_MENZ127) += gpio-menz127.o
obj-$(CONFIG_GPIO_MERRIFIELD) += gpio-merrifield.o obj-$(CONFIG_GPIO_MERRIFIELD) += gpio-merrifield.o
obj-$(CONFIG_GPIO_MC33880) += gpio-mc33880.o obj-$(CONFIG_GPIO_MC33880) += gpio-mc33880.o
obj-$(CONFIG_GPIO_MC9S08DZ60) += gpio-mc9s08dz60.o obj-$(CONFIG_GPIO_MC9S08DZ60) += gpio-mc9s08dz60.o
obj-$(CONFIG_GPIO_MCP23S08) += gpio-mcp23s08.o
obj-$(CONFIG_GPIO_ML_IOH) += gpio-ml-ioh.o obj-$(CONFIG_GPIO_ML_IOH) += gpio-ml-ioh.o
obj-$(CONFIG_GPIO_MM_LANTIQ) += gpio-mm-lantiq.o obj-$(CONFIG_GPIO_MM_LANTIQ) += gpio-mm-lantiq.o
obj-$(CONFIG_GPIO_MOCKUP) += gpio-mockup.o obj-$(CONFIG_GPIO_MOCKUP) += gpio-mockup.o
......
This diff is collapsed.
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/pinctrl/consumer.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/scatterlist.h> #include <linux/scatterlist.h>
...@@ -27,7 +28,6 @@ ...@@ -27,7 +28,6 @@
#include <linux/bitops.h> #include <linux/bitops.h>
#include <linux/gpio.h> #include <linux/gpio.h>
#include <asm/mach-jz4740/gpio.h>
#include <asm/cacheflush.h> #include <asm/cacheflush.h>
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
#include <linux/dmaengine.h> #include <linux/dmaengine.h>
...@@ -901,15 +901,6 @@ static const struct mmc_host_ops jz4740_mmc_ops = { ...@@ -901,15 +901,6 @@ static const struct mmc_host_ops jz4740_mmc_ops = {
.enable_sdio_irq = jz4740_mmc_enable_sdio_irq, .enable_sdio_irq = jz4740_mmc_enable_sdio_irq,
}; };
static const struct jz_gpio_bulk_request jz4740_mmc_pins[] = {
JZ_GPIO_BULK_PIN(MSC_CMD),
JZ_GPIO_BULK_PIN(MSC_CLK),
JZ_GPIO_BULK_PIN(MSC_DATA0),
JZ_GPIO_BULK_PIN(MSC_DATA1),
JZ_GPIO_BULK_PIN(MSC_DATA2),
JZ_GPIO_BULK_PIN(MSC_DATA3),
};
static int jz4740_mmc_request_gpio(struct device *dev, int gpio, static int jz4740_mmc_request_gpio(struct device *dev, int gpio,
const char *name, bool output, int value) const char *name, bool output, int value)
{ {
...@@ -973,15 +964,6 @@ static void jz4740_mmc_free_gpios(struct platform_device *pdev) ...@@ -973,15 +964,6 @@ static void jz4740_mmc_free_gpios(struct platform_device *pdev)
gpio_free(pdata->gpio_power); gpio_free(pdata->gpio_power);
} }
static inline size_t jz4740_mmc_num_pins(struct jz4740_mmc_host *host)
{
size_t num_pins = ARRAY_SIZE(jz4740_mmc_pins);
if (host->pdata && host->pdata->data_1bit)
num_pins -= 3;
return num_pins;
}
static int jz4740_mmc_probe(struct platform_device* pdev) static int jz4740_mmc_probe(struct platform_device* pdev)
{ {
int ret; int ret;
...@@ -1022,15 +1004,9 @@ static int jz4740_mmc_probe(struct platform_device* pdev) ...@@ -1022,15 +1004,9 @@ static int jz4740_mmc_probe(struct platform_device* pdev)
goto err_free_host; goto err_free_host;
} }
ret = jz_gpio_bulk_request(jz4740_mmc_pins, jz4740_mmc_num_pins(host));
if (ret) {
dev_err(&pdev->dev, "Failed to request mmc pins: %d\n", ret);
goto err_free_host;
}
ret = jz4740_mmc_request_gpios(mmc, pdev); ret = jz4740_mmc_request_gpios(mmc, pdev);
if (ret) if (ret)
goto err_gpio_bulk_free; goto err_release_dma;
mmc->ops = &jz4740_mmc_ops; mmc->ops = &jz4740_mmc_ops;
mmc->f_min = JZ_MMC_CLK_RATE / 128; mmc->f_min = JZ_MMC_CLK_RATE / 128;
...@@ -1086,10 +1062,9 @@ static int jz4740_mmc_probe(struct platform_device* pdev) ...@@ -1086,10 +1062,9 @@ static int jz4740_mmc_probe(struct platform_device* pdev)
free_irq(host->irq, host); free_irq(host->irq, host);
err_free_gpios: err_free_gpios:
jz4740_mmc_free_gpios(pdev); jz4740_mmc_free_gpios(pdev);
err_gpio_bulk_free: err_release_dma:
if (host->use_dma) if (host->use_dma)
jz4740_mmc_release_dma_channels(host); jz4740_mmc_release_dma_channels(host);
jz_gpio_bulk_free(jz4740_mmc_pins, jz4740_mmc_num_pins(host));
err_free_host: err_free_host:
mmc_free_host(mmc); mmc_free_host(mmc);
...@@ -1109,7 +1084,6 @@ static int jz4740_mmc_remove(struct platform_device *pdev) ...@@ -1109,7 +1084,6 @@ static int jz4740_mmc_remove(struct platform_device *pdev)
free_irq(host->irq, host); free_irq(host->irq, host);
jz4740_mmc_free_gpios(pdev); jz4740_mmc_free_gpios(pdev);
jz_gpio_bulk_free(jz4740_mmc_pins, jz4740_mmc_num_pins(host));
if (host->use_dma) if (host->use_dma)
jz4740_mmc_release_dma_channels(host); jz4740_mmc_release_dma_channels(host);
...@@ -1123,20 +1097,12 @@ static int jz4740_mmc_remove(struct platform_device *pdev) ...@@ -1123,20 +1097,12 @@ static int jz4740_mmc_remove(struct platform_device *pdev)
static int jz4740_mmc_suspend(struct device *dev) static int jz4740_mmc_suspend(struct device *dev)
{ {
struct jz4740_mmc_host *host = dev_get_drvdata(dev); return pinctrl_pm_select_sleep_state(dev);
jz_gpio_bulk_suspend(jz4740_mmc_pins, jz4740_mmc_num_pins(host));
return 0;
} }
static int jz4740_mmc_resume(struct device *dev) static int jz4740_mmc_resume(struct device *dev)
{ {
struct jz4740_mmc_host *host = dev_get_drvdata(dev); return pinctrl_pm_select_default_state(dev);
jz_gpio_bulk_resume(jz4740_mmc_pins, jz4740_mmc_num_pins(host));
return 0;
} }
static SIMPLE_DEV_PM_OPS(jz4740_mmc_pm_ops, jz4740_mmc_suspend, static SIMPLE_DEV_PM_OPS(jz4740_mmc_pm_ops, jz4740_mmc_suspend,
......
...@@ -25,7 +25,6 @@ ...@@ -25,7 +25,6 @@
#include <linux/gpio.h> #include <linux/gpio.h>
#include <asm/mach-jz4740/gpio.h>
#include <asm/mach-jz4740/jz4740_nand.h> #include <asm/mach-jz4740/jz4740_nand.h>
#define JZ_REG_NAND_CTRL 0x50 #define JZ_REG_NAND_CTRL 0x50
...@@ -310,34 +309,20 @@ static int jz_nand_detect_bank(struct platform_device *pdev, ...@@ -310,34 +309,20 @@ static int jz_nand_detect_bank(struct platform_device *pdev,
uint8_t *nand_dev_id) uint8_t *nand_dev_id)
{ {
int ret; int ret;
int gpio;
char gpio_name[9];
char res_name[6]; char res_name[6];
uint32_t ctrl; uint32_t ctrl;
struct nand_chip *chip = &nand->chip; struct nand_chip *chip = &nand->chip;
struct mtd_info *mtd = nand_to_mtd(chip); struct mtd_info *mtd = nand_to_mtd(chip);
/* Request GPIO port. */
gpio = JZ_GPIO_MEM_CS0 + bank - 1;
sprintf(gpio_name, "NAND CS%d", bank);
ret = gpio_request(gpio, gpio_name);
if (ret) {
dev_warn(&pdev->dev,
"Failed to request %s gpio %d: %d\n",
gpio_name, gpio, ret);
goto notfound_gpio;
}
/* Request I/O resource. */ /* Request I/O resource. */
sprintf(res_name, "bank%d", bank); sprintf(res_name, "bank%d", bank);
ret = jz_nand_ioremap_resource(pdev, res_name, ret = jz_nand_ioremap_resource(pdev, res_name,
&nand->bank_mem[bank - 1], &nand->bank_mem[bank - 1],
&nand->bank_base[bank - 1]); &nand->bank_base[bank - 1]);
if (ret) if (ret)
goto notfound_resource; return ret;
/* Enable chip in bank. */ /* Enable chip in bank. */
jz_gpio_set_function(gpio, JZ_GPIO_FUNC_MEM_CS0);
ctrl = readl(nand->base + JZ_REG_NAND_CTRL); ctrl = readl(nand->base + JZ_REG_NAND_CTRL);
ctrl |= JZ_NAND_CTRL_ENABLE_CHIP(bank - 1); ctrl |= JZ_NAND_CTRL_ENABLE_CHIP(bank - 1);
writel(ctrl, nand->base + JZ_REG_NAND_CTRL); writel(ctrl, nand->base + JZ_REG_NAND_CTRL);
...@@ -377,12 +362,8 @@ static int jz_nand_detect_bank(struct platform_device *pdev, ...@@ -377,12 +362,8 @@ static int jz_nand_detect_bank(struct platform_device *pdev,
dev_info(&pdev->dev, "No chip found on bank %i\n", bank); dev_info(&pdev->dev, "No chip found on bank %i\n", bank);
ctrl &= ~(JZ_NAND_CTRL_ENABLE_CHIP(bank - 1)); ctrl &= ~(JZ_NAND_CTRL_ENABLE_CHIP(bank - 1));
writel(ctrl, nand->base + JZ_REG_NAND_CTRL); writel(ctrl, nand->base + JZ_REG_NAND_CTRL);
jz_gpio_set_function(gpio, JZ_GPIO_FUNC_NONE);
jz_nand_iounmap_resource(nand->bank_mem[bank - 1], jz_nand_iounmap_resource(nand->bank_mem[bank - 1],
nand->bank_base[bank - 1]); nand->bank_base[bank - 1]);
notfound_resource:
gpio_free(gpio);
notfound_gpio:
return ret; return ret;
} }
...@@ -503,7 +484,6 @@ static int jz_nand_probe(struct platform_device *pdev) ...@@ -503,7 +484,6 @@ static int jz_nand_probe(struct platform_device *pdev)
err_unclaim_banks: err_unclaim_banks:
while (chipnr--) { while (chipnr--) {
unsigned char bank = nand->banks[chipnr]; unsigned char bank = nand->banks[chipnr];
gpio_free(JZ_GPIO_MEM_CS0 + bank - 1);
jz_nand_iounmap_resource(nand->bank_mem[bank - 1], jz_nand_iounmap_resource(nand->bank_mem[bank - 1],
nand->bank_base[bank - 1]); nand->bank_base[bank - 1]);
} }
...@@ -530,7 +510,6 @@ static int jz_nand_remove(struct platform_device *pdev) ...@@ -530,7 +510,6 @@ static int jz_nand_remove(struct platform_device *pdev)
if (bank != 0) { if (bank != 0) {
jz_nand_iounmap_resource(nand->bank_mem[bank - 1], jz_nand_iounmap_resource(nand->bank_mem[bank - 1],
nand->bank_base[bank - 1]); nand->bank_base[bank - 1]);
gpio_free(JZ_GPIO_MEM_CS0 + bank - 1);
} }
} }
......
...@@ -146,6 +146,20 @@ config PINCTRL_FALCON ...@@ -146,6 +146,20 @@ config PINCTRL_FALCON
depends on SOC_FALCON depends on SOC_FALCON
depends on PINCTRL_LANTIQ depends on PINCTRL_LANTIQ
config PINCTRL_MCP23S08
tristate "Microchip MCP23xxx I/O expander"
depends on SPI_MASTER || I2C
depends on I2C || I2C=n
select GPIOLIB_IRQCHIP
select REGMAP_I2C if I2C
select REGMAP_SPI if SPI_MASTER
select GENERIC_PINCONF
help
SPI/I2C driver for Microchip MCP23S08/MCP23S17/MCP23008/MCP23017
I/O expanders.
This provides a GPIO interface supporting inputs and outputs.
The I2C versions of the chips can be used as interrupt-controller.
config PINCTRL_MESON config PINCTRL_MESON
bool bool
depends on OF depends on OF
...@@ -174,6 +188,17 @@ config PINCTRL_ROCKCHIP ...@@ -174,6 +188,17 @@ config PINCTRL_ROCKCHIP
select GENERIC_IRQ_CHIP select GENERIC_IRQ_CHIP
select MFD_SYSCON select MFD_SYSCON
config PINCTRL_RZA1
bool "Renesas RZ/A1 gpio and pinctrl driver"
depends on OF
depends on ARCH_R7S72100 || COMPILE_TEST
select GPIOLIB
select GENERIC_PINCTRL_GROUPS
select GENERIC_PINMUX_FUNCTIONS
select GENERIC_PINCONF
help
This selects pinctrl driver for Renesas RZ/A1 platforms.
config PINCTRL_SINGLE config PINCTRL_SINGLE
tristate "One-register-per-pin type device tree based pinctrl driver" tristate "One-register-per-pin type device tree based pinctrl driver"
depends on OF depends on OF
...@@ -296,6 +321,16 @@ config PINCTRL_ZYNQ ...@@ -296,6 +321,16 @@ config PINCTRL_ZYNQ
help help
This selects the pinctrl driver for Xilinx Zynq. This selects the pinctrl driver for Xilinx Zynq.
config PINCTRL_INGENIC
bool "Pinctrl driver for the Ingenic JZ47xx SoCs"
default y
depends on OF
depends on MACH_INGENIC || COMPILE_TEST
select GENERIC_PINCONF
select GENERIC_PINCTRL_GROUPS
select GENERIC_PINMUX_FUNCTIONS
select REGMAP_MMIO
source "drivers/pinctrl/aspeed/Kconfig" source "drivers/pinctrl/aspeed/Kconfig"
source "drivers/pinctrl/bcm/Kconfig" source "drivers/pinctrl/bcm/Kconfig"
source "drivers/pinctrl/berlin/Kconfig" source "drivers/pinctrl/berlin/Kconfig"
...@@ -315,6 +350,7 @@ source "drivers/pinctrl/ti/Kconfig" ...@@ -315,6 +350,7 @@ source "drivers/pinctrl/ti/Kconfig"
source "drivers/pinctrl/uniphier/Kconfig" source "drivers/pinctrl/uniphier/Kconfig"
source "drivers/pinctrl/vt8500/Kconfig" source "drivers/pinctrl/vt8500/Kconfig"
source "drivers/pinctrl/mediatek/Kconfig" source "drivers/pinctrl/mediatek/Kconfig"
source "drivers/pinctrl/zte/Kconfig"
config PINCTRL_XWAY config PINCTRL_XWAY
bool bool
......
...@@ -19,12 +19,14 @@ obj-$(CONFIG_PINCTRL_DA850_PUPD) += pinctrl-da850-pupd.o ...@@ -19,12 +19,14 @@ obj-$(CONFIG_PINCTRL_DA850_PUPD) += pinctrl-da850-pupd.o
obj-$(CONFIG_PINCTRL_DIGICOLOR) += pinctrl-digicolor.o obj-$(CONFIG_PINCTRL_DIGICOLOR) += pinctrl-digicolor.o
obj-$(CONFIG_PINCTRL_FALCON) += pinctrl-falcon.o obj-$(CONFIG_PINCTRL_FALCON) += pinctrl-falcon.o
obj-$(CONFIG_PINCTRL_MAX77620) += pinctrl-max77620.o obj-$(CONFIG_PINCTRL_MAX77620) += pinctrl-max77620.o
obj-$(CONFIG_PINCTRL_MCP23S08) += pinctrl-mcp23s08.o
obj-$(CONFIG_PINCTRL_MESON) += meson/ obj-$(CONFIG_PINCTRL_MESON) += meson/
obj-$(CONFIG_PINCTRL_OXNAS) += pinctrl-oxnas.o obj-$(CONFIG_PINCTRL_OXNAS) += pinctrl-oxnas.o
obj-$(CONFIG_PINCTRL_PALMAS) += pinctrl-palmas.o obj-$(CONFIG_PINCTRL_PALMAS) += pinctrl-palmas.o
obj-$(CONFIG_PINCTRL_PIC32) += pinctrl-pic32.o obj-$(CONFIG_PINCTRL_PIC32) += pinctrl-pic32.o
obj-$(CONFIG_PINCTRL_PISTACHIO) += pinctrl-pistachio.o obj-$(CONFIG_PINCTRL_PISTACHIO) += pinctrl-pistachio.o
obj-$(CONFIG_PINCTRL_ROCKCHIP) += pinctrl-rockchip.o obj-$(CONFIG_PINCTRL_ROCKCHIP) += pinctrl-rockchip.o
obj-$(CONFIG_PINCTRL_RZA1) += pinctrl-rza1.o
obj-$(CONFIG_PINCTRL_SINGLE) += pinctrl-single.o obj-$(CONFIG_PINCTRL_SINGLE) += pinctrl-single.o
obj-$(CONFIG_PINCTRL_SIRF) += sirf/ obj-$(CONFIG_PINCTRL_SIRF) += sirf/
obj-$(CONFIG_PINCTRL_SX150X) += pinctrl-sx150x.o obj-$(CONFIG_PINCTRL_SX150X) += pinctrl-sx150x.o
...@@ -39,6 +41,7 @@ obj-$(CONFIG_PINCTRL_LPC18XX) += pinctrl-lpc18xx.o ...@@ -39,6 +41,7 @@ obj-$(CONFIG_PINCTRL_LPC18XX) += pinctrl-lpc18xx.o
obj-$(CONFIG_PINCTRL_TB10X) += pinctrl-tb10x.o obj-$(CONFIG_PINCTRL_TB10X) += pinctrl-tb10x.o
obj-$(CONFIG_PINCTRL_ST) += pinctrl-st.o obj-$(CONFIG_PINCTRL_ST) += pinctrl-st.o
obj-$(CONFIG_PINCTRL_ZYNQ) += pinctrl-zynq.o obj-$(CONFIG_PINCTRL_ZYNQ) += pinctrl-zynq.o
obj-$(CONFIG_PINCTRL_INGENIC) += pinctrl-ingenic.o
obj-$(CONFIG_ARCH_ASPEED) += aspeed/ obj-$(CONFIG_ARCH_ASPEED) += aspeed/
obj-y += bcm/ obj-y += bcm/
...@@ -58,3 +61,4 @@ obj-y += ti/ ...@@ -58,3 +61,4 @@ obj-y += ti/
obj-$(CONFIG_PINCTRL_UNIPHIER) += uniphier/ obj-$(CONFIG_PINCTRL_UNIPHIER) += uniphier/
obj-$(CONFIG_ARCH_VT8500) += vt8500/ obj-$(CONFIG_ARCH_VT8500) += vt8500/
obj-$(CONFIG_PINCTRL_MTK) += mediatek/ obj-$(CONFIG_PINCTRL_MTK) += mediatek/
obj-$(CONFIG_PINCTRL_ZX) += zte/
/* /*
* Copyright (C) 2013 Broadcom Corporation * Copyright (C) 2013-2017 Broadcom
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as * modify it under the terms of the GNU General Public License as
...@@ -10,9 +10,10 @@ ...@@ -10,9 +10,10 @@
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
*/ */
#include <linux/err.h> #include <linux/err.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/module.h> #include <linux/init.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/pinctrl/pinctrl.h> #include <linux/pinctrl/pinctrl.h>
...@@ -1444,10 +1445,4 @@ static struct platform_driver bcm281xx_pinctrl_driver = { ...@@ -1444,10 +1445,4 @@ static struct platform_driver bcm281xx_pinctrl_driver = {
.of_match_table = bcm281xx_pinctrl_of_match, .of_match_table = bcm281xx_pinctrl_of_match,
}, },
}; };
builtin_platform_driver_probe(bcm281xx_pinctrl_driver, bcm281xx_pinctrl_probe);
module_platform_driver_probe(bcm281xx_pinctrl_driver, bcm281xx_pinctrl_probe);
MODULE_AUTHOR("Broadcom Corporation <bcm-kernel-feedback-list@broadcom.com>");
MODULE_AUTHOR("Sherman Yin <syin@broadcom.com>");
MODULE_DESCRIPTION("Broadcom BCM281xx pinctrl driver");
MODULE_LICENSE("GPL v2");
...@@ -27,7 +27,7 @@ ...@@ -27,7 +27,7 @@
#include <linux/io.h> #include <linux/io.h>
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/irqdesc.h> #include <linux/irqdesc.h>
#include <linux/module.h> #include <linux/init.h>
#include <linux/of_address.h> #include <linux/of_address.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_irq.h> #include <linux/of_irq.h>
...@@ -1048,6 +1048,10 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev) ...@@ -1048,6 +1048,10 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev)
for (i = 0; i < BCM2835_NUM_IRQS; i++) { for (i = 0; i < BCM2835_NUM_IRQS; i++) {
pc->irq[i] = irq_of_parse_and_map(np, i); pc->irq[i] = irq_of_parse_and_map(np, i);
pc->irq_group[i] = i; pc->irq_group[i] = i;
if (pc->irq[i] == 0)
continue;
/* /*
* Use the same handler for all groups: this is necessary * Use the same handler for all groups: this is necessary
* since we use one gpiochip to cover all lines - the * since we use one gpiochip to cover all lines - the
...@@ -1075,31 +1079,17 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev) ...@@ -1075,31 +1079,17 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev)
return 0; return 0;
} }
static int bcm2835_pinctrl_remove(struct platform_device *pdev)
{
struct bcm2835_pinctrl *pc = platform_get_drvdata(pdev);
gpiochip_remove(&pc->gpio_chip);
return 0;
}
static const struct of_device_id bcm2835_pinctrl_match[] = { static const struct of_device_id bcm2835_pinctrl_match[] = {
{ .compatible = "brcm,bcm2835-gpio" }, { .compatible = "brcm,bcm2835-gpio" },
{} {}
}; };
MODULE_DEVICE_TABLE(of, bcm2835_pinctrl_match);
static struct platform_driver bcm2835_pinctrl_driver = { static struct platform_driver bcm2835_pinctrl_driver = {
.probe = bcm2835_pinctrl_probe, .probe = bcm2835_pinctrl_probe,
.remove = bcm2835_pinctrl_remove,
.driver = { .driver = {
.name = MODULE_NAME, .name = MODULE_NAME,
.of_match_table = bcm2835_pinctrl_match, .of_match_table = bcm2835_pinctrl_match,
.suppress_bind_attrs = true,
}, },
}; };
module_platform_driver(bcm2835_pinctrl_driver); builtin_platform_driver(bcm2835_pinctrl_driver);
MODULE_AUTHOR("Chris Boot, Simon Arlott, Stephen Warren");
MODULE_DESCRIPTION("BCM2835 Pin control driver");
MODULE_LICENSE("GPL");
/* Copyright (C) 2014-2015 Broadcom Corporation /*
* Copyright (C) 2014-2017 Broadcom
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as * modify it under the terms of the GNU General Public License as
...@@ -8,6 +9,10 @@ ...@@ -8,6 +9,10 @@
* kind, whether express or implied; without even the implied warranty * kind, whether express or implied; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
*/
/*
* Broadcom Cygnus IOMUX driver
* *
* This file contains the Cygnus IOMUX driver that supports group based PINMUX * This file contains the Cygnus IOMUX driver that supports group based PINMUX
* configuration. Although PINMUX configuration is mainly group based, the * configuration. Although PINMUX configuration is mainly group based, the
...@@ -17,7 +22,6 @@ ...@@ -17,7 +22,6 @@
#include <linux/err.h> #include <linux/err.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/module.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
...@@ -1016,7 +1020,3 @@ static int __init cygnus_pinmux_init(void) ...@@ -1016,7 +1020,3 @@ static int __init cygnus_pinmux_init(void)
return platform_driver_register(&cygnus_pinmux_driver); return platform_driver_register(&cygnus_pinmux_driver);
} }
arch_initcall(cygnus_pinmux_init); arch_initcall(cygnus_pinmux_init);
MODULE_AUTHOR("Ray Jui <rjui@broadcom.com>");
MODULE_DESCRIPTION("Broadcom Cygnus IOMUX driver");
MODULE_LICENSE("GPL v2");
/* /*
* Copyright (C) 2014-2015 Broadcom Corporation * Copyright (C) 2014-2017 Broadcom
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as * modify it under the terms of the GNU General Public License as
...@@ -9,7 +9,9 @@ ...@@ -9,7 +9,9 @@
* kind, whether express or implied; without even the implied warranty * kind, whether express or implied; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* */
/*
* This file contains the Broadcom Iproc GPIO driver that supports 3 * This file contains the Broadcom Iproc GPIO driver that supports 3
* GPIO controllers on Iproc including the ASIU GPIO controller, the * GPIO controllers on Iproc including the ASIU GPIO controller, the
* chipCommonG GPIO controller, and the always-on GPIO controller. Basic * chipCommonG GPIO controller, and the always-on GPIO controller. Basic
......
/* /*
* Copyright (C) 2015 Broadcom Corporation * Copyright (C) 2014-2017 Broadcom
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as * modify it under the terms of the GNU General Public License as
...@@ -9,7 +9,9 @@ ...@@ -9,7 +9,9 @@
* kind, whether express or implied; without even the implied warranty * kind, whether express or implied; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* */
/*
* This file contains the Broadcom Northstar Plus (NSP) GPIO driver that * This file contains the Broadcom Northstar Plus (NSP) GPIO driver that
* supports the chipCommonA GPIO controller. Basic PINCONF such as bias, * supports the chipCommonA GPIO controller. Basic PINCONF such as bias,
* pull up/down, slew and drive strength are also supported in this driver. * pull up/down, slew and drive strength are also supported in this driver.
......
...@@ -170,7 +170,7 @@ const char *pin_get_name(struct pinctrl_dev *pctldev, const unsigned pin) ...@@ -170,7 +170,7 @@ const char *pin_get_name(struct pinctrl_dev *pctldev, const unsigned pin)
const struct pin_desc *desc; const struct pin_desc *desc;
desc = pin_desc_get(pctldev, pin); desc = pin_desc_get(pctldev, pin);
if (desc == NULL) { if (!desc) {
dev_err(pctldev->dev, "failed to get pin(%d) name\n", dev_err(pctldev->dev, "failed to get pin(%d) name\n",
pin); pin);
return NULL; return NULL;
...@@ -214,7 +214,7 @@ static void pinctrl_free_pindescs(struct pinctrl_dev *pctldev, ...@@ -214,7 +214,7 @@ static void pinctrl_free_pindescs(struct pinctrl_dev *pctldev,
pindesc = radix_tree_lookup(&pctldev->pin_desc_tree, pindesc = radix_tree_lookup(&pctldev->pin_desc_tree,
pins[i].number); pins[i].number);
if (pindesc != NULL) { if (pindesc) {
radix_tree_delete(&pctldev->pin_desc_tree, radix_tree_delete(&pctldev->pin_desc_tree,
pins[i].number); pins[i].number);
if (pindesc->dynamic_name) if (pindesc->dynamic_name)
...@@ -230,7 +230,7 @@ static int pinctrl_register_one_pin(struct pinctrl_dev *pctldev, ...@@ -230,7 +230,7 @@ static int pinctrl_register_one_pin(struct pinctrl_dev *pctldev,
struct pin_desc *pindesc; struct pin_desc *pindesc;
pindesc = pin_desc_get(pctldev, pin->number); pindesc = pin_desc_get(pctldev, pin->number);
if (pindesc != NULL) { if (pindesc) {
dev_err(pctldev->dev, "pin %d already registered\n", dev_err(pctldev->dev, "pin %d already registered\n",
pin->number); pin->number);
return -EINVAL; return -EINVAL;
...@@ -248,7 +248,7 @@ static int pinctrl_register_one_pin(struct pinctrl_dev *pctldev, ...@@ -248,7 +248,7 @@ static int pinctrl_register_one_pin(struct pinctrl_dev *pctldev,
pindesc->name = pin->name; pindesc->name = pin->name;
} else { } else {
pindesc->name = kasprintf(GFP_KERNEL, "PIN%u", pin->number); pindesc->name = kasprintf(GFP_KERNEL, "PIN%u", pin->number);
if (pindesc->name == NULL) { if (!pindesc->name) {
kfree(pindesc); kfree(pindesc);
return -ENOMEM; return -ENOMEM;
} }
...@@ -402,7 +402,7 @@ static int pinctrl_get_device_gpio_range(unsigned gpio, ...@@ -402,7 +402,7 @@ static int pinctrl_get_device_gpio_range(unsigned gpio,
struct pinctrl_gpio_range *range; struct pinctrl_gpio_range *range;
range = pinctrl_match_gpio_range(pctldev, gpio); range = pinctrl_match_gpio_range(pctldev, gpio);
if (range != NULL) { if (range) {
*outdev = pctldev; *outdev = pctldev;
*outrange = range; *outrange = range;
mutex_unlock(&pinctrldev_list_mutex); mutex_unlock(&pinctrldev_list_mutex);
...@@ -933,7 +933,7 @@ static int add_setting(struct pinctrl *p, struct pinctrl_dev *pctldev, ...@@ -933,7 +933,7 @@ static int add_setting(struct pinctrl *p, struct pinctrl_dev *pctldev,
else else
setting->pctldev = setting->pctldev =
get_pinctrl_dev_from_devname(map->ctrl_dev_name); get_pinctrl_dev_from_devname(map->ctrl_dev_name);
if (setting->pctldev == NULL) { if (!setting->pctldev) {
kfree(setting); kfree(setting);
/* Do not defer probing of hogs (circular loop) */ /* Do not defer probing of hogs (circular loop) */
if (!strcmp(map->ctrl_dev_name, map->dev_name)) if (!strcmp(map->ctrl_dev_name, map->dev_name))
...@@ -1024,6 +1024,16 @@ static struct pinctrl *create_pinctrl(struct device *dev, ...@@ -1024,6 +1024,16 @@ static struct pinctrl *create_pinctrl(struct device *dev,
/* Map must be for this device */ /* Map must be for this device */
if (strcmp(map->dev_name, devname)) if (strcmp(map->dev_name, devname))
continue; continue;
/*
* If pctldev is not null, we are claiming hog for it,
* that means, setting that is served by pctldev by itself.
*
* Thus we must skip map that is for this device but is served
* by other device.
*/
if (pctldev &&
strcmp(dev_name(pctldev->dev), map->ctrl_dev_name))
continue;
ret = add_setting(p, pctldev, map); ret = add_setting(p, pctldev, map);
/* /*
...@@ -1080,7 +1090,7 @@ struct pinctrl *pinctrl_get(struct device *dev) ...@@ -1080,7 +1090,7 @@ struct pinctrl *pinctrl_get(struct device *dev)
* return another pointer to it. * return another pointer to it.
*/ */
p = find_pinctrl(dev); p = find_pinctrl(dev);
if (p != NULL) { if (p) {
dev_dbg(dev, "obtain a copy of previously claimed pinctrl\n"); dev_dbg(dev, "obtain a copy of previously claimed pinctrl\n");
kref_get(&p->users); kref_get(&p->users);
return p; return p;
...@@ -1551,7 +1561,7 @@ static int pinctrl_pins_show(struct seq_file *s, void *what) ...@@ -1551,7 +1561,7 @@ static int pinctrl_pins_show(struct seq_file *s, void *what)
pin = pctldev->desc->pins[i].number; pin = pctldev->desc->pins[i].number;
desc = pin_desc_get(pctldev, pin); desc = pin_desc_get(pctldev, pin);
/* Pin space may be sparse */ /* Pin space may be sparse */
if (desc == NULL) if (!desc)
continue; continue;
seq_printf(s, "pin %d (%s) ", pin, desc->name); seq_printf(s, "pin %d (%s) ", pin, desc->name);
...@@ -1718,7 +1728,7 @@ static int pinctrl_maps_show(struct seq_file *s, void *what) ...@@ -1718,7 +1728,7 @@ static int pinctrl_maps_show(struct seq_file *s, void *what)
break; break;
} }
seq_printf(s, "\n"); seq_putc(s, '\n');
} }
mutex_unlock(&pinctrl_maps_mutex); mutex_unlock(&pinctrl_maps_mutex);
...@@ -2131,7 +2141,7 @@ void pinctrl_unregister(struct pinctrl_dev *pctldev) ...@@ -2131,7 +2141,7 @@ void pinctrl_unregister(struct pinctrl_dev *pctldev)
{ {
struct pinctrl_gpio_range *range, *n; struct pinctrl_gpio_range *range, *n;
if (pctldev == NULL) if (!pctldev)
return; return;
mutex_lock(&pctldev->mutex); mutex_lock(&pctldev->mutex);
......
...@@ -2,7 +2,7 @@ config PINCTRL_IMX ...@@ -2,7 +2,7 @@ config PINCTRL_IMX
bool bool
select GENERIC_PINCTRL_GROUPS select GENERIC_PINCTRL_GROUPS
select GENERIC_PINMUX_FUNCTIONS select GENERIC_PINMUX_FUNCTIONS
select PINCONF select GENERIC_PINCONF
select REGMAP select REGMAP
config PINCTRL_IMX1_CORE config PINCTRL_IMX1_CORE
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include <linux/regmap.h> #include <linux/regmap.h>
#include "../core.h" #include "../core.h"
#include "../pinconf.h"
#include "../pinmux.h" #include "../pinmux.h"
#include "pinctrl-imx.h" #include "pinctrl-imx.h"
...@@ -196,14 +197,16 @@ static int imx_pmx_set(struct pinctrl_dev *pctldev, unsigned selector, ...@@ -196,14 +197,16 @@ static int imx_pmx_set(struct pinctrl_dev *pctldev, unsigned selector,
if (info->flags & SHARE_MUX_CONF_REG) { if (info->flags & SHARE_MUX_CONF_REG) {
u32 reg; u32 reg;
reg = readl(ipctl->base + pin_reg->mux_reg); reg = readl(ipctl->base + pin_reg->mux_reg);
reg &= ~(0x7 << 20); reg &= ~info->mux_mask;
reg |= (pin->mux_mode << 20); reg |= (pin->mux_mode << info->mux_shift);
writel(reg, ipctl->base + pin_reg->mux_reg); writel(reg, ipctl->base + pin_reg->mux_reg);
dev_dbg(ipctl->dev, "write: offset 0x%x val 0x%x\n",
pin_reg->mux_reg, reg);
} else { } else {
writel(pin->mux_mode, ipctl->base + pin_reg->mux_reg); writel(pin->mux_mode, ipctl->base + pin_reg->mux_reg);
dev_dbg(ipctl->dev, "write: offset 0x%x val 0x%x\n",
pin_reg->mux_reg, pin->mux_mode);
} }
dev_dbg(ipctl->dev, "write: offset 0x%x val 0x%x\n",
pin_reg->mux_reg, pin->mux_mode);
/* /*
* If the select input value begins with 0xff, it's a quirky * If the select input value begins with 0xff, it's a quirky
...@@ -287,7 +290,7 @@ static int imx_pmx_gpio_request_enable(struct pinctrl_dev *pctldev, ...@@ -287,7 +290,7 @@ static int imx_pmx_gpio_request_enable(struct pinctrl_dev *pctldev,
mux_pin: mux_pin:
reg = readl(ipctl->base + pin_reg->mux_reg); reg = readl(ipctl->base + pin_reg->mux_reg);
reg &= ~(0x7 << 20); reg &= ~info->mux_mask;
reg |= imx_pin->config; reg |= imx_pin->config;
writel(reg, ipctl->base + pin_reg->mux_reg); writel(reg, ipctl->base + pin_reg->mux_reg);
...@@ -359,6 +362,62 @@ static const struct pinmux_ops imx_pmx_ops = { ...@@ -359,6 +362,62 @@ static const struct pinmux_ops imx_pmx_ops = {
.gpio_set_direction = imx_pmx_gpio_set_direction, .gpio_set_direction = imx_pmx_gpio_set_direction,
}; };
/* decode generic config into raw register values */
static u32 imx_pinconf_decode_generic_config(struct imx_pinctrl *ipctl,
unsigned long *configs,
unsigned int num_configs)
{
struct imx_pinctrl_soc_info *info = ipctl->info;
struct imx_cfg_params_decode *decode;
enum pin_config_param param;
u32 raw_config = 0;
u32 param_val;
int i, j;
WARN_ON(num_configs > info->num_decodes);
for (i = 0; i < num_configs; i++) {
param = pinconf_to_config_param(configs[i]);
param_val = pinconf_to_config_argument(configs[i]);
decode = info->decodes;
for (j = 0; j < info->num_decodes; j++) {
if (param == decode->param) {
if (decode->invert)
param_val = !param_val;
raw_config |= (param_val << decode->shift)
& decode->mask;
break;
}
decode++;
}
}
if (info->fixup)
info->fixup(configs, num_configs, &raw_config);
return raw_config;
}
static u32 imx_pinconf_parse_generic_config(struct device_node *np,
struct imx_pinctrl *ipctl)
{
struct imx_pinctrl_soc_info *info = ipctl->info;
struct pinctrl_dev *pctl = ipctl->pctl;
unsigned int num_configs;
unsigned long *configs;
int ret;
if (!info->generic_pinconf)
return 0;
ret = pinconf_generic_parse_dt_config(np, pctl, &configs,
&num_configs);
if (ret)
return 0;
return imx_pinconf_decode_generic_config(ipctl, configs, num_configs);
}
static int imx_pinconf_get(struct pinctrl_dev *pctldev, static int imx_pinconf_get(struct pinctrl_dev *pctldev,
unsigned pin_id, unsigned long *config) unsigned pin_id, unsigned long *config)
{ {
...@@ -375,7 +434,7 @@ static int imx_pinconf_get(struct pinctrl_dev *pctldev, ...@@ -375,7 +434,7 @@ static int imx_pinconf_get(struct pinctrl_dev *pctldev,
*config = readl(ipctl->base + pin_reg->conf_reg); *config = readl(ipctl->base + pin_reg->conf_reg);
if (info->flags & SHARE_MUX_CONF_REG) if (info->flags & SHARE_MUX_CONF_REG)
*config &= 0xffff; *config &= ~info->mux_mask;
return 0; return 0;
} }
...@@ -402,14 +461,16 @@ static int imx_pinconf_set(struct pinctrl_dev *pctldev, ...@@ -402,14 +461,16 @@ static int imx_pinconf_set(struct pinctrl_dev *pctldev,
if (info->flags & SHARE_MUX_CONF_REG) { if (info->flags & SHARE_MUX_CONF_REG) {
u32 reg; u32 reg;
reg = readl(ipctl->base + pin_reg->conf_reg); reg = readl(ipctl->base + pin_reg->conf_reg);
reg &= ~0xffff; reg &= info->mux_mask;
reg |= configs[i]; reg |= configs[i];
writel(reg, ipctl->base + pin_reg->conf_reg); writel(reg, ipctl->base + pin_reg->conf_reg);
dev_dbg(ipctl->dev, "write: offset 0x%x val 0x%x\n",
pin_reg->conf_reg, reg);
} else { } else {
writel(configs[i], ipctl->base + pin_reg->conf_reg); writel(configs[i], ipctl->base + pin_reg->conf_reg);
dev_dbg(ipctl->dev, "write: offset 0x%x val 0x%lx\n",
pin_reg->conf_reg, configs[i]);
} }
dev_dbg(ipctl->dev, "write: offset 0x%x val 0x%lx\n",
pin_reg->conf_reg, configs[i]);
} /* for each config */ } /* for each config */
return 0; return 0;
...@@ -475,9 +536,10 @@ static const struct pinconf_ops imx_pinconf_ops = { ...@@ -475,9 +536,10 @@ static const struct pinconf_ops imx_pinconf_ops = {
static int imx_pinctrl_parse_groups(struct device_node *np, static int imx_pinctrl_parse_groups(struct device_node *np,
struct group_desc *grp, struct group_desc *grp,
struct imx_pinctrl_soc_info *info, struct imx_pinctrl *ipctl,
u32 index) u32 index)
{ {
struct imx_pinctrl_soc_info *info = ipctl->info;
int size, pin_size; int size, pin_size;
const __be32 *list; const __be32 *list;
int i; int i;
...@@ -489,25 +551,44 @@ static int imx_pinctrl_parse_groups(struct device_node *np, ...@@ -489,25 +551,44 @@ static int imx_pinctrl_parse_groups(struct device_node *np,
pin_size = SHARE_FSL_PIN_SIZE; pin_size = SHARE_FSL_PIN_SIZE;
else else
pin_size = FSL_PIN_SIZE; pin_size = FSL_PIN_SIZE;
if (info->generic_pinconf)
pin_size -= 4;
/* Initialise group */ /* Initialise group */
grp->name = np->name; grp->name = np->name;
/* /*
* the binding format is fsl,pins = <PIN_FUNC_ID CONFIG ...>, * the binding format is fsl,pins = <PIN_FUNC_ID CONFIG ...>,
* do sanity check and calculate pins number * do sanity check and calculate pins number
*
* First try legacy 'fsl,pins' property, then fall back to the
* generic 'pins'.
*
* Note: for generic 'pins' case, there's no CONFIG part in
* the binding format.
*/ */
list = of_get_property(np, "fsl,pins", &size); list = of_get_property(np, "fsl,pins", &size);
if (!list) { if (!list) {
dev_err(info->dev, "no fsl,pins property in node %s\n", np->full_name); list = of_get_property(np, "pins", &size);
return -EINVAL; if (!list) {
dev_err(info->dev,
"no fsl,pins and pins property in node %s\n",
np->full_name);
return -EINVAL;
}
} }
/* we do not check return since it's safe node passed down */ /* we do not check return since it's safe node passed down */
if (!size || size % pin_size) { if (!size || size % pin_size) {
dev_err(info->dev, "Invalid fsl,pins property in node %s\n", np->full_name); dev_err(info->dev, "Invalid fsl,pins or pins property in node %s\n",
np->full_name);
return -EINVAL; return -EINVAL;
} }
/* first try to parse the generic pin config */
config = imx_pinconf_parse_generic_config(np, ipctl);
grp->num_pins = size / pin_size; grp->num_pins = size / pin_size;
grp->data = devm_kzalloc(info->dev, grp->num_pins * grp->data = devm_kzalloc(info->dev, grp->num_pins *
sizeof(struct imx_pin), GFP_KERNEL); sizeof(struct imx_pin), GFP_KERNEL);
...@@ -544,11 +625,18 @@ static int imx_pinctrl_parse_groups(struct device_node *np, ...@@ -544,11 +625,18 @@ static int imx_pinctrl_parse_groups(struct device_node *np,
pin->mux_mode = be32_to_cpu(*list++); pin->mux_mode = be32_to_cpu(*list++);
pin->input_val = be32_to_cpu(*list++); pin->input_val = be32_to_cpu(*list++);
/* SION bit is in mux register */ if (info->generic_pinconf) {
config = be32_to_cpu(*list++); /* generic pin config decoded */
if (config & IMX_PAD_SION) pin->config = config;
pin->mux_mode |= IOMUXC_CONFIG_SION; } else {
pin->config = config & ~IMX_PAD_SION; /* legacy pin config read from devicetree */
config = be32_to_cpu(*list++);
/* SION bit is in mux register */
if (config & IMX_PAD_SION)
pin->mux_mode |= IOMUXC_CONFIG_SION;
pin->config = config & ~IMX_PAD_SION;
}
dev_dbg(info->dev, "%s: 0x%x 0x%08lx", info->pins[pin_id].name, dev_dbg(info->dev, "%s: 0x%x 0x%08lx", info->pins[pin_id].name,
pin->mux_mode, pin->config); pin->mux_mode, pin->config);
...@@ -581,9 +669,10 @@ static int imx_pinctrl_parse_functions(struct device_node *np, ...@@ -581,9 +669,10 @@ static int imx_pinctrl_parse_functions(struct device_node *np,
dev_err(info->dev, "no groups defined in %s\n", np->full_name); dev_err(info->dev, "no groups defined in %s\n", np->full_name);
return -EINVAL; return -EINVAL;
} }
func->group_names = devm_kzalloc(info->dev, func->group_names = devm_kcalloc(info->dev, func->num_group_names,
func->num_group_names *
sizeof(char *), GFP_KERNEL); sizeof(char *), GFP_KERNEL);
if (!func->group_names)
return -ENOMEM;
for_each_child_of_node(np, child) { for_each_child_of_node(np, child) {
func->group_names[i] = child->name; func->group_names[i] = child->name;
...@@ -598,7 +687,7 @@ static int imx_pinctrl_parse_functions(struct device_node *np, ...@@ -598,7 +687,7 @@ static int imx_pinctrl_parse_functions(struct device_node *np,
info->group_index++, grp); info->group_index++, grp);
mutex_unlock(&info->mutex); mutex_unlock(&info->mutex);
imx_pinctrl_parse_groups(child, grp, info, i++); imx_pinctrl_parse_groups(child, grp, ipctl, i++);
} }
return 0; return 0;
...@@ -769,6 +858,10 @@ int imx_pinctrl_probe(struct platform_device *pdev, ...@@ -769,6 +858,10 @@ int imx_pinctrl_probe(struct platform_device *pdev,
imx_pinctrl_desc->confops = &imx_pinconf_ops; imx_pinctrl_desc->confops = &imx_pinconf_ops;
imx_pinctrl_desc->owner = THIS_MODULE; imx_pinctrl_desc->owner = THIS_MODULE;
/* for generic pinconf */
imx_pinctrl_desc->custom_params = info->custom_params;
imx_pinctrl_desc->num_custom_params = info->num_custom_params;
mutex_init(&info->mutex); mutex_init(&info->mutex);
ipctl->info = info; ipctl->info = info;
......
...@@ -15,6 +15,8 @@ ...@@ -15,6 +15,8 @@
#ifndef __DRIVERS_PINCTRL_IMX_H #ifndef __DRIVERS_PINCTRL_IMX_H
#define __DRIVERS_PINCTRL_IMX_H #define __DRIVERS_PINCTRL_IMX_H
#include <linux/pinctrl/pinconf-generic.h>
struct platform_device; struct platform_device;
/** /**
...@@ -44,6 +46,14 @@ struct imx_pin_reg { ...@@ -44,6 +46,14 @@ struct imx_pin_reg {
s16 conf_reg; s16 conf_reg;
}; };
/* decode a generic config into raw register value */
struct imx_cfg_params_decode {
enum pin_config_param param;
u32 mask;
u8 shift;
bool invert;
};
struct imx_pinctrl_soc_info { struct imx_pinctrl_soc_info {
struct device *dev; struct device *dev;
const struct pinctrl_pin_desc *pins; const struct pinctrl_pin_desc *pins;
...@@ -53,8 +63,27 @@ struct imx_pinctrl_soc_info { ...@@ -53,8 +63,27 @@ struct imx_pinctrl_soc_info {
unsigned int flags; unsigned int flags;
const char *gpr_compatible; const char *gpr_compatible;
struct mutex mutex; struct mutex mutex;
/* MUX_MODE shift and mask in case SHARE_MUX_CONF_REG */
unsigned int mux_mask;
u8 mux_shift;
/* generic pinconf */
bool generic_pinconf;
const struct pinconf_generic_params *custom_params;
unsigned int num_custom_params;
struct imx_cfg_params_decode *decodes;
unsigned int num_decodes;
void (*fixup)(unsigned long *configs, unsigned int num_configs,
u32 *raw_config);
}; };
#define IMX_CFG_PARAMS_DECODE(p, m, o) \
{ .param = p, .mask = m, .shift = o, .invert = false, }
#define IMX_CFG_PARAMS_DECODE_INVERT(p, m, o) \
{ .param = p, .mask = m, .shift = o, .invert = true, }
#define SHARE_MUX_CONF_REG 0x1 #define SHARE_MUX_CONF_REG 0x1
#define ZERO_OFFSET_VALID 0x2 #define ZERO_OFFSET_VALID 0x2
......
...@@ -358,19 +358,19 @@ static const struct pinctrl_pin_desc imx7d_lpsr_pinctrl_pads[] = { ...@@ -358,19 +358,19 @@ static const struct pinctrl_pin_desc imx7d_lpsr_pinctrl_pads[] = {
IMX_PINCTRL_PIN(MX7D_PAD_GPIO1_IO07), IMX_PINCTRL_PIN(MX7D_PAD_GPIO1_IO07),
}; };
static struct imx_pinctrl_soc_info imx7d_pinctrl_info = { static const struct imx_pinctrl_soc_info imx7d_pinctrl_info = {
.pins = imx7d_pinctrl_pads, .pins = imx7d_pinctrl_pads,
.npins = ARRAY_SIZE(imx7d_pinctrl_pads), .npins = ARRAY_SIZE(imx7d_pinctrl_pads),
.gpr_compatible = "fsl,imx7d-iomuxc-gpr", .gpr_compatible = "fsl,imx7d-iomuxc-gpr",
}; };
static struct imx_pinctrl_soc_info imx7d_lpsr_pinctrl_info = { static const struct imx_pinctrl_soc_info imx7d_lpsr_pinctrl_info = {
.pins = imx7d_lpsr_pinctrl_pads, .pins = imx7d_lpsr_pinctrl_pads,
.npins = ARRAY_SIZE(imx7d_lpsr_pinctrl_pads), .npins = ARRAY_SIZE(imx7d_lpsr_pinctrl_pads),
.flags = ZERO_OFFSET_VALID, .flags = ZERO_OFFSET_VALID,
}; };
static struct of_device_id imx7d_pinctrl_of_match[] = { static const struct of_device_id imx7d_pinctrl_of_match[] = {
{ .compatible = "fsl,imx7d-iomuxc", .data = &imx7d_pinctrl_info, }, { .compatible = "fsl,imx7d-iomuxc", .data = &imx7d_pinctrl_info, },
{ .compatible = "fsl,imx7d-iomuxc-lpsr", .data = &imx7d_lpsr_pinctrl_info }, { .compatible = "fsl,imx7d-iomuxc-lpsr", .data = &imx7d_lpsr_pinctrl_info },
{ /* sentinel */ } { /* sentinel */ }
......
...@@ -299,6 +299,8 @@ static struct imx_pinctrl_soc_info vf610_pinctrl_info = { ...@@ -299,6 +299,8 @@ static struct imx_pinctrl_soc_info vf610_pinctrl_info = {
.pins = vf610_pinctrl_pads, .pins = vf610_pinctrl_pads,
.npins = ARRAY_SIZE(vf610_pinctrl_pads), .npins = ARRAY_SIZE(vf610_pinctrl_pads),
.flags = SHARE_MUX_CONF_REG | ZERO_OFFSET_VALID, .flags = SHARE_MUX_CONF_REG | ZERO_OFFSET_VALID,
.mux_mask = 0x700000,
.mux_shift = 20,
}; };
static const struct of_device_id vf610_pinctrl_of_match[] = { static const struct of_device_id vf610_pinctrl_of_match[] = {
......
...@@ -56,6 +56,14 @@ config PINCTRL_BROXTON ...@@ -56,6 +56,14 @@ config PINCTRL_BROXTON
Broxton pinctrl driver provides an interface that allows Broxton pinctrl driver provides an interface that allows
configuring of SoC pins and using them as GPIOs. configuring of SoC pins and using them as GPIOs.
config PINCTRL_CANNONLAKE
tristate "Intel Cannon Lake PCH pinctrl and GPIO driver"
depends on ACPI
select PINCTRL_INTEL
help
This pinctrl driver provides an interface that allows configuring
of Intel Cannon Lake PCH pins and using them as GPIOs.
config PINCTRL_GEMINILAKE config PINCTRL_GEMINILAKE
tristate "Intel Gemini Lake SoC pinctrl and GPIO driver" tristate "Intel Gemini Lake SoC pinctrl and GPIO driver"
depends on ACPI depends on ACPI
......
...@@ -5,5 +5,6 @@ obj-$(CONFIG_PINCTRL_CHERRYVIEW) += pinctrl-cherryview.o ...@@ -5,5 +5,6 @@ obj-$(CONFIG_PINCTRL_CHERRYVIEW) += pinctrl-cherryview.o
obj-$(CONFIG_PINCTRL_MERRIFIELD) += pinctrl-merrifield.o obj-$(CONFIG_PINCTRL_MERRIFIELD) += pinctrl-merrifield.o
obj-$(CONFIG_PINCTRL_INTEL) += pinctrl-intel.o obj-$(CONFIG_PINCTRL_INTEL) += pinctrl-intel.o
obj-$(CONFIG_PINCTRL_BROXTON) += pinctrl-broxton.o obj-$(CONFIG_PINCTRL_BROXTON) += pinctrl-broxton.o
obj-$(CONFIG_PINCTRL_CANNONLAKE) += pinctrl-cannonlake.o
obj-$(CONFIG_PINCTRL_GEMINILAKE) += pinctrl-geminilake.o obj-$(CONFIG_PINCTRL_GEMINILAKE) += pinctrl-geminilake.o
obj-$(CONFIG_PINCTRL_SUNRISEPOINT) += pinctrl-sunrisepoint.o obj-$(CONFIG_PINCTRL_SUNRISEPOINT) += pinctrl-sunrisepoint.o
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment