Commit 5ab35662 authored by Linus Torvalds's avatar Linus Torvalds

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

Pull pin control updates from Linus Walleij:
 "Pin control bulk changes for the v4.11 kernel cycle.

  Core changes:

   - Switch the generic pin config argument from 16 to 24 bits, only use
     8 bits for the configuration type. We might need to encode more
     information about a certain setting than we need to encode
     different generic settings.

   - Add a cross-talk API to the pin control GPIO back-end, utilizing
     pinctrl_gpio_set_config() from GPIO drivers that want to set up a
     certain pin configuration in the back-end.

     This also includes the .set_config() refactoring of the GPIO chips,
     so that they pass a generic configuration for things like
     debouncing and single ended (typically open drain). This change has
     also been merged in an immutable branch to the GPIO tree.

   - Take hogs with a delayed work, so that we finalize probing a pin
     controller before trying to get any hogs.

   - For pin controllers putting all group and function definitions into
     the device tree, we now have generic code to deal with this and it
     is used in two drivers so far.

   - Simplifications of the pin request conflict check.

   - Make dt_free_map() optional.

  Updates to drivers:

   - pinctrl-single now use the generic helpers to generate dynamic
     group and function tables from the device tree.

   - Texas Instruments IOdelay configuration driver add-on to
     pinctrl-single.

   - i.MX: use radix trees to store groups and functions, use the new
     generic group and function helpers to manage them.

   - Intel: add support for hardware debouncing and 1K pull-down. New
     subdriver for the Gemini Lake SoC.

   - Renesas SH-PFC: drive strength and bias support, CAN bus muxing,
     MSIOF, SDHI, HSCIF for r8a7796. Gyro-ADC supporton r8a7791.

   - Aspeed: use syscon cross-dependencies to set up related bits in the
     LPC host controller and display controller.

   - Aspeed: finalize G4 and G5 support. Fix mux configuration on GPIOs.
     Add banks Y, Z, AA, AB and AC.

   - AMD: support additional GPIO.

   - STM32: set this controller to strict muxing mode. STM32H743 MCU
     support.

   - Allwinner sunxi: deep simplifications on how to support subvariants
     of SoCs without adding to much SoC-specific data for each
     subvariant, especially for sun5i variants. New driver for V3s SoCs.
     New driver for the H5 SoC. Support A31/A31s variants with the new
     variant framework.

   - Mvebu: simplifications to use a MMIO and regmap abstraction. New
     subdrivers for the 98DX3236, 98DX5241 SoCs.

   - Samsung Exynos: delete Exynos4415 support. Add crosstalk to the SoC
     driver to access regmaps. Add infrastructure for pin-bank retention
     control. Clean out the pin retention control from
     arch/arm/mach-exynos and arch/arm/mach-s5p and put it properly in
     the Samsung pin control driver(s).

   - Meson: add HDMI HPD/DDC pins. Add pwm_ao_b pin.

   - Qualcomm: use raw spinlock variants: this makes the qualcomm driver
     realtime-safe"

* tag 'pinctrl-v4.11-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl: (111 commits)
  pinctrl: samsung: Fix return value check in samsung_pinctrl_get_soc_data()
  pinctrl: intel: unlock on error in intel_config_set_pull()
  pinctrl: berlin: make bool drivers explicitly non-modular
  pinctrl: spear: make bool drivers explicitly non-modular
  pinctrl: mvebu: make bool drivers explicitly non-modular
  pinctrl: sunxi: make sun5i explicitly non-modular
  pinctrl: sunxi: Remove stray printk call in sun5i driver's probe function
  pinctrl: samsung: mark PM functions as __maybe_unused
  pinctrl: sunxi: Remove redundant A31s pinctrl driver
  pinctrl: sunxi: Support A31/A31s with pinctrl variants
  pinctrl: Amend bindings for STM32 pinctrl
  pinctrl: Add STM32 pinctrl driver DT bindings
  pinctrl: stm32: Add STM32H743 MCU support
  include: dt-bindings: Add STM32H7 pinctrl DT defines
  gpio: aspeed: Remove dependence on GPIOF_* macros
  pinctrl: stm32: fix bad location of gpiochip_lock_as_irq
  drivers: pinctrl: add driver for Allwinner H5 SoC
  pinctrl: intel: Add Intel Gemini Lake pin controller support
  pinctrl: intel: Add support for 1k additional pull-down
  pinctrl: intel: Add support for hardware debouncer
  ...
parents 6d1c42d9 baafacab
......@@ -23,6 +23,7 @@ Required properties:
"allwinner,sun8i-h3-pinctrl"
"allwinner,sun8i-h3-r-pinctrl"
"allwinner,sun50i-a64-pinctrl"
"allwinner,sun50i-h5-r-pinctrl"
"nextthing,gr8-pinctrl"
- reg: Should contain the register physical address and length for the
......
......@@ -19,7 +19,7 @@ iomuxc: iomuxc@30330000 {
reg = <0x30330000 0x10000>;
};
Pheriparials using pads from iomuxc-lpsr support low state retention power
Peripherals using pads from iomuxc-lpsr support low state retention power
state, under LPSR mode GPIO's state of pads are retain.
Please refer to fsl,imx-pinctrl.txt in this directory for common binding part
......
* Marvell 98dx3236 pinctrl driver for mpp
Please refer to marvell,mvebu-pinctrl.txt in this directory for common binding
part and usage
Required properties:
- compatible: "marvell,98dx3236-pinctrl" or "marvell,98dx4251-pinctrl"
- reg: register specifier of MPP registers
This driver supports all 98dx3236, 98dx3336 and 98dx4251 variants
name pins functions
================================================================================
mpp0 0 gpo, spi0(mosi), dev(ad8)
mpp1 1 gpio, spi0(miso), dev(ad9)
mpp2 2 gpo, spi0(sck), dev(ad10)
mpp3 3 gpio, spi0(cs0), dev(ad11)
mpp4 4 gpio, spi0(cs1), smi(mdc), dev(cs0)
mpp5 5 gpio, pex(rsto), sd0(cmd), dev(bootcs)
mpp6 6 gpo, sd0(clk), dev(a2)
mpp7 7 gpio, sd0(d0), dev(ale0)
mpp8 8 gpio, sd0(d1), dev(ale1)
mpp9 9 gpio, sd0(d2), dev(ready0)
mpp10 10 gpio, sd0(d3), dev(ad12)
mpp11 11 gpio, uart1(rxd), uart0(cts), dev(ad13)
mpp12 12 gpo, uart1(txd), uart0(rts), dev(ad14)
mpp13 13 gpio, intr(out), dev(ad15)
mpp14 14 gpio, i2c0(sck)
mpp15 15 gpio, i2c0(sda)
mpp16 16 gpo, dev(oe)
mpp17 17 gpo, dev(clkout)
mpp18 18 gpio, uart1(txd)
mpp19 19 gpio, uart1(rxd), dev(rb)
mpp20 20 gpo, dev(we0)
mpp21 21 gpo, dev(ad0)
mpp22 22 gpo, dev(ad1)
mpp23 23 gpo, dev(ad2)
mpp24 24 gpo, dev(ad3)
mpp25 25 gpo, dev(ad4)
mpp26 26 gpo, dev(ad5)
mpp27 27 gpo, dev(ad6)
mpp28 28 gpo, dev(ad7)
mpp29 29 gpo, dev(a0)
mpp30 30 gpo, dev(a1)
mpp31 31 gpio, slv_smi(mdc), smi(mdc), dev(we1)
mpp32 32 gpio, slv_smi(mdio), smi(mdio), dev(cs1)
......@@ -44,16 +44,16 @@ mpp16 16 gpio, sdio(d2), uart0(cts), uart1(rxd), mii(crs)
mpp17 17 gpio, sdio(d3)
mpp18 18 gpo, nand(io0)
mpp19 19 gpo, nand(io1)
mpp20 20 gpio, mii(rxerr)
mpp21 21 gpio, audio(spdifi)
mpp22 22 gpio, audio(spdifo)
mpp23 23 gpio, audio(rmclk)
mpp24 24 gpio, audio(bclk)
mpp25 25 gpio, audio(sdo)
mpp26 26 gpio, audio(lrclk)
mpp27 27 gpio, audio(mclk)
mpp28 28 gpio, audio(sdi)
mpp29 29 gpio, audio(extclk)
mpp35 35 gpio, mii(rxerr)
mpp36 36 gpio, audio(spdifi)
mpp37 37 gpio, audio(spdifo)
mpp38 38 gpio, audio(rmclk)
mpp39 39 gpio, audio(bclk)
mpp40 40 gpio, audio(sdo)
mpp41 41 gpio, audio(lrclk)
mpp42 42 gpio, audio(mclk)
mpp43 43 gpio, audio(sdi)
mpp44 44 gpio, audio(extclk)
* Marvell Kirkwood 88f6190
......
======================
Aspeed Pin Controllers
----------------------
======================
The Aspeed SoCs vary in functionality inside a generation but have a common mux
device register layout.
Required properties:
- compatible : Should be any one of the following:
Required properties for g4:
- compatible : Should be one of the following:
"aspeed,ast2400-pinctrl"
"aspeed,g4-pinctrl"
Required properties for g5:
- compatible : Should be one of the following:
"aspeed,ast2500-pinctrl"
"aspeed,g5-pinctrl"
The pin controller node should be a child of a syscon node with the required
- aspeed,external-nodes: A cell of phandles to external controller nodes:
0: compatible with "aspeed,ast2500-gfx", "syscon"
1: compatible with "aspeed,ast2500-lhc", "syscon"
The pin controller node should be the child of a syscon node with the required
property:
- compatible: "syscon", "simple-mfd"
- compatible : Should be one of the following:
"aspeed,ast2400-scu", "syscon", "simple-mfd"
"aspeed,g4-scu", "syscon", "simple-mfd"
"aspeed,ast2500-scu", "syscon", "simple-mfd"
"aspeed,g5-scu", "syscon", "simple-mfd"
Refer to the the bindings described in
Documentation/devicetree/bindings/mfd/syscon.txt
Subnode Format
--------------
==============
The required properties of child nodes are (as defined in pinctrl-bindings):
- function
......@@ -31,26 +44,43 @@ supported:
aspeed,ast2400-pinctrl, aspeed,g4-pinctrl:
ACPI BMCINT DDCCLK DDCDAT FLACK FLBUSY FLWP GPID0 GPIE0 GPIE2 GPIE4 GPIE6 I2C10
I2C11 I2C12 I2C13 I2C3 I2C4 I2C5 I2C6 I2C7 I2C8 I2C9 LPCPD LPCPME LPCSMI MDIO1
MDIO2 NCTS1 NCTS3 NCTS4 NDCD1 NDCD3 NDCD4 NDSR1 NDSR3 NDTR1 NDTR3 NRI1 NRI3
NRI4 NRTS1 NRTS3 PWM0 PWM1 PWM2 PWM3 PWM4 PWM5 PWM6 PWM7 RGMII1 RMII1 ROM16
ROM8 ROMCS1 ROMCS2 ROMCS3 ROMCS4 RXD1 RXD3 RXD4 SD1 SGPMI SIOPBI SIOPBO TIMER3
TIMER5 TIMER6 TIMER7 TIMER8 TXD1 TXD3 TXD4 UART6 VGAHS VGAVS VPI18 VPI24 VPI30
VPO12 VPO24
ACPI ADC0 ADC1 ADC10 ADC11 ADC12 ADC13 ADC14 ADC15 ADC2 ADC3 ADC4 ADC5 ADC6
ADC7 ADC8 ADC9 BMCINT DDCCLK DDCDAT EXTRST FLACK FLBUSY FLWP GPID GPID0 GPID2
GPID4 GPID6 GPIE0 GPIE2 GPIE4 GPIE6 I2C10 I2C11 I2C12 I2C13 I2C14 I2C3 I2C4
I2C5 I2C6 I2C7 I2C8 I2C9 LPCPD LPCPME LPCRST LPCSMI MAC1LINK MAC2LINK MDIO1
MDIO2 NCTS1 NCTS2 NCTS3 NCTS4 NDCD1 NDCD2 NDCD3 NDCD4 NDSR1 NDSR2 NDSR3 NDSR4
NDTR1 NDTR2 NDTR3 NDTR4 NDTS4 NRI1 NRI2 NRI3 NRI4 NRTS1 NRTS2 NRTS3 OSCCLK PWM0
PWM1 PWM2 PWM3 PWM4 PWM5 PWM6 PWM7 RGMII1 RGMII2 RMII1 RMII2 ROM16 ROM8 ROMCS1
ROMCS2 ROMCS3 ROMCS4 RXD1 RXD2 RXD3 RXD4 SALT1 SALT2 SALT3 SALT4 SD1 SD2 SGPMCK
SGPMI SGPMLD SGPMO SGPSCK SGPSI0 SGPSI1 SGPSLD SIOONCTRL SIOPBI SIOPBO SIOPWREQ
SIOPWRGD SIOS3 SIOS5 SIOSCI SPI1 SPI1DEBUG SPI1PASSTHRU SPICS1 TIMER3 TIMER4
TIMER5 TIMER6 TIMER7 TIMER8 TXD1 TXD2 TXD3 TXD4 UART6 USBCKI VGABIOS_ROM VGAHS
VGAVS VPI18 VPI24 VPI30 VPO12 VPO24 WDTRST1 WDTRST2
aspeed,ast2500-pinctrl, aspeed,g5-pinctrl:
GPID0 GPID2 GPIE0 I2C10 I2C11 I2C12 I2C13 I2C14 I2C3 I2C4 I2C5 I2C6 I2C7 I2C8
I2C9 MAC1LINK MDIO1 MDIO2 OSCCLK PEWAKE PWM0 PWM1 PWM2 PWM3 PWM4 PWM5 PWM6 PWM7
RGMII1 RGMII2 RMII1 RMII2 SD1 SPI1 SPI1DEBUG SPI1PASSTHRU TIMER4 TIMER5 TIMER6
TIMER7 TIMER8 VGABIOSROM
Examples:
ACPI ADC0 ADC1 ADC10 ADC11 ADC12 ADC13 ADC14 ADC15 ADC2 ADC3 ADC4 ADC5 ADC6
ADC7 ADC8 ADC9 BMCINT DDCCLK DDCDAT ESPI FWSPICS1 FWSPICS2 GPID0 GPID2 GPID4
GPID6 GPIE0 GPIE2 GPIE4 GPIE6 I2C10 I2C11 I2C12 I2C13 I2C14 I2C3 I2C4 I2C5 I2C6
I2C7 I2C8 I2C9 LAD0 LAD1 LAD2 LAD3 LCLK LFRAME LPCHC LPCPD LPCPLUS LPCPME
LPCRST LPCSMI LSIRQ MAC1LINK MAC2LINK MDIO1 MDIO2 NCTS1 NCTS2 NCTS3 NCTS4 NDCD1
NDCD2 NDCD3 NDCD4 NDSR1 NDSR2 NDSR3 NDSR4 NDTR1 NDTR2 NDTR3 NDTR4 NRI1 NRI2
NRI3 NRI4 NRTS1 NRTS2 NRTS3 NRTS4 OSCCLK PEWAKE PNOR PWM0 PWM1 PWM2 PWM3 PWM4
PWM5 PWM6 PWM7 RGMII1 RGMII2 RMII1 RMII2 RXD1 RXD2 RXD3 RXD4 SALT1 SALT10
SALT11 SALT12 SALT13 SALT14 SALT2 SALT3 SALT4 SALT5 SALT6 SALT7 SALT8 SALT9
SCL1 SCL2 SD1 SD2 SDA1 SDA2 SGPS1 SGPS2 SIOONCTRL SIOPBI SIOPBO SIOPWREQ
SIOPWRGD SIOS3 SIOS5 SIOSCI SPI1 SPI1CS1 SPI1DEBUG SPI1PASSTHRU SPI2CK SPI2CS0
SPI2CS1 SPI2MISO SPI2MOSI TIMER3 TIMER4 TIMER5 TIMER6 TIMER7 TIMER8 TXD1 TXD2
TXD3 TXD4 UART6 USBCKI VGABIOSROM VGAHS VGAVS VPI24 VPO WDTRST1 WDTRST2
Examples
========
g4 Example
----------
syscon: scu@1e6e2000 {
compatible = "syscon", "simple-mfd";
compatible = "aspeed,ast2400-scu", "syscon", "simple-mfd";
reg = <0x1e6e2000 0x1a8>;
pinctrl: pinctrl {
......@@ -63,5 +93,56 @@ syscon: scu@1e6e2000 {
};
};
g5 Example
----------
ahb {
apb {
syscon: scu@1e6e2000 {
compatible = "aspeed,ast2500-scu", "syscon", "simple-mfd";
reg = <0x1e6e2000 0x1a8>;
pinctrl: pinctrl {
compatible = "aspeed,g5-pinctrl";
aspeed,external-nodes = <&gfx &lhc>;
pinctrl_i2c3_default: i2c3_default {
function = "I2C3";
groups = "I2C3";
};
};
};
gfx: display@1e6e6000 {
compatible = "aspeed,ast2500-gfx", "syscon";
reg = <0x1e6e6000 0x1000>;
};
};
lpc: lpc@1e789000 {
compatible = "aspeed,ast2500-lpc", "simple-mfd";
reg = <0x1e789000 0x1000>;
#address-cells = <1>;
#size-cells = <1>;
ranges = <0x0 0x1e789000 0x1000>;
lpc_host: lpc-host@80 {
compatible = "aspeed,ast2500-lpc-host", "simple-mfd", "syscon";
reg = <0x80 0x1e0>;
reg-io-width = <4>;
#address-cells = <1>;
#size-cells = <1>;
ranges = <0x0 0x80 0x1e0>;
lhc: lhc@20 {
compatible = "aspeed,ast2500-lhc";
reg = <0x20 0x24 0x48 0x8>;
};
};
};
};
Please refer to pinctrl-bindings.txt in this directory for details of the
common pinctrl bindings used by client devices.
......@@ -13,6 +13,7 @@ Required Properties:
- "samsung,s3c2450-pinctrl": for S3C2450-compatible pin-controller,
- "samsung,s3c64xx-pinctrl": for S3C64xx-compatible pin-controller,
- "samsung,s5pv210-pinctrl": for S5PV210-compatible pin-controller,
- "samsung,exynos3250-pinctrl": for Exynos3250 compatible pin-controller.
- "samsung,exynos4210-pinctrl": for Exynos4210 compatible pin-controller.
- "samsung,exynos4x12-pinctrl": for Exynos4x12 compatible pin-controller.
- "samsung,exynos5250-pinctrl": for Exynos5250 compatible pin-controller.
......
......@@ -8,8 +8,9 @@ controllers onto these pads.
Pin controller node:
Required properies:
- compatible: value should be one of the following:
(a) "st,stm32f429-pinctrl"
(b) "st,stm32f746-pinctrl"
"st,stm32f429-pinctrl"
"st,stm32f746-pinctrl"
"st,stm32h743-pinctrl"
- #address-cells: The value of this property must be 1
- #size-cells : The value of this property must be 1
- ranges : defines mapping between pin controller node (parent) to
......@@ -37,8 +38,23 @@ Optional properties:
- st,syscfg: Should be phandle/offset pair. The phandle to the syscon node
which includes IRQ mux selection register, and the offset of the IRQ mux
selection register.
- ngpios: Number of gpios in a bank (to use if bank gpio numbers is less
than 16).
- gpio-ranges: Define a dedicated mapping between a pin-controller and
a gpio controller. Format is <&phandle a b c> with:
-(phandle): phandle of pin-controller.
-(a): gpio base offset in range.
-(b): pin base offset in range.
-(c): gpio count in range
This entry has to be used either if there are holes inside a bank:
GPIOB0/B1/B2/B14/B15 (see example 2)
or if banks are not contiguous:
GPIOA/B/C/E...
NOTE: If "gpio-ranges" is used for a gpio controller, all gpio-controller
have to use a "gpio-ranges" entry.
More details in Documentation/devicetree/bindings/gpio/gpio.txt.
Example:
Example 1:
#include <dt-bindings/pinctrl/stm32f429-pinfunc.h>
...
......@@ -60,6 +76,43 @@ Example:
pin-functions nodes follow...
};
Example 2:
#include <dt-bindings/pinctrl/stm32f429-pinfunc.h>
...
pinctrl: pin-controller {
#address-cells = <1>;
#size-cells = <1>;
compatible = "st,stm32f429-pinctrl";
ranges = <0 0x40020000 0x3000>;
pins-are-numbered;
gpioa: gpio@40020000 {
gpio-controller;
#gpio-cells = <2>;
reg = <0x0 0x400>;
resets = <&reset_ahb1 0>;
st,bank-name = "GPIOA";
gpio-ranges = <&pinctrl 0 0 16>;
};
gpiob: gpio@40020400 {
gpio-controller;
#gpio-cells = <2>;
reg = <0x0 0x400>;
resets = <&reset_ahb1 0>;
st,bank-name = "GPIOB";
ngpios = 4;
gpio-ranges = <&pinctrl 0 16 3>,
<&pinctrl 14 30 2>;
};
...
pin-functions nodes follow...
};
Contents of function subnode node:
----------------------------------
Subnode format
......
* Pin configuration for TI IODELAY controller
TI dra7 based SoCs such as am57xx have a controller for setting the IO delay
for each pin. For most part the IO delay values are programmed by the bootloader,
but some pins need to be configured dynamically by the kernel such as the
MMC pins.
Required Properties:
- compatible: Must be "ti,dra7-iodelay"
- reg: Base address and length of the memory resource used
- #address-cells: Number of address cells
- #size-cells: Size of cells
- #pinctrl-cells: Number of pinctrl cells, must be 2. See also
Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
Example
-------
In the SoC specific dtsi file:
dra7_iodelay_core: padconf@4844a000 {
compatible = "ti,dra7-iodelay";
reg = <0x4844a000 0x0d1c>;
#address-cells = <1>;
#size-cells = <0>;
#pinctrl-cells = <2>;
};
In board-specific file:
&dra7_iodelay_core {
mmc2_iodelay_3v3_conf: mmc2_iodelay_3v3_conf {
pinctrl-pin-array = <
0x18c A_DELAY_PS(0) G_DELAY_PS(120) /* CFG_GPMC_A19_IN */
0x1a4 A_DELAY_PS(265) G_DELAY_PS(360) /* CFG_GPMC_A20_IN */
0x1b0 A_DELAY_PS(0) G_DELAY_PS(120) /* CFG_GPMC_A21_IN */
0x1bc A_DELAY_PS(0) G_DELAY_PS(120) /* CFG_GPMC_A22_IN */
0x1c8 A_DELAY_PS(287) G_DELAY_PS(420) /* CFG_GPMC_A23_IN */
0x1d4 A_DELAY_PS(144) G_DELAY_PS(240) /* CFG_GPMC_A24_IN */
0x1e0 A_DELAY_PS(0) G_DELAY_PS(0) /* CFG_GPMC_A25_IN */
0x1ec A_DELAY_PS(120) G_DELAY_PS(0) /* CFG_GPMC_A26_IN */
0x1f8 A_DELAY_PS(120) G_DELAY_PS(180) /* CFG_GPMC_A27_IN */
0x360 A_DELAY_PS(0) G_DELAY_PS(0) /* CFG_GPMC_CS1_IN */
>;
};
};
......@@ -146,10 +146,11 @@ a pull-up resistor is needed on the outgoing rail to complete the circuit, and
in the second case, a pull-down resistor is needed on the rail.
Hardware that supports open drain or open source or both, can implement a
special callback in the gpio_chip: .set_single_ended() that takes an enum flag
telling whether to configure the line as open drain, open source or push-pull.
This will happen in response to the GPIO_OPEN_DRAIN or GPIO_OPEN_SOURCE flag
set in the machine file, or coming from other hardware descriptions.
special callback in the gpio_chip: .set_config() that takes a generic
pinconf packed value telling whether to configure the line as open drain,
open source or push-pull. This will happen in response to the
GPIO_OPEN_DRAIN or GPIO_OPEN_SOURCE flag set in the machine file, or coming
from other hardware descriptions.
If this state can not be configured in hardware, i.e. if the GPIO hardware does
not support open drain/open source in hardware, the GPIO library will instead
......
......@@ -79,9 +79,7 @@ int __init foo_probe(void)
{
struct pinctrl_dev *pctl;
pctl = pinctrl_register(&foo_desc, <PARENT>, NULL);
if (!pctl)
pr_err("could not register foo pin driver\n");
return pinctrl_register_and_init(&foo_desc, <PARENT>, NULL, &pctl);
}
To enable the pinctrl subsystem and the subgroups for PINMUX and PINCONF and
......
......@@ -57,7 +57,6 @@ struct exynos_wkup_irq {
struct exynos_pm_data {
const struct exynos_wkup_irq *wkup_irq;
unsigned int wake_disable_mask;
unsigned int *release_ret_regs;
void (*pm_prepare)(void);
void (*pm_resume_prepare)(void);
......@@ -95,47 +94,6 @@ static const struct exynos_wkup_irq exynos5250_wkup_irq[] = {
{ /* sentinel */ },
};
static unsigned int exynos_release_ret_regs[] = {
S5P_PAD_RET_MAUDIO_OPTION,
S5P_PAD_RET_GPIO_OPTION,
S5P_PAD_RET_UART_OPTION,
S5P_PAD_RET_MMCA_OPTION,
S5P_PAD_RET_MMCB_OPTION,
S5P_PAD_RET_EBIA_OPTION,
S5P_PAD_RET_EBIB_OPTION,
REG_TABLE_END,
};
static unsigned int exynos3250_release_ret_regs[] = {
S5P_PAD_RET_MAUDIO_OPTION,
S5P_PAD_RET_GPIO_OPTION,
S5P_PAD_RET_UART_OPTION,
S5P_PAD_RET_MMCA_OPTION,
S5P_PAD_RET_MMCB_OPTION,
S5P_PAD_RET_EBIA_OPTION,
S5P_PAD_RET_EBIB_OPTION,
S5P_PAD_RET_MMC2_OPTION,
S5P_PAD_RET_SPI_OPTION,
REG_TABLE_END,
};
static unsigned int exynos5420_release_ret_regs[] = {
EXYNOS_PAD_RET_DRAM_OPTION,
EXYNOS_PAD_RET_MAUDIO_OPTION,
EXYNOS_PAD_RET_JTAG_OPTION,
EXYNOS5420_PAD_RET_GPIO_OPTION,
EXYNOS5420_PAD_RET_UART_OPTION,
EXYNOS5420_PAD_RET_MMCA_OPTION,
EXYNOS5420_PAD_RET_MMCB_OPTION,
EXYNOS5420_PAD_RET_MMCC_OPTION,
EXYNOS5420_PAD_RET_HSI_OPTION,
EXYNOS_PAD_RET_EBIA_OPTION,
EXYNOS_PAD_RET_EBIB_OPTION,
EXYNOS5420_PAD_RET_SPI_OPTION,
EXYNOS5420_PAD_RET_DRAM_COREBLK_OPTION,
REG_TABLE_END,
};
static int exynos_irq_set_wake(struct irq_data *data, unsigned int state)
{
const struct exynos_wkup_irq *wkup_irq;
......@@ -442,15 +400,6 @@ static int exynos5420_pm_suspend(void)
return 0;
}
static void exynos_pm_release_retention(void)
{
unsigned int i;
for (i = 0; (pm_data->release_ret_regs[i] != REG_TABLE_END); i++)
pmu_raw_writel(EXYNOS_WAKEUP_FROM_LOWPWR,
pm_data->release_ret_regs[i]);
}
static void exynos_pm_resume(void)
{
u32 cpuid = read_cpuid_part();
......@@ -458,9 +407,6 @@ static void exynos_pm_resume(void)
if (exynos_pm_central_resume())
goto early_wakeup;
/* For release retention */
exynos_pm_release_retention();
if (cpuid == ARM_CPU_PART_CORTEX_A9)
scu_enable(S5P_VA_SCU);
......@@ -482,9 +428,6 @@ static void exynos3250_pm_resume(void)
if (exynos_pm_central_resume())
goto early_wakeup;
/* For release retention */
exynos_pm_release_retention();
pmu_raw_writel(S5P_USE_STANDBY_WFI_ALL, S5P_CENTRAL_SEQ_OPTION);
if (call_firmware_op(resume) == -ENOSYS
......@@ -522,9 +465,6 @@ static void exynos5420_pm_resume(void)
if (exynos_pm_central_resume())
goto early_wakeup;
/* For release retention */
exynos_pm_release_retention();
pmu_raw_writel(exynos_pmu_spare3, S5P_PMU_SPARE3);
early_wakeup:
......@@ -637,7 +577,6 @@ static const struct platform_suspend_ops exynos_suspend_ops = {
static const struct exynos_pm_data exynos3250_pm_data = {
.wkup_irq = exynos3250_wkup_irq,
.wake_disable_mask = ((0xFF << 8) | (0x1F << 1)),
.release_ret_regs = exynos3250_release_ret_regs,
.pm_suspend = exynos_pm_suspend,
.pm_resume = exynos3250_pm_resume,
.pm_prepare = exynos3250_pm_prepare,
......@@ -647,7 +586,6 @@ static const struct exynos_pm_data exynos3250_pm_data = {
static const struct exynos_pm_data exynos4_pm_data = {
.wkup_irq = exynos4_wkup_irq,
.wake_disable_mask = ((0xFF << 8) | (0x1F << 1)),
.release_ret_regs = exynos_release_ret_regs,
.pm_suspend = exynos_pm_suspend,
.pm_resume = exynos_pm_resume,
.pm_prepare = exynos_pm_prepare,
......@@ -657,7 +595,6 @@ static const struct exynos_pm_data exynos4_pm_data = {
static const struct exynos_pm_data exynos5250_pm_data = {
.wkup_irq = exynos5250_wkup_irq,
.wake_disable_mask = ((0xFF << 8) | (0x1F << 1)),
.release_ret_regs = exynos_release_ret_regs,
.pm_suspend = exynos_pm_suspend,
.pm_resume = exynos_pm_resume,
.pm_prepare = exynos_pm_prepare,
......@@ -667,7 +604,6 @@ static const struct exynos_pm_data exynos5250_pm_data = {
static const struct exynos_pm_data exynos5420_pm_data = {
.wkup_irq = exynos5250_wkup_irq,
.wake_disable_mask = (0x7F << 7) | (0x1F << 1),
.release_ret_regs = exynos5420_release_ret_regs,
.pm_resume_prepare = exynos5420_prepare_pm_resume,
.pm_resume = exynos5420_pm_resume,
.pm_suspend = exynos5420_pm_suspend,
......
......@@ -155,13 +155,6 @@ static const struct platform_suspend_ops s5pv210_suspend_ops = {
*/
static void s5pv210_pm_resume(void)
{
u32 tmp;
tmp = __raw_readl(S5P_OTHERS);
tmp |= (S5P_OTHERS_RET_IO | S5P_OTHERS_RET_CF |\
S5P_OTHERS_RET_MMC | S5P_OTHERS_RET_UART);
__raw_writel(tmp , S5P_OTHERS);
s3c_pm_do_restore_core(s5pv210_core_save, ARRAY_SIZE(s5pv210_core_save));
}
......
......@@ -188,10 +188,6 @@
#define S5P_SLEEP_CFG_USBOSC_EN (1 << 1)
/* OTHERS Resgister */
#define S5P_OTHERS_RET_IO (1 << 31)
#define S5P_OTHERS_RET_CF (1 << 30)
#define S5P_OTHERS_RET_MMC (1 << 29)
#define S5P_OTHERS_RET_UART (1 << 28)
#define S5P_OTHERS_USB_SIG_MASK (1 << 16)
/* S5P_DAC_CONTROL */
......
......@@ -18,55 +18,72 @@
#include <linux/gpio/driver.h>
#include <linux/pinctrl/consumer.h>
struct aspeed_bank_props {
unsigned int bank;
u32 input;
u32 output;
};
struct aspeed_gpio_config {
unsigned int nr_gpios;
const struct aspeed_bank_props *props;
};
struct aspeed_gpio {
struct gpio_chip chip;
spinlock_t lock;
void __iomem *base;
int irq;
const struct aspeed_gpio_config *config;
};
struct aspeed_gpio_bank {
uint16_t val_regs;
uint16_t irq_regs;
const char names[4];
const char names[4][3];
};
static const struct aspeed_gpio_bank aspeed_gpio_banks[] = {
{
.val_regs = 0x0000,
.irq_regs = 0x0008,
.names = { 'A', 'B', 'C', 'D' },
.names = { "A", "B", "C", "D" },
},
{
.val_regs = 0x0020,
.irq_regs = 0x0028,
.names = { 'E', 'F', 'G', 'H' },
.names = { "E", "F", "G", "H" },
},
{
.val_regs = 0x0070,
.irq_regs = 0x0098,
.names = { 'I', 'J', 'K', 'L' },
.names = { "I", "J", "K", "L" },
},
{
.val_regs = 0x0078,
.irq_regs = 0x00e8,
.names = { 'M', 'N', 'O', 'P' },
.names = { "M", "N", "O", "P" },
},
{
.val_regs = 0x0080,
.irq_regs = 0x0118,
.names = { 'Q', 'R', 'S', 'T' },
.names = { "Q", "R", "S", "T" },
},
{
.val_regs = 0x0088,
.irq_regs = 0x0148,
.names = { 'U', 'V', 'W', 'X' },
.names = { "U", "V", "W", "X" },
},
{
.val_regs = 0x01E0,
.irq_regs = 0x0178,
.names = { "Y", "Z", "AA", "AB" },
},
{
.val_regs = 0x01E8,
.irq_regs = 0x01A8,
.names = { "AC", "", "", "" },
},
/*
* A bank exists for { 'Y', 'Z', "AA", "AB" }, but is not implemented.
* Only half of GPIOs Y support interrupt configuration, and none of Z,
* AA or AB do as they are output only.
*/
};
#define GPIO_BANK(x) ((x) >> 5)
......@@ -90,6 +107,51 @@ static const struct aspeed_gpio_bank *to_bank(unsigned int offset)
return &aspeed_gpio_banks[bank];
}
static inline bool is_bank_props_sentinel(const struct aspeed_bank_props *props)
{
return !(props->input || props->output);
}
static inline const struct aspeed_bank_props *find_bank_props(
struct aspeed_gpio *gpio, unsigned int offset)
{
const struct aspeed_bank_props *props = gpio->config->props;
while (!is_bank_props_sentinel(props)) {
if (props->bank == GPIO_BANK(offset))
return props;
props++;
}
return NULL;
}
static inline bool have_gpio(struct aspeed_gpio *gpio, unsigned int offset)
{
const struct aspeed_bank_props *props = find_bank_props(gpio, offset);
const struct aspeed_gpio_bank *bank = to_bank(offset);
unsigned int group = GPIO_OFFSET(offset) / 8;
return bank->names[group][0] != '\0' &&
(!props || ((props->input | props->output) & GPIO_BIT(offset)));
}
static inline bool have_input(struct aspeed_gpio *gpio, unsigned int offset)
{
const struct aspeed_bank_props *props = find_bank_props(gpio, offset);
return !props || (props->input & GPIO_BIT(offset));
}
#define have_irq(g, o) have_input((g), (o))
static inline bool have_output(struct aspeed_gpio *gpio, unsigned int offset)
{
const struct aspeed_bank_props *props = find_bank_props(gpio, offset);
return !props || (props->output & GPIO_BIT(offset));
}
static void __iomem *bank_val_reg(struct aspeed_gpio *gpio,
const struct aspeed_gpio_bank *bank,
unsigned int reg)
......@@ -152,6 +214,9 @@ static int aspeed_gpio_dir_in(struct gpio_chip *gc, unsigned int offset)
unsigned long flags;
u32 reg;
if (!have_input(gpio, offset))
return -ENOTSUPP;
spin_lock_irqsave(&gpio->lock, flags);
reg = ioread32(bank_val_reg(gpio, bank, GPIO_DIR));
......@@ -170,6 +235,9 @@ static int aspeed_gpio_dir_out(struct gpio_chip *gc,
unsigned long flags;
u32 reg;
if (!have_output(gpio, offset))
return -ENOTSUPP;
spin_lock_irqsave(&gpio->lock, flags);
reg = ioread32(bank_val_reg(gpio, bank, GPIO_DIR));
......@@ -189,6 +257,12 @@ static int aspeed_gpio_get_direction(struct gpio_chip *gc, unsigned int offset)
unsigned long flags;
u32 val;
if (!have_input(gpio, offset))
return 0;
if (!have_output(gpio, offset))
return 1;
spin_lock_irqsave(&gpio->lock, flags);
val = ioread32(bank_val_reg(gpio, bank, GPIO_DIR)) & GPIO_BIT(offset);
......@@ -205,10 +279,17 @@ static inline int irqd_to_aspeed_gpio_data(struct irq_data *d,
u32 *bit)
{
int offset;
struct aspeed_gpio *internal;
offset = irqd_to_hwirq(d);
*gpio = irq_data_get_irq_chip_data(d);
internal = irq_data_get_irq_chip_data(d);
/* This might be a bit of a questionable place to check */
if (!have_irq(internal, offset))
return -ENOTSUPP;
*gpio = internal;
*bank = to_bank(offset);
*bit = GPIO_BIT(offset);
......@@ -364,6 +445,28 @@ static struct irq_chip aspeed_gpio_irqchip = {
.irq_set_type = aspeed_gpio_set_type,
};
static void set_irq_valid_mask(struct aspeed_gpio *gpio)
{
const struct aspeed_bank_props *props = gpio->config->props;
while (!is_bank_props_sentinel(props)) {
unsigned int offset;
const unsigned long int input = props->input;
/* Pretty crummy approach, but similar to GPIO core */
for_each_clear_bit(offset, &input, 32) {
unsigned int i = props->bank * 32 + offset;
if (i >= gpio->config->nr_gpios)
break;
clear_bit(i, gpio->chip.irq_valid_mask);
}
props++;
}
}
static int aspeed_gpio_setup_irqs(struct aspeed_gpio *gpio,
struct platform_device *pdev)
{
......@@ -375,6 +478,8 @@ static int aspeed_gpio_setup_irqs(struct aspeed_gpio *gpio,
gpio->irq = rc;
set_irq_valid_mask(gpio);
rc = gpiochip_irqchip_add(&gpio->chip, &aspeed_gpio_irqchip,
0, handle_bad_irq, IRQ_TYPE_NONE);
if (rc) {
......@@ -390,6 +495,9 @@ static int aspeed_gpio_setup_irqs(struct aspeed_gpio *gpio,
static int aspeed_gpio_request(struct gpio_chip *chip, unsigned int offset)
{
if (!have_gpio(gpiochip_get_data(chip), offset))
return -ENODEV;
return pinctrl_request_gpio(chip->base + offset);
}
......@@ -398,8 +506,46 @@ static void aspeed_gpio_free(struct gpio_chip *chip, unsigned int offset)
pinctrl_free_gpio(chip->base + offset);
}
/*
* Any banks not specified in a struct aspeed_bank_props array are assumed to
* have the properties:
*
* { .input = 0xffffffff, .output = 0xffffffff }
*/
static const struct aspeed_bank_props ast2400_bank_props[] = {
/* input output */
{ 5, 0xffffffff, 0x0000ffff }, /* U/V/W/X */
{ 6, 0x0000000f, 0x0fffff0f }, /* Y/Z/AA/AB, two 4-GPIO holes */
{ },
};
static const struct aspeed_gpio_config ast2400_config =
/* 220 for simplicity, really 216 with two 4-GPIO holes, four at end */
{ .nr_gpios = 220, .props = ast2400_bank_props, };
static const struct aspeed_bank_props ast2500_bank_props[] = {
/* input output */
{ 5, 0xffffffff, 0x0000ffff }, /* U/V/W/X */
{ 6, 0x0fffffff, 0x0fffffff }, /* Y/Z/AA/AB, 4-GPIO hole */
{ 7, 0x000000ff, 0x000000ff }, /* AC */
{ },
};
static const struct aspeed_gpio_config ast2500_config =
/* 232 for simplicity, actual number is 228 (4-GPIO hole in GPIOAB) */
{ .nr_gpios = 232, .props = ast2500_bank_props, };
static const struct of_device_id aspeed_gpio_of_table[] = {
{ .compatible = "aspeed,ast2400-gpio", .data = &ast2400_config, },
{ .compatible = "aspeed,ast2500-gpio", .data = &ast2500_config, },
{}
};
MODULE_DEVICE_TABLE(of, aspeed_gpio_of_table);
static int __init aspeed_gpio_probe(struct platform_device *pdev)
{
const struct of_device_id *gpio_id;
struct aspeed_gpio *gpio;
struct resource *res;
int rc;
......@@ -415,8 +561,13 @@ static int __init aspeed_gpio_probe(struct platform_device *pdev)
spin_lock_init(&gpio->lock);
gpio->chip.ngpio = ARRAY_SIZE(aspeed_gpio_banks) * 32;
gpio_id = of_match_node(aspeed_gpio_of_table, pdev->dev.of_node);
if (!gpio_id)
return -EINVAL;
gpio->config = gpio_id->data;
gpio->chip.ngpio = gpio->config->nr_gpios;
gpio->chip.parent = &pdev->dev;
gpio->chip.direction_input = aspeed_gpio_dir_in;
gpio->chip.direction_output = aspeed_gpio_dir_out;
......@@ -427,6 +578,7 @@ static int __init aspeed_gpio_probe(struct platform_device *pdev)
gpio->chip.set = aspeed_gpio_set;
gpio->chip.label = dev_name(&pdev->dev);
gpio->chip.base = -1;
gpio->chip.irq_need_valid_mask = true;
rc = devm_gpiochip_add_data(&pdev->dev, &gpio->chip, gpio);
if (rc < 0)
......@@ -435,13 +587,6 @@ static int __init aspeed_gpio_probe(struct platform_device *pdev)
return aspeed_gpio_setup_irqs(gpio, pdev);
}
static const struct of_device_id aspeed_gpio_of_table[] = {
{ .compatible = "aspeed,ast2400-gpio" },
{ .compatible = "aspeed,ast2500-gpio" },
{}
};
MODULE_DEVICE_TABLE(of, aspeed_gpio_of_table);
static struct platform_driver aspeed_gpio_driver = {
.driver = {
.name = KBUILD_MODNAME,
......
......@@ -308,6 +308,18 @@ static int bcm_kona_gpio_set_debounce(struct gpio_chip *chip, unsigned gpio,
return 0;
}
static int bcm_kona_gpio_set_config(struct gpio_chip *chip, unsigned gpio,
unsigned long config)
{
u32 debounce;
if (pinconf_to_config_param(config) != PIN_CONFIG_INPUT_DEBOUNCE)
return -ENOTSUPP;
debounce = pinconf_to_config_argument(config);
return bcm_kona_gpio_set_debounce(chip, gpio, debounce);
}
static const struct gpio_chip template_chip = {
.label = "bcm-kona-gpio",
.owner = THIS_MODULE,
......@@ -318,7 +330,7 @@ static const struct gpio_chip template_chip = {
.get = bcm_kona_gpio_get,
.direction_output = bcm_kona_gpio_direction_output,
.set = bcm_kona_gpio_set,
.set_debounce = bcm_kona_gpio_set_debounce,
.set_config = bcm_kona_gpio_set_config,
.to_irq = bcm_kona_gpio_to_irq,
.base = 0,
};
......
......@@ -272,12 +272,16 @@ static int dln2_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
return dln2_gpio_set_direction(chip, offset, DLN2_GPIO_DIRECTION_OUT);
}
static int dln2_gpio_set_debounce(struct gpio_chip *chip, unsigned offset,
unsigned debounce)
static int dln2_gpio_set_config(struct gpio_chip *chip, unsigned offset,
unsigned long config)
{
struct dln2_gpio *dln2 = gpiochip_get_data(chip);
__le32 duration = cpu_to_le32(debounce);
__le32 duration;
if (pinconf_to_config_param(config) != PIN_CONFIG_INPUT_DEBOUNCE)
return -ENOTSUPP;
duration = cpu_to_le32(pinconf_to_config_argument(config));
return dln2_transfer_tx(dln2->pdev, DLN2_GPIO_SET_DEBOUNCE,
&duration, sizeof(duration));
}
......@@ -474,7 +478,7 @@ static int dln2_gpio_probe(struct platform_device *pdev)
dln2->gpio.get_direction = dln2_gpio_get_direction;
dln2->gpio.direction_input = dln2_gpio_direction_input;
dln2->gpio.direction_output = dln2_gpio_direction_output;
dln2->gpio.set_debounce = dln2_gpio_set_debounce;
dln2->gpio.set_config = dln2_gpio_set_config;
platform_set_drvdata(pdev, dln2);
......
......@@ -279,6 +279,18 @@ static int dwapb_gpio_set_debounce(struct gpio_chip *gc,
return 0;
}
static int dwapb_gpio_set_config(struct gpio_chip *gc, unsigned offset,
unsigned long config)
{
u32 debounce;
if (pinconf_to_config_param(config) != PIN_CONFIG_INPUT_DEBOUNCE)
return -ENOTSUPP;
debounce = pinconf_to_config_argument(config);
return dwapb_gpio_set_debounce(gc, offset, debounce);
}
static irqreturn_t dwapb_irq_handler_mfd(int irq, void *dev_id)
{
u32 worked;
......@@ -426,7 +438,7 @@ static int dwapb_gpio_add_port(struct dwapb_gpio *gpio,
/* Only port A support debounce */
if (pp->idx == 0)
port->gc.set_debounce = dwapb_gpio_set_debounce;
port->gc.set_config = dwapb_gpio_set_config;
if (pp->irq)
dwapb_configure_irqs(gpio, port, pp);
......
......@@ -291,15 +291,20 @@ static struct ep93xx_gpio_bank ep93xx_gpio_banks[] = {
EP93XX_GPIO_BANK("H", 0x40, 0x44, 56, false),
};
static int ep93xx_gpio_set_debounce(struct gpio_chip *chip,
unsigned offset, unsigned debounce)
static int ep93xx_gpio_set_config(struct gpio_chip *chip, unsigned offset,
unsigned long config)
{
int gpio = chip->base + offset;
int irq = gpio_to_irq(gpio);
u32 debounce;
if (pinconf_to_config_param(config) != PIN_CONFIG_INPUT_DEBOUNCE)
return -ENOTSUPP;
if (irq < 0)
return -EINVAL;
debounce = pinconf_to_config_argument(config);
ep93xx_gpio_int_debounce(irq, debounce ? true : false);
return 0;
......@@ -335,7 +340,7 @@ static int ep93xx_gpio_add_bank(struct gpio_chip *gc, struct device *dev,
gc->base = bank->base;
if (bank->has_debounce) {
gc->set_debounce = ep93xx_gpio_set_debounce;
gc->set_config = ep93xx_gpio_set_config;
gc->to_irq = ep93xx_gpio_to_irq;
}
......
......@@ -131,9 +131,8 @@ static int f7188x_gpio_get(struct gpio_chip *chip, unsigned offset);
static int f7188x_gpio_direction_out(struct gpio_chip *chip,
unsigned offset, int value);
static void f7188x_gpio_set(struct gpio_chip *chip, unsigned offset, int value);
static int f7188x_gpio_set_single_ended(struct gpio_chip *gc,
unsigned offset,
enum single_ended_mode mode);
static int f7188x_gpio_set_config(struct gpio_chip *chip, unsigned offset,
unsigned long config);
#define F7188X_GPIO_BANK(_base, _ngpio, _regbase) \
{ \
......@@ -145,7 +144,7 @@ static int f7188x_gpio_set_single_ended(struct gpio_chip *gc,
.get = f7188x_gpio_get, \
.direction_output = f7188x_gpio_direction_out, \
.set = f7188x_gpio_set, \
.set_single_ended = f7188x_gpio_set_single_ended, \
.set_config = f7188x_gpio_set_config, \
.base = _base, \
.ngpio = _ngpio, \
.can_sleep = true, \
......@@ -326,17 +325,17 @@ static void f7188x_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
superio_exit(sio->addr);
}
static int f7188x_gpio_set_single_ended(struct gpio_chip *chip,
unsigned offset,
enum single_ended_mode mode)
static int f7188x_gpio_set_config(struct gpio_chip *chip, unsigned offset,
unsigned long config)
{
int err;
enum pin_config_param param = pinconf_to_config_param(config);
struct f7188x_gpio_bank *bank = gpiochip_get_data(chip);
struct f7188x_sio *sio = bank->data->sio;
u8 data;
if (mode != LINE_MODE_OPEN_DRAIN &&
mode != LINE_MODE_PUSH_PULL)
if (param != PIN_CONFIG_DRIVE_OPEN_DRAIN &&
param != PIN_CONFIG_DRIVE_PUSH_PULL)
return -ENOTSUPP;
err = superio_enter(sio->addr);
......@@ -345,7 +344,7 @@ static int f7188x_gpio_set_single_ended(struct gpio_chip *chip,
superio_select(sio->addr, SIO_LD_GPIO);
data = superio_inb(sio->addr, gpio_out_mode(bank->regbase));
if (mode == LINE_MODE_OPEN_DRAIN)
if (param == PIN_CONFIG_DRIVE_OPEN_DRAIN)
data &= ~BIT(offset);
else
data |= BIT(offset);
......
......@@ -100,21 +100,21 @@ static int lp873x_gpio_request(struct gpio_chip *gc, unsigned int offset)
return 0;
}
static int lp873x_gpio_set_single_ended(struct gpio_chip *gc,
unsigned int offset,
enum single_ended_mode mode)
static int lp873x_gpio_set_config(struct gpio_chip *gc, unsigned offset,
unsigned long config)
{
struct lp873x_gpio *gpio = gpiochip_get_data(gc);
switch (mode) {
case LINE_MODE_OPEN_DRAIN:
switch (pinconf_to_config_param(config)) {
case PIN_CONFIG_DRIVE_OPEN_DRAIN:
return regmap_update_bits(gpio->lp873->regmap,
LP873X_REG_GPO_CTRL,
BIT(offset * BITS_PER_GPO +
LP873X_GPO_CTRL_OD),
BIT(offset * BITS_PER_GPO +
LP873X_GPO_CTRL_OD));
case LINE_MODE_PUSH_PULL:
case PIN_CONFIG_DRIVE_PUSH_PULL:
return regmap_update_bits(gpio->lp873->regmap,
LP873X_REG_GPO_CTRL,
BIT(offset * BITS_PER_GPO +
......@@ -133,7 +133,7 @@ static const struct gpio_chip template_chip = {
.direction_output = lp873x_gpio_direction_output,
.get = lp873x_gpio_get,
.set = lp873x_gpio_set,
.set_single_ended = lp873x_gpio_set_single_ended,
.set_config = lp873x_gpio_set_config,
.base = -1,
.ngpio = 2,
.can_sleep = true,
......
......@@ -152,11 +152,10 @@ static int max77620_gpio_dir_output(struct gpio_chip *gc, unsigned int offset,
return ret;
}
static int max77620_gpio_set_debounce(struct gpio_chip *gc,
static int max77620_gpio_set_debounce(struct max77620_gpio *mgpio,
unsigned int offset,
unsigned int debounce)
{
struct max77620_gpio *mgpio = gpiochip_get_data(gc);
u8 val;
int ret;
......@@ -202,21 +201,23 @@ static void max77620_gpio_set(struct gpio_chip *gc, unsigned int offset,
dev_err(mgpio->dev, "CNFG_GPIO_OUT update failed: %d\n", ret);
}
static int max77620_gpio_set_single_ended(struct gpio_chip *gc,
unsigned int offset,
enum single_ended_mode mode)
static int max77620_gpio_set_config(struct gpio_chip *gc, unsigned int offset,
unsigned long config)
{
struct max77620_gpio *mgpio = gpiochip_get_data(gc);
switch (mode) {
case LINE_MODE_OPEN_DRAIN:
switch (pinconf_to_config_param(config)) {
case PIN_CONFIG_DRIVE_OPEN_DRAIN:
return regmap_update_bits(mgpio->rmap, GPIO_REG_ADDR(offset),
MAX77620_CNFG_GPIO_DRV_MASK,
MAX77620_CNFG_GPIO_DRV_OPENDRAIN);
case LINE_MODE_PUSH_PULL:
case PIN_CONFIG_DRIVE_PUSH_PULL:
return regmap_update_bits(mgpio->rmap, GPIO_REG_ADDR(offset),
MAX77620_CNFG_GPIO_DRV_MASK,
MAX77620_CNFG_GPIO_DRV_PUSHPULL);
case PIN_CONFIG_INPUT_DEBOUNCE:
return max77620_gpio_set_debounce(mgpio, offset,
pinconf_to_config_argument(config));
default:
break;
}
......@@ -257,9 +258,8 @@ static int max77620_gpio_probe(struct platform_device *pdev)
mgpio->gpio_chip.direction_input = max77620_gpio_dir_input;
mgpio->gpio_chip.get = max77620_gpio_get;
mgpio->gpio_chip.direction_output = max77620_gpio_dir_output;
mgpio->gpio_chip.set_debounce = max77620_gpio_set_debounce;
mgpio->gpio_chip.set = max77620_gpio_set;
mgpio->gpio_chip.set_single_ended = max77620_gpio_set_single_ended;
mgpio->gpio_chip.set_config = max77620_gpio_set_config;
mgpio->gpio_chip.to_irq = max77620_gpio_to_irq;
mgpio->gpio_chip.ngpio = MAX77620_GPIO_NR;
mgpio->gpio_chip.can_sleep = 1;
......
......@@ -89,22 +89,18 @@ static int men_z127_debounce(struct gpio_chip *gc, unsigned gpio,
static int men_z127_set_single_ended(struct gpio_chip *gc,
unsigned offset,
enum single_ended_mode mode)
enum pin_config_param param)
{
struct men_z127_gpio *priv = gpiochip_get_data(gc);
u32 od_en;
if (mode != LINE_MODE_OPEN_DRAIN &&
mode != LINE_MODE_PUSH_PULL)
return -ENOTSUPP;
spin_lock(&gc->bgpio_lock);
od_en = readl(priv->reg_base + MEN_Z127_ODER);
if (mode == LINE_MODE_OPEN_DRAIN)
if (param == PIN_CONFIG_DRIVE_OPEN_DRAIN)
od_en |= BIT(offset);
else
/* Implicitly LINE_MODE_PUSH_PULL */
/* Implicitly PIN_CONFIG_DRIVE_PUSH_PULL */
od_en &= ~BIT(offset);
writel(od_en, priv->reg_base + MEN_Z127_ODER);
......@@ -113,6 +109,27 @@ static int men_z127_set_single_ended(struct gpio_chip *gc,
return 0;
}
static int men_z127_set_config(struct gpio_chip *gc, unsigned offset,
unsigned long config)
{
enum pin_config_param param = pinconf_to_config_param(config);
switch (param) {
case PIN_CONFIG_DRIVE_OPEN_DRAIN:
case PIN_CONFIG_DRIVE_PUSH_PULL:
return men_z127_set_single_ended(gc, offset, param);
case PIN_CONFIG_INPUT_DEBOUNCE:
return men_z127_debounce(gc, offset,
pinconf_to_config_argument(config));
default:
break;
}
return -ENOTSUPP;
}
static int men_z127_probe(struct mcb_device *mdev,
const struct mcb_device_id *id)
{
......@@ -149,8 +166,7 @@ static int men_z127_probe(struct mcb_device *mdev,
if (ret)
goto err_unmap;
men_z127_gpio->gc.set_debounce = men_z127_debounce;
men_z127_gpio->gc.set_single_ended = men_z127_set_single_ended;
men_z127_gpio->gc.set_config = men_z127_set_config;
ret = gpiochip_add_data(&men_z127_gpio->gc, men_z127_gpio);
if (ret) {
......
......@@ -190,6 +190,18 @@ static int mrfld_gpio_set_debounce(struct gpio_chip *chip, unsigned int offset,
return 0;
}
static int mrfld_gpio_set_config(struct gpio_chip *chip, unsigned int offset,
unsigned long config)
{
u32 debounce;
if (pinconf_to_config_param(config) != PIN_CONFIG_INPUT_DEBOUNCE)
return -ENOTSUPP;
debounce = pinconf_to_config_argument(config);
return mrfld_gpio_set_debounce(chip, offset, debounce);
}
static void mrfld_irq_ack(struct irq_data *d)
{
struct mrfld_gpio *priv = irq_data_get_irq_chip_data(d);
......@@ -414,7 +426,7 @@ static int mrfld_gpio_probe(struct pci_dev *pdev, const struct pci_device_id *id
priv->chip.get = mrfld_gpio_get;
priv->chip.set = mrfld_gpio_set;
priv->chip.get_direction = mrfld_gpio_get_direction;
priv->chip.set_debounce = mrfld_gpio_set_debounce;
priv->chip.set_config = mrfld_gpio_set_config;
priv->chip.base = gpio_base;
priv->chip.ngpio = MRFLD_NGPIO;
priv->chip.can_sleep = false;
......
......@@ -974,6 +974,18 @@ static int omap_gpio_debounce(struct gpio_chip *chip, unsigned offset,
return 0;
}
static int omap_gpio_set_config(struct gpio_chip *chip, unsigned offset,
unsigned long config)
{
u32 debounce;
if (pinconf_to_config_param(config) != PIN_CONFIG_INPUT_DEBOUNCE)
return -ENOTSUPP;
debounce = pinconf_to_config_argument(config);
return omap_gpio_debounce(chip, offset, debounce);
}
static void omap_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
{
struct gpio_bank *bank;
......@@ -1045,7 +1057,7 @@ static int omap_gpio_chip_init(struct gpio_bank *bank, struct irq_chip *irqc)
bank->chip.direction_input = omap_gpio_input;
bank->chip.get = omap_gpio_get;
bank->chip.direction_output = omap_gpio_output;
bank->chip.set_debounce = omap_gpio_debounce;
bank->chip.set_config = omap_gpio_set_config;
bank->chip.set = omap_gpio_set;
if (bank->is_mpuio) {
bank->chip.label = "mpuio";
......
......@@ -100,9 +100,8 @@ static int tc3589x_gpio_get_direction(struct gpio_chip *chip,
return !(ret & BIT(pos));
}
static int tc3589x_gpio_set_single_ended(struct gpio_chip *chip,
unsigned int offset,
enum single_ended_mode mode)
static int tc3589x_gpio_set_config(struct gpio_chip *chip, unsigned int offset,
unsigned long config)
{
struct tc3589x_gpio *tc3589x_gpio = gpiochip_get_data(chip);
struct tc3589x *tc3589x = tc3589x_gpio->tc3589x;
......@@ -116,22 +115,22 @@ static int tc3589x_gpio_set_single_ended(struct gpio_chip *chip,
unsigned int pos = offset % 8;
int ret;
switch(mode) {
case LINE_MODE_OPEN_DRAIN:
switch (pinconf_to_config_param(config)) {
case PIN_CONFIG_DRIVE_OPEN_DRAIN:
/* Set open drain mode */
ret = tc3589x_set_bits(tc3589x, odmreg, BIT(pos), 0);
if (ret)
return ret;
/* Enable open drain/source mode */
return tc3589x_set_bits(tc3589x, odereg, BIT(pos), BIT(pos));
case LINE_MODE_OPEN_SOURCE:
case PIN_CONFIG_DRIVE_OPEN_SOURCE:
/* Set open source mode */
ret = tc3589x_set_bits(tc3589x, odmreg, BIT(pos), BIT(pos));
if (ret)
return ret;
/* Enable open drain/source mode */
return tc3589x_set_bits(tc3589x, odereg, BIT(pos), BIT(pos));
case LINE_MODE_PUSH_PULL:
case PIN_CONFIG_DRIVE_PUSH_PULL:
/* Disable open drain/source mode */
return tc3589x_set_bits(tc3589x, odereg, BIT(pos), 0);
default:
......@@ -148,7 +147,7 @@ static const struct gpio_chip template_chip = {
.direction_output = tc3589x_gpio_direction_output,
.direction_input = tc3589x_gpio_direction_input,
.get_direction = tc3589x_gpio_get_direction,
.set_single_ended = tc3589x_gpio_set_single_ended,
.set_config = tc3589x_gpio_set_config,
.can_sleep = true,
};
......
......@@ -238,6 +238,18 @@ static int tegra_gpio_set_debounce(struct gpio_chip *chip, unsigned int offset,
return 0;
}
static int tegra_gpio_set_config(struct gpio_chip *chip, unsigned int offset,
unsigned long config)
{
u32 debounce;
if (pinconf_to_config_param(config) != PIN_CONFIG_INPUT_DEBOUNCE)
return -ENOTSUPP;
debounce = pinconf_to_config_argument(config);
return tegra_gpio_set_debounce(chip, offset, debounce);
}
static int tegra_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
{
struct tegra_gpio_info *tgi = gpiochip_get_data(chip);
......@@ -615,7 +627,7 @@ static int tegra_gpio_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, tgi);
if (config->debounce_supported)
tgi->gc.set_debounce = tegra_gpio_set_debounce;
tgi->gc.set_config = tegra_gpio_set_config;
tgi->bank_info = devm_kzalloc(&pdev->dev, tgi->bank_count *
sizeof(*tgi->bank_info), GFP_KERNEL);
......
......@@ -139,28 +139,28 @@ static int tps65218_gpio_request(struct gpio_chip *gc, unsigned offset)
return 0;
}
static int tps65218_gpio_set_single_ended(struct gpio_chip *gc,
unsigned offset,
enum single_ended_mode mode)
static int tps65218_gpio_set_config(struct gpio_chip *gc, unsigned offset,
unsigned long config)
{
struct tps65218_gpio *tps65218_gpio = gpiochip_get_data(gc);
struct tps65218 *tps65218 = tps65218_gpio->tps65218;
enum pin_config_param param = pinconf_to_config_param(config);
switch (offset) {
case 0:
case 2:
/* GPO1 is hardwired to be open drain */
if (mode == LINE_MODE_OPEN_DRAIN)
if (param == PIN_CONFIG_DRIVE_OPEN_DRAIN)
return 0;
return -ENOTSUPP;
case 1:
/* GPO2 is push-pull by default, can be set as open drain. */
if (mode == LINE_MODE_OPEN_DRAIN)
if (param == PIN_CONFIG_DRIVE_OPEN_DRAIN)
return tps65218_clear_bits(tps65218,
TPS65218_REG_CONFIG1,
TPS65218_CONFIG1_GPO2_BUF,
TPS65218_PROTECT_L1);
if (mode == LINE_MODE_PUSH_PULL)
if (param == PIN_CONFIG_DRIVE_PUSH_PULL)
return tps65218_set_bits(tps65218,
TPS65218_REG_CONFIG1,
TPS65218_CONFIG1_GPO2_BUF,
......@@ -181,7 +181,7 @@ static const struct gpio_chip template_chip = {
.direction_input = tps65218_gpio_input,
.get = tps65218_gpio_get,
.set = tps65218_gpio_set,
.set_single_ended = tps65218_gpio_set_single_ended,
.set_config = tps65218_gpio_set_config,
.can_sleep = true,
.ngpio = 3,
.base = -1,
......
......@@ -186,23 +186,24 @@ static int vx855gpio_direction_output(struct gpio_chip *gpio,
return 0;
}
static int vx855gpio_set_single_ended(struct gpio_chip *gpio,
unsigned int nr,
enum single_ended_mode mode)
static int vx855gpio_set_config(struct gpio_chip *gpio, unsigned int nr,
unsigned long config)
{
enum pin_config_param param = pinconf_to_config_param(config);
/* The GPI cannot be single-ended */
if (nr < NR_VX855_GPI)
return -EINVAL;
/* The GPO's are push-pull */
if (nr < NR_VX855_GPInO) {
if (mode != LINE_MODE_PUSH_PULL)
if (param != PIN_CONFIG_DRIVE_PUSH_PULL)
return -ENOTSUPP;
return 0;
}
/* The GPIO's are open drain */
if (mode != LINE_MODE_OPEN_DRAIN)
if (param != PIN_CONFIG_DRIVE_OPEN_DRAIN)
return -ENOTSUPP;
return 0;
......@@ -231,7 +232,7 @@ static void vx855gpio_gpio_setup(struct vx855_gpio *vg)
c->direction_output = vx855gpio_direction_output;
c->get = vx855gpio_get;
c->set = vx855gpio_set;
c->set_single_ended = vx855gpio_set_single_ended;
c->set_config = vx855gpio_set_config,
c->dbg_show = NULL;
c->base = 0;
c->ngpio = NR_VX855_GP;
......
......@@ -202,17 +202,16 @@ static void wcove_gpio_set(struct gpio_chip *chip,
regmap_update_bits(wg->regmap, to_reg(gpio, CTRL_OUT), 1, 0);
}
static int wcove_gpio_set_single_ended(struct gpio_chip *chip,
unsigned int gpio,
enum single_ended_mode mode)
static int wcove_gpio_set_config(struct gpio_chip *chip, unsigned int gpio,
unsigned long config)
{
struct wcove_gpio *wg = gpiochip_get_data(chip);
switch (mode) {
case LINE_MODE_OPEN_DRAIN:
switch (pinconf_to_config_param(config)) {
case PIN_CONFIG_DRIVE_OPEN_DRAIN:
return regmap_update_bits(wg->regmap, to_reg(gpio, CTRL_OUT),
CTLO_DRV_MASK, CTLO_DRV_OD);
case LINE_MODE_PUSH_PULL:
case PIN_CONFIG_DRIVE_PUSH_PULL:
return regmap_update_bits(wg->regmap, to_reg(gpio, CTRL_OUT),
CTLO_DRV_MASK, CTLO_DRV_CMOS);
default:
......@@ -411,7 +410,7 @@ static int wcove_gpio_probe(struct platform_device *pdev)
wg->chip.get_direction = wcove_gpio_get_direction;
wg->chip.get = wcove_gpio_get;
wg->chip.set = wcove_gpio_set;
wg->chip.set_single_ended = wcove_gpio_set_single_ended,
wg->chip.set_config = wcove_gpio_set_config,
wg->chip.base = -1;
wg->chip.ngpio = WCOVE_VGPIO_NUM;
wg->chip.can_sleep = true;
......
......@@ -101,11 +101,9 @@ static int wm831x_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
WM831X_IRQ_GPIO_1 + offset);
}
static int wm831x_gpio_set_debounce(struct gpio_chip *chip, unsigned offset,
static int wm831x_gpio_set_debounce(struct wm831x *wm831x, unsigned offset,
unsigned debounce)
{
struct wm831x_gpio *wm831x_gpio = gpiochip_get_data(chip);
struct wm831x *wm831x = wm831x_gpio->wm831x;
int reg = WM831X_GPIO1_CONTROL + offset;
int ret, fn;
......@@ -132,21 +130,23 @@ static int wm831x_gpio_set_debounce(struct gpio_chip *chip, unsigned offset,
return wm831x_set_bits(wm831x, reg, WM831X_GPN_FN_MASK, fn);
}
static int wm831x_set_single_ended(struct gpio_chip *chip,
unsigned int offset,
enum single_ended_mode mode)
static int wm831x_set_config(struct gpio_chip *chip, unsigned int offset,
unsigned long config)
{
struct wm831x_gpio *wm831x_gpio = gpiochip_get_data(chip);
struct wm831x *wm831x = wm831x_gpio->wm831x;
int reg = WM831X_GPIO1_CONTROL + offset;
switch (mode) {
case LINE_MODE_OPEN_DRAIN:
switch (pinconf_to_config_param(config)) {
case PIN_CONFIG_DRIVE_OPEN_DRAIN:
return wm831x_set_bits(wm831x, reg,
WM831X_GPN_OD_MASK, WM831X_GPN_OD);
case LINE_MODE_PUSH_PULL:
case PIN_CONFIG_DRIVE_PUSH_PULL:
return wm831x_set_bits(wm831x, reg,
WM831X_GPN_OD_MASK, 0);
case PIN_CONFIG_INPUT_DEBOUNCE:
return wm831x_gpio_set_debounce(wm831x, offset,
pinconf_to_config_argument(config));
default:
break;
}
......@@ -255,8 +255,7 @@ static const struct gpio_chip template_chip = {
.direction_output = wm831x_gpio_direction_out,
.set = wm831x_gpio_set,
.to_irq = wm831x_gpio_to_irq,
.set_debounce = wm831x_gpio_set_debounce,
.set_single_ended = wm831x_set_single_ended,
.set_config = wm831x_set_config,
.dbg_show = wm831x_gpio_dbg_show,
.can_sleep = true,
};
......
......@@ -103,19 +103,18 @@ static void wm8994_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
wm8994_set_bits(wm8994, WM8994_GPIO_1 + offset, WM8994_GPN_LVL, value);
}
static int wm8994_gpio_set_single_ended(struct gpio_chip *chip,
unsigned int offset,
enum single_ended_mode mode)
static int wm8994_gpio_set_config(struct gpio_chip *chip, unsigned int offset,
unsigned long config)
{
struct wm8994_gpio *wm8994_gpio = gpiochip_get_data(chip);
struct wm8994 *wm8994 = wm8994_gpio->wm8994;
switch (mode) {
case LINE_MODE_OPEN_DRAIN:
switch (pinconf_to_config_param(config)) {
case PIN_CONFIG_DRIVE_OPEN_DRAIN:
return wm8994_set_bits(wm8994, WM8994_GPIO_1 + offset,
WM8994_GPN_OP_CFG_MASK,
WM8994_GPN_OP_CFG);
case LINE_MODE_PUSH_PULL:
case PIN_CONFIG_DRIVE_PUSH_PULL:
return wm8994_set_bits(wm8994, WM8994_GPIO_1 + offset,
WM8994_GPN_OP_CFG_MASK, 0);
default:
......@@ -257,7 +256,7 @@ static const struct gpio_chip template_chip = {
.get = wm8994_gpio_get,
.direction_output = wm8994_gpio_direction_out,
.set = wm8994_gpio_set,
.set_single_ended = wm8994_gpio_set_single_ended,
.set_config = wm8994_gpio_set_config,
.to_irq = wm8994_gpio_to_irq,
.dbg_show = wm8994_gpio_dbg_show,
.can_sleep = true,
......
......@@ -1876,6 +1876,19 @@ void gpiochip_generic_free(struct gpio_chip *chip, unsigned offset)
}
EXPORT_SYMBOL_GPL(gpiochip_generic_free);
/**
* gpiochip_generic_config() - apply configuration for a pin
* @chip: the gpiochip owning the GPIO
* @offset: the offset of the GPIO to apply the configuration
* @config: the configuration to be applied
*/
int gpiochip_generic_config(struct gpio_chip *chip, unsigned offset,
unsigned long config)
{
return pinctrl_gpio_set_config(chip->gpiodev->base + offset, config);
}
EXPORT_SYMBOL_GPL(gpiochip_generic_config);
#ifdef CONFIG_PINCTRL
/**
......@@ -2264,6 +2277,14 @@ int gpiod_direction_input(struct gpio_desc *desc)
}
EXPORT_SYMBOL_GPL(gpiod_direction_input);
static int gpio_set_drive_single_ended(struct gpio_chip *gc, unsigned offset,
enum pin_config_param mode)
{
unsigned long config = { PIN_CONF_PACKED(mode, 0) };
return gc->set_config ? gc->set_config(gc, offset, config) : -ENOTSUPP;
}
static int _gpiod_direction_output_raw(struct gpio_desc *desc, int value)
{
struct gpio_chip *gc = desc->gdev->chip;
......@@ -2280,32 +2301,25 @@ static int _gpiod_direction_output_raw(struct gpio_desc *desc, int value)
if (test_bit(FLAG_OPEN_DRAIN, &desc->flags)) {
/* First see if we can enable open drain in hardware */
if (gc->set_single_ended) {
ret = gc->set_single_ended(gc, gpio_chip_hwgpio(desc),
LINE_MODE_OPEN_DRAIN);
ret = gpio_set_drive_single_ended(gc, gpio_chip_hwgpio(desc),
PIN_CONFIG_DRIVE_OPEN_DRAIN);
if (!ret)
goto set_output_value;
}
/* Emulate open drain by not actively driving the line high */
if (val)
return gpiod_direction_input(desc);
}
else if (test_bit(FLAG_OPEN_SOURCE, &desc->flags)) {
if (gc->set_single_ended) {
ret = gc->set_single_ended(gc, gpio_chip_hwgpio(desc),
LINE_MODE_OPEN_SOURCE);
ret = gpio_set_drive_single_ended(gc, gpio_chip_hwgpio(desc),
PIN_CONFIG_DRIVE_OPEN_SOURCE);
if (!ret)
goto set_output_value;
}
/* Emulate open source by not actively driving the line low */
if (!val)
return gpiod_direction_input(desc);
} else {
/* Make sure to disable open drain/source hardware, if any */
if (gc->set_single_ended)
gc->set_single_ended(gc,
gpio_chip_hwgpio(desc),
LINE_MODE_PUSH_PULL);
gpio_set_drive_single_ended(gc, gpio_chip_hwgpio(desc),
PIN_CONFIG_DRIVE_PUSH_PULL);
}
set_output_value:
......@@ -2376,17 +2390,19 @@ EXPORT_SYMBOL_GPL(gpiod_direction_output);
int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce)
{
struct gpio_chip *chip;
unsigned long config;
VALIDATE_DESC(desc);
chip = desc->gdev->chip;
if (!chip->set || !chip->set_debounce) {
if (!chip->set || !chip->set_config) {
gpiod_dbg(desc,
"%s: missing set() or set_debounce() operations\n",
"%s: missing set() or set_config() operations\n",
__func__);
return -ENOTSUPP;
}
return chip->set_debounce(chip, gpio_chip_hwgpio(desc), debounce);
config = pinconf_to_config_packed(PIN_CONFIG_INPUT_DEBOUNCE, debounce);
return chip->set_config(chip, gpio_chip_hwgpio(desc), config);
}
EXPORT_SYMBOL_GPL(gpiod_set_debounce);
......
......@@ -8,9 +8,16 @@ config PINCTRL
menu "Pin controllers"
depends on PINCTRL
config GENERIC_PINCTRL_GROUPS
bool
config PINMUX
bool "Support pin multiplexing controllers" if COMPILE_TEST
config GENERIC_PINMUX_FUNCTIONS
bool
select PINMUX
config PINCONF
bool "Support pin configuration controllers" if COMPILE_TEST
......@@ -159,8 +166,8 @@ config PINCTRL_ROCKCHIP
config PINCTRL_SINGLE
tristate "One-register-per-pin type device tree based pinctrl driver"
depends on OF
select PINMUX
select PINCONF
select GENERIC_PINCTRL_GROUPS
select GENERIC_PINMUX_FUNCTIONS
select GENERIC_PINCONF
help
This selects the device tree based generic pinctrl driver.
......@@ -293,6 +300,7 @@ source "drivers/pinctrl/spear/Kconfig"
source "drivers/pinctrl/stm32/Kconfig"
source "drivers/pinctrl/sunxi/Kconfig"
source "drivers/pinctrl/tegra/Kconfig"
source "drivers/pinctrl/ti/Kconfig"
source "drivers/pinctrl/uniphier/Kconfig"
source "drivers/pinctrl/vt8500/Kconfig"
source "drivers/pinctrl/mediatek/Kconfig"
......
......@@ -53,6 +53,7 @@ obj-$(CONFIG_PINCTRL_SH_PFC) += sh-pfc/
obj-$(CONFIG_PINCTRL_SPEAR) += spear/
obj-$(CONFIG_PINCTRL_STM32) += stm32/
obj-$(CONFIG_PINCTRL_SUNXI) += sunxi/
obj-y += ti/
obj-$(CONFIG_PINCTRL_UNIPHIER) += uniphier/
obj-$(CONFIG_ARCH_VT8500) += vt8500/
obj-$(CONFIG_PINCTRL_MTK) += mediatek/
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -232,6 +232,11 @@
* group.
*/
#define ASPEED_IP_SCU 0
#define ASPEED_IP_GFX 1
#define ASPEED_IP_LPC 2
#define ASPEED_NR_PINMUX_IPS 3
/*
* The "Multi-function Pins Mapping and Control" table in the SoC datasheet
* references registers by the device/offset mnemonic. The register macros
......@@ -255,13 +260,16 @@
#define SCUA0 0xA0 /* Multi-function Pin Control #7 */
#define SCUA4 0xA4 /* Multi-function Pin Control #8 */
#define SCUA8 0xA8 /* Multi-function Pin Control #9 */
#define SCUAC 0xAC /* Multi-function Pin Control #10 */
#define HW_STRAP2 0xD0 /* Strapping */
/**
* A signal descriptor, which describes the register, bits and the
* enable/disable values that should be compared or written.
*
* @reg: The register offset from base in bytes
* @ip: The IP block identifier, used as an index into the regmap array in
* struct aspeed_pinctrl_data
* @reg: The register offset with respect to the base address of the IP block
* @mask: The mask to apply to the register. The lowest set bit of the mask is
* used to derive the shift value.
* @enable: The value that enables the function. Value should be in the LSBs,
......@@ -270,6 +278,7 @@
* LSBs, not at the position of the mask.
*/
struct aspeed_sig_desc {
unsigned int ip;
unsigned int reg;
u32 mask;
u32 enable;
......@@ -313,24 +322,30 @@ struct aspeed_pin_desc {
/* Macro hell */
#define SIG_DESC_IP_BIT(ip, reg, idx, val) \
{ ip, reg, BIT_MASK(idx), val, (((val) + 1) & 1) }
/**
* Short-hand macro for describing a configuration enabled by the state of one
* bit. The disable value is derived.
* Short-hand macro for describing an SCU descriptor enabled by the state of
* one bit. The disable value is derived.
*
* @reg: The signal's associated register, offset from base
* @idx: The signal's bit index in the register
* @val: The value (0 or 1) that enables the function
*/
#define SIG_DESC_BIT(reg, idx, val) \
{ reg, BIT_MASK(idx), val, (((val) + 1) & 1) }
SIG_DESC_IP_BIT(ASPEED_IP_SCU, reg, idx, val)
#define SIG_DESC_IP_SET(ip, reg, idx) SIG_DESC_IP_BIT(ip, reg, idx, 1)
/**
* A further short-hand macro describing a configuration enabled with a set bit.
* A further short-hand macro expanding to an SCU descriptor enabled by a set
* bit.
*
* @reg: The configuration's associated register, offset from base
* @idx: The configuration's bit index in the register
* @reg: The register, offset from base
* @idx: The bit index in the register
*/
#define SIG_DESC_SET(reg, idx) SIG_DESC_BIT(reg, idx, 1)
#define SIG_DESC_SET(reg, idx) SIG_DESC_IP_BIT(ASPEED_IP_SCU, reg, idx, 1)
#define SIG_DESC_LIST_SYM(sig, func) sig_descs_ ## sig ## _ ## func
#define SIG_DESC_LIST_DECL(sig, func, ...) \
......@@ -500,7 +515,7 @@ struct aspeed_pin_desc {
MS_PIN_DECL_(pin, SIG_EXPR_LIST_PTR(gpio))
struct aspeed_pinctrl_data {
struct regmap *map;
struct regmap *maps[ASPEED_NR_PINMUX_IPS];
const struct pinctrl_pin_desc *pins;
const unsigned int npins;
......
......@@ -1106,7 +1106,7 @@ static int bcm281xx_std_pin_update(struct pinctrl_dev *pctldev,
struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
int i;
enum pin_config_param param;
u16 arg;
u32 arg;
for (i = 0; i < num_configs; i++) {
param = pinconf_to_config_param(configs[i]);
......@@ -1222,7 +1222,7 @@ static int bcm281xx_i2c_pin_update(struct pinctrl_dev *pctldev,
struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
int i, j;
enum pin_config_param param;
u16 arg;
u32 arg;
for (i = 0; i < num_configs; i++) {
param = pinconf_to_config_param(configs[i]);
......@@ -1292,7 +1292,7 @@ static int bcm281xx_hdmi_pin_update(struct pinctrl_dev *pctldev,
struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
int i;
enum pin_config_param param;
u16 arg;
u32 arg;
for (i = 0; i < num_configs; i++) {
param = pinconf_to_config_param(configs[i]);
......
......@@ -619,7 +619,7 @@ static int iproc_pin_config_set(struct pinctrl_dev *pctldev, unsigned pin,
{
struct iproc_gpio *chip = pinctrl_dev_get_drvdata(pctldev);
enum pin_config_param param;
u16 arg;
u32 arg;
unsigned i, gpio = iproc_pin_to_gpio(pin);
int ret = -ENOTSUPP;
......
......@@ -703,7 +703,7 @@ static int ns2_pin_get_enable(struct pinctrl_dev *pctrldev, unsigned int pin)
}
static int ns2_pin_set_slew(struct pinctrl_dev *pctrldev, unsigned int pin,
u16 slew)
u32 slew)
{
struct ns2_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctrldev);
struct ns2_pin *pin_data = pctrldev->desc->pins[pin].drv_data;
......@@ -793,7 +793,7 @@ static void ns2_pin_get_pull(struct pinctrl_dev *pctrldev,
}
static int ns2_pin_set_strength(struct pinctrl_dev *pctrldev, unsigned int pin,
u16 strength)
u32 strength)
{
struct ns2_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctrldev);
struct ns2_pin *pin_data = pctrldev->desc->pins[pin].drv_data;
......@@ -904,7 +904,7 @@ static int ns2_pin_config_set(struct pinctrl_dev *pctrldev, unsigned int pin,
struct ns2_pin *pin_data = pctrldev->desc->pins[pin].drv_data;
enum pin_config_param param;
unsigned int i;
u16 arg;
u32 arg;
int ret = -ENOTSUPP;
if (pin_data->pin_conf.base == -1)
......
......@@ -366,7 +366,7 @@ static const struct pinctrl_ops nsp_pctrl_ops = {
.dt_free_map = pinctrl_utils_free_map,
};
static int nsp_gpio_set_slew(struct nsp_gpio *chip, unsigned gpio, u16 slew)
static int nsp_gpio_set_slew(struct nsp_gpio *chip, unsigned gpio, u32 slew)
{
if (slew)
nsp_set_bit(chip, IO_CTRL, NSP_GPIO_SLEW_RATE_EN, gpio, true);
......@@ -403,7 +403,7 @@ static void nsp_gpio_get_pull(struct nsp_gpio *chip, unsigned gpio,
}
static int nsp_gpio_set_strength(struct nsp_gpio *chip, unsigned gpio,
u16 strength)
u32 strength)
{
u32 offset, shift, i;
u32 val;
......@@ -522,7 +522,7 @@ static int nsp_pin_config_set(struct pinctrl_dev *pctldev, unsigned pin,
{
struct nsp_gpio *chip = pinctrl_dev_get_drvdata(pctldev);
enum pin_config_param param;
u16 arg;
u32 arg;
unsigned int i, gpio;
int ret = -ENOTSUPP;
......
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.
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