1
0
Fork 0

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.
 -----BEGIN PGP SIGNATURE-----
 
 iQIcBAABAgAGBQJYq/7kAAoJEEEQszewGV1zf4oQALVaN5tuaCbzN4QOq87jzXmk
 K195kKG0nkNvN6o5llNhBszHfCSmX1+oSscxuCF/88kH4mFHeDIbvg0KOk5IZYxA
 YlT8NA75C9+flARE3gQUyL320ulahWbvOthntQprzsVU4RJa0zP38peQsfiUd8W1
 ch8GInJYYkczcsAbmziyUOBu5a2o9tX3u8BF8FaBf2uyrCiBC/ZT2VpzvbOR5NeU
 MvjFvc7bq2fNltzDNHdZZUo/5iCbnPlRNig2umDp5fFa8rZcdPmGMAOl4p6nizHY
 S16xDl38xxDQx8sp1IH4n+th3G2cXoONEj9eZ6woWTJhLbLc13CacYPfleYfqEOe
 +JyrUgBgFBINiFWDHHaebWJeD2M/QF4FnSDGnnJBy/bKWe6lJnknGvSZNcIEvdvB
 QeeKyfrvnKiCyjNY4N+ZNdMLA2vj5o86vG2hSqztPiwYWDePbN76yeZ7l79bFfOo
 ZnCa2ay70Np7xwrQWors4Gl2LV2zJG7AkaNA7vvS9NX6OURu/SkNVePkY1XHCLwu
 lNvYd4iwFJxzXm08TsgtLC080eZfvCot9xqbgzvoapnwx7tBuaAakXI4bh0T3x4n
 pEauKO3oNE/K89mN9QK2jfsD9kDWvm4xvc+ilA6DGU0C37XnDQjF+Q5xy16262Gh
 9w0yWMlqzrr7stUXAjS4
 =IMY0
 -----END PGP SIGNATURE-----

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
  ...
zero-colors
Linus Torvalds 2017-02-21 16:34:22 -08:00
commit 5ab356626f
143 changed files with 14096 additions and 3950 deletions

View File

@ -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

View File

@ -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

View File

@ -0,0 +1,46 @@
* 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)

View File

@ -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

View File

@ -1,25 +1,38 @@
======================
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:
"aspeed,ast2400-pinctrl"
"aspeed,g4-pinctrl"
"aspeed,ast2500-pinctrl"
"aspeed,g5-pinctrl"
Required properties for g4:
- compatible : Should be one of the following:
"aspeed,ast2400-pinctrl"
"aspeed,g4-pinctrl"
The pin controller node should be a child of a syscon node with the required
Required properties for g5:
- compatible : Should be one of the following:
"aspeed,ast2500-pinctrl"
"aspeed,g5-pinctrl"
- 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
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
========
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.

View File

@ -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.

View File

@ -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

View File

@ -0,0 +1,47 @@
* 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 */
>;
};
};

View File

@ -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

View File

@ -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

View File

@ -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,

View File

@ -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));
}

View File

@ -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 */

View File

@ -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,

View File

@ -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,
};

View File

@ -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);

View File

@ -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);

View File

@ -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;
}

View File

@ -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);

View File

@ -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,

View File

@ -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;

View File

@ -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) {

View File

@ -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;

View File

@ -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";

View File

@ -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,
};

View File

@ -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);

View File

@ -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,

View File

@ -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;

View File

@ -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;

View File

@ -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,
};

View File

@ -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,

View File

@ -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);
if (!ret)
goto set_output_value;
}
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);
if (!ret)
goto set_output_value;
}
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);

View File

@ -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"

View File

@ -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/

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -14,6 +14,12 @@
#include "../core.h"
#include "pinctrl-aspeed.h"
static const char *const aspeed_pinmux_ips[] = {
[ASPEED_IP_SCU] = "SCU",
[ASPEED_IP_GFX] = "GFX",
[ASPEED_IP_LPC] = "LPC",
};
int aspeed_pinctrl_get_groups_count(struct pinctrl_dev *pctldev)
{
struct aspeed_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
@ -78,7 +84,8 @@ int aspeed_pinmux_get_fn_groups(struct pinctrl_dev *pctldev,
static inline void aspeed_sig_desc_print_val(
const struct aspeed_sig_desc *desc, bool enable, u32 rv)
{
pr_debug("SCU%x[0x%08x]=0x%x, got 0x%x from 0x%08x\n", desc->reg,
pr_debug("Want %s%X[0x%08X]=0x%X, got 0x%X from 0x%08X\n",
aspeed_pinmux_ips[desc->ip], desc->reg,
desc->mask, enable ? desc->enable : desc->disable,
(rv & desc->mask) >> __ffs(desc->mask), rv);
}
@ -88,10 +95,11 @@ static inline void aspeed_sig_desc_print_val(
*
* @desc: The signal descriptor of interest
* @enabled: True to query the enabled state, false to query disabled state
* @regmap: The SCU regmap instance
* @regmap: The IP block's regmap instance
*
* @return True if the descriptor's bitfield is configured to the state
* selected by @enabled, false otherwise
* Return: 1 if the descriptor's bitfield is configured to the state
* selected by @enabled, 0 if not, and less than zero if an unrecoverable
* failure occurred
*
* Evaluation of descriptor state is non-trivial in that it is not a binary
* outcome: The bitfields can be greater than one bit in size and thus can take
@ -99,14 +107,19 @@ static inline void aspeed_sig_desc_print_val(
* descriptor (typically this means a different function to the one of interest
* is enabled). Thus we must explicitly test for either condition as required.
*/
static bool aspeed_sig_desc_eval(const struct aspeed_sig_desc *desc,
static int aspeed_sig_desc_eval(const struct aspeed_sig_desc *desc,
bool enabled, struct regmap *map)
{
int ret;
unsigned int raw;
u32 want;
if (regmap_read(map, desc->reg, &raw) < 0)
return false;
if (!map)
return -ENODEV;
ret = regmap_read(map, desc->reg, &raw);
if (ret)
return ret;
aspeed_sig_desc_print_val(desc, enabled, raw);
want = enabled ? desc->enable : desc->disable;
@ -119,10 +132,10 @@ static bool aspeed_sig_desc_eval(const struct aspeed_sig_desc *desc,
*
* @expr: An expression controlling the signal for a mux function on a pin
* @enabled: True to query the enabled state, false to query disabled state
* @regmap: The SCU regmap instance
* @maps: The list of regmap instances
*
* @return True if the expression composed by @enabled evaluates true, false
* otherwise
* Return: 1 if the expression composed by @enabled evaluates true, 0 if not,
* and less than zero if an unrecoverable failure occurred.
*
* A mux function is enabled or disabled if the function's signal expression
* for each pin in the function's pin group evaluates true for the desired
@ -135,19 +148,21 @@ static bool aspeed_sig_desc_eval(const struct aspeed_sig_desc *desc,
* neither the enabled nor disabled state. Thus we must explicitly test for
* either condition as required.
*/
static bool aspeed_sig_expr_eval(const struct aspeed_sig_expr *expr,
bool enabled, struct regmap *map)
static int aspeed_sig_expr_eval(const struct aspeed_sig_expr *expr,
bool enabled, struct regmap * const *maps)
{
int i;
int ret;
for (i = 0; i < expr->ndescs; i++) {
const struct aspeed_sig_desc *desc = &expr->descs[i];
if (!aspeed_sig_desc_eval(desc, enabled, map))
return false;
ret = aspeed_sig_desc_eval(desc, enabled, maps[desc->ip]);
if (ret <= 0)
return ret;
}
return true;
return 1;
}
/**
@ -158,19 +173,24 @@ static bool aspeed_sig_expr_eval(const struct aspeed_sig_expr *expr,
* configured
* @enable: true to enable an function's signal through a pin's signal
* expression, false to disable the function's signal
* @map: The SCU's regmap instance for pinmux register access.
* @maps: The list of regmap instances for pinmux register access.
*
* @return true if the expression is configured as requested, false otherwise
* Return: 0 if the expression is configured as requested and a negative error
* code otherwise
*/
static bool aspeed_sig_expr_set(const struct aspeed_sig_expr *expr,
bool enable, struct regmap *map)
static int aspeed_sig_expr_set(const struct aspeed_sig_expr *expr,
bool enable, struct regmap * const *maps)
{
int ret;
int i;
for (i = 0; i < expr->ndescs; i++) {
bool ret;
const struct aspeed_sig_desc *desc = &expr->descs[i];
u32 pattern = enable ? desc->enable : desc->disable;
u32 val = (pattern << __ffs(desc->mask));
if (!maps[desc->ip])
return -ENODEV;
/*
* Strap registers are configured in hardware or by early-boot
@ -179,64 +199,79 @@ static bool aspeed_sig_expr_set(const struct aspeed_sig_expr *expr,
* deconfigured and is the reason we re-evaluate after writing
* all descriptor bits.
*/
if (desc->reg == HW_STRAP1 || desc->reg == HW_STRAP2)
if ((desc->reg == HW_STRAP1 || desc->reg == HW_STRAP2) &&
desc->ip == ASPEED_IP_SCU)
continue;
ret = regmap_update_bits(map, desc->reg, desc->mask,
pattern << __ffs(desc->mask)) == 0;
ret = regmap_update_bits(maps[desc->ip], desc->reg,
desc->mask, val);
if (!ret)
if (ret)
return ret;
}
return aspeed_sig_expr_eval(expr, enable, map);
ret = aspeed_sig_expr_eval(expr, enable, maps);
if (ret < 0)
return ret;
if (!ret)
return -EPERM;
return 0;
}
static bool aspeed_sig_expr_enable(const struct aspeed_sig_expr *expr,
struct regmap *map)
static int aspeed_sig_expr_enable(const struct aspeed_sig_expr *expr,
struct regmap * const *maps)
{
if (aspeed_sig_expr_eval(expr, true, map))
return true;
int ret;
return aspeed_sig_expr_set(expr, true, map);
ret = aspeed_sig_expr_eval(expr, true, maps);
if (ret < 0)
return ret;
if (!ret)
return aspeed_sig_expr_set(expr, true, maps);
return 0;
}
static bool aspeed_sig_expr_disable(const struct aspeed_sig_expr *expr,
struct regmap *map)
static int aspeed_sig_expr_disable(const struct aspeed_sig_expr *expr,
struct regmap * const *maps)
{
if (!aspeed_sig_expr_eval(expr, true, map))
return true;
int ret;
return aspeed_sig_expr_set(expr, false, map);
ret = aspeed_sig_expr_eval(expr, true, maps);
if (ret < 0)
return ret;
if (ret)
return aspeed_sig_expr_set(expr, false, maps);
return 0;
}
/**
* Disable a signal on a pin by disabling all provided signal expressions.
*
* @exprs: The list of signal expressions (from a priority level on a pin)
* @map: The SCU's regmap instance for pinmux register access.
* @maps: The list of regmap instances for pinmux register access.
*
* @return true if all expressions in the list are successfully disabled, false
* otherwise
* Return: 0 if all expressions are disabled, otherwise a negative error code
*/
static bool aspeed_disable_sig(const struct aspeed_sig_expr **exprs,
struct regmap *map)
static int aspeed_disable_sig(const struct aspeed_sig_expr **exprs,
struct regmap * const *maps)
{
bool disabled = true;
int ret = 0;
if (!exprs)
return true;
while (*exprs) {
bool ret;
ret = aspeed_sig_expr_disable(*exprs, map);
disabled = disabled && ret;
while (*exprs && !ret) {
ret = aspeed_sig_expr_disable(*exprs, maps);
exprs++;
}
return disabled;
return ret;
}
/**
@ -246,8 +281,8 @@ static bool aspeed_disable_sig(const struct aspeed_sig_expr **exprs,
* @exprs: List of signal expressions (haystack)
* @name: The name of the requested function (needle)
*
* @return A pointer to the signal expression whose function tag matches the
* provided name, otherwise NULL.
* Return: A pointer to the signal expression whose function tag matches the
* provided name, otherwise NULL.
*
*/
static const struct aspeed_sig_expr *aspeed_find_expr_by_name(
@ -330,6 +365,7 @@ int aspeed_pinmux_set_mux(struct pinctrl_dev *pctldev, unsigned int function,
unsigned int group)
{
int i;
int ret;
const struct aspeed_pinctrl_data *pdata =
pinctrl_dev_get_drvdata(pctldev);
const struct aspeed_pin_group *pgroup = &pdata->groups[group];
@ -343,6 +379,8 @@ int aspeed_pinmux_set_mux(struct pinctrl_dev *pctldev, unsigned int function,
const struct aspeed_sig_expr **funcs;
const struct aspeed_sig_expr ***prios;
pr_debug("Muxing pin %d for %s\n", pin, pfunc->name);
if (!pdesc)
return -EINVAL;
@ -358,8 +396,9 @@ int aspeed_pinmux_set_mux(struct pinctrl_dev *pctldev, unsigned int function,
if (expr)
break;
if (!aspeed_disable_sig(funcs, pdata->map))
return -EPERM;
ret = aspeed_disable_sig(funcs, pdata->maps);
if (ret)
return ret;
prios++;
}
@ -377,8 +416,9 @@ int aspeed_pinmux_set_mux(struct pinctrl_dev *pctldev, unsigned int function,
return -ENXIO;
}
if (!aspeed_sig_expr_enable(expr, pdata->map))
return -EPERM;
ret = aspeed_sig_expr_enable(expr, pdata->maps);
if (ret)
return ret;
}
return 0;
@ -414,6 +454,7 @@ int aspeed_gpio_request_enable(struct pinctrl_dev *pctldev,
struct pinctrl_gpio_range *range,
unsigned int offset)
{
int ret;
const struct aspeed_pinctrl_data *pdata =
pinctrl_dev_get_drvdata(pctldev);
const struct aspeed_pin_desc *pdesc = pdata->pins[offset].drv_data;
@ -432,8 +473,9 @@ int aspeed_gpio_request_enable(struct pinctrl_dev *pctldev,
if (aspeed_gpio_in_exprs(funcs))
break;
if (!aspeed_disable_sig(funcs, pdata->map))
return -EPERM;
ret = aspeed_disable_sig(funcs, pdata->maps);
if (ret)
return ret;
prios++;
}
@ -462,10 +504,7 @@ int aspeed_gpio_request_enable(struct pinctrl_dev *pctldev,
* If GPIO is not the lowest priority signal type, assume there is only
* one expression defined to enable the GPIO function
*/
if (!aspeed_sig_expr_enable(expr, pdata->map))
return -EPERM;
return 0;
return aspeed_sig_expr_enable(expr, pdata->maps);
}
int aspeed_pinctrl_probe(struct platform_device *pdev,
@ -481,10 +520,10 @@ int aspeed_pinctrl_probe(struct platform_device *pdev,
return -ENODEV;
}
pdata->map = syscon_node_to_regmap(parent->of_node);
if (IS_ERR(pdata->map)) {
pdata->maps[ASPEED_IP_SCU] = syscon_node_to_regmap(parent->of_node);
if (IS_ERR(pdata->maps[ASPEED_IP_SCU])) {
dev_err(&pdev->dev, "No regmap for syscon pincontroller parent\n");
return PTR_ERR(pdata->map);
return PTR_ERR(pdata->maps[ASPEED_IP_SCU]);
}
pctl = pinctrl_register(pdesc, &pdev->dev, pdata);

View File

@ -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;

View File

@ -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]);

View File

@ -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;

View File

@ -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)

View File

@ -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;

View File

@ -10,7 +10,7 @@
* warranty of any kind, whether express or implied.
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
@ -227,7 +227,6 @@ static const struct of_device_id berlin2_pinctrl_match[] = {
},
{}
};
MODULE_DEVICE_TABLE(of, berlin2_pinctrl_match);
static int berlin2_pinctrl_probe(struct platform_device *pdev)
{
@ -244,8 +243,4 @@ static struct platform_driver berlin2_pinctrl_driver = {
.of_match_table = berlin2_pinctrl_match,
},
};
module_platform_driver(berlin2_pinctrl_driver);
MODULE_AUTHOR("Antoine Ténart <antoine.tenart@free-electrons.com>");
MODULE_DESCRIPTION("Marvell Berlin BG2 pinctrl driver");
MODULE_LICENSE("GPL");
builtin_platform_driver(berlin2_pinctrl_driver);

View File

@ -10,7 +10,7 @@
* warranty of any kind, whether express or implied.
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
@ -172,7 +172,6 @@ static const struct of_device_id berlin2cd_pinctrl_match[] = {
},
{}
};
MODULE_DEVICE_TABLE(of, berlin2cd_pinctrl_match);
static int berlin2cd_pinctrl_probe(struct platform_device *pdev)
{
@ -189,8 +188,4 @@ static struct platform_driver berlin2cd_pinctrl_driver = {
.of_match_table = berlin2cd_pinctrl_match,
},
};
module_platform_driver(berlin2cd_pinctrl_driver);
MODULE_AUTHOR("Antoine Ténart <antoine.tenart@free-electrons.com>");
MODULE_DESCRIPTION("Marvell Berlin BG2CD pinctrl driver");
MODULE_LICENSE("GPL");
builtin_platform_driver(berlin2cd_pinctrl_driver);

View File

@ -10,7 +10,7 @@
* warranty of any kind, whether express or implied.
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
@ -389,7 +389,6 @@ static const struct of_device_id berlin2q_pinctrl_match[] = {
},
{}
};
MODULE_DEVICE_TABLE(of, berlin2q_pinctrl_match);
static int berlin2q_pinctrl_probe(struct platform_device *pdev)
{
@ -406,8 +405,4 @@ static struct platform_driver berlin2q_pinctrl_driver = {
.of_match_table = berlin2q_pinctrl_match,
},
};
module_platform_driver(berlin2q_pinctrl_driver);
MODULE_AUTHOR("Antoine Ténart <antoine.tenart@free-electrons.com>");
MODULE_DESCRIPTION("Marvell Berlin BG2Q pinctrl driver");
MODULE_LICENSE("GPL");
builtin_platform_driver(berlin2q_pinctrl_driver);

View File

@ -18,7 +18,7 @@
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
@ -457,7 +457,6 @@ static const struct of_device_id berlin4ct_pinctrl_match[] = {
},
{}
};
MODULE_DEVICE_TABLE(of, berlin4ct_pinctrl_match);
static int berlin4ct_pinctrl_probe(struct platform_device *pdev)
{
@ -496,8 +495,4 @@ static struct platform_driver berlin4ct_pinctrl_driver = {
.of_match_table = berlin4ct_pinctrl_match,
},
};
module_platform_driver(berlin4ct_pinctrl_driver);
MODULE_AUTHOR("Jisheng Zhang <jszhang@marvell.com>");
MODULE_DESCRIPTION("Marvell berlin4ct pinctrl driver");
MODULE_LICENSE("GPL");
builtin_platform_driver(berlin4ct_pinctrl_driver);

View File

@ -237,10 +237,8 @@ static int pinctrl_register_one_pin(struct pinctrl_dev *pctldev,
}
pindesc = kzalloc(sizeof(*pindesc), GFP_KERNEL);
if (pindesc == NULL) {
dev_err(pctldev->dev, "failed to alloc struct pin_desc\n");
if (!pindesc)
return -ENOMEM;
}
/* Set owner */
pindesc->pctldev = pctldev;
@ -540,6 +538,182 @@ void pinctrl_remove_gpio_range(struct pinctrl_dev *pctldev,
}
EXPORT_SYMBOL_GPL(pinctrl_remove_gpio_range);
#ifdef CONFIG_GENERIC_PINCTRL_GROUPS
/**
* pinctrl_generic_get_group_count() - returns the number of pin groups
* @pctldev: pin controller device
*/
int pinctrl_generic_get_group_count(struct pinctrl_dev *pctldev)
{
return pctldev->num_groups;
}
EXPORT_SYMBOL_GPL(pinctrl_generic_get_group_count);
/**
* pinctrl_generic_get_group_name() - returns the name of a pin group
* @pctldev: pin controller device
* @selector: group number
*/
const char *pinctrl_generic_get_group_name(struct pinctrl_dev *pctldev,
unsigned int selector)
{
struct group_desc *group;
group = radix_tree_lookup(&pctldev->pin_group_tree,
selector);
if (!group)
return NULL;
return group->name;
}
EXPORT_SYMBOL_GPL(pinctrl_generic_get_group_name);
/**
* pinctrl_generic_get_group_pins() - gets the pin group pins
* @pctldev: pin controller device
* @selector: group number
* @pins: pins in the group
* @num_pins: number of pins in the group
*/
int pinctrl_generic_get_group_pins(struct pinctrl_dev *pctldev,
unsigned int selector,
const unsigned int **pins,
unsigned int *num_pins)
{
struct group_desc *group;
group = radix_tree_lookup(&pctldev->pin_group_tree,
selector);
if (!group) {
dev_err(pctldev->dev, "%s could not find pingroup%i\n",
__func__, selector);
return -EINVAL;
}
*pins = group->pins;
*num_pins = group->num_pins;
return 0;
}
EXPORT_SYMBOL_GPL(pinctrl_generic_get_group_pins);
/**
* pinctrl_generic_get_group() - returns a pin group based on the number
* @pctldev: pin controller device
* @gselector: group number
*/
struct group_desc *pinctrl_generic_get_group(struct pinctrl_dev *pctldev,
unsigned int selector)
{
struct group_desc *group;
group = radix_tree_lookup(&pctldev->pin_group_tree,
selector);
if (!group)
return NULL;
return group;
}
EXPORT_SYMBOL_GPL(pinctrl_generic_get_group);
/**
* pinctrl_generic_add_group() - adds a new pin group
* @pctldev: pin controller device
* @name: name of the pin group
* @pins: pins in the pin group
* @num_pins: number of pins in the pin group
* @data: pin controller driver specific data
*
* Note that the caller must take care of locking.
*/
int pinctrl_generic_add_group(struct pinctrl_dev *pctldev, const char *name,
int *pins, int num_pins, void *data)
{
struct group_desc *group;
group = devm_kzalloc(pctldev->dev, sizeof(*group), GFP_KERNEL);
if (!group)
return -ENOMEM;
group->name = name;
group->pins = pins;
group->num_pins = num_pins;
group->data = data;
radix_tree_insert(&pctldev->pin_group_tree, pctldev->num_groups,
group);
pctldev->num_groups++;
return 0;
}
EXPORT_SYMBOL_GPL(pinctrl_generic_add_group);
/**
* pinctrl_generic_remove_group() - removes a numbered pin group
* @pctldev: pin controller device
* @selector: group number
*
* Note that the caller must take care of locking.
*/
int pinctrl_generic_remove_group(struct pinctrl_dev *pctldev,
unsigned int selector)
{
struct group_desc *group;
group = radix_tree_lookup(&pctldev->pin_group_tree,
selector);
if (!group)
return -ENOENT;
radix_tree_delete(&pctldev->pin_group_tree, selector);
devm_kfree(pctldev->dev, group);
pctldev->num_groups--;
return 0;
}
EXPORT_SYMBOL_GPL(pinctrl_generic_remove_group);
/**
* pinctrl_generic_free_groups() - removes all pin groups
* @pctldev: pin controller device
*
* Note that the caller must take care of locking.
*/
static void pinctrl_generic_free_groups(struct pinctrl_dev *pctldev)
{
struct radix_tree_iter iter;
struct group_desc *group;
unsigned long *indices;
void **slot;
int i = 0;
indices = devm_kzalloc(pctldev->dev, sizeof(*indices) *
pctldev->num_groups, GFP_KERNEL);
if (!indices)
return;
radix_tree_for_each_slot(slot, &pctldev->pin_group_tree, &iter, 0)
indices[i++] = iter.index;
for (i = 0; i < pctldev->num_groups; i++) {
group = radix_tree_lookup(&pctldev->pin_group_tree,
indices[i]);
radix_tree_delete(&pctldev->pin_group_tree, indices[i]);
devm_kfree(pctldev->dev, group);
}
pctldev->num_groups = 0;
}
#else
static inline void pinctrl_generic_free_groups(struct pinctrl_dev *pctldev)
{
}
#endif /* CONFIG_GENERIC_PINCTRL_GROUPS */
/**
* pinctrl_get_group_selector() - returns the group selector for a group
* @pctldev: the pin controller handling the group
@ -688,6 +862,35 @@ int pinctrl_gpio_direction_output(unsigned gpio)
}
EXPORT_SYMBOL_GPL(pinctrl_gpio_direction_output);
/**
* pinctrl_gpio_set_config() - Apply config to given GPIO pin
* @gpio: the GPIO pin number from the GPIO subsystem number space
* @config: the configuration to apply to the GPIO
*
* This function should *ONLY* be used from gpiolib-based GPIO drivers, if
* they need to call the underlying pin controller to change GPIO config
* (for example set debounce time).
*/
int pinctrl_gpio_set_config(unsigned gpio, unsigned long config)
{
unsigned long configs[] = { config };
struct pinctrl_gpio_range *range;
struct pinctrl_dev *pctldev;
int ret, pin;
ret = pinctrl_get_device_gpio_range(gpio, &pctldev, &range);
if (ret)
return ret;
mutex_lock(&pctldev->mutex);
pin = gpio_to_pin(range, gpio);
ret = pinconf_set_config(pctldev, pin, configs, ARRAY_SIZE(configs));
mutex_unlock(&pctldev->mutex);
return ret;
}
EXPORT_SYMBOL_GPL(pinctrl_gpio_set_config);
static struct pinctrl_state *find_state(struct pinctrl *p,
const char *name)
{
@ -706,11 +909,8 @@ static struct pinctrl_state *create_state(struct pinctrl *p,
struct pinctrl_state *state;
state = kzalloc(sizeof(*state), GFP_KERNEL);
if (state == NULL) {
dev_err(p->dev,
"failed to alloc struct pinctrl_state\n");
if (!state)
return ERR_PTR(-ENOMEM);
}
state->name = name;
INIT_LIST_HEAD(&state->settings);
@ -720,7 +920,8 @@ static struct pinctrl_state *create_state(struct pinctrl *p,
return state;
}
static int add_setting(struct pinctrl *p, struct pinctrl_map const *map)
static int add_setting(struct pinctrl *p, struct pinctrl_dev *pctldev,
struct pinctrl_map const *map)
{
struct pinctrl_state *state;
struct pinctrl_setting *setting;
@ -736,15 +937,16 @@ static int add_setting(struct pinctrl *p, struct pinctrl_map const *map)
return 0;
setting = kzalloc(sizeof(*setting), GFP_KERNEL);
if (setting == NULL) {
dev_err(p->dev,
"failed to alloc struct pinctrl_setting\n");
if (!setting)
return -ENOMEM;
}
setting->type = map->type;
setting->pctldev = get_pinctrl_dev_from_devname(map->ctrl_dev_name);
if (pctldev)
setting->pctldev = pctldev;
else
setting->pctldev =
get_pinctrl_dev_from_devname(map->ctrl_dev_name);
if (setting->pctldev == NULL) {
kfree(setting);
/* Do not defer probing of hogs (circular loop) */
@ -800,7 +1002,8 @@ static struct pinctrl *find_pinctrl(struct device *dev)
static void pinctrl_free(struct pinctrl *p, bool inlist);
static struct pinctrl *create_pinctrl(struct device *dev)
static struct pinctrl *create_pinctrl(struct device *dev,
struct pinctrl_dev *pctldev)
{
struct pinctrl *p;
const char *devname;
@ -815,15 +1018,13 @@ static struct pinctrl *create_pinctrl(struct device *dev)
* a pin control handle with pinctrl_get()
*/
p = kzalloc(sizeof(*p), GFP_KERNEL);
if (p == NULL) {
dev_err(dev, "failed to alloc struct pinctrl\n");
if (!p)
return ERR_PTR(-ENOMEM);
}
p->dev = dev;
INIT_LIST_HEAD(&p->states);
INIT_LIST_HEAD(&p->dt_maps);
ret = pinctrl_dt_to_map(p);
ret = pinctrl_dt_to_map(p, pctldev);
if (ret < 0) {
kfree(p);
return ERR_PTR(ret);
@ -838,7 +1039,7 @@ static struct pinctrl *create_pinctrl(struct device *dev)
if (strcmp(map->dev_name, devname))
continue;
ret = add_setting(p, map);
ret = add_setting(p, pctldev, map);
/*
* At this point the adding of a setting may:
*
@ -899,7 +1100,7 @@ struct pinctrl *pinctrl_get(struct device *dev)
return p;
}
return create_pinctrl(dev);
return create_pinctrl(dev, NULL);
}
EXPORT_SYMBOL_GPL(pinctrl_get);
@ -1175,10 +1376,8 @@ int pinctrl_register_map(struct pinctrl_map const *maps, unsigned num_maps,
}
maps_node = kzalloc(sizeof(*maps_node), GFP_KERNEL);
if (!maps_node) {
pr_err("failed to alloc struct pinctrl_maps\n");
if (!maps_node)
return -ENOMEM;
}
maps_node->num_maps = num_maps;
if (dup) {
@ -1731,20 +1930,18 @@ static int pinctrl_check_ops(struct pinctrl_dev *pctldev)
!ops->get_group_name)
return -EINVAL;
if (ops->dt_node_to_map && !ops->dt_free_map)
return -EINVAL;
return 0;
}
/**
* pinctrl_register() - register a pin controller device
* pinctrl_init_controller() - init a pin controller device
* @pctldesc: descriptor for this pin controller
* @dev: parent device for this pin controller
* @driver_data: private pin controller data for this pin controller
*/
struct pinctrl_dev *pinctrl_register(struct pinctrl_desc *pctldesc,
struct device *dev, void *driver_data)
struct pinctrl_dev *pinctrl_init_controller(struct pinctrl_desc *pctldesc,
struct device *dev,
void *driver_data)
{
struct pinctrl_dev *pctldev;
int ret;
@ -1755,17 +1952,22 @@ struct pinctrl_dev *pinctrl_register(struct pinctrl_desc *pctldesc,
return ERR_PTR(-EINVAL);
pctldev = kzalloc(sizeof(*pctldev), GFP_KERNEL);
if (pctldev == NULL) {
dev_err(dev, "failed to alloc struct pinctrl_dev\n");
if (!pctldev)
return ERR_PTR(-ENOMEM);
}
/* Initialize pin control device struct */
pctldev->owner = pctldesc->owner;
pctldev->desc = pctldesc;
pctldev->driver_data = driver_data;
INIT_RADIX_TREE(&pctldev->pin_desc_tree, GFP_KERNEL);
#ifdef CONFIG_GENERIC_PINCTRL_GROUPS
INIT_RADIX_TREE(&pctldev->pin_group_tree, GFP_KERNEL);
#endif
#ifdef CONFIG_GENERIC_PINMUX_FUNCTIONS
INIT_RADIX_TREE(&pctldev->pin_function_tree, GFP_KERNEL);
#endif
INIT_LIST_HEAD(&pctldev->gpio_ranges);
INIT_LIST_HEAD(&pctldev->node);
pctldev->dev = dev;
mutex_init(&pctldev->mutex);
@ -1800,33 +2002,6 @@ struct pinctrl_dev *pinctrl_register(struct pinctrl_desc *pctldesc,
goto out_err;
}
mutex_lock(&pinctrldev_list_mutex);
list_add_tail(&pctldev->node, &pinctrldev_list);
mutex_unlock(&pinctrldev_list_mutex);
pctldev->p = pinctrl_get(pctldev->dev);
if (!IS_ERR(pctldev->p)) {
pctldev->hog_default =
pinctrl_lookup_state(pctldev->p, PINCTRL_STATE_DEFAULT);
if (IS_ERR(pctldev->hog_default)) {
dev_dbg(dev, "failed to lookup the default state\n");
} else {
if (pinctrl_select_state(pctldev->p,
pctldev->hog_default))
dev_err(dev,
"failed to select default state\n");
}
pctldev->hog_sleep =
pinctrl_lookup_state(pctldev->p,
PINCTRL_STATE_SLEEP);
if (IS_ERR(pctldev->hog_sleep))
dev_dbg(dev, "failed to lookup the sleep state\n");
}
pinctrl_init_device_debugfs(pctldev);
return pctldev;
out_err:
@ -1834,8 +2009,107 @@ out_err:
kfree(pctldev);
return ERR_PTR(ret);
}
static int pinctrl_create_and_start(struct pinctrl_dev *pctldev)
{
pctldev->p = create_pinctrl(pctldev->dev, pctldev);
if (!IS_ERR(pctldev->p)) {
kref_get(&pctldev->p->users);
pctldev->hog_default =
pinctrl_lookup_state(pctldev->p, PINCTRL_STATE_DEFAULT);
if (IS_ERR(pctldev->hog_default)) {
dev_dbg(pctldev->dev,
"failed to lookup the default state\n");
} else {
if (pinctrl_select_state(pctldev->p,
pctldev->hog_default))
dev_err(pctldev->dev,
"failed to select default state\n");
}
pctldev->hog_sleep =
pinctrl_lookup_state(pctldev->p,
PINCTRL_STATE_SLEEP);
if (IS_ERR(pctldev->hog_sleep))
dev_dbg(pctldev->dev,
"failed to lookup the sleep state\n");
}
mutex_lock(&pinctrldev_list_mutex);
list_add_tail(&pctldev->node, &pinctrldev_list);
mutex_unlock(&pinctrldev_list_mutex);
pinctrl_init_device_debugfs(pctldev);
return 0;
}
/**
* pinctrl_register() - register a pin controller device
* @pctldesc: descriptor for this pin controller
* @dev: parent device for this pin controller
* @driver_data: private pin controller data for this pin controller
*
* Note that pinctrl_register() is known to have problems as the pin
* controller driver functions are called before the driver has a
* struct pinctrl_dev handle. To avoid issues later on, please use the
* new pinctrl_register_and_init() below instead.
*/
struct pinctrl_dev *pinctrl_register(struct pinctrl_desc *pctldesc,
struct device *dev, void *driver_data)
{
struct pinctrl_dev *pctldev;
int error;
pctldev = pinctrl_init_controller(pctldesc, dev, driver_data);
if (IS_ERR(pctldev))
return pctldev;
error = pinctrl_create_and_start(pctldev);
if (error) {
mutex_destroy(&pctldev->mutex);
kfree(pctldev);
return ERR_PTR(error);
}
return pctldev;
}
EXPORT_SYMBOL_GPL(pinctrl_register);
int pinctrl_register_and_init(struct pinctrl_desc *pctldesc,
struct device *dev, void *driver_data,
struct pinctrl_dev **pctldev)
{
struct pinctrl_dev *p;
int error;
p = pinctrl_init_controller(pctldesc, dev, driver_data);
if (IS_ERR(p))
return PTR_ERR(p);
/*
* We have pinctrl_start() call functions in the pin controller
* driver with create_pinctrl() for at least dt_node_to_map(). So
* let's make sure pctldev is properly initialized for the
* pin controller driver before we do anything.
*/
*pctldev = p;
error = pinctrl_create_and_start(p);
if (error) {
mutex_destroy(&p->mutex);
kfree(p);
*pctldev = NULL;
return error;
}
return 0;
}
EXPORT_SYMBOL_GPL(pinctrl_register_and_init);
/**
* pinctrl_unregister() - unregister pinmux
* @pctldev: pin controller to unregister
@ -1845,6 +2119,7 @@ EXPORT_SYMBOL_GPL(pinctrl_register);
void pinctrl_unregister(struct pinctrl_dev *pctldev)
{
struct pinctrl_gpio_range *range, *n;
if (pctldev == NULL)
return;
@ -1852,13 +2127,15 @@ void pinctrl_unregister(struct pinctrl_dev *pctldev)
pinctrl_remove_device_debugfs(pctldev);
mutex_unlock(&pctldev->mutex);
if (!IS_ERR(pctldev->p))
if (!IS_ERR_OR_NULL(pctldev->p))
pinctrl_put(pctldev->p);
mutex_lock(&pinctrldev_list_mutex);
mutex_lock(&pctldev->mutex);
/* TODO: check that no pinmuxes are still active? */
list_del(&pctldev->node);
pinmux_generic_free_functions(pctldev);
pinctrl_generic_free_groups(pctldev);
/* Destroy descriptor tree */
pinctrl_free_pindescs(pctldev, pctldev->desc->pins,
pctldev->desc->npins);
@ -1924,6 +2201,42 @@ struct pinctrl_dev *devm_pinctrl_register(struct device *dev,
}
EXPORT_SYMBOL_GPL(devm_pinctrl_register);
/**
* devm_pinctrl_register_and_init() - Resource managed pinctrl register and init
* @dev: parent device for this pin controller
* @pctldesc: descriptor for this pin controller
* @driver_data: private pin controller data for this pin controller
*
* Returns an error pointer if pincontrol register failed. Otherwise
* it returns valid pinctrl handle.
*
* The pinctrl device will be automatically released when the device is unbound.
*/
int devm_pinctrl_register_and_init(struct device *dev,
struct pinctrl_desc *pctldesc,
void *driver_data,
struct pinctrl_dev **pctldev)
{
struct pinctrl_dev **ptr;
int error;
ptr = devres_alloc(devm_pinctrl_dev_release, sizeof(*ptr), GFP_KERNEL);
if (!ptr)
return -ENOMEM;
error = pinctrl_register_and_init(pctldesc, dev, driver_data, pctldev);
if (error) {
devres_free(ptr);
return error;
}
*ptr = *pctldev;
devres_add(dev, ptr);
return 0;
}
EXPORT_SYMBOL_GPL(devm_pinctrl_register_and_init);
/**
* devm_pinctrl_unregister() - Resource managed version of pinctrl_unregister().
* @dev: device for which which resource was allocated

View File

@ -24,6 +24,10 @@ struct pinctrl_gpio_range;
* controller
* @pin_desc_tree: each pin descriptor for this pin controller is stored in
* this radix tree
* @pin_group_tree: optionally each pin group can be stored in this radix tree
* @num_groups: optionally number of groups can be kept here
* @pin_function_tree: optionally each function can be stored in this radix tree
* @num_functions: optionally number of functions can be kept here
* @gpio_ranges: a list of GPIO ranges that is handled by this pin controller,
* ranges are added to this list at runtime
* @dev: the device entry for this pin controller
@ -40,6 +44,14 @@ struct pinctrl_dev {
struct list_head node;
struct pinctrl_desc *desc;
struct radix_tree_root pin_desc_tree;
#ifdef CONFIG_GENERIC_PINCTRL_GROUPS
struct radix_tree_root pin_group_tree;
unsigned int num_groups;
#endif
#ifdef CONFIG_GENERIC_PINMUX_FUNCTIONS
struct radix_tree_root pin_function_tree;
unsigned int num_functions;
#endif
struct list_head gpio_ranges;
struct device *dev;
struct module *owner;
@ -171,6 +183,49 @@ struct pinctrl_maps {
unsigned num_maps;
};
#ifdef CONFIG_GENERIC_PINCTRL_GROUPS
/**
* struct group_desc - generic pin group descriptor
* @name: name of the pin group
* @pins: array of pins that belong to the group
* @num_pins: number of pins in the group
* @data: pin controller driver specific data
*/
struct group_desc {
const char *name;
int *pins;
int num_pins;
void *data;
};
int pinctrl_generic_get_group_count(struct pinctrl_dev *pctldev);
const char *pinctrl_generic_get_group_name(struct pinctrl_dev *pctldev,
unsigned int group_selector);
int pinctrl_generic_get_group_pins(struct pinctrl_dev *pctldev,
unsigned int group_selector,
const unsigned int **pins,
unsigned int *npins);
struct group_desc *pinctrl_generic_get_group(struct pinctrl_dev *pctldev,
unsigned int group_selector);
int pinctrl_generic_add_group(struct pinctrl_dev *pctldev, const char *name,
int *gpins, int ngpins, void *data);
int pinctrl_generic_remove_group(struct pinctrl_dev *pctldev,
unsigned int group_selector);
static inline int
pinctrl_generic_remove_last_group(struct pinctrl_dev *pctldev)
{
return pinctrl_generic_remove_group(pctldev, pctldev->num_groups - 1);
}
#endif /* CONFIG_GENERIC_PINCTRL_GROUPS */
struct pinctrl_dev *get_pinctrl_dev_from_devname(const char *dev_name);
struct pinctrl_dev *get_pinctrl_dev_from_of_node(struct device_node *np);
int pin_get_from_name(struct pinctrl_dev *pctldev, const char *name);

View File

@ -42,7 +42,8 @@ static void dt_free_map(struct pinctrl_dev *pctldev,
{
if (pctldev) {
const struct pinctrl_ops *ops = pctldev->desc->pctlops;
ops->dt_free_map(pctldev, map, num_maps);
if (ops->dt_free_map)
ops->dt_free_map(pctldev, map, num_maps);
} else {
/* There is no pctldev for PIN_MAP_TYPE_DUMMY_STATE */
kfree(map);
@ -100,11 +101,12 @@ struct pinctrl_dev *of_pinctrl_get(struct device_node *np)
return get_pinctrl_dev_from_of_node(np);
}
static int dt_to_map_one_config(struct pinctrl *p, const char *statename,
static int dt_to_map_one_config(struct pinctrl *p,
struct pinctrl_dev *pctldev,
const char *statename,
struct device_node *np_config)
{
struct device_node *np_pctldev;
struct pinctrl_dev *pctldev;
const struct pinctrl_ops *ops;
int ret;
struct pinctrl_map *map;
@ -121,7 +123,8 @@ static int dt_to_map_one_config(struct pinctrl *p, const char *statename,
/* OK let's just assume this will appear later then */
return -EPROBE_DEFER;
}
pctldev = get_pinctrl_dev_from_of_node(np_pctldev);
if (!pctldev)
pctldev = get_pinctrl_dev_from_of_node(np_pctldev);
if (pctldev)
break;
/* Do not defer probing of hogs (circular loop) */
@ -166,7 +169,22 @@ static int dt_remember_dummy_state(struct pinctrl *p, const char *statename)
return dt_remember_or_free_map(p, statename, NULL, map, 1);
}
int pinctrl_dt_to_map(struct pinctrl *p)
bool pinctrl_dt_has_hogs(struct pinctrl_dev *pctldev)
{
struct device_node *np;
struct property *prop;
int size;
np = pctldev->dev->of_node;
if (!np)
return false;
prop = of_find_property(np, "pinctrl-0", &size);
return prop ? true : false;
}
int pinctrl_dt_to_map(struct pinctrl *p, struct pinctrl_dev *pctldev)
{
struct device_node *np = p->dev->of_node;
int state, ret;
@ -233,7 +251,8 @@ int pinctrl_dt_to_map(struct pinctrl *p)
}
/* Parse the node */
ret = dt_to_map_one_config(p, statename, np_config);
ret = dt_to_map_one_config(p, pctldev, statename,
np_config);
of_node_put(np_config);
if (ret < 0)
goto err;

View File

@ -20,8 +20,10 @@ struct of_phandle_args;
#ifdef CONFIG_OF
bool pinctrl_dt_has_hogs(struct pinctrl_dev *pctldev);
void pinctrl_dt_free_maps(struct pinctrl *p);
int pinctrl_dt_to_map(struct pinctrl *p);
int pinctrl_dt_to_map(struct pinctrl *p, struct pinctrl_dev *pctldev);
int pinctrl_count_index_with_args(const struct device_node *np,
const char *list_name);
@ -32,7 +34,13 @@ int pinctrl_parse_index_with_args(const struct device_node *np,
#else
static inline int pinctrl_dt_to_map(struct pinctrl *p)
static inline bool pinctrl_dt_has_hogs(struct pinctrl_dev *pctldev)
{
return false;
}
static inline int pinctrl_dt_to_map(struct pinctrl *p,
struct pinctrl_dev *pctldev)
{
return 0;
}

View File

@ -1,6 +1,7 @@
config PINCTRL_IMX
bool
select PINMUX
select GENERIC_PINCTRL_GROUPS
select GENERIC_PINMUX_FUNCTIONS
select PINCONF
select REGMAP

View File

@ -27,6 +27,7 @@
#include <linux/regmap.h>
#include "../core.h"
#include "../pinmux.h"
#include "pinctrl-imx.h"
/* The bits in CONFIG cell defined in binding doc*/
@ -42,59 +43,25 @@ struct imx_pinctrl {
struct pinctrl_dev *pctl;
void __iomem *base;
void __iomem *input_sel_base;
const struct imx_pinctrl_soc_info *info;
struct imx_pinctrl_soc_info *info;
};
static inline const struct imx_pin_group *imx_pinctrl_find_group_by_name(
const struct imx_pinctrl_soc_info *info,
static inline const struct group_desc *imx_pinctrl_find_group_by_name(
struct pinctrl_dev *pctldev,
const char *name)
{
const struct imx_pin_group *grp = NULL;
const struct group_desc *grp = NULL;
int i;
for (i = 0; i < info->ngroups; i++) {
if (!strcmp(info->groups[i].name, name)) {
grp = &info->groups[i];
for (i = 0; i < pctldev->num_groups; i++) {
grp = pinctrl_generic_get_group(pctldev, i);
if (grp && !strcmp(grp->name, name))
break;
}
}
return grp;
}
static int imx_get_groups_count(struct pinctrl_dev *pctldev)
{
struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
const struct imx_pinctrl_soc_info *info = ipctl->info;
return info->ngroups;
}
static const char *imx_get_group_name(struct pinctrl_dev *pctldev,
unsigned selector)
{
struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
const struct imx_pinctrl_soc_info *info = ipctl->info;
return info->groups[selector].name;
}
static int imx_get_group_pins(struct pinctrl_dev *pctldev, unsigned selector,
const unsigned **pins,
unsigned *npins)
{
struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
const struct imx_pinctrl_soc_info *info = ipctl->info;
if (selector >= info->ngroups)
return -EINVAL;
*pins = info->groups[selector].pin_ids;
*npins = info->groups[selector].npins;
return 0;
}
static void imx_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
unsigned offset)
{
@ -106,8 +73,8 @@ static int imx_dt_node_to_map(struct pinctrl_dev *pctldev,
struct pinctrl_map **map, unsigned *num_maps)
{
struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
const struct imx_pinctrl_soc_info *info = ipctl->info;
const struct imx_pin_group *grp;
struct imx_pinctrl_soc_info *info = ipctl->info;
const struct group_desc *grp;
struct pinctrl_map *new_map;
struct device_node *parent;
int map_num = 1;
@ -117,15 +84,17 @@ static int imx_dt_node_to_map(struct pinctrl_dev *pctldev,
* first find the group of this node and check if we need create
* config maps for pins
*/
grp = imx_pinctrl_find_group_by_name(info, np->name);
grp = imx_pinctrl_find_group_by_name(pctldev, np->name);
if (!grp) {
dev_err(info->dev, "unable to find group for node %s\n",
np->name);
return -EINVAL;
}
for (i = 0; i < grp->npins; i++) {
if (!(grp->pins[i].config & IMX_NO_PAD_CTL))
for (i = 0; i < grp->num_pins; i++) {
struct imx_pin *pin = &((struct imx_pin *)(grp->data))[i];
if (!(pin->config & IMX_NO_PAD_CTL))
map_num++;
}
@ -149,12 +118,14 @@ static int imx_dt_node_to_map(struct pinctrl_dev *pctldev,
/* create config map */
new_map++;
for (i = j = 0; i < grp->npins; i++) {
if (!(grp->pins[i].config & IMX_NO_PAD_CTL)) {
for (i = j = 0; i < grp->num_pins; i++) {
struct imx_pin *pin = &((struct imx_pin *)(grp->data))[i];
if (!(pin->config & IMX_NO_PAD_CTL)) {
new_map[j].type = PIN_MAP_TYPE_CONFIGS_PIN;
new_map[j].data.configs.group_or_pin =
pin_get_name(pctldev, grp->pins[i].pin);
new_map[j].data.configs.configs = &grp->pins[i].config;
pin_get_name(pctldev, pin->pin);
new_map[j].data.configs.configs = &pin->config;
new_map[j].data.configs.num_configs = 1;
j++;
}
@ -173,9 +144,9 @@ static void imx_dt_free_map(struct pinctrl_dev *pctldev,
}
static const struct pinctrl_ops imx_pctrl_ops = {
.get_groups_count = imx_get_groups_count,
.get_group_name = imx_get_group_name,
.get_group_pins = imx_get_group_pins,
.get_groups_count = pinctrl_generic_get_group_count,
.get_group_name = pinctrl_generic_get_group_name,
.get_group_pins = pinctrl_generic_get_group_pins,
.pin_dbg_show = imx_pin_dbg_show,
.dt_node_to_map = imx_dt_node_to_map,
.dt_free_map = imx_dt_free_map,
@ -186,24 +157,33 @@ static int imx_pmx_set(struct pinctrl_dev *pctldev, unsigned selector,
unsigned group)
{
struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
const struct imx_pinctrl_soc_info *info = ipctl->info;
struct imx_pinctrl_soc_info *info = ipctl->info;
const struct imx_pin_reg *pin_reg;
unsigned int npins, pin_id;
int i;
struct imx_pin_group *grp;
struct group_desc *grp = NULL;
struct function_desc *func = NULL;
/*
* Configure the mux mode for each pin in the group for a specific
* function.
*/
grp = &info->groups[group];
npins = grp->npins;
grp = pinctrl_generic_get_group(pctldev, group);
if (!grp)
return -EINVAL;
func = pinmux_generic_get_function(pctldev, selector);
if (!func)
return -EINVAL;
npins = grp->num_pins;
dev_dbg(ipctl->dev, "enable function %s group %s\n",
info->functions[selector].name, grp->name);
func->name, grp->name);
for (i = 0; i < npins; i++) {
struct imx_pin *pin = &grp->pins[i];
struct imx_pin *pin = &((struct imx_pin *)(grp->data))[i];
pin_id = pin->pin;
pin_reg = &info->pin_regs[pin_id];
@ -272,43 +252,13 @@ static int imx_pmx_set(struct pinctrl_dev *pctldev, unsigned selector,
return 0;
}
static int imx_pmx_get_funcs_count(struct pinctrl_dev *pctldev)
{
struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
const struct imx_pinctrl_soc_info *info = ipctl->info;
return info->nfunctions;
}
static const char *imx_pmx_get_func_name(struct pinctrl_dev *pctldev,
unsigned selector)
{
struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
const struct imx_pinctrl_soc_info *info = ipctl->info;
return info->functions[selector].name;
}
static int imx_pmx_get_groups(struct pinctrl_dev *pctldev, unsigned selector,
const char * const **groups,
unsigned * const num_groups)
{
struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
const struct imx_pinctrl_soc_info *info = ipctl->info;
*groups = info->functions[selector].groups;
*num_groups = info->functions[selector].num_groups;
return 0;
}
static int imx_pmx_gpio_request_enable(struct pinctrl_dev *pctldev,
struct pinctrl_gpio_range *range, unsigned offset)
{
struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
const struct imx_pinctrl_soc_info *info = ipctl->info;
struct imx_pinctrl_soc_info *info = ipctl->info;
const struct imx_pin_reg *pin_reg;
struct imx_pin_group *grp;
struct group_desc *grp;
struct imx_pin *imx_pin;
unsigned int pin, group;
u32 reg;
@ -322,10 +272,12 @@ static int imx_pmx_gpio_request_enable(struct pinctrl_dev *pctldev,
return -EINVAL;
/* Find the pinctrl config with GPIO mux mode for the requested pin */
for (group = 0; group < info->ngroups; group++) {
grp = &info->groups[group];
for (pin = 0; pin < grp->npins; pin++) {
imx_pin = &grp->pins[pin];
for (group = 0; group < pctldev->num_groups; group++) {
grp = pinctrl_generic_get_group(pctldev, group);
if (!grp)
continue;
for (pin = 0; pin < grp->num_pins; pin++) {
imx_pin = &((struct imx_pin *)(grp->data))[pin];
if (imx_pin->pin == offset && !imx_pin->mux_mode)
goto mux_pin;
}
@ -346,7 +298,7 @@ static void imx_pmx_gpio_disable_free(struct pinctrl_dev *pctldev,
struct pinctrl_gpio_range *range, unsigned offset)
{
struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
const struct imx_pinctrl_soc_info *info = ipctl->info;
struct imx_pinctrl_soc_info *info = ipctl->info;
const struct imx_pin_reg *pin_reg;
u32 reg;
@ -371,7 +323,7 @@ static int imx_pmx_gpio_set_direction(struct pinctrl_dev *pctldev,
struct pinctrl_gpio_range *range, unsigned offset, bool input)
{
struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
const struct imx_pinctrl_soc_info *info = ipctl->info;
struct imx_pinctrl_soc_info *info = ipctl->info;
const struct imx_pin_reg *pin_reg;
u32 reg;
@ -398,9 +350,9 @@ static int imx_pmx_gpio_set_direction(struct pinctrl_dev *pctldev,
}
static const struct pinmux_ops imx_pmx_ops = {
.get_functions_count = imx_pmx_get_funcs_count,
.get_function_name = imx_pmx_get_func_name,
.get_function_groups = imx_pmx_get_groups,
.get_functions_count = pinmux_generic_get_function_count,
.get_function_name = pinmux_generic_get_function_name,
.get_function_groups = pinmux_generic_get_function_groups,
.set_mux = imx_pmx_set,
.gpio_request_enable = imx_pmx_gpio_request_enable,
.gpio_disable_free = imx_pmx_gpio_disable_free,
@ -411,7 +363,7 @@ static int imx_pinconf_get(struct pinctrl_dev *pctldev,
unsigned pin_id, unsigned long *config)
{
struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
const struct imx_pinctrl_soc_info *info = ipctl->info;
struct imx_pinctrl_soc_info *info = ipctl->info;
const struct imx_pin_reg *pin_reg = &info->pin_regs[pin_id];
if (pin_reg->conf_reg == -1) {
@ -433,7 +385,7 @@ static int imx_pinconf_set(struct pinctrl_dev *pctldev,
unsigned num_configs)
{
struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
const struct imx_pinctrl_soc_info *info = ipctl->info;
struct imx_pinctrl_soc_info *info = ipctl->info;
const struct imx_pin_reg *pin_reg = &info->pin_regs[pin_id];
int i;
@ -467,7 +419,7 @@ static void imx_pinconf_dbg_show(struct pinctrl_dev *pctldev,
struct seq_file *s, unsigned pin_id)
{
struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
const struct imx_pinctrl_soc_info *info = ipctl->info;
struct imx_pinctrl_soc_info *info = ipctl->info;
const struct imx_pin_reg *pin_reg = &info->pin_regs[pin_id];
unsigned long config;
@ -483,20 +435,22 @@ static void imx_pinconf_dbg_show(struct pinctrl_dev *pctldev,
static void imx_pinconf_group_dbg_show(struct pinctrl_dev *pctldev,
struct seq_file *s, unsigned group)
{
struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
const struct imx_pinctrl_soc_info *info = ipctl->info;
struct imx_pin_group *grp;
struct group_desc *grp;
unsigned long config;
const char *name;
int i, ret;
if (group > info->ngroups)
if (group > pctldev->num_groups)
return;
seq_printf(s, "\n");
grp = &info->groups[group];
for (i = 0; i < grp->npins; i++) {
struct imx_pin *pin = &grp->pins[i];
grp = pinctrl_generic_get_group(pctldev, group);
if (!grp)
return;
for (i = 0; i < grp->num_pins; i++) {
struct imx_pin *pin = &((struct imx_pin *)(grp->data))[i];
name = pin_get_name(pctldev, pin->pin);
ret = imx_pinconf_get(pctldev, pin->pin, &config);
if (ret)
@ -520,7 +474,7 @@ static const struct pinconf_ops imx_pinconf_ops = {
#define SHARE_FSL_PIN_SIZE 20
static int imx_pinctrl_parse_groups(struct device_node *np,
struct imx_pin_group *grp,
struct group_desc *grp,
struct imx_pinctrl_soc_info *info,
u32 index)
{
@ -554,20 +508,20 @@ static int imx_pinctrl_parse_groups(struct device_node *np,
return -EINVAL;
}
grp->npins = size / pin_size;
grp->pins = devm_kzalloc(info->dev, grp->npins * sizeof(struct imx_pin),
GFP_KERNEL);
grp->pin_ids = devm_kzalloc(info->dev, grp->npins * sizeof(unsigned int),
GFP_KERNEL);
if (!grp->pins || ! grp->pin_ids)
grp->num_pins = size / pin_size;
grp->data = devm_kzalloc(info->dev, grp->num_pins *
sizeof(struct imx_pin), GFP_KERNEL);
grp->pins = devm_kzalloc(info->dev, grp->num_pins *
sizeof(unsigned int), GFP_KERNEL);
if (!grp->pins || !grp->data)
return -ENOMEM;
for (i = 0; i < grp->npins; i++) {
for (i = 0; i < grp->num_pins; i++) {
u32 mux_reg = be32_to_cpu(*list++);
u32 conf_reg;
unsigned int pin_id;
struct imx_pin_reg *pin_reg;
struct imx_pin *pin = &grp->pins[i];
struct imx_pin *pin = &((struct imx_pin *)(grp->data))[i];
if (!(info->flags & ZERO_OFFSET_VALID) && !mux_reg)
mux_reg = -1;
@ -583,7 +537,7 @@ static int imx_pinctrl_parse_groups(struct device_node *np,
pin_id = (mux_reg != -1) ? mux_reg / 4 : conf_reg / 4;
pin_reg = &info->pin_regs[pin_id];
pin->pin = pin_id;
grp->pin_ids[i] = pin_id;
grp->pins[i] = pin_id;
pin_reg->mux_reg = mux_reg;
pin_reg->conf_reg = conf_reg;
pin->input_reg = be32_to_cpu(*list++);
@ -604,31 +558,46 @@ static int imx_pinctrl_parse_groups(struct device_node *np,
}
static int imx_pinctrl_parse_functions(struct device_node *np,
struct imx_pinctrl_soc_info *info,
struct imx_pinctrl *ipctl,
u32 index)
{
struct pinctrl_dev *pctl = ipctl->pctl;
struct imx_pinctrl_soc_info *info = ipctl->info;
struct device_node *child;
struct imx_pmx_func *func;
struct imx_pin_group *grp;
struct function_desc *func;
struct group_desc *grp;
u32 i = 0;
dev_dbg(info->dev, "parse function(%d): %s\n", index, np->name);
func = &info->functions[index];
func = pinmux_generic_get_function(pctl, index);
if (!func)
return -EINVAL;
/* Initialise function */
func->name = np->name;
func->num_groups = of_get_child_count(np);
if (func->num_groups == 0) {
func->num_group_names = of_get_child_count(np);
if (func->num_group_names == 0) {
dev_err(info->dev, "no groups defined in %s\n", np->full_name);
return -EINVAL;
}
func->groups = devm_kzalloc(info->dev,
func->num_groups * sizeof(char *), GFP_KERNEL);
func->group_names = devm_kzalloc(info->dev,
func->num_group_names *
sizeof(char *), GFP_KERNEL);
for_each_child_of_node(np, child) {
func->groups[i] = child->name;
grp = &info->groups[info->group_index++];
func->group_names[i] = child->name;
grp = devm_kzalloc(info->dev, sizeof(struct group_desc),
GFP_KERNEL);
if (!grp)
return -ENOMEM;
mutex_lock(&info->mutex);
radix_tree_insert(&pctl->pin_group_tree,
info->group_index++, grp);
mutex_unlock(&info->mutex);
imx_pinctrl_parse_groups(child, grp, info, i++);
}
@ -659,10 +628,12 @@ static bool imx_pinctrl_dt_is_flat_functions(struct device_node *np)
}
static int imx_pinctrl_probe_dt(struct platform_device *pdev,
struct imx_pinctrl_soc_info *info)
struct imx_pinctrl *ipctl)
{
struct device_node *np = pdev->dev.of_node;
struct device_node *child;
struct pinctrl_dev *pctl = ipctl->pctl;
struct imx_pinctrl_soc_info *info = ipctl->info;
u32 nfuncs = 0;
u32 i = 0;
bool flat_funcs;
@ -681,35 +652,50 @@ static int imx_pinctrl_probe_dt(struct platform_device *pdev,
}
}
info->nfunctions = nfuncs;
info->functions = devm_kzalloc(&pdev->dev, nfuncs * sizeof(struct imx_pmx_func),
for (i = 0; i < nfuncs; i++) {
struct function_desc *function;
function = devm_kzalloc(&pdev->dev, sizeof(*function),
GFP_KERNEL);
if (!info->functions)
return -ENOMEM;
if (!function)
return -ENOMEM;
mutex_lock(&info->mutex);
radix_tree_insert(&pctl->pin_function_tree, i, function);
mutex_unlock(&info->mutex);
}
pctl->num_functions = nfuncs;
info->group_index = 0;
if (flat_funcs) {
info->ngroups = of_get_child_count(np);
pctl->num_groups = of_get_child_count(np);
} else {
info->ngroups = 0;
pctl->num_groups = 0;
for_each_child_of_node(np, child)
info->ngroups += of_get_child_count(child);
pctl->num_groups += of_get_child_count(child);
}
info->groups = devm_kzalloc(&pdev->dev, info->ngroups * sizeof(struct imx_pin_group),
GFP_KERNEL);
if (!info->groups)
return -ENOMEM;
if (flat_funcs) {
imx_pinctrl_parse_functions(np, info, 0);
imx_pinctrl_parse_functions(np, ipctl, 0);
} else {
i = 0;
for_each_child_of_node(np, child)
imx_pinctrl_parse_functions(child, info, i++);
imx_pinctrl_parse_functions(child, ipctl, i++);
}
return 0;
}
/*
* imx_free_resources() - free memory used by this driver
* @info: info driver instance
*/
static void imx_free_resources(struct imx_pinctrl *ipctl)
{
if (ipctl->pctl)
pinctrl_unregister(ipctl->pctl);
}
int imx_pinctrl_probe(struct platform_device *pdev,
struct imx_pinctrl_soc_info *info)
{
@ -783,23 +769,31 @@ int imx_pinctrl_probe(struct platform_device *pdev,
imx_pinctrl_desc->confops = &imx_pinconf_ops;
imx_pinctrl_desc->owner = THIS_MODULE;
ret = imx_pinctrl_probe_dt(pdev, info);
if (ret) {
dev_err(&pdev->dev, "fail to probe dt properties\n");
return ret;
}
mutex_init(&info->mutex);
ipctl->info = info;
ipctl->dev = info->dev;
platform_set_drvdata(pdev, ipctl);
ipctl->pctl = devm_pinctrl_register(&pdev->dev,
imx_pinctrl_desc, ipctl);
if (IS_ERR(ipctl->pctl)) {
ret = devm_pinctrl_register_and_init(&pdev->dev,
imx_pinctrl_desc, ipctl,
&ipctl->pctl);
if (ret) {
dev_err(&pdev->dev, "could not register IMX pinctrl driver\n");
return PTR_ERR(ipctl->pctl);
goto free;
}
ret = imx_pinctrl_probe_dt(pdev, ipctl);
if (ret) {
dev_err(&pdev->dev, "fail to probe dt properties\n");
goto free;
}
dev_info(&pdev->dev, "initialized IMX pinctrl driver\n");
return 0;
free:
imx_free_resources(ipctl);
return ret;
}

View File

@ -18,7 +18,7 @@
struct platform_device;
/**
* struct imx_pin_group - describes a single i.MX pin
* struct imx_pin - describes a single i.MX pin
* @pin: the pin_id of this pin
* @mux_mode: the mux mode for this pin.
* @input_reg: the select input register offset for this pin if any
@ -34,33 +34,6 @@ struct imx_pin {
unsigned long config;
};
/**
* struct imx_pin_group - describes an IMX pin group
* @name: the name of this specific pin group
* @npins: the number of pins in this group array, i.e. the number of
* elements in .pins so we can iterate over that array
* @pin_ids: array of pin_ids. pinctrl forces us to maintain such an array
* @pins: array of pins
*/
struct imx_pin_group {
const char *name;
unsigned npins;
unsigned int *pin_ids;
struct imx_pin *pins;
};
/**
* struct imx_pmx_func - describes IMX pinmux functions
* @name: the name of this specific function
* @groups: corresponding pin groups
* @num_groups: the number of groups
*/
struct imx_pmx_func {
const char *name;
const char **groups;
unsigned num_groups;
};
/**
* struct imx_pin_reg - describe a pin reg map
* @mux_reg: mux register offset
@ -76,13 +49,10 @@ struct imx_pinctrl_soc_info {
const struct pinctrl_pin_desc *pins;
unsigned int npins;
struct imx_pin_reg *pin_regs;
struct imx_pin_group *groups;
unsigned int ngroups;
unsigned int group_index;
struct imx_pmx_func *functions;
unsigned int nfunctions;
unsigned int flags;
const char *gpr_compatible;
struct mutex mutex;
};
#define SHARE_MUX_CONF_REG 0x1

View File

@ -56,6 +56,14 @@ config PINCTRL_BROXTON
Broxton pinctrl driver provides an interface that allows
configuring of SoC pins and using them as GPIOs.
config PINCTRL_GEMINILAKE
tristate "Intel Gemini Lake SoC pinctrl and GPIO driver"
depends on ACPI
select PINCTRL_INTEL
help
This pinctrl driver provides an interface that allows configuring
of Intel Gemini Lake SoC pins and using them as GPIOs.
config PINCTRL_SUNRISEPOINT
tristate "Intel Sunrisepoint pinctrl and GPIO driver"
depends on ACPI

View File

@ -5,4 +5,5 @@ obj-$(CONFIG_PINCTRL_CHERRYVIEW) += pinctrl-cherryview.o
obj-$(CONFIG_PINCTRL_MERRIFIELD) += pinctrl-merrifield.o
obj-$(CONFIG_PINCTRL_INTEL) += pinctrl-intel.o
obj-$(CONFIG_PINCTRL_BROXTON) += pinctrl-broxton.o
obj-$(CONFIG_PINCTRL_GEMINILAKE) += pinctrl-geminilake.o
obj-$(CONFIG_PINCTRL_SUNRISEPOINT) += pinctrl-sunrisepoint.o

View File

@ -1466,7 +1466,7 @@ static void byt_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
val & BYT_INPUT_EN ? " " : "in",
val & BYT_OUTPUT_EN ? " " : "out",
val & BYT_LEVEL ? "hi" : "lo",
comm->pad_map[i], comm->pad_map[i] * 32,
comm->pad_map[i], comm->pad_map[i] * 16,
conf0 & 0x7,
conf0 & BYT_TRIG_NEG ? " fall" : " ",
conf0 & BYT_TRIG_POS ? " rise" : " ",
@ -1709,7 +1709,7 @@ static int byt_gpio_probe(struct byt_gpio *vg)
vg->saved_context = devm_kcalloc(&vg->pdev->dev, gc->ngpio,
sizeof(*vg->saved_context), GFP_KERNEL);
#endif
ret = gpiochip_add_data(gc, vg);
ret = devm_gpiochip_add_data(&vg->pdev->dev, gc, vg);
if (ret) {
dev_err(&vg->pdev->dev, "failed adding byt-gpio chip\n");
return ret;
@ -1719,7 +1719,7 @@ static int byt_gpio_probe(struct byt_gpio *vg)
0, 0, vg->soc_data->npins);
if (ret) {
dev_err(&vg->pdev->dev, "failed to add GPIO pin range\n");
goto fail;
return ret;
}
/* set up interrupts */
@ -1730,7 +1730,7 @@ static int byt_gpio_probe(struct byt_gpio *vg)
handle_bad_irq, IRQ_TYPE_NONE);
if (ret) {
dev_err(&vg->pdev->dev, "failed to add irqchip\n");
goto fail;
return ret;
}
gpiochip_set_chained_irqchip(gc, &byt_irqchip,
@ -1738,11 +1738,6 @@ static int byt_gpio_probe(struct byt_gpio *vg)
byt_gpio_irq_handler);
}
return ret;
fail:
gpiochip_remove(&vg->chip);
return ret;
}
@ -1826,7 +1821,7 @@ static int byt_pinctrl_probe(struct platform_device *pdev)
vg->pctl_desc.pins = vg->soc_data->pins;
vg->pctl_desc.npins = vg->soc_data->npins;
vg->pctl_dev = pinctrl_register(&vg->pctl_desc, &pdev->dev, vg);
vg->pctl_dev = devm_pinctrl_register(&pdev->dev, &vg->pctl_desc, vg);
if (IS_ERR(vg->pctl_dev)) {
dev_err(&pdev->dev, "failed to register pinctrl driver\n");
return PTR_ERR(vg->pctl_dev);
@ -1835,10 +1830,8 @@ static int byt_pinctrl_probe(struct platform_device *pdev)
raw_spin_lock_init(&vg->lock);
ret = byt_gpio_probe(vg);
if (ret) {
pinctrl_unregister(vg->pctl_dev);
if (ret)
return ret;
}
platform_set_drvdata(pdev, vg);
pm_runtime_enable(&pdev->dev);

View File

@ -1004,8 +1004,8 @@ static const struct acpi_device_id bxt_pinctrl_acpi_match[] = {
MODULE_DEVICE_TABLE(acpi, bxt_pinctrl_acpi_match);
static const struct platform_device_id bxt_pinctrl_platform_ids[] = {
{ "apl-pinctrl", (kernel_ulong_t)&apl_pinctrl_soc_data },
{ "broxton-pinctrl", (kernel_ulong_t)&bxt_pinctrl_soc_data },
{ "apollolake-pinctrl", (kernel_ulong_t)apl_pinctrl_soc_data },
{ "broxton-pinctrl", (kernel_ulong_t)bxt_pinctrl_soc_data },
{ },
};
@ -1058,7 +1058,6 @@ static const struct dev_pm_ops bxt_pinctrl_pm_ops = {
static struct platform_driver bxt_pinctrl_driver = {
.probe = bxt_pinctrl_probe,
.remove = intel_pinctrl_remove,
.driver = {
.name = "broxton-pinctrl",
.acpi_match_table = bxt_pinctrl_acpi_match,

View File

@ -1059,7 +1059,7 @@ static int chv_config_get(struct pinctrl_dev *pctldev, unsigned pin,
}
static int chv_config_set_pull(struct chv_pinctrl *pctrl, unsigned pin,
enum pin_config_param param, u16 arg)
enum pin_config_param param, u32 arg)
{
void __iomem *reg = chv_padreg(pctrl, pin, CHV_PADCTRL0);
unsigned long flags;
@ -1151,7 +1151,7 @@ static int chv_config_set(struct pinctrl_dev *pctldev, unsigned pin,
struct chv_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
enum pin_config_param param;
int i, ret;
u16 arg;
u32 arg;
if (chv_pad_locked(pctrl, pin))
return -EBUSY;

View File

@ -0,0 +1,512 @@
/*
* Intel Gemini Lake SoC pinctrl/GPIO driver
*
* Copyright (C) 2017 Intel Corporation
* Author: Mika Westerberg <mika.westerberg@linux.intel.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/acpi.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/pm.h>
#include <linux/pinctrl/pinctrl.h>
#include "pinctrl-intel.h"
#define GLK_PAD_OWN 0x020
#define GLK_HOSTSW_OWN 0x0b0
#define GLK_PADCFGLOCK 0x080
#define GLK_GPI_IE 0x110
#define GLK_COMMUNITY(s, e) \
{ \
.padown_offset = GLK_PAD_OWN, \
.padcfglock_offset = GLK_PADCFGLOCK, \
.hostown_offset = GLK_HOSTSW_OWN, \
.ie_offset = GLK_GPI_IE, \
.gpp_size = 32, \
.pin_base = (s), \
.npins = ((e) - (s) + 1), \
}
/* GLK */
static const struct pinctrl_pin_desc glk_northwest_pins[] = {
PINCTRL_PIN(0, "TCK"),
PINCTRL_PIN(1, "TRST_B"),
PINCTRL_PIN(2, "TMS"),
PINCTRL_PIN(3, "TDI"),
PINCTRL_PIN(4, "TDO"),
PINCTRL_PIN(5, "JTAGX"),
PINCTRL_PIN(6, "CX_PREQ_B"),
PINCTRL_PIN(7, "CX_PRDY_B"),
PINCTRL_PIN(8, "GPIO_8"),
PINCTRL_PIN(9, "GPIO_9"),
PINCTRL_PIN(10, "GPIO_10"),
PINCTRL_PIN(11, "GPIO_11"),
PINCTRL_PIN(12, "GPIO_12"),
PINCTRL_PIN(13, "GPIO_13"),
PINCTRL_PIN(14, "GPIO_14"),
PINCTRL_PIN(15, "GPIO_15"),
PINCTRL_PIN(16, "GPIO_16"),
PINCTRL_PIN(17, "GPIO_17"),
PINCTRL_PIN(18, "GPIO_18"),
PINCTRL_PIN(19, "GPIO_19"),
PINCTRL_PIN(20, "GPIO_20"),
PINCTRL_PIN(21, "GPIO_21"),
PINCTRL_PIN(22, "GPIO_22"),
PINCTRL_PIN(23, "GPIO_23"),
PINCTRL_PIN(24, "GPIO_24"),
PINCTRL_PIN(25, "GPIO_25"),
PINCTRL_PIN(26, "GPIO_26"),
PINCTRL_PIN(27, "GPIO_27"),
PINCTRL_PIN(28, "GPIO_28"),
PINCTRL_PIN(29, "GPIO_29"),
PINCTRL_PIN(30, "GPIO_30"),
PINCTRL_PIN(31, "GPIO_31"),
PINCTRL_PIN(32, "GPIO_32"),
PINCTRL_PIN(33, "GPIO_33"),
PINCTRL_PIN(34, "GPIO_34"),
PINCTRL_PIN(35, "GPIO_35"),
PINCTRL_PIN(36, "GPIO_36"),
PINCTRL_PIN(37, "GPIO_37"),
PINCTRL_PIN(38, "GPIO_38"),
PINCTRL_PIN(39, "GPIO_39"),
PINCTRL_PIN(40, "GPIO_40"),
PINCTRL_PIN(41, "GPIO_41"),
PINCTRL_PIN(42, "GP_INTD_DSI_TE1"),
PINCTRL_PIN(43, "GP_INTD_DSI_TE2"),
PINCTRL_PIN(44, "USB_OC0_B"),
PINCTRL_PIN(45, "USB_OC1_B"),
PINCTRL_PIN(46, "DSI_I2C_SDA"),
PINCTRL_PIN(47, "DSI_I2C_SCL"),
PINCTRL_PIN(48, "PMC_I2C_SDA"),
PINCTRL_PIN(49, "PMC_I2C_SCL"),
PINCTRL_PIN(50, "LPSS_I2C0_SDA"),
PINCTRL_PIN(51, "LPSS_I2C0_SCL"),
PINCTRL_PIN(52, "LPSS_I2C1_SDA"),
PINCTRL_PIN(53, "LPSS_I2C1_SCL"),
PINCTRL_PIN(54, "LPSS_I2C2_SDA"),
PINCTRL_PIN(55, "LPSS_I2C2_SCL"),
PINCTRL_PIN(56, "LPSS_I2C3_SDA"),
PINCTRL_PIN(57, "LPSS_I2C3_SCL"),
PINCTRL_PIN(58, "LPSS_I2C4_SDA"),
PINCTRL_PIN(59, "LPSS_I2C4_SCL"),
PINCTRL_PIN(60, "LPSS_UART0_RXD"),
PINCTRL_PIN(61, "LPSS_UART0_TXD"),
PINCTRL_PIN(62, "LPSS_UART0_RTS_B"),
PINCTRL_PIN(63, "LPSS_UART0_CTS_B"),
PINCTRL_PIN(64, "LPSS_UART2_RXD"),
PINCTRL_PIN(65, "LPSS_UART2_TXD"),
PINCTRL_PIN(66, "LPSS_UART2_RTS_B"),
PINCTRL_PIN(67, "LPSS_UART2_CTS_B"),
PINCTRL_PIN(68, "PMC_SPI_FS0"),
PINCTRL_PIN(69, "PMC_SPI_FS1"),
PINCTRL_PIN(70, "PMC_SPI_FS2"),
PINCTRL_PIN(71, "PMC_SPI_RXD"),
PINCTRL_PIN(72, "PMC_SPI_TXD"),
PINCTRL_PIN(73, "PMC_SPI_CLK"),
PINCTRL_PIN(74, "THERMTRIP_B"),
PINCTRL_PIN(75, "PROCHOT_B"),
PINCTRL_PIN(76, "EMMC_RST_B"),
PINCTRL_PIN(77, "GPIO_212"),
PINCTRL_PIN(78, "GPIO_213"),
PINCTRL_PIN(79, "GPIO_214"),
};
static const unsigned int glk_northwest_uart1_pins[] = { 26, 27, 28, 29 };
static const unsigned int glk_northwest_pwm0_pins[] = { 42 };
static const unsigned int glk_northwest_pwm1_pins[] = { 43 };
static const unsigned int glk_northwest_pwm2_pins[] = { 44 };
static const unsigned int glk_northwest_pwm3_pins[] = { 45 };
static const unsigned int glk_northwest_i2c0_pins[] = { 50, 51 };
static const unsigned int glk_northwest_i2c1_pins[] = { 52, 53 };
static const unsigned int glk_northwest_i2c2_pins[] = { 54, 55 };
static const unsigned int glk_northwest_i2c3_pins[] = { 56, 57 };
static const unsigned int glk_northwest_i2c4_pins[] = { 58, 59 };
static const unsigned int glk_northwest_uart0_pins[] = { 60, 61, 62, 63 };
static const unsigned int glk_northwest_uart2_pins[] = { 64, 65, 66, 67 };
static const struct intel_pingroup glk_northwest_groups[] = {
PIN_GROUP("uart1_grp", glk_northwest_uart1_pins, 2),
PIN_GROUP("pwm0_grp", glk_northwest_pwm0_pins, 2),
PIN_GROUP("pwm1_grp", glk_northwest_pwm1_pins, 2),
PIN_GROUP("pwm2_grp", glk_northwest_pwm2_pins, 2),
PIN_GROUP("pwm3_grp", glk_northwest_pwm3_pins, 2),
PIN_GROUP("i2c0_grp", glk_northwest_i2c0_pins, 1),
PIN_GROUP("i2c1_grp", glk_northwest_i2c1_pins, 1),
PIN_GROUP("i2c2_grp", glk_northwest_i2c2_pins, 1),
PIN_GROUP("i2c3_grp", glk_northwest_i2c3_pins, 1),
PIN_GROUP("i2c4_grp", glk_northwest_i2c4_pins, 1),
PIN_GROUP("uart0_grp", glk_northwest_uart0_pins, 1),
PIN_GROUP("uart2_grp", glk_northwest_uart2_pins, 1),
};
static const char * const glk_northwest_uart1_groups[] = { "uart1_grp" };
static const char * const glk_northwest_pwm0_groups[] = { "pwm0_grp" };
static const char * const glk_northwest_pwm1_groups[] = { "pwm1_grp" };
static const char * const glk_northwest_pwm2_groups[] = { "pwm2_grp" };
static const char * const glk_northwest_pwm3_groups[] = { "pwm3_grp" };
static const char * const glk_northwest_i2c0_groups[] = { "i2c0_grp" };
static const char * const glk_northwest_i2c1_groups[] = { "i2c1_grp" };
static const char * const glk_northwest_i2c2_groups[] = { "i2c2_grp" };
static const char * const glk_northwest_i2c3_groups[] = { "i2c3_grp" };
static const char * const glk_northwest_i2c4_groups[] = { "i2c4_grp" };
static const char * const glk_northwest_uart0_groups[] = { "uart0_grp" };
static const char * const glk_northwest_uart2_groups[] = { "uart2_grp" };
static const struct intel_function glk_northwest_functions[] = {
FUNCTION("uart1", glk_northwest_uart1_groups),
FUNCTION("pmw0", glk_northwest_pwm0_groups),
FUNCTION("pmw1", glk_northwest_pwm1_groups),
FUNCTION("pmw2", glk_northwest_pwm2_groups),
FUNCTION("pmw3", glk_northwest_pwm3_groups),
FUNCTION("i2c0", glk_northwest_i2c0_groups),
FUNCTION("i2c1", glk_northwest_i2c1_groups),
FUNCTION("i2c2", glk_northwest_i2c2_groups),
FUNCTION("i2c3", glk_northwest_i2c3_groups),
FUNCTION("i2c4", glk_northwest_i2c4_groups),
FUNCTION("uart0", glk_northwest_uart0_groups),
FUNCTION("uart2", glk_northwest_uart2_groups),
};
static const struct intel_community glk_northwest_communities[] = {
GLK_COMMUNITY(0, 79),
};
static const struct intel_pinctrl_soc_data glk_northwest_soc_data = {
.uid = "1",
.pins = glk_northwest_pins,
.npins = ARRAY_SIZE(glk_northwest_pins),
.groups = glk_northwest_groups,
.ngroups = ARRAY_SIZE(glk_northwest_groups),
.functions = glk_northwest_functions,
.nfunctions = ARRAY_SIZE(glk_northwest_functions),
.communities = glk_northwest_communities,
.ncommunities = ARRAY_SIZE(glk_northwest_communities),
};
static const struct pinctrl_pin_desc glk_north_pins[] = {
PINCTRL_PIN(0, "SVID0_ALERT_B"),
PINCTRL_PIN(1, "SVID0_DATA"),
PINCTRL_PIN(2, "SVID0_CLK"),
PINCTRL_PIN(3, "LPSS_SPI_0_CLK"),
PINCTRL_PIN(4, "LPSS_SPI_0_FS0"),
PINCTRL_PIN(5, "LPSS_SPI_0_FS1"),
PINCTRL_PIN(6, "LPSS_SPI_0_RXD"),
PINCTRL_PIN(7, "LPSS_SPI_0_TXD"),
PINCTRL_PIN(8, "LPSS_SPI_1_CLK"),
PINCTRL_PIN(9, "LPSS_SPI_1_FS0"),
PINCTRL_PIN(10, "LPSS_SPI_1_FS1"),
PINCTRL_PIN(11, "LPSS_SPI_1_FS2"),
PINCTRL_PIN(12, "LPSS_SPI_1_RXD"),
PINCTRL_PIN(13, "LPSS_SPI_1_TXD"),
PINCTRL_PIN(14, "FST_SPI_CS0_B"),
PINCTRL_PIN(15, "FST_SPI_CS1_B"),
PINCTRL_PIN(16, "FST_SPI_MOSI_IO0"),
PINCTRL_PIN(17, "FST_SPI_MISO_IO1"),
PINCTRL_PIN(18, "FST_SPI_IO2"),
PINCTRL_PIN(19, "FST_SPI_IO3"),
PINCTRL_PIN(20, "FST_SPI_CLK"),
PINCTRL_PIN(21, "FST_SPI_CLK_FB"),
PINCTRL_PIN(22, "PMU_PLTRST_B"),
PINCTRL_PIN(23, "PMU_PWRBTN_B"),
PINCTRL_PIN(24, "PMU_SLP_S0_B"),
PINCTRL_PIN(25, "PMU_SLP_S3_B"),
PINCTRL_PIN(26, "PMU_SLP_S4_B"),
PINCTRL_PIN(27, "SUSPWRDNACK"),
PINCTRL_PIN(28, "EMMC_PWR_EN_B"),
PINCTRL_PIN(29, "PMU_AC_PRESENT"),
PINCTRL_PIN(30, "PMU_BATLOW_B"),
PINCTRL_PIN(31, "PMU_RESETBUTTON_B"),
PINCTRL_PIN(32, "PMU_SUSCLK"),
PINCTRL_PIN(33, "SUS_STAT_B"),
PINCTRL_PIN(34, "LPSS_I2C5_SDA"),
PINCTRL_PIN(35, "LPSS_I2C5_SCL"),
PINCTRL_PIN(36, "LPSS_I2C6_SDA"),
PINCTRL_PIN(37, "LPSS_I2C6_SCL"),
PINCTRL_PIN(38, "LPSS_I2C7_SDA"),
PINCTRL_PIN(39, "LPSS_I2C7_SCL"),
PINCTRL_PIN(40, "PCIE_WAKE0_B"),
PINCTRL_PIN(41, "PCIE_WAKE1_B"),
PINCTRL_PIN(42, "PCIE_WAKE2_B"),
PINCTRL_PIN(43, "PCIE_WAKE3_B"),
PINCTRL_PIN(44, "PCIE_CLKREQ0_B"),
PINCTRL_PIN(45, "PCIE_CLKREQ1_B"),
PINCTRL_PIN(46, "PCIE_CLKREQ2_B"),
PINCTRL_PIN(47, "PCIE_CLKREQ3_B"),
PINCTRL_PIN(48, "HV_DDI0_DDC_SDA"),
PINCTRL_PIN(49, "HV_DDI0_DDC_SCL"),
PINCTRL_PIN(50, "HV_DDI1_DDC_SDA"),
PINCTRL_PIN(51, "HV_DDI1_DDC_SCL"),
PINCTRL_PIN(52, "PANEL0_VDDEN"),
PINCTRL_PIN(53, "PANEL0_BKLTEN"),
PINCTRL_PIN(54, "PANEL0_BKLTCTL"),
PINCTRL_PIN(55, "HV_DDI0_HPD"),
PINCTRL_PIN(56, "HV_DDI1_HPD"),
PINCTRL_PIN(57, "HV_EDP_HPD"),
PINCTRL_PIN(58, "GPIO_134"),
PINCTRL_PIN(59, "GPIO_135"),
PINCTRL_PIN(60, "GPIO_136"),
PINCTRL_PIN(61, "GPIO_137"),
PINCTRL_PIN(62, "GPIO_138"),
PINCTRL_PIN(63, "GPIO_139"),
PINCTRL_PIN(64, "GPIO_140"),
PINCTRL_PIN(65, "GPIO_141"),
PINCTRL_PIN(66, "GPIO_142"),
PINCTRL_PIN(67, "GPIO_143"),
PINCTRL_PIN(68, "GPIO_144"),
PINCTRL_PIN(69, "GPIO_145"),
PINCTRL_PIN(70, "GPIO_146"),
PINCTRL_PIN(71, "LPC_ILB_SERIRQ"),
PINCTRL_PIN(72, "LPC_CLKOUT0"),
PINCTRL_PIN(73, "LPC_CLKOUT1"),
PINCTRL_PIN(74, "LPC_AD0"),
PINCTRL_PIN(75, "LPC_AD1"),
PINCTRL_PIN(76, "LPC_AD2"),
PINCTRL_PIN(77, "LPC_AD3"),
PINCTRL_PIN(78, "LPC_CLKRUNB"),
PINCTRL_PIN(79, "LPC_FRAMEB"),
};
static const unsigned int glk_north_spi0_pins[] = { 3, 4, 5, 6, 7 };
static const unsigned int glk_north_spi1_pins[] = { 8, 9, 10, 11, 12, 13 };
static const unsigned int glk_north_i2c5_pins[] = { 34, 35 };
static const unsigned int glk_north_i2c6_pins[] = { 36, 37 };
static const unsigned int glk_north_i2c7_pins[] = { 38, 39 };
static const unsigned int glk_north_uart0_pins[] = { 62, 63, 64, 65 };
static const unsigned int glk_north_spi0b_pins[] = { 66, 67, 68, 69, 70 };
static const struct intel_pingroup glk_north_groups[] = {
PIN_GROUP("spi0_grp", glk_north_spi0_pins, 1),
PIN_GROUP("spi1_grp", glk_north_spi1_pins, 1),
PIN_GROUP("i2c5_grp", glk_north_i2c5_pins, 1),
PIN_GROUP("i2c6_grp", glk_north_i2c6_pins, 1),
PIN_GROUP("i2c7_grp", glk_north_i2c7_pins, 1),
PIN_GROUP("uart0_grp", glk_north_uart0_pins, 2),
PIN_GROUP("spi0b_grp", glk_north_spi0b_pins, 2),
};
static const char * const glk_north_spi0_groups[] = { "spi0_grp", "spi0b_grp" };
static const char * const glk_north_spi1_groups[] = { "spi1_grp" };
static const char * const glk_north_i2c5_groups[] = { "i2c5_grp" };
static const char * const glk_north_i2c6_groups[] = { "i2c6_grp" };
static const char * const glk_north_i2c7_groups[] = { "i2c7_grp" };
static const char * const glk_north_uart0_groups[] = { "uart0_grp" };
static const struct intel_function glk_north_functions[] = {
FUNCTION("spi0", glk_north_spi0_groups),
FUNCTION("spi1", glk_north_spi1_groups),
FUNCTION("i2c5", glk_north_i2c5_groups),
FUNCTION("i2c6", glk_north_i2c6_groups),
FUNCTION("i2c7", glk_north_i2c7_groups),
FUNCTION("uart0", glk_north_uart0_groups),
};
static const struct intel_community glk_north_communities[] = {
GLK_COMMUNITY(0, 79),
};
static const struct intel_pinctrl_soc_data glk_north_soc_data = {
.uid = "2",
.pins = glk_north_pins,
.npins = ARRAY_SIZE(glk_north_pins),
.groups = glk_north_groups,
.ngroups = ARRAY_SIZE(glk_north_groups),
.functions = glk_north_functions,
.nfunctions = ARRAY_SIZE(glk_north_functions),
.communities = glk_north_communities,
.ncommunities = ARRAY_SIZE(glk_north_communities),
};
static const struct pinctrl_pin_desc glk_audio_pins[] = {
PINCTRL_PIN(0, "AVS_I2S0_MCLK"),
PINCTRL_PIN(1, "AVS_I2S0_BCLK"),
PINCTRL_PIN(2, "AVS_I2S0_WS_SYNC"),
PINCTRL_PIN(3, "AVS_I2S0_SDI"),
PINCTRL_PIN(4, "AVS_I2S0_SDO"),
PINCTRL_PIN(5, "AVS_I2S1_MCLK"),
PINCTRL_PIN(6, "AVS_I2S1_BCLK"),
PINCTRL_PIN(7, "AVS_I2S1_WS_SYNC"),
PINCTRL_PIN(8, "AVS_I2S1_SDI"),
PINCTRL_PIN(9, "AVS_I2S1_SDO"),
PINCTRL_PIN(10, "AVS_HDA_BCLK"),
PINCTRL_PIN(11, "AVS_HDA_WS_SYNC"),
PINCTRL_PIN(12, "AVS_HDA_SDI"),
PINCTRL_PIN(13, "AVS_HDA_SDO"),
PINCTRL_PIN(14, "AVS_HDA_RSTB"),
PINCTRL_PIN(15, "AVS_M_CLK_A1"),
PINCTRL_PIN(16, "AVS_M_CLK_B1"),
PINCTRL_PIN(17, "AVS_M_DATA_1"),
PINCTRL_PIN(18, "AVS_M_CLK_AB2"),
PINCTRL_PIN(19, "AVS_M_DATA_2"),
};
static const struct intel_community glk_audio_communities[] = {
GLK_COMMUNITY(0, 19),
};
static const struct intel_pinctrl_soc_data glk_audio_soc_data = {
.uid = "3",
.pins = glk_audio_pins,
.npins = ARRAY_SIZE(glk_audio_pins),
.communities = glk_audio_communities,
.ncommunities = ARRAY_SIZE(glk_audio_communities),
};
static const struct pinctrl_pin_desc glk_scc_pins[] = {
PINCTRL_PIN(0, "SMB_ALERTB"),
PINCTRL_PIN(1, "SMB_CLK"),
PINCTRL_PIN(2, "SMB_DATA"),
PINCTRL_PIN(3, "SDCARD_LVL_WP"),
PINCTRL_PIN(4, "SDCARD_CLK"),
PINCTRL_PIN(5, "SDCARD_CLK_FB"),
PINCTRL_PIN(6, "SDCARD_D0"),
PINCTRL_PIN(7, "SDCARD_D1"),
PINCTRL_PIN(8, "SDCARD_D2"),
PINCTRL_PIN(9, "SDCARD_D3"),
PINCTRL_PIN(10, "SDCARD_CMD"),
PINCTRL_PIN(11, "SDCARD_CD_B"),
PINCTRL_PIN(12, "SDCARD_PWR_DOWN_B"),
PINCTRL_PIN(13, "GPIO_210"),
PINCTRL_PIN(14, "OSC_CLK_OUT_0"),
PINCTRL_PIN(15, "OSC_CLK_OUT_1"),
PINCTRL_PIN(16, "CNV_BRI_DT"),
PINCTRL_PIN(17, "CNV_BRI_RSP"),
PINCTRL_PIN(18, "CNV_RGI_DT"),
PINCTRL_PIN(19, "CNV_RGI_RSP"),
PINCTRL_PIN(20, "CNV_RF_RESET_B"),
PINCTRL_PIN(21, "XTAL_CLKREQ"),
PINCTRL_PIN(22, "SDIO_CLK_FB"),
PINCTRL_PIN(23, "EMMC0_CLK"),
PINCTRL_PIN(24, "EMMC0_CLK_FB"),
PINCTRL_PIN(25, "EMMC0_D0"),
PINCTRL_PIN(26, "EMMC0_D1"),
PINCTRL_PIN(27, "EMMC0_D2"),
PINCTRL_PIN(28, "EMMC0_D3"),
PINCTRL_PIN(29, "EMMC0_D4"),
PINCTRL_PIN(30, "EMMC0_D5"),
PINCTRL_PIN(31, "EMMC0_D6"),
PINCTRL_PIN(32, "EMMC0_D7"),
PINCTRL_PIN(33, "EMMC0_CMD"),
PINCTRL_PIN(34, "EMMC0_STROBE"),
};
static const unsigned int glk_scc_i2c7_pins[] = { 1, 2 };
static const unsigned int glk_scc_sdcard_pins[] = {
3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
};
static const unsigned int glk_scc_sdio_pins[] = { 16, 17, 18, 19, 20, 21, 22 };
static const unsigned int glk_scc_uart1_pins[] = { 16, 17, 18, 19 };
static const unsigned int glk_scc_emmc_pins[] = {
23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
};
static const struct intel_pingroup glk_scc_groups[] = {
PIN_GROUP("i2c7_grp", glk_scc_i2c7_pins, 2),
PIN_GROUP("sdcard_grp", glk_scc_sdcard_pins, 1),
PIN_GROUP("sdio_grp", glk_scc_sdio_pins, 2),
PIN_GROUP("uart1_grp", glk_scc_uart1_pins, 3),
PIN_GROUP("emmc_grp", glk_scc_emmc_pins, 1),
};
static const char * const glk_scc_i2c7_groups[] = { "i2c7_grp" };
static const char * const glk_scc_sdcard_groups[] = { "sdcard_grp" };
static const char * const glk_scc_sdio_groups[] = { "sdio_grp" };
static const char * const glk_scc_uart1_groups[] = { "uart1_grp" };
static const char * const glk_scc_emmc_groups[] = { "emmc_grp" };
static const struct intel_function glk_scc_functions[] = {
FUNCTION("i2c7", glk_scc_i2c7_groups),
FUNCTION("sdcard", glk_scc_sdcard_groups),
FUNCTION("sdio", glk_scc_sdio_groups),
FUNCTION("uart1", glk_scc_uart1_groups),
FUNCTION("emmc", glk_scc_emmc_groups),
};
static const struct intel_community glk_scc_communities[] = {
GLK_COMMUNITY(0, 34),
};
static const struct intel_pinctrl_soc_data glk_scc_soc_data = {
.uid = "4",
.pins = glk_scc_pins,
.npins = ARRAY_SIZE(glk_scc_pins),
.groups = glk_scc_groups,
.ngroups = ARRAY_SIZE(glk_scc_groups),
.functions = glk_scc_functions,
.nfunctions = ARRAY_SIZE(glk_scc_functions),
.communities = glk_scc_communities,
.ncommunities = ARRAY_SIZE(glk_scc_communities),
};
static const struct intel_pinctrl_soc_data *glk_pinctrl_soc_data[] = {
&glk_northwest_soc_data,
&glk_north_soc_data,
&glk_audio_soc_data,
&glk_scc_soc_data,
NULL,
};
static const struct acpi_device_id glk_pinctrl_acpi_match[] = {
{ "INT3453" },
{ }
};
MODULE_DEVICE_TABLE(acpi, glk_pinctrl_acpi_match);
static int glk_pinctrl_probe(struct platform_device *pdev)
{
const struct intel_pinctrl_soc_data *soc_data = NULL;
struct acpi_device *adev;
int i;
adev = ACPI_COMPANION(&pdev->dev);
if (!adev)
return -ENODEV;
for (i = 0; glk_pinctrl_soc_data[i]; i++) {
if (!strcmp(adev->pnp.unique_id,
glk_pinctrl_soc_data[i]->uid)) {
soc_data = glk_pinctrl_soc_data[i];
break;
}
}
if (!soc_data)
return -ENODEV;
return intel_pinctrl_probe(pdev, soc_data);
}
static const struct dev_pm_ops glk_pinctrl_pm_ops = {
SET_LATE_SYSTEM_SLEEP_PM_OPS(intel_pinctrl_suspend,
intel_pinctrl_resume)
};
static struct platform_driver glk_pinctrl_driver = {
.probe = glk_pinctrl_probe,
.driver = {
.name = "geminilake-pinctrl",
.acpi_match_table = glk_pinctrl_acpi_match,
.pm = &glk_pinctrl_pm_ops,
},
};
static int __init glk_pinctrl_init(void)
{
return platform_driver_register(&glk_pinctrl_driver);
}
subsys_initcall(glk_pinctrl_init);
static void __exit glk_pinctrl_exit(void)
{
platform_driver_unregister(&glk_pinctrl_driver);
}
module_exit(glk_pinctrl_exit);
MODULE_AUTHOR("Mika Westerberg <mika.westerberg@linux.intel.com>");
MODULE_DESCRIPTION("Intel Gemini Lake SoC pinctrl/GPIO driver");
MODULE_LICENSE("GPL v2");

View File

@ -13,6 +13,7 @@
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/gpio/driver.h>
#include <linux/log2.h>
#include <linux/platform_device.h>
#include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/pinmux.h>
@ -23,6 +24,10 @@
#include "pinctrl-intel.h"
/* Offset from regs */
#define REVID 0x000
#define REVID_SHIFT 16
#define REVID_MASK GENMASK(31, 16)
#define PADBAR 0x00c
#define GPI_IS 0x100
#define GPI_GPE_STS 0x140
@ -41,6 +46,7 @@
#define PADCFG0_RXEVCFG_EDGE 1
#define PADCFG0_RXEVCFG_DISABLED 2
#define PADCFG0_RXEVCFG_EDGE_BOTH 3
#define PADCFG0_PREGFRXSEL BIT(24)
#define PADCFG0_RXINV BIT(23)
#define PADCFG0_GPIROUTIOXAPIC BIT(20)
#define PADCFG0_GPIROUTSCI BIT(19)
@ -62,9 +68,17 @@
#define PADCFG1_TERM_5K 2
#define PADCFG1_TERM_1K 1
#define PADCFG2 0x008
#define PADCFG2_DEBEN BIT(0)
#define PADCFG2_DEBOUNCE_SHIFT 1
#define PADCFG2_DEBOUNCE_MASK GENMASK(4, 1)
#define DEBOUNCE_PERIOD 31250 /* ns */
struct intel_pad_context {
u32 padcfg0;
u32 padcfg1;
u32 padcfg2;
};
struct intel_community_context {
@ -126,13 +140,19 @@ static void __iomem *intel_get_padcfg(struct intel_pinctrl *pctrl, unsigned pin,
{
const struct intel_community *community;
unsigned padno;
size_t nregs;
community = intel_get_community(pctrl, pin);
if (!community)
return NULL;
padno = pin_to_padno(community, pin);
return community->pad_regs + reg + padno * 8;
nregs = (community->features & PINCTRL_FEATURE_DEBOUNCE) ? 4 : 2;
if (reg == PADCFG2 && !(community->features & PINCTRL_FEATURE_DEBOUNCE))
return NULL;
return community->pad_regs + reg + padno * nregs * 4;
}
static bool intel_pad_owned_by_host(struct intel_pinctrl *pctrl, unsigned pin)
@ -244,6 +264,7 @@ static void intel_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
unsigned pin)
{
struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
void __iomem *padcfg;
u32 cfg0, cfg1, mode;
bool locked, acpi;
@ -263,6 +284,11 @@ static void intel_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
seq_printf(s, "0x%08x 0x%08x", cfg0, cfg1);
/* Dump the additional PADCFG registers if available */
padcfg = intel_get_padcfg(pctrl, pin, PADCFG2);
if (padcfg)
seq_printf(s, " 0x%08x", readl(padcfg));
locked = intel_pad_locked(pctrl, pin);
acpi = intel_pad_acpi_mode(pctrl, pin);
@ -432,12 +458,14 @@ static int intel_config_get(struct pinctrl_dev *pctldev, unsigned pin,
{
struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
enum pin_config_param param = pinconf_to_config_param(*config);
const struct intel_community *community;
u32 value, term;
u16 arg = 0;
u32 arg = 0;
if (!intel_pad_owned_by_host(pctrl, pin))
return -ENOTSUPP;
community = intel_get_community(pctrl, pin);
value = readl(intel_get_padcfg(pctrl, pin, PADCFG1));
term = (value & PADCFG1_TERM_MASK) >> PADCFG1_TERM_SHIFT;
@ -473,6 +501,11 @@ static int intel_config_get(struct pinctrl_dev *pctldev, unsigned pin,
return -EINVAL;
switch (term) {
case PADCFG1_TERM_1K:
if (!(community->features & PINCTRL_FEATURE_1K_PD))
return -EINVAL;
arg = 1000;
break;
case PADCFG1_TERM_5K:
arg = 5000;
break;
@ -483,6 +516,24 @@ static int intel_config_get(struct pinctrl_dev *pctldev, unsigned pin,
break;
case PIN_CONFIG_INPUT_DEBOUNCE: {
void __iomem *padcfg2;
u32 v;
padcfg2 = intel_get_padcfg(pctrl, pin, PADCFG2);
if (!padcfg2)
return -ENOTSUPP;
v = readl(padcfg2);
if (!(v & PADCFG2_DEBEN))
return -EINVAL;
v = (v & PADCFG2_DEBOUNCE_MASK) >> PADCFG2_DEBOUNCE_SHIFT;
arg = BIT(v) * DEBOUNCE_PERIOD / 1000;
break;
}
default:
return -ENOTSUPP;
}
@ -496,6 +547,7 @@ static int intel_config_set_pull(struct intel_pinctrl *pctrl, unsigned pin,
{
unsigned param = pinconf_to_config_param(config);
unsigned arg = pinconf_to_config_argument(config);
const struct intel_community *community;
void __iomem *padcfg1;
unsigned long flags;
int ret = 0;
@ -503,6 +555,7 @@ static int intel_config_set_pull(struct intel_pinctrl *pctrl, unsigned pin,
raw_spin_lock_irqsave(&pctrl->lock, flags);
community = intel_get_community(pctrl, pin);
padcfg1 = intel_get_padcfg(pctrl, pin, PADCFG1);
value = readl(padcfg1);
@ -545,6 +598,13 @@ static int intel_config_set_pull(struct intel_pinctrl *pctrl, unsigned pin,
case 5000:
value |= PADCFG1_TERM_5K << PADCFG1_TERM_SHIFT;
break;
case 1000:
if (!(community->features & PINCTRL_FEATURE_1K_PD)) {
ret = -EINVAL;
break;
}
value |= PADCFG1_TERM_1K << PADCFG1_TERM_SHIFT;
break;
default:
ret = -EINVAL;
}
@ -560,6 +620,53 @@ static int intel_config_set_pull(struct intel_pinctrl *pctrl, unsigned pin,
return ret;
}
static int intel_config_set_debounce(struct intel_pinctrl *pctrl, unsigned pin,
unsigned debounce)
{
void __iomem *padcfg0, *padcfg2;
unsigned long flags;
u32 value0, value2;
int ret = 0;
padcfg2 = intel_get_padcfg(pctrl, pin, PADCFG2);
if (!padcfg2)
return -ENOTSUPP;
padcfg0 = intel_get_padcfg(pctrl, pin, PADCFG0);
raw_spin_lock_irqsave(&pctrl->lock, flags);
value0 = readl(padcfg0);
value2 = readl(padcfg2);
/* Disable glitch filter and debouncer */
value0 &= ~PADCFG0_PREGFRXSEL;
value2 &= ~(PADCFG2_DEBEN | PADCFG2_DEBOUNCE_MASK);
if (debounce) {
unsigned long v;
v = order_base_2(debounce * 1000 / DEBOUNCE_PERIOD);
if (v < 3 || v > 15) {
ret = -EINVAL;
goto exit_unlock;
} else {
/* Enable glitch filter and debouncer */
value0 |= PADCFG0_PREGFRXSEL;
value2 |= v << PADCFG2_DEBOUNCE_SHIFT;
value2 |= PADCFG2_DEBEN;
}
}
writel(value0, padcfg0);
writel(value2, padcfg2);
exit_unlock:
raw_spin_unlock_irqrestore(&pctrl->lock, flags);
return ret;
}
static int intel_config_set(struct pinctrl_dev *pctldev, unsigned pin,
unsigned long *configs, unsigned nconfigs)
{
@ -579,6 +686,13 @@ static int intel_config_set(struct pinctrl_dev *pctldev, unsigned pin,
return ret;
break;
case PIN_CONFIG_INPUT_DEBOUNCE:
ret = intel_config_set_debounce(pctrl, pin,
pinconf_to_config_argument(configs[i]));
if (ret)
return ret;
break;
default:
return -ENOTSUPP;
}
@ -653,6 +767,7 @@ static const struct gpio_chip intel_gpio_chip = {
.direction_output = intel_gpio_direction_output,
.get = intel_gpio_get,
.set = intel_gpio_set,
.set_config = gpiochip_generic_config,
};
static void intel_gpio_irq_ack(struct irq_data *d)
@ -892,7 +1007,7 @@ static int intel_gpio_probe(struct intel_pinctrl *pctrl, int irq)
pctrl->chip.base = -1;
pctrl->irq = irq;
ret = gpiochip_add_data(&pctrl->chip, pctrl);
ret = devm_gpiochip_add_data(pctrl->dev, &pctrl->chip, pctrl);
if (ret) {
dev_err(pctrl->dev, "failed to register gpiochip\n");
return ret;
@ -902,7 +1017,7 @@ static int intel_gpio_probe(struct intel_pinctrl *pctrl, int irq)
0, 0, pctrl->soc->npins);
if (ret) {
dev_err(pctrl->dev, "failed to add GPIO pin range\n");
goto fail;
return ret;
}
/*
@ -915,24 +1030,19 @@ static int intel_gpio_probe(struct intel_pinctrl *pctrl, int irq)
dev_name(pctrl->dev), pctrl);
if (ret) {
dev_err(pctrl->dev, "failed to request interrupt\n");
goto fail;
return ret;
}
ret = gpiochip_irqchip_add(&pctrl->chip, &intel_gpio_irqchip, 0,
handle_bad_irq, IRQ_TYPE_NONE);
if (ret) {
dev_err(pctrl->dev, "failed to add irqchip\n");
goto fail;
return ret;
}
gpiochip_set_chained_irqchip(&pctrl->chip, &intel_gpio_irqchip, irq,
NULL);
return 0;
fail:
gpiochip_remove(&pctrl->chip);
return ret;
}
static int intel_pinctrl_pm_init(struct intel_pinctrl *pctrl)
@ -1013,6 +1123,20 @@ int intel_pinctrl_probe(struct platform_device *pdev,
if (IS_ERR(regs))
return PTR_ERR(regs);
/*
* Determine community features based on the revision if
* not specified already.
*/
if (!community->features) {
u32 rev;
rev = (readl(regs + REVID) & REVID_MASK) >> REVID_SHIFT;
if (rev >= 0x94) {
community->features |= PINCTRL_FEATURE_DEBOUNCE;
community->features |= PINCTRL_FEATURE_1K_PD;
}
}
/* Read offset of the pad configuration registers */
padbar = readl(regs + PADBAR);
@ -1054,16 +1178,6 @@ int intel_pinctrl_probe(struct platform_device *pdev,
}
EXPORT_SYMBOL_GPL(intel_pinctrl_probe);
int intel_pinctrl_remove(struct platform_device *pdev)
{
struct intel_pinctrl *pctrl = platform_get_drvdata(pdev);
gpiochip_remove(&pctrl->chip);
return 0;
}
EXPORT_SYMBOL_GPL(intel_pinctrl_remove);
#ifdef CONFIG_PM_SLEEP
static bool intel_pinctrl_should_save(struct intel_pinctrl *pctrl, unsigned pin)
{
@ -1096,6 +1210,7 @@ int intel_pinctrl_suspend(struct device *dev)
pads = pctrl->context.pads;
for (i = 0; i < pctrl->soc->npins; i++) {
const struct pinctrl_pin_desc *desc = &pctrl->soc->pins[i];
void __iomem *padcfg;
u32 val;
if (!intel_pinctrl_should_save(pctrl, desc->number))
@ -1105,6 +1220,10 @@ int intel_pinctrl_suspend(struct device *dev)
pads[i].padcfg0 = val & ~PADCFG0_GPIORXSTATE;
val = readl(intel_get_padcfg(pctrl, desc->number, PADCFG1));
pads[i].padcfg1 = val;
padcfg = intel_get_padcfg(pctrl, desc->number, PADCFG2);
if (padcfg)
pads[i].padcfg2 = readl(padcfg);
}
communities = pctrl->context.communities;
@ -1177,6 +1296,16 @@ int intel_pinctrl_resume(struct device *dev)
dev_dbg(dev, "restored pin %u padcfg1 %#08x\n",
desc->number, readl(padcfg));
}
padcfg = intel_get_padcfg(pctrl, desc->number, PADCFG2);
if (padcfg) {
val = readl(padcfg);
if (val != pads[i].padcfg2) {
writel(pads[i].padcfg2, padcfg);
dev_dbg(dev, "restored pin %u padcfg2 %#08x\n",
desc->number, readl(padcfg));
}
}
}
communities = pctrl->context.communities;

View File

@ -58,6 +58,7 @@ struct intel_function {
* @gpp_size: Maximum number of pads in each group, such as PADCFGLOCK,
* HOSTSW_OWN, GPI_IS, GPI_IE, etc.
* @npins: Number of pins in this community
* @features: Additional features supported by the hardware
* @regs: Community specific common registers (reserved for core driver)
* @pad_regs: Community specific pad registers (reserved for core driver)
* @ngpps: Number of groups (hw groups) in this community (reserved for
@ -72,11 +73,16 @@ struct intel_community {
unsigned pin_base;
unsigned gpp_size;
size_t npins;
unsigned features;
void __iomem *regs;
void __iomem *pad_regs;
size_t ngpps;
};
/* Additional features supported by the hardware */
#define PINCTRL_FEATURE_DEBOUNCE BIT(0)
#define PINCTRL_FEATURE_1K_PD BIT(1)
#define PIN_GROUP(n, p, m) \
{ \
.name = (n), \
@ -121,8 +127,6 @@ struct intel_pinctrl_soc_data {
int intel_pinctrl_probe(struct platform_device *pdev,
const struct intel_pinctrl_soc_data *soc_data);
int intel_pinctrl_remove(struct platform_device *pdev);
#ifdef CONFIG_PM_SLEEP
int intel_pinctrl_suspend(struct device *dev);
int intel_pinctrl_resume(struct device *dev);

View File

@ -574,7 +574,6 @@ static const struct dev_pm_ops spt_pinctrl_pm_ops = {
static struct platform_driver spt_pinctrl_driver = {
.probe = spt_pinctrl_probe,
.remove = intel_pinctrl_remove,
.driver = {
.name = "sunrisepoint-pinctrl",
.acpi_match_table = spt_pinctrl_acpi_match,

View File

@ -10,25 +10,29 @@ config PINCTRL_MTK
# For ARMv7 SoCs
config PINCTRL_MT2701
bool "Mediatek MT2701 pin control" if COMPILE_TEST && !MACH_MT2701
bool "Mediatek MT2701 pin control"
depends on MACH_MT2701 || COMPILE_TEST
depends on OF
default MACH_MT2701
select PINCTRL_MTK
config PINCTRL_MT7623
bool "Mediatek MT7623 pin control" if COMPILE_TEST && !MACH_MT7623
bool "Mediatek MT7623 pin control"
depends on MACH_MT7623 || COMPILE_TEST
depends on OF
default MACH_MT7623
select PINCTRL_MTK_COMMON
config PINCTRL_MT8135
bool "Mediatek MT8135 pin control" if COMPILE_TEST && !MACH_MT8135
bool "Mediatek MT8135 pin control"
depends on MACH_MT8135 || COMPILE_TEST
depends on OF
default MACH_MT8135
select PINCTRL_MTK
config PINCTRL_MT8127
bool "Mediatek MT8127 pin control" if COMPILE_TEST && !MACH_MT8127
bool "Mediatek MT8127 pin control"
depends on MACH_MT8127 || COMPILE_TEST
depends on OF
default MACH_MT8127
select PINCTRL_MTK
@ -43,7 +47,8 @@ config PINCTRL_MT8173
# For PMIC
config PINCTRL_MT6397
bool "Mediatek MT6397 pin control" if COMPILE_TEST && !MFD_MT6397
bool "Mediatek MT6397 pin control"
depends on MFD_MT6397 || COMPILE_TEST
depends on OF
default MFD_MT6397
select PINCTRL_MTK

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016 John Crispin <blogic@openwrt.org>
* Copyright (c) 2016 John Crispin <john@phrozen.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as

View File

@ -1054,6 +1054,18 @@ static int mtk_gpio_set_debounce(struct gpio_chip *chip, unsigned offset,
return 0;
}
static int mtk_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 mtk_gpio_set_debounce(chip, offset, debounce);
}
static const struct gpio_chip mtk_gpio_chip = {
.owner = THIS_MODULE,
.request = gpiochip_generic_request,
@ -1064,7 +1076,7 @@ static const struct gpio_chip mtk_gpio_chip = {
.get = mtk_gpio_get,
.set = mtk_gpio_set,
.to_irq = mtk_gpio_to_irq,
.set_debounce = mtk_gpio_set_debounce,
.set_config = mtk_gpio_set_config,
.of_gpio_n_cells = 2,
};

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016 John Crispin <blogic@openwrt.org>
* Copyright (c) 2016 John Crispin <john@phrozen.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as

View File

@ -232,6 +232,10 @@ static const unsigned int pwm_e_pins[] = { PIN(GPIOX_19, EE_OFF) };
static const unsigned int pwm_f_x_pins[] = { PIN(GPIOX_7, EE_OFF) };
static const unsigned int pwm_f_y_pins[] = { PIN(GPIOY_15, EE_OFF) };
static const unsigned int hdmi_hpd_pins[] = { PIN(GPIOH_0, EE_OFF) };
static const unsigned int hdmi_sda_pins[] = { PIN(GPIOH_1, EE_OFF) };
static const unsigned int hdmi_scl_pins[] = { PIN(GPIOH_2, EE_OFF) };
static const struct pinctrl_pin_desc meson_gxbb_aobus_pins[] = {
MESON_PIN(GPIOAO_0, 0),
MESON_PIN(GPIOAO_1, 0),
@ -439,6 +443,11 @@ static struct meson_pmx_group meson_gxbb_periphs_groups[] = {
GROUP(eth_txd2, 6, 3),
GROUP(eth_txd3, 6, 2),
/* Bank H */
GROUP(hdmi_hpd, 1, 26),
GROUP(hdmi_sda, 1, 25),
GROUP(hdmi_scl, 1, 24),
/* Bank DV */
GROUP(uart_tx_b, 2, 29),
GROUP(uart_rx_b, 2, 28),
@ -635,6 +644,14 @@ static const char * const pwm_f_y_groups[] = {
"pwm_f_y",
};
static const char * const hdmi_hpd_groups[] = {
"hdmi_hpd",
};
static const char * const hdmi_i2c_groups[] = {
"hdmi_sda", "hdmi_scl",
};
static const char * const gpio_aobus_groups[] = {
"GPIOAO_0", "GPIOAO_1", "GPIOAO_2", "GPIOAO_3", "GPIOAO_4",
"GPIOAO_5", "GPIOAO_6", "GPIOAO_7", "GPIOAO_8", "GPIOAO_9",
@ -698,6 +715,8 @@ static struct meson_pmx_func meson_gxbb_periphs_functions[] = {
FUNCTION(pwm_e),
FUNCTION(pwm_f_x),
FUNCTION(pwm_f_y),
FUNCTION(hdmi_hpd),
FUNCTION(hdmi_i2c),
};
static struct meson_pmx_func meson_gxbb_aobus_functions[] = {

View File

@ -197,6 +197,10 @@ static const unsigned int eth_txd3_pins[] = { PIN(GPIOZ_13, EE_OFF) };
static const unsigned int pwm_e_pins[] = { PIN(GPIOX_16, EE_OFF) };
static const unsigned int hdmi_hpd_pins[] = { PIN(GPIOH_0, EE_OFF) };
static const unsigned int hdmi_sda_pins[] = { PIN(GPIOH_1, EE_OFF) };
static const unsigned int hdmi_scl_pins[] = { PIN(GPIOH_2, EE_OFF) };
static const struct pinctrl_pin_desc meson_gxl_aobus_pins[] = {
MESON_PIN(GPIOAO_0, 0),
MESON_PIN(GPIOAO_1, 0),
@ -221,6 +225,8 @@ static const unsigned int uart_rts_ao_b_pins[] = { PIN(GPIOAO_3, 0) };
static const unsigned int remote_input_ao_pins[] = {PIN(GPIOAO_7, 0) };
static const unsigned int pwm_ao_b_pins[] = { PIN(GPIOAO_9, 0) };
static struct meson_pmx_group meson_gxl_periphs_groups[] = {
GPIO_GROUP(GPIOZ_0, EE_OFF),
GPIO_GROUP(GPIOZ_1, EE_OFF),
@ -362,6 +368,11 @@ static struct meson_pmx_group meson_gxl_periphs_groups[] = {
GROUP(eth_txd2, 4, 11),
GROUP(eth_txd3, 4, 10),
/* Bank H */
GROUP(hdmi_hpd, 6, 31),
GROUP(hdmi_sda, 6, 30),
GROUP(hdmi_scl, 6, 29),
/* Bank DV */
GROUP(uart_tx_b, 2, 16),
GROUP(uart_rx_b, 2, 15),
@ -417,6 +428,7 @@ static struct meson_pmx_group meson_gxl_aobus_groups[] = {
GROUP(uart_cts_ao_b, 0, 8),
GROUP(uart_rts_ao_b, 0, 7),
GROUP(remote_input_ao, 0, 0),
GROUP(pwm_ao_b, 0, 3),
};
static const char * const gpio_periphs_groups[] = {
@ -505,6 +517,14 @@ static const char * const pwm_e_groups[] = {
"pwm_e",
};
static const char * const hdmi_hpd_groups[] = {
"hdmi_hpd",
};
static const char * const hdmi_i2c_groups[] = {
"hdmi_sda", "hdmi_scl",
};
static const char * const gpio_aobus_groups[] = {
"GPIOAO_0", "GPIOAO_1", "GPIOAO_2", "GPIOAO_3", "GPIOAO_4",
"GPIOAO_5", "GPIOAO_6", "GPIOAO_7", "GPIOAO_8", "GPIOAO_9",
@ -522,6 +542,10 @@ static const char * const remote_input_ao_groups[] = {
"remote_input_ao",
};
static const char * const pwm_ao_b_groups[] = {
"pwm_ao_b",
};
static struct meson_pmx_func meson_gxl_periphs_functions[] = {
FUNCTION(gpio_periphs),
FUNCTION(emmc),
@ -536,6 +560,8 @@ static struct meson_pmx_func meson_gxl_periphs_functions[] = {
FUNCTION(i2c_c),
FUNCTION(eth),
FUNCTION(pwm_e),
FUNCTION(hdmi_hpd),
FUNCTION(hdmi_i2c),
};
static struct meson_pmx_func meson_gxl_aobus_functions[] = {
@ -543,6 +569,7 @@ static struct meson_pmx_func meson_gxl_aobus_functions[] = {
FUNCTION(uart_ao),
FUNCTION(uart_ao_b),
FUNCTION(remote_input_ao),
FUNCTION(pwm_ao_b),
};
static struct meson_bank meson_gxl_periphs_banks[] = {

View File

@ -260,7 +260,6 @@ static int meson_pinconf_set(struct pinctrl_dev *pcdev, unsigned int pin,
enum pin_config_param param;
unsigned int reg, bit;
int i, ret;
u16 arg;
ret = meson_get_bank(pc, pin, &bank);
if (ret)
@ -268,7 +267,6 @@ static int meson_pinconf_set(struct pinctrl_dev *pcdev, unsigned int pin,
for (i = 0; i < num_configs; i++) {
param = pinconf_to_config_param(configs[i]);
arg = pinconf_to_config_argument(configs[i]);
switch (param) {
case PIN_CONFIG_BIAS_DISABLE:

View File

@ -14,7 +14,6 @@
#include <linux/err.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <linux/of.h>
@ -23,18 +22,6 @@
#include "pinctrl-mvebu.h"
static void __iomem *mpp_base;
static int armada_370_mpp_ctrl_get(unsigned pid, unsigned long *config)
{
return default_mpp_ctrl_get(mpp_base, pid, config);
}
static int armada_370_mpp_ctrl_set(unsigned pid, unsigned long config)
{
return default_mpp_ctrl_set(mpp_base, pid, config);
}
static struct mvebu_mpp_mode mv88f6710_mpp_modes[] = {
MPP_MODE(0,
MPP_FUNCTION(0x0, "gpio", NULL),
@ -384,8 +371,8 @@ static const struct of_device_id armada_370_pinctrl_of_match[] = {
{ },
};
static struct mvebu_mpp_ctrl mv88f6710_mpp_controls[] = {
MPP_FUNC_CTRL(0, 65, NULL, armada_370_mpp_ctrl),
static const struct mvebu_mpp_ctrl mv88f6710_mpp_controls[] = {
MPP_FUNC_CTRL(0, 65, NULL, mvebu_mmio_mpp_ctrl),
};
static struct pinctrl_gpio_range mv88f6710_mpp_gpio_ranges[] = {
@ -397,12 +384,6 @@ static struct pinctrl_gpio_range mv88f6710_mpp_gpio_ranges[] = {
static int armada_370_pinctrl_probe(struct platform_device *pdev)
{
struct mvebu_pinctrl_soc_info *soc = &armada_370_pinctrl_info;
struct resource *res;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
mpp_base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(mpp_base))
return PTR_ERR(mpp_base);
soc->variant = 0; /* no variants for Armada 370 */
soc->controls = mv88f6710_mpp_controls;
@ -414,7 +395,7 @@ static int armada_370_pinctrl_probe(struct platform_device *pdev)
pdev->dev.platform_data = soc;
return mvebu_pinctrl_probe(pdev);
return mvebu_pinctrl_simple_mmio_probe(pdev);
}
static struct platform_driver armada_370_pinctrl_driver = {
@ -424,9 +405,4 @@ static struct platform_driver armada_370_pinctrl_driver = {
},
.probe = armada_370_pinctrl_probe,
};
module_platform_driver(armada_370_pinctrl_driver);
MODULE_AUTHOR("Thomas Petazzoni <thomas.petazzoni@free-electrons.com>");
MODULE_DESCRIPTION("Marvell Armada 370 pinctrl driver");
MODULE_LICENSE("GPL v2");
builtin_platform_driver(armada_370_pinctrl_driver);

View File

@ -14,7 +14,6 @@
#include <linux/err.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <linux/of.h>
@ -23,18 +22,6 @@
#include "pinctrl-mvebu.h"
static void __iomem *mpp_base;
static int armada_375_mpp_ctrl_get(unsigned pid, unsigned long *config)
{
return default_mpp_ctrl_get(mpp_base, pid, config);
}
static int armada_375_mpp_ctrl_set(unsigned pid, unsigned long config)
{
return default_mpp_ctrl_set(mpp_base, pid, config);
}
static struct mvebu_mpp_mode mv88f6720_mpp_modes[] = {
MPP_MODE(0,
MPP_FUNCTION(0x0, "gpio", NULL),
@ -402,8 +389,8 @@ static const struct of_device_id armada_375_pinctrl_of_match[] = {
{ },
};
static struct mvebu_mpp_ctrl mv88f6720_mpp_controls[] = {
MPP_FUNC_CTRL(0, 69, NULL, armada_375_mpp_ctrl),
static const struct mvebu_mpp_ctrl mv88f6720_mpp_controls[] = {
MPP_FUNC_CTRL(0, 69, NULL, mvebu_mmio_mpp_ctrl),
};
static struct pinctrl_gpio_range mv88f6720_mpp_gpio_ranges[] = {
@ -415,12 +402,6 @@ static struct pinctrl_gpio_range mv88f6720_mpp_gpio_ranges[] = {
static int armada_375_pinctrl_probe(struct platform_device *pdev)
{
struct mvebu_pinctrl_soc_info *soc = &armada_375_pinctrl_info;
struct resource *res;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
mpp_base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(mpp_base))
return PTR_ERR(mpp_base);
soc->variant = 0; /* no variants for Armada 375 */
soc->controls = mv88f6720_mpp_controls;
@ -432,7 +413,7 @@ static int armada_375_pinctrl_probe(struct platform_device *pdev)
pdev->dev.platform_data = soc;
return mvebu_pinctrl_probe(pdev);
return mvebu_pinctrl_simple_mmio_probe(pdev);
}
static struct platform_driver armada_375_pinctrl_driver = {
@ -442,9 +423,4 @@ static struct platform_driver armada_375_pinctrl_driver = {
},
.probe = armada_375_pinctrl_probe,
};
module_platform_driver(armada_375_pinctrl_driver);
MODULE_AUTHOR("Thomas Petazzoni <thomas.petazzoni@free-electrons.com>");
MODULE_DESCRIPTION("Marvell Armada 375 pinctrl driver");
MODULE_LICENSE("GPL v2");
builtin_platform_driver(armada_375_pinctrl_driver);

View File

@ -14,7 +14,6 @@
#include <linux/err.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/of_device.h>
@ -22,18 +21,6 @@
#include "pinctrl-mvebu.h"
static void __iomem *mpp_base;
static int armada_38x_mpp_ctrl_get(unsigned pid, unsigned long *config)
{
return default_mpp_ctrl_get(mpp_base, pid, config);
}
static int armada_38x_mpp_ctrl_set(unsigned pid, unsigned long config)
{
return default_mpp_ctrl_set(mpp_base, pid, config);
}
enum {
V_88F6810 = BIT(0),
V_88F6820 = BIT(1),
@ -409,8 +396,8 @@ static const struct of_device_id armada_38x_pinctrl_of_match[] = {
{ },
};
static struct mvebu_mpp_ctrl armada_38x_mpp_controls[] = {
MPP_FUNC_CTRL(0, 59, NULL, armada_38x_mpp_ctrl),
static const struct mvebu_mpp_ctrl armada_38x_mpp_controls[] = {
MPP_FUNC_CTRL(0, 59, NULL, mvebu_mmio_mpp_ctrl),
};
static struct pinctrl_gpio_range armada_38x_mpp_gpio_ranges[] = {
@ -423,16 +410,10 @@ static int armada_38x_pinctrl_probe(struct platform_device *pdev)
struct mvebu_pinctrl_soc_info *soc = &armada_38x_pinctrl_info;
const struct of_device_id *match =
of_match_device(armada_38x_pinctrl_of_match, &pdev->dev);
struct resource *res;
if (!match)
return -ENODEV;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
mpp_base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(mpp_base))
return PTR_ERR(mpp_base);
soc->variant = (unsigned) match->data & 0xff;
soc->controls = armada_38x_mpp_controls;
soc->ncontrols = ARRAY_SIZE(armada_38x_mpp_controls);
@ -443,7 +424,7 @@ static int armada_38x_pinctrl_probe(struct platform_device *pdev)
pdev->dev.platform_data = soc;
return mvebu_pinctrl_probe(pdev);
return mvebu_pinctrl_simple_mmio_probe(pdev);
}
static struct platform_driver armada_38x_pinctrl_driver = {
@ -453,9 +434,4 @@ static struct platform_driver armada_38x_pinctrl_driver = {
},
.probe = armada_38x_pinctrl_probe,
};
module_platform_driver(armada_38x_pinctrl_driver);
MODULE_AUTHOR("Thomas Petazzoni <thomas.petazzoni@free-electrons.com>");
MODULE_DESCRIPTION("Marvell Armada 38x pinctrl driver");
MODULE_LICENSE("GPL v2");
builtin_platform_driver(armada_38x_pinctrl_driver);

View File

@ -14,7 +14,6 @@
#include <linux/err.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/of_device.h>
@ -22,18 +21,6 @@
#include "pinctrl-mvebu.h"
static void __iomem *mpp_base;
static int armada_39x_mpp_ctrl_get(unsigned pid, unsigned long *config)
{
return default_mpp_ctrl_get(mpp_base, pid, config);
}
static int armada_39x_mpp_ctrl_set(unsigned pid, unsigned long config)
{
return default_mpp_ctrl_set(mpp_base, pid, config);
}
enum {
V_88F6920 = BIT(0),
V_88F6925 = BIT(1),
@ -391,8 +378,8 @@ static const struct of_device_id armada_39x_pinctrl_of_match[] = {
{ },
};
static struct mvebu_mpp_ctrl armada_39x_mpp_controls[] = {
MPP_FUNC_CTRL(0, 59, NULL, armada_39x_mpp_ctrl),
static const struct mvebu_mpp_ctrl armada_39x_mpp_controls[] = {
MPP_FUNC_CTRL(0, 59, NULL, mvebu_mmio_mpp_ctrl),
};
static struct pinctrl_gpio_range armada_39x_mpp_gpio_ranges[] = {
@ -405,16 +392,10 @@ static int armada_39x_pinctrl_probe(struct platform_device *pdev)
struct mvebu_pinctrl_soc_info *soc = &armada_39x_pinctrl_info;
const struct of_device_id *match =
of_match_device(armada_39x_pinctrl_of_match, &pdev->dev);
struct resource *res;
if (!match)
return -ENODEV;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
mpp_base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(mpp_base))
return PTR_ERR(mpp_base);
soc->variant = (unsigned) match->data & 0xff;
soc->controls = armada_39x_mpp_controls;
soc->ncontrols = ARRAY_SIZE(armada_39x_mpp_controls);
@ -425,7 +406,7 @@ static int armada_39x_pinctrl_probe(struct platform_device *pdev)
pdev->dev.platform_data = soc;
return mvebu_pinctrl_probe(pdev);
return mvebu_pinctrl_simple_mmio_probe(pdev);
}
static struct platform_driver armada_39x_pinctrl_driver = {
@ -435,9 +416,4 @@ static struct platform_driver armada_39x_pinctrl_driver = {
},
.probe = armada_39x_pinctrl_probe,
};
module_platform_driver(armada_39x_pinctrl_driver);
MODULE_AUTHOR("Thomas Petazzoni <thomas.petazzoni@free-electrons.com>");
MODULE_DESCRIPTION("Marvell Armada 39x pinctrl driver");
MODULE_LICENSE("GPL v2");
builtin_platform_driver(armada_39x_pinctrl_driver);

View File

@ -20,7 +20,6 @@
#include <linux/err.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <linux/of.h>
@ -30,25 +29,18 @@
#include "pinctrl-mvebu.h"
static void __iomem *mpp_base;
static u32 *mpp_saved_regs;
static int armada_xp_mpp_ctrl_get(unsigned pid, unsigned long *config)
{
return default_mpp_ctrl_get(mpp_base, pid, config);
}
static int armada_xp_mpp_ctrl_set(unsigned pid, unsigned long config)
{
return default_mpp_ctrl_set(mpp_base, pid, config);
}
enum armada_xp_variant {
V_MV78230 = BIT(0),
V_MV78260 = BIT(1),
V_MV78460 = BIT(2),
V_MV78230_PLUS = (V_MV78230 | V_MV78260 | V_MV78460),
V_MV78260_PLUS = (V_MV78260 | V_MV78460),
V_98DX3236 = BIT(3),
V_98DX3336 = BIT(4),
V_98DX4251 = BIT(5),
V_98DX3236_PLUS = (V_98DX3236 | V_98DX3336 | V_98DX4251),
};
static struct mvebu_mpp_mode armada_xp_mpp_modes[] = {
@ -360,6 +352,131 @@ static struct mvebu_mpp_mode armada_xp_mpp_modes[] = {
MPP_VAR_FUNCTION(0x1, "dev", "ad31", V_MV78260_PLUS)),
};
static struct mvebu_mpp_mode mv98dx3236_mpp_modes[] = {
MPP_MODE(0,
MPP_VAR_FUNCTION(0x0, "gpo", NULL, V_98DX3236_PLUS),
MPP_VAR_FUNCTION(0x2, "spi0", "mosi", V_98DX3236_PLUS),
MPP_VAR_FUNCTION(0x4, "dev", "ad8", V_98DX3236_PLUS)),
MPP_MODE(1,
MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_98DX3236_PLUS),
MPP_VAR_FUNCTION(0x2, "spi0", "miso", V_98DX3236_PLUS),
MPP_VAR_FUNCTION(0x4, "dev", "ad9", V_98DX3236_PLUS)),
MPP_MODE(2,
MPP_VAR_FUNCTION(0x0, "gpo", NULL, V_98DX3236_PLUS),
MPP_VAR_FUNCTION(0x2, "spi0", "sck", V_98DX3236_PLUS),
MPP_VAR_FUNCTION(0x4, "dev", "ad10", V_98DX3236_PLUS)),
MPP_MODE(3,
MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_98DX3236_PLUS),
MPP_VAR_FUNCTION(0x2, "spi0", "cs0", V_98DX3236_PLUS),
MPP_VAR_FUNCTION(0x4, "dev", "ad11", V_98DX3236_PLUS)),
MPP_MODE(4,
MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_98DX3236_PLUS),
MPP_VAR_FUNCTION(0x2, "spi0", "cs1", V_98DX3236_PLUS),
MPP_VAR_FUNCTION(0x3, "smi", "mdc", V_98DX3236_PLUS),
MPP_VAR_FUNCTION(0x4, "dev", "cs0", V_98DX3236_PLUS)),
MPP_MODE(5,
MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_98DX3236_PLUS),
MPP_VAR_FUNCTION(0x1, "pex", "rsto", V_98DX3236_PLUS),
MPP_VAR_FUNCTION(0x2, "sd0", "cmd", V_98DX4251),
MPP_VAR_FUNCTION(0x4, "dev", "bootcs", V_98DX3236_PLUS)),
MPP_MODE(6,
MPP_VAR_FUNCTION(0x0, "gpo", NULL, V_98DX3236_PLUS),
MPP_VAR_FUNCTION(0x2, "sd0", "clk", V_98DX4251),
MPP_VAR_FUNCTION(0x4, "dev", "a2", V_98DX3236_PLUS)),
MPP_MODE(7,
MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_98DX3236_PLUS),
MPP_VAR_FUNCTION(0x2, "sd0", "d0", V_98DX4251),
MPP_VAR_FUNCTION(0x4, "dev", "ale0", V_98DX3236_PLUS)),
MPP_MODE(8,
MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_98DX3236_PLUS),
MPP_VAR_FUNCTION(0x2, "sd0", "d1", V_98DX4251),
MPP_VAR_FUNCTION(0x4, "dev", "ale1", V_98DX3236_PLUS)),
MPP_MODE(9,
MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_98DX3236_PLUS),
MPP_VAR_FUNCTION(0x2, "sd0", "d2", V_98DX4251),
MPP_VAR_FUNCTION(0x4, "dev", "ready0", V_98DX3236_PLUS)),
MPP_MODE(10,
MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_98DX3236_PLUS),
MPP_VAR_FUNCTION(0x2, "sd0", "d3", V_98DX4251),
MPP_VAR_FUNCTION(0x4, "dev", "ad12", V_98DX3236_PLUS)),
MPP_MODE(11,
MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_98DX3236_PLUS),
MPP_VAR_FUNCTION(0x2, "uart1", "rxd", V_98DX3236_PLUS),
MPP_VAR_FUNCTION(0x3, "uart0", "cts", V_98DX3236_PLUS),
MPP_VAR_FUNCTION(0x4, "dev", "ad13", V_98DX3236_PLUS)),
MPP_MODE(12,
MPP_VAR_FUNCTION(0x0, "gpo", NULL, V_98DX3236_PLUS),
MPP_VAR_FUNCTION(0x2, "uart1", "txd", V_98DX3236_PLUS),
MPP_VAR_FUNCTION(0x3, "uart0", "rts", V_98DX3236_PLUS),
MPP_VAR_FUNCTION(0x4, "dev", "ad14", V_98DX3236_PLUS)),
MPP_MODE(13,
MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_98DX3236_PLUS),
MPP_VAR_FUNCTION(0x1, "intr", "out", V_98DX3236_PLUS),
MPP_VAR_FUNCTION(0x4, "dev", "ad15", V_98DX3236_PLUS)),
MPP_MODE(14,
MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_98DX3236_PLUS),
MPP_VAR_FUNCTION(0x1, "i2c0", "sck", V_98DX3236_PLUS)),
MPP_MODE(15,
MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_98DX3236_PLUS),
MPP_VAR_FUNCTION(0x4, "i2c0", "sda", V_98DX3236_PLUS)),
MPP_MODE(16,
MPP_VAR_FUNCTION(0x0, "gpo", NULL, V_98DX3236_PLUS),
MPP_VAR_FUNCTION(0x4, "dev", "oe", V_98DX3236_PLUS)),
MPP_MODE(17,
MPP_VAR_FUNCTION(0x0, "gpo", NULL, V_98DX3236_PLUS),
MPP_VAR_FUNCTION(0x4, "dev", "clkout", V_98DX3236_PLUS)),
MPP_MODE(18,
MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_98DX3236_PLUS),
MPP_VAR_FUNCTION(0x3, "uart1", "txd", V_98DX3236_PLUS)),
MPP_MODE(19,
MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_98DX3236_PLUS),
MPP_VAR_FUNCTION(0x3, "uart1", "rxd", V_98DX3236_PLUS),
MPP_VAR_FUNCTION(0x4, "dev", "rb", V_98DX3236_PLUS)),
MPP_MODE(20,
MPP_VAR_FUNCTION(0x0, "gpo", NULL, V_98DX3236_PLUS),
MPP_VAR_FUNCTION(0x4, "dev", "we0", V_98DX3236_PLUS)),
MPP_MODE(21,
MPP_VAR_FUNCTION(0x0, "gpo", NULL, V_98DX3236_PLUS),
MPP_VAR_FUNCTION(0x1, "dev", "ad0", V_98DX3236_PLUS)),
MPP_MODE(22,
MPP_VAR_FUNCTION(0x0, "gpo", NULL, V_98DX3236_PLUS),
MPP_VAR_FUNCTION(0x1, "dev", "ad1", V_98DX3236_PLUS)),
MPP_MODE(23,
MPP_VAR_FUNCTION(0x0, "gpo", NULL, V_98DX3236_PLUS),
MPP_VAR_FUNCTION(0x1, "dev", "ad2", V_98DX3236_PLUS)),
MPP_MODE(24,
MPP_VAR_FUNCTION(0x0, "gpo", NULL, V_98DX3236_PLUS),
MPP_VAR_FUNCTION(0x1, "dev", "ad3", V_98DX3236_PLUS)),
MPP_MODE(25,
MPP_VAR_FUNCTION(0x0, "gpo", NULL, V_98DX3236_PLUS),
MPP_VAR_FUNCTION(0x1, "dev", "ad4", V_98DX3236_PLUS)),
MPP_MODE(26,
MPP_VAR_FUNCTION(0x0, "gpo", NULL, V_98DX3236_PLUS),
MPP_VAR_FUNCTION(0x1, "dev", "ad5", V_98DX3236_PLUS)),
MPP_MODE(27,
MPP_VAR_FUNCTION(0x0, "gpo", NULL, V_98DX3236_PLUS),
MPP_VAR_FUNCTION(0x1, "dev", "ad6", V_98DX3236_PLUS)),
MPP_MODE(28,
MPP_VAR_FUNCTION(0x0, "gpo", NULL, V_98DX3236_PLUS),
MPP_VAR_FUNCTION(0x1, "dev", "ad7", V_98DX3236_PLUS)),
MPP_MODE(29,
MPP_VAR_FUNCTION(0x0, "gpo", NULL, V_98DX3236_PLUS),
MPP_VAR_FUNCTION(0x1, "dev", "a0", V_98DX3236_PLUS)),
MPP_MODE(30,
MPP_VAR_FUNCTION(0x0, "gpo", NULL, V_98DX3236_PLUS),
MPP_VAR_FUNCTION(0x1, "dev", "a1", V_98DX3236_PLUS)),
MPP_MODE(31,
MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_98DX3236_PLUS),
MPP_VAR_FUNCTION(0x1, "slv_smi", "mdc", V_98DX3236_PLUS),
MPP_VAR_FUNCTION(0x3, "smi", "mdc", V_98DX3236_PLUS),
MPP_VAR_FUNCTION(0x4, "dev", "we1", V_98DX3236_PLUS)),
MPP_MODE(32,
MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_98DX3236_PLUS),
MPP_VAR_FUNCTION(0x1, "slv_smi", "mdio", V_98DX3236_PLUS),
MPP_VAR_FUNCTION(0x3, "smi", "mdio", V_98DX3236_PLUS),
MPP_VAR_FUNCTION(0x4, "dev", "cs1", V_98DX3236_PLUS)),
};
static struct mvebu_pinctrl_soc_info armada_xp_pinctrl_info;
static const struct of_device_id armada_xp_pinctrl_of_match[] = {
@ -375,11 +492,19 @@ static const struct of_device_id armada_xp_pinctrl_of_match[] = {
.compatible = "marvell,mv78460-pinctrl",
.data = (void *) V_MV78460,
},
{
.compatible = "marvell,98dx3236-pinctrl",
.data = (void *) V_98DX3236,
},
{
.compatible = "marvell,98dx4251-pinctrl",
.data = (void *) V_98DX4251,
},
{ },
};
static struct mvebu_mpp_ctrl mv78230_mpp_controls[] = {
MPP_FUNC_CTRL(0, 48, NULL, armada_xp_mpp_ctrl),
static const struct mvebu_mpp_ctrl mv78230_mpp_controls[] = {
MPP_FUNC_CTRL(0, 48, NULL, mvebu_mmio_mpp_ctrl),
};
static struct pinctrl_gpio_range mv78230_mpp_gpio_ranges[] = {
@ -387,8 +512,8 @@ static struct pinctrl_gpio_range mv78230_mpp_gpio_ranges[] = {
MPP_GPIO_RANGE(1, 32, 32, 17),
};
static struct mvebu_mpp_ctrl mv78260_mpp_controls[] = {
MPP_FUNC_CTRL(0, 66, NULL, armada_xp_mpp_ctrl),
static const struct mvebu_mpp_ctrl mv78260_mpp_controls[] = {
MPP_FUNC_CTRL(0, 66, NULL, mvebu_mmio_mpp_ctrl),
};
static struct pinctrl_gpio_range mv78260_mpp_gpio_ranges[] = {
@ -397,8 +522,8 @@ static struct pinctrl_gpio_range mv78260_mpp_gpio_ranges[] = {
MPP_GPIO_RANGE(2, 64, 64, 3),
};
static struct mvebu_mpp_ctrl mv78460_mpp_controls[] = {
MPP_FUNC_CTRL(0, 66, NULL, armada_xp_mpp_ctrl),
static const struct mvebu_mpp_ctrl mv78460_mpp_controls[] = {
MPP_FUNC_CTRL(0, 66, NULL, mvebu_mmio_mpp_ctrl),
};
static struct pinctrl_gpio_range mv78460_mpp_gpio_ranges[] = {
@ -407,6 +532,14 @@ static struct pinctrl_gpio_range mv78460_mpp_gpio_ranges[] = {
MPP_GPIO_RANGE(2, 64, 64, 3),
};
static struct mvebu_mpp_ctrl mv98dx3236_mpp_controls[] = {
MPP_FUNC_CTRL(0, 32, NULL, mvebu_mmio_mpp_ctrl),
};
static struct pinctrl_gpio_range mv98dx3236_mpp_gpio_ranges[] = {
MPP_GPIO_RANGE(0, 0, 0, 32),
};
static int armada_xp_pinctrl_suspend(struct platform_device *pdev,
pm_message_t state)
{
@ -417,7 +550,7 @@ static int armada_xp_pinctrl_suspend(struct platform_device *pdev,
nregs = DIV_ROUND_UP(soc->nmodes, MVEBU_MPPS_PER_REG);
for (i = 0; i < nregs; i++)
mpp_saved_regs[i] = readl(mpp_base + i * 4);
mpp_saved_regs[i] = readl(soc->control_data[0].base + i * 4);
return 0;
}
@ -431,7 +564,7 @@ static int armada_xp_pinctrl_resume(struct platform_device *pdev)
nregs = DIV_ROUND_UP(soc->nmodes, MVEBU_MPPS_PER_REG);
for (i = 0; i < nregs; i++)
writel(mpp_saved_regs[i], mpp_base + i * 4);
writel(mpp_saved_regs[i], soc->control_data[0].base + i * 4);
return 0;
}
@ -441,17 +574,11 @@ static int armada_xp_pinctrl_probe(struct platform_device *pdev)
struct mvebu_pinctrl_soc_info *soc = &armada_xp_pinctrl_info;
const struct of_device_id *match =
of_match_device(armada_xp_pinctrl_of_match, &pdev->dev);
struct resource *res;
int nregs;
if (!match)
return -ENODEV;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
mpp_base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(mpp_base))
return PTR_ERR(mpp_base);
soc->variant = (unsigned) match->data & 0xff;
switch (soc->variant) {
@ -488,6 +615,17 @@ static int armada_xp_pinctrl_probe(struct platform_device *pdev)
soc->gpioranges = mv78460_mpp_gpio_ranges;
soc->ngpioranges = ARRAY_SIZE(mv78460_mpp_gpio_ranges);
break;
case V_98DX3236:
case V_98DX3336:
case V_98DX4251:
/* fall-through */
soc->controls = mv98dx3236_mpp_controls;
soc->ncontrols = ARRAY_SIZE(mv98dx3236_mpp_controls);
soc->modes = mv98dx3236_mpp_modes;
soc->nmodes = mv98dx3236_mpp_controls[0].npins;
soc->gpioranges = mv98dx3236_mpp_gpio_ranges;
soc->ngpioranges = ARRAY_SIZE(mv98dx3236_mpp_gpio_ranges);
break;
}
nregs = DIV_ROUND_UP(soc->nmodes, MVEBU_MPPS_PER_REG);
@ -499,7 +637,7 @@ static int armada_xp_pinctrl_probe(struct platform_device *pdev)
pdev->dev.platform_data = soc;
return mvebu_pinctrl_probe(pdev);
return mvebu_pinctrl_simple_mmio_probe(pdev);
}
static struct platform_driver armada_xp_pinctrl_driver = {
@ -511,9 +649,4 @@ static struct platform_driver armada_xp_pinctrl_driver = {
.suspend = armada_xp_pinctrl_suspend,
.resume = armada_xp_pinctrl_resume,
};
module_platform_driver(armada_xp_pinctrl_driver);
MODULE_AUTHOR("Thomas Petazzoni <thomas.petazzoni@free-electrons.com>");
MODULE_DESCRIPTION("Marvell Armada XP pinctrl driver");
MODULE_LICENSE("GPL v2");
builtin_platform_driver(armada_xp_pinctrl_driver);

View File

@ -12,7 +12,6 @@
#include <linux/err.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/bitops.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
@ -61,30 +60,20 @@
#define CONFIG_PMU BIT(4)
static void __iomem *mpp_base;
static void __iomem *mpp4_base;
static void __iomem *pmu_base;
static struct regmap *gconfmap;
static int dove_mpp_ctrl_get(unsigned pid, unsigned long *config)
{
return default_mpp_ctrl_get(mpp_base, pid, config);
}
static int dove_mpp_ctrl_set(unsigned pid, unsigned long config)
{
return default_mpp_ctrl_set(mpp_base, pid, config);
}
static int dove_pmu_mpp_ctrl_get(unsigned pid, unsigned long *config)
static int dove_pmu_mpp_ctrl_get(struct mvebu_mpp_ctrl_data *data,
unsigned pid, unsigned long *config)
{
unsigned off = (pid / MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;
unsigned shift = (pid % MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;
unsigned long pmu = readl(mpp_base + PMU_MPP_GENERAL_CTRL);
unsigned long pmu = readl(data->base + PMU_MPP_GENERAL_CTRL);
unsigned long func;
if ((pmu & BIT(pid)) == 0)
return default_mpp_ctrl_get(mpp_base, pid, config);
return mvebu_mmio_mpp_ctrl_get(data, pid, config);
func = readl(pmu_base + PMU_SIGNAL_SELECT_0 + off);
*config = (func >> shift) & MVEBU_MPP_MASK;
@ -93,19 +82,20 @@ static int dove_pmu_mpp_ctrl_get(unsigned pid, unsigned long *config)
return 0;
}
static int dove_pmu_mpp_ctrl_set(unsigned pid, unsigned long config)
static int dove_pmu_mpp_ctrl_set(struct mvebu_mpp_ctrl_data *data,
unsigned pid, unsigned long config)
{
unsigned off = (pid / MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;
unsigned shift = (pid % MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;
unsigned long pmu = readl(mpp_base + PMU_MPP_GENERAL_CTRL);
unsigned long pmu = readl(data->base + PMU_MPP_GENERAL_CTRL);
unsigned long func;
if ((config & CONFIG_PMU) == 0) {
writel(pmu & ~BIT(pid), mpp_base + PMU_MPP_GENERAL_CTRL);
return default_mpp_ctrl_set(mpp_base, pid, config);
writel(pmu & ~BIT(pid), data->base + PMU_MPP_GENERAL_CTRL);
return mvebu_mmio_mpp_ctrl_set(data, pid, config);
}
writel(pmu | BIT(pid), mpp_base + PMU_MPP_GENERAL_CTRL);
writel(pmu | BIT(pid), data->base + PMU_MPP_GENERAL_CTRL);
func = readl(pmu_base + PMU_SIGNAL_SELECT_0 + off);
func &= ~(MVEBU_MPP_MASK << shift);
func |= (config & MVEBU_MPP_MASK) << shift;
@ -114,7 +104,8 @@ static int dove_pmu_mpp_ctrl_set(unsigned pid, unsigned long config)
return 0;
}
static int dove_mpp4_ctrl_get(unsigned pid, unsigned long *config)
static int dove_mpp4_ctrl_get(struct mvebu_mpp_ctrl_data *data, unsigned pid,
unsigned long *config)
{
unsigned long mpp4 = readl(mpp4_base);
unsigned long mask;
@ -144,7 +135,8 @@ static int dove_mpp4_ctrl_get(unsigned pid, unsigned long *config)
return 0;
}
static int dove_mpp4_ctrl_set(unsigned pid, unsigned long config)
static int dove_mpp4_ctrl_set(struct mvebu_mpp_ctrl_data *data, unsigned pid,
unsigned long config)
{
unsigned long mpp4 = readl(mpp4_base);
unsigned long mask;
@ -178,7 +170,8 @@ static int dove_mpp4_ctrl_set(unsigned pid, unsigned long config)
return 0;
}
static int dove_nand_ctrl_get(unsigned pid, unsigned long *config)
static int dove_nand_ctrl_get(struct mvebu_mpp_ctrl_data *data, unsigned pid,
unsigned long *config)
{
unsigned int gmpp;
@ -188,7 +181,8 @@ static int dove_nand_ctrl_get(unsigned pid, unsigned long *config)
return 0;
}
static int dove_nand_ctrl_set(unsigned pid, unsigned long config)
static int dove_nand_ctrl_set(struct mvebu_mpp_ctrl_data *data, unsigned pid,
unsigned long config)
{
regmap_update_bits(gconfmap, MPP_GENERAL_CONFIG,
NAND_GPIO_EN,
@ -196,28 +190,31 @@ static int dove_nand_ctrl_set(unsigned pid, unsigned long config)
return 0;
}
static int dove_audio0_ctrl_get(unsigned pid, unsigned long *config)
static int dove_audio0_ctrl_get(struct mvebu_mpp_ctrl_data *data, unsigned pid,
unsigned long *config)
{
unsigned long pmu = readl(mpp_base + PMU_MPP_GENERAL_CTRL);
unsigned long pmu = readl(data->base + PMU_MPP_GENERAL_CTRL);
*config = ((pmu & AU0_AC97_SEL) != 0);
return 0;
}
static int dove_audio0_ctrl_set(unsigned pid, unsigned long config)
static int dove_audio0_ctrl_set(struct mvebu_mpp_ctrl_data *data, unsigned pid,
unsigned long config)
{
unsigned long pmu = readl(mpp_base + PMU_MPP_GENERAL_CTRL);
unsigned long pmu = readl(data->base + PMU_MPP_GENERAL_CTRL);
pmu &= ~AU0_AC97_SEL;
if (config)
pmu |= AU0_AC97_SEL;
writel(pmu, mpp_base + PMU_MPP_GENERAL_CTRL);
writel(pmu, data->base + PMU_MPP_GENERAL_CTRL);
return 0;
}
static int dove_audio1_ctrl_get(unsigned pid, unsigned long *config)
static int dove_audio1_ctrl_get(struct mvebu_mpp_ctrl_data *data, unsigned pid,
unsigned long *config)
{
unsigned int mpp4 = readl(mpp4_base);
unsigned int sspc1;
@ -247,7 +244,8 @@ static int dove_audio1_ctrl_get(unsigned pid, unsigned long *config)
return 0;
}
static int dove_audio1_ctrl_set(unsigned pid, unsigned long config)
static int dove_audio1_ctrl_set(struct mvebu_mpp_ctrl_data *data, unsigned pid,
unsigned long config)
{
unsigned int mpp4 = readl(mpp4_base);
@ -274,11 +272,12 @@ static int dove_audio1_ctrl_set(unsigned pid, unsigned long config)
* break other functions. If you require all mpps as gpio
* enforce gpio setting by pinctrl mapping.
*/
static int dove_audio1_ctrl_gpio_req(unsigned pid)
static int dove_audio1_ctrl_gpio_req(struct mvebu_mpp_ctrl_data *data,
unsigned pid)
{
unsigned long config;
dove_audio1_ctrl_get(pid, &config);
dove_audio1_ctrl_get(data, pid, &config);
switch (config) {
case 0x02: /* i2s1 : gpio[56:57] */
@ -301,14 +300,16 @@ static int dove_audio1_ctrl_gpio_req(unsigned pid)
}
/* mpp[52:57] has gpio pins capable of in and out */
static int dove_audio1_ctrl_gpio_dir(unsigned pid, bool input)
static int dove_audio1_ctrl_gpio_dir(struct mvebu_mpp_ctrl_data *data,
unsigned pid, bool input)
{
if (pid < 52 || pid > 57)
return -ENOTSUPP;
return 0;
}
static int dove_twsi_ctrl_get(unsigned pid, unsigned long *config)
static int dove_twsi_ctrl_get(struct mvebu_mpp_ctrl_data *data, unsigned pid,
unsigned long *config)
{
unsigned int gcfg1;
unsigned int gcfg2;
@ -327,7 +328,8 @@ static int dove_twsi_ctrl_get(unsigned pid, unsigned long *config)
return 0;
}
static int dove_twsi_ctrl_set(unsigned pid, unsigned long config)
static int dove_twsi_ctrl_set(struct mvebu_mpp_ctrl_data *data, unsigned pid,
unsigned long config)
{
unsigned int gcfg1 = 0;
unsigned int gcfg2 = 0;
@ -354,9 +356,9 @@ static int dove_twsi_ctrl_set(unsigned pid, unsigned long config)
return 0;
}
static struct mvebu_mpp_ctrl dove_mpp_controls[] = {
static const struct mvebu_mpp_ctrl dove_mpp_controls[] = {
MPP_FUNC_CTRL(0, 15, NULL, dove_pmu_mpp_ctrl),
MPP_FUNC_CTRL(16, 23, NULL, dove_mpp_ctrl),
MPP_FUNC_CTRL(16, 23, NULL, mvebu_mmio_mpp_ctrl),
MPP_FUNC_CTRL(24, 39, "mpp_camera", dove_mpp4_ctrl),
MPP_FUNC_CTRL(40, 45, "mpp_sdio0", dove_mpp4_ctrl),
MPP_FUNC_CTRL(46, 51, "mpp_sdio1", dove_mpp4_ctrl),
@ -769,6 +771,10 @@ static int dove_pinctrl_probe(struct platform_device *pdev)
struct resource fb_res;
const struct of_device_id *match =
of_match_device(dove_pinctrl_of_match, &pdev->dev);
struct mvebu_mpp_ctrl_data *mpp_data;
void __iomem *base;
int i;
pdev->dev.platform_data = (void *)match->data;
/*
@ -783,9 +789,18 @@ static int dove_pinctrl_probe(struct platform_device *pdev)
clk_prepare_enable(clk);
mpp_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
mpp_base = devm_ioremap_resource(&pdev->dev, mpp_res);
if (IS_ERR(mpp_base))
return PTR_ERR(mpp_base);
base = devm_ioremap_resource(&pdev->dev, mpp_res);
if (IS_ERR(base))
return PTR_ERR(base);
mpp_data = devm_kcalloc(&pdev->dev, dove_pinctrl_info.ncontrols,
sizeof(*mpp_data), GFP_KERNEL);
if (!mpp_data)
return -ENOMEM;
dove_pinctrl_info.control_data = mpp_data;
for (i = 0; i < ARRAY_SIZE(dove_mpp_controls); i++)
mpp_data[i].base = base;
/* prepare fallback resource */
memcpy(&fb_res, mpp_res, sizeof(struct resource));
@ -838,24 +853,12 @@ static int dove_pinctrl_probe(struct platform_device *pdev)
return mvebu_pinctrl_probe(pdev);
}
static int dove_pinctrl_remove(struct platform_device *pdev)
{
if (!IS_ERR(clk))
clk_disable_unprepare(clk);
return 0;
}
static struct platform_driver dove_pinctrl_driver = {
.driver = {
.name = "dove-pinctrl",
.suppress_bind_attrs = true,
.of_match_table = dove_pinctrl_of_match,
},
.probe = dove_pinctrl_probe,
.remove = dove_pinctrl_remove,
};
module_platform_driver(dove_pinctrl_driver);
MODULE_AUTHOR("Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>");
MODULE_DESCRIPTION("Marvell Dove pinctrl driver");
MODULE_LICENSE("GPL v2");
builtin_platform_driver(dove_pinctrl_driver);

View File

@ -12,7 +12,6 @@
#include <linux/err.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <linux/of.h>
@ -21,18 +20,6 @@
#include "pinctrl-mvebu.h"
static void __iomem *mpp_base;
static int kirkwood_mpp_ctrl_get(unsigned pid, unsigned long *config)
{
return default_mpp_ctrl_get(mpp_base, pid, config);
}
static int kirkwood_mpp_ctrl_set(unsigned pid, unsigned long config)
{
return default_mpp_ctrl_set(mpp_base, pid, config);
}
#define V(f6180, f6190, f6192, f6281, f6282, dx4122) \
((f6180 << 0) | (f6190 << 1) | (f6192 << 2) | \
(f6281 << 3) | (f6282 << 4) | (dx4122 << 5))
@ -370,8 +357,8 @@ static struct mvebu_mpp_mode mv88f6xxx_mpp_modes[] = {
MPP_VAR_FUNCTION(0xb, "lcd", "d17", V(0, 0, 0, 0, 1, 0))),
};
static struct mvebu_mpp_ctrl mv88f6180_mpp_controls[] = {
MPP_FUNC_CTRL(0, 44, NULL, kirkwood_mpp_ctrl),
static const struct mvebu_mpp_ctrl mv88f6180_mpp_controls[] = {
MPP_FUNC_CTRL(0, 44, NULL, mvebu_mmio_mpp_ctrl),
};
static struct pinctrl_gpio_range mv88f6180_gpio_ranges[] = {
@ -379,8 +366,8 @@ static struct pinctrl_gpio_range mv88f6180_gpio_ranges[] = {
MPP_GPIO_RANGE(1, 35, 35, 10),
};
static struct mvebu_mpp_ctrl mv88f619x_mpp_controls[] = {
MPP_FUNC_CTRL(0, 35, NULL, kirkwood_mpp_ctrl),
static const struct mvebu_mpp_ctrl mv88f619x_mpp_controls[] = {
MPP_FUNC_CTRL(0, 35, NULL, mvebu_mmio_mpp_ctrl),
};
static struct pinctrl_gpio_range mv88f619x_gpio_ranges[] = {
@ -388,8 +375,8 @@ static struct pinctrl_gpio_range mv88f619x_gpio_ranges[] = {
MPP_GPIO_RANGE(1, 32, 32, 4),
};
static struct mvebu_mpp_ctrl mv88f628x_mpp_controls[] = {
MPP_FUNC_CTRL(0, 49, NULL, kirkwood_mpp_ctrl),
static const struct mvebu_mpp_ctrl mv88f628x_mpp_controls[] = {
MPP_FUNC_CTRL(0, 49, NULL, mvebu_mmio_mpp_ctrl),
};
static struct pinctrl_gpio_range mv88f628x_gpio_ranges[] = {
@ -469,17 +456,12 @@ static const struct of_device_id kirkwood_pinctrl_of_match[] = {
static int kirkwood_pinctrl_probe(struct platform_device *pdev)
{
struct resource *res;
const struct of_device_id *match =
of_match_device(kirkwood_pinctrl_of_match, &pdev->dev);
pdev->dev.platform_data = (void *)match->data;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
mpp_base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(mpp_base))
return PTR_ERR(mpp_base);
return mvebu_pinctrl_probe(pdev);
return mvebu_pinctrl_simple_mmio_probe(pdev);
}
static struct platform_driver kirkwood_pinctrl_driver = {
@ -489,9 +471,4 @@ static struct platform_driver kirkwood_pinctrl_driver = {
},
.probe = kirkwood_pinctrl_probe,
};
module_platform_driver(kirkwood_pinctrl_driver);
MODULE_AUTHOR("Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>");
MODULE_DESCRIPTION("Marvell Kirkwood pinctrl driver");
MODULE_LICENSE("GPL v2");
builtin_platform_driver(kirkwood_pinctrl_driver);

View File

@ -11,7 +11,6 @@
*/
#include <linux/platform_device.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/io.h>
#include <linux/of.h>
@ -23,6 +22,8 @@
#include <linux/pinctrl/pinconf.h>
#include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/pinmux.h>
#include <linux/mfd/syscon.h>
#include <linux/regmap.h>
#include "pinctrl-mvebu.h"
@ -38,7 +39,8 @@ struct mvebu_pinctrl_function {
struct mvebu_pinctrl_group {
const char *name;
struct mvebu_mpp_ctrl *ctrl;
const struct mvebu_mpp_ctrl *ctrl;
struct mvebu_mpp_ctrl_data *data;
struct mvebu_mpp_ctrl_setting *settings;
unsigned num_settings;
unsigned gid;
@ -57,6 +59,30 @@ struct mvebu_pinctrl {
u8 variant;
};
int mvebu_mmio_mpp_ctrl_get(struct mvebu_mpp_ctrl_data *data,
unsigned int pid, unsigned long *config)
{
unsigned off = (pid / MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;
unsigned shift = (pid % MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;
*config = (readl(data->base + off) >> shift) & MVEBU_MPP_MASK;
return 0;
}
int mvebu_mmio_mpp_ctrl_set(struct mvebu_mpp_ctrl_data *data,
unsigned int pid, unsigned long config)
{
unsigned off = (pid / MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;
unsigned shift = (pid % MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;
unsigned long reg;
reg = readl(data->base + off) & ~(MVEBU_MPP_MASK << shift);
writel(reg | (config << shift), data->base + off);
return 0;
}
static struct mvebu_pinctrl_group *mvebu_pinctrl_find_group_by_pid(
struct mvebu_pinctrl *pctl, unsigned pid)
{
@ -146,7 +172,7 @@ static int mvebu_pinconf_group_get(struct pinctrl_dev *pctldev,
if (!grp->ctrl)
return -EINVAL;
return grp->ctrl->mpp_get(grp->pins[0], config);
return grp->ctrl->mpp_get(grp->data, grp->pins[0], config);
}
static int mvebu_pinconf_group_set(struct pinctrl_dev *pctldev,
@ -161,7 +187,7 @@ static int mvebu_pinconf_group_set(struct pinctrl_dev *pctldev,
return -EINVAL;
for (i = 0; i < num_configs; i++) {
ret = grp->ctrl->mpp_set(grp->pins[0], configs[i]);
ret = grp->ctrl->mpp_set(grp->data, grp->pins[0], configs[i]);
if (ret)
return ret;
} /* for each config */
@ -188,18 +214,19 @@ static void mvebu_pinconf_group_dbg_show(struct pinctrl_dev *pctldev,
if (curr->subname)
seq_printf(s, "(%s)", curr->subname);
if (curr->flags & (MVEBU_SETTING_GPO | MVEBU_SETTING_GPI)) {
seq_printf(s, "(");
seq_putc(s, '(');
if (curr->flags & MVEBU_SETTING_GPI)
seq_printf(s, "i");
seq_putc(s, 'i');
if (curr->flags & MVEBU_SETTING_GPO)
seq_printf(s, "o");
seq_printf(s, ")");
seq_putc(s, 'o');
seq_putc(s, ')');
}
} else
seq_printf(s, "current: UNKNOWN");
} else {
seq_puts(s, "current: UNKNOWN");
}
if (grp->num_settings > 1) {
seq_printf(s, ", available = [");
seq_puts(s, ", available = [");
for (n = 0; n < grp->num_settings; n++) {
if (curr == &grp->settings[n])
continue;
@ -214,17 +241,16 @@ static void mvebu_pinconf_group_dbg_show(struct pinctrl_dev *pctldev,
seq_printf(s, "(%s)", grp->settings[n].subname);
if (grp->settings[n].flags &
(MVEBU_SETTING_GPO | MVEBU_SETTING_GPI)) {
seq_printf(s, "(");
seq_putc(s, '(');
if (grp->settings[n].flags & MVEBU_SETTING_GPI)
seq_printf(s, "i");
seq_putc(s, 'i');
if (grp->settings[n].flags & MVEBU_SETTING_GPO)
seq_printf(s, "o");
seq_printf(s, ")");
seq_putc(s, 'o');
seq_putc(s, ')');
}
}
seq_printf(s, " ]");
seq_puts(s, " ]");
}
return;
}
static const struct pinconf_ops mvebu_pinconf_ops = {
@ -302,7 +328,7 @@ static int mvebu_pinmux_gpio_request_enable(struct pinctrl_dev *pctldev,
return -EINVAL;
if (grp->ctrl->mpp_gpio_req)
return grp->ctrl->mpp_gpio_req(offset);
return grp->ctrl->mpp_gpio_req(grp->data, offset);
setting = mvebu_pinctrl_find_gpio_setting(pctl, grp);
if (!setting)
@ -325,7 +351,7 @@ static int mvebu_pinmux_gpio_set_direction(struct pinctrl_dev *pctldev,
return -EINVAL;
if (grp->ctrl->mpp_gpio_dir)
return grp->ctrl->mpp_gpio_dir(offset, input);
return grp->ctrl->mpp_gpio_dir(grp->data, offset, input);
setting = mvebu_pinctrl_find_gpio_setting(pctl, grp);
if (!setting)
@ -398,13 +424,9 @@ static int mvebu_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
return 0;
}
*map = kmalloc(nmaps * sizeof(struct pinctrl_map), GFP_KERNEL);
if (*map == NULL) {
dev_err(pctl->dev,
"cannot allocate pinctrl_map memory for %s\n",
np->name);
*map = kmalloc_array(nmaps, sizeof(**map), GFP_KERNEL);
if (!*map)
return -ENOMEM;
}
n = 0;
of_property_for_each_string(np, "marvell,pins", prop, group) {
@ -563,10 +585,8 @@ int mvebu_pinctrl_probe(struct platform_device *pdev)
pctl = devm_kzalloc(&pdev->dev, sizeof(struct mvebu_pinctrl),
GFP_KERNEL);
if (!pctl) {
dev_err(&pdev->dev, "unable to alloc driver\n");
if (!pctl)
return -ENOMEM;
}
pctl->desc.name = dev_name(&pdev->dev);
pctl->desc.owner = THIS_MODULE;
@ -582,7 +602,7 @@ int mvebu_pinctrl_probe(struct platform_device *pdev)
pctl->num_groups = 0;
pctl->desc.npins = 0;
for (n = 0; n < soc->ncontrols; n++) {
struct mvebu_mpp_ctrl *ctrl = &soc->controls[n];
const struct mvebu_mpp_ctrl *ctrl = &soc->controls[n];
pctl->desc.npins += ctrl->npins;
/* initialize control's pins[] array */
@ -604,10 +624,8 @@ int mvebu_pinctrl_probe(struct platform_device *pdev)
pdesc = devm_kzalloc(&pdev->dev, pctl->desc.npins *
sizeof(struct pinctrl_pin_desc), GFP_KERNEL);
if (!pdesc) {
dev_err(&pdev->dev, "failed to alloc pinctrl pins\n");
if (!pdesc)
return -ENOMEM;
}
for (n = 0; n < pctl->desc.npins; n++)
pdesc[n].number = n;
@ -628,9 +646,13 @@ int mvebu_pinctrl_probe(struct platform_device *pdev)
/* assign mpp controls to groups */
gid = 0;
for (n = 0; n < soc->ncontrols; n++) {
struct mvebu_mpp_ctrl *ctrl = &soc->controls[n];
const struct mvebu_mpp_ctrl *ctrl = &soc->controls[n];
struct mvebu_mpp_ctrl_data *data = soc->control_data ?
&soc->control_data[n] : NULL;
pctl->groups[gid].gid = gid;
pctl->groups[gid].ctrl = ctrl;
pctl->groups[gid].data = data;
pctl->groups[gid].name = ctrl->name;
pctl->groups[gid].pins = ctrl->pins;
pctl->groups[gid].npins = ctrl->npins;
@ -650,6 +672,7 @@ int mvebu_pinctrl_probe(struct platform_device *pdev)
gid++;
pctl->groups[gid].gid = gid;
pctl->groups[gid].ctrl = ctrl;
pctl->groups[gid].data = data;
pctl->groups[gid].name = noname_buf;
pctl->groups[gid].pins = &ctrl->pins[k];
pctl->groups[gid].npins = 1;
@ -725,3 +748,94 @@ int mvebu_pinctrl_probe(struct platform_device *pdev)
return 0;
}
/*
* mvebu_pinctrl_simple_mmio_probe - probe a simple mmio pinctrl
* @pdev: platform device (with platform data already attached)
*
* Initialise a simple (single base address) mmio pinctrl driver,
* assigning the MMIO base address to all mvebu mpp ctrl instances.
*/
int mvebu_pinctrl_simple_mmio_probe(struct platform_device *pdev)
{
struct mvebu_pinctrl_soc_info *soc = dev_get_platdata(&pdev->dev);
struct mvebu_mpp_ctrl_data *mpp_data;
struct resource *res;
void __iomem *base;
int i;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(base))
return PTR_ERR(base);
mpp_data = devm_kcalloc(&pdev->dev, soc->ncontrols, sizeof(*mpp_data),
GFP_KERNEL);
if (!mpp_data)
return -ENOMEM;
for (i = 0; i < soc->ncontrols; i++)
mpp_data[i].base = base;
soc->control_data = mpp_data;
return mvebu_pinctrl_probe(pdev);
}
int mvebu_regmap_mpp_ctrl_get(struct mvebu_mpp_ctrl_data *data,
unsigned int pid, unsigned long *config)
{
unsigned off = (pid / MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;
unsigned shift = (pid % MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;
unsigned int val;
int err;
err = regmap_read(data->regmap.map, data->regmap.offset + off, &val);
if (err)
return err;
*config = (val >> shift) & MVEBU_MPP_MASK;
return 0;
}
int mvebu_regmap_mpp_ctrl_set(struct mvebu_mpp_ctrl_data *data,
unsigned int pid, unsigned long config)
{
unsigned off = (pid / MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;
unsigned shift = (pid % MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;
return regmap_update_bits(data->regmap.map, data->regmap.offset + off,
MVEBU_MPP_MASK << shift, config << shift);
}
int mvebu_pinctrl_simple_regmap_probe(struct platform_device *pdev,
struct device *syscon_dev)
{
struct mvebu_pinctrl_soc_info *soc = dev_get_platdata(&pdev->dev);
struct mvebu_mpp_ctrl_data *mpp_data;
struct regmap *regmap;
u32 offset;
int i;
regmap = syscon_node_to_regmap(syscon_dev->of_node);
if (IS_ERR(regmap))
return PTR_ERR(regmap);
if (of_property_read_u32(pdev->dev.of_node, "offset", &offset))
return -EINVAL;
mpp_data = devm_kcalloc(&pdev->dev, soc->ncontrols, sizeof(*mpp_data),
GFP_KERNEL);
if (!mpp_data)
return -ENOMEM;
for (i = 0; i < soc->ncontrols; i++) {
mpp_data[i].regmap.map = regmap;
mpp_data[i].regmap.offset = offset;
}
soc->control_data = mpp_data;
return mvebu_pinctrl_probe(pdev);
}

View File

@ -13,6 +13,22 @@
#ifndef __PINCTRL_MVEBU_H__
#define __PINCTRL_MVEBU_H__
/**
* struct mvebu_mpp_ctrl_data - private data for the mpp ctrl operations
* @base: base address of pinctrl hardware
* @regmap.map: regmap structure
* @regmap.offset: regmap offset
*/
struct mvebu_mpp_ctrl_data {
union {
void __iomem *base;
struct {
struct regmap *map;
u32 offset;
} regmap;
};
};
/**
* struct mvebu_mpp_ctrl - describe a mpp control
* @name: name of the control group
@ -37,10 +53,13 @@ struct mvebu_mpp_ctrl {
u8 pid;
u8 npins;
unsigned *pins;
int (*mpp_get)(unsigned pid, unsigned long *config);
int (*mpp_set)(unsigned pid, unsigned long config);
int (*mpp_gpio_req)(unsigned pid);
int (*mpp_gpio_dir)(unsigned pid, bool input);
int (*mpp_get)(struct mvebu_mpp_ctrl_data *data, unsigned pid,
unsigned long *config);
int (*mpp_set)(struct mvebu_mpp_ctrl_data *data, unsigned pid,
unsigned long config);
int (*mpp_gpio_req)(struct mvebu_mpp_ctrl_data *data, unsigned pid);
int (*mpp_gpio_dir)(struct mvebu_mpp_ctrl_data *data, unsigned pid,
bool input);
};
/**
@ -93,6 +112,7 @@ struct mvebu_mpp_mode {
* struct mvebu_pinctrl_soc_info - SoC specific info passed to pinctrl-mvebu
* @variant: variant mask of soc_info
* @controls: list of available mvebu_mpp_ctrls
* @control_data: optional array, one entry for each control
* @ncontrols: number of available mvebu_mpp_ctrls
* @modes: list of available mvebu_mpp_modes
* @nmodes: number of available mvebu_mpp_modes
@ -105,7 +125,8 @@ struct mvebu_mpp_mode {
*/
struct mvebu_pinctrl_soc_info {
u8 variant;
struct mvebu_mpp_ctrl *controls;
const struct mvebu_mpp_ctrl *controls;
struct mvebu_mpp_ctrl_data *control_data;
int ncontrols;
struct mvebu_mpp_mode *modes;
int nmodes;
@ -177,30 +198,18 @@ struct mvebu_pinctrl_soc_info {
#define MVEBU_MPP_BITS 4
#define MVEBU_MPP_MASK 0xf
static inline int default_mpp_ctrl_get(void __iomem *base, unsigned int pid,
unsigned long *config)
{
unsigned off = (pid / MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;
unsigned shift = (pid % MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;
*config = (readl(base + off) >> shift) & MVEBU_MPP_MASK;
return 0;
}
static inline int default_mpp_ctrl_set(void __iomem *base, unsigned int pid,
unsigned long config)
{
unsigned off = (pid / MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;
unsigned shift = (pid % MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;
unsigned long reg;
reg = readl(base + off) & ~(MVEBU_MPP_MASK << shift);
writel(reg | (config << shift), base + off);
return 0;
}
int mvebu_mmio_mpp_ctrl_get(struct mvebu_mpp_ctrl_data *data, unsigned pid,
unsigned long *config);
int mvebu_mmio_mpp_ctrl_set(struct mvebu_mpp_ctrl_data *data, unsigned pid,
unsigned long config);
int mvebu_regmap_mpp_ctrl_get(struct mvebu_mpp_ctrl_data *data, unsigned pid,
unsigned long *config);
int mvebu_regmap_mpp_ctrl_set(struct mvebu_mpp_ctrl_data *data, unsigned pid,
unsigned long config);
int mvebu_pinctrl_probe(struct platform_device *pdev);
int mvebu_pinctrl_simple_mmio_probe(struct platform_device *pdev);
int mvebu_pinctrl_simple_regmap_probe(struct platform_device *pdev,
struct device *syscon_dev);
#endif

View File

@ -20,7 +20,6 @@
#include <linux/err.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <linux/of.h>
@ -32,7 +31,8 @@
static void __iomem *mpp_base;
static void __iomem *high_mpp_base;
static int orion_mpp_ctrl_get(unsigned pid, unsigned long *config)
static int orion_mpp_ctrl_get(struct mvebu_mpp_ctrl_data *data,
unsigned pid, unsigned long *config)
{
unsigned shift = (pid % MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;
@ -47,7 +47,8 @@ static int orion_mpp_ctrl_get(unsigned pid, unsigned long *config)
return 0;
}
static int orion_mpp_ctrl_set(unsigned pid, unsigned long config)
static int orion_mpp_ctrl_set(struct mvebu_mpp_ctrl_data *data,
unsigned pid, unsigned long config)
{
unsigned shift = (pid % MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;
@ -161,7 +162,7 @@ static struct mvebu_mpp_mode orion_mpp_modes[] = {
MPP_VAR_FUNCTION(0x5, "gpio", NULL, V_5182)),
};
static struct mvebu_mpp_ctrl orion_mpp_controls[] = {
static const struct mvebu_mpp_ctrl orion_mpp_controls[] = {
MPP_FUNC_CTRL(0, 19, NULL, orion_mpp_ctrl),
};
@ -247,9 +248,4 @@ static struct platform_driver orion_pinctrl_driver = {
},
.probe = orion_pinctrl_probe,
};
module_platform_driver(orion_pinctrl_driver);
MODULE_AUTHOR("Thomas Petazzoni <thomas.petazzoni@free-electrons.com>");
MODULE_DESCRIPTION("Marvell Orion pinctrl driver");
MODULE_LICENSE("GPL v2");
builtin_platform_driver(orion_pinctrl_driver);

View File

@ -200,6 +200,18 @@ int pinconf_apply_setting(struct pinctrl_setting const *setting)
return 0;
}
int pinconf_set_config(struct pinctrl_dev *pctldev, unsigned pin,
unsigned long *configs, size_t nconfigs)
{
const struct pinconf_ops *ops;
ops = pctldev->desc->confops;
if (!ops)
return -ENOTSUPP;
return ops->pin_config_set(pctldev, pin, configs, nconfigs);
}
#ifdef CONFIG_DEBUG_FS
static void pinconf_show_config(struct seq_file *s, struct pinctrl_dev *pctldev,

View File

@ -20,6 +20,9 @@ int pinconf_map_to_setting(struct pinctrl_map const *map,
void pinconf_free_setting(struct pinctrl_setting const *setting);
int pinconf_apply_setting(struct pinctrl_setting const *setting);
int pinconf_set_config(struct pinctrl_dev *pctldev, unsigned pin,
unsigned long *configs, size_t nconfigs);
/*
* You will only be interested in these if you're using PINCONF
* so don't supply any stubs for these.
@ -56,6 +59,12 @@ static inline int pinconf_apply_setting(struct pinctrl_setting const *setting)
return 0;
}
static inline int pinconf_set_config(struct pinctrl_dev *pctldev, unsigned pin,
unsigned long *configs, size_t nconfigs)
{
return -ENOTSUPP;
}
#endif
#if defined(CONFIG_PINCONF) && defined(CONFIG_DEBUG_FS)

View File

@ -164,6 +164,18 @@ static int amd_gpio_set_debounce(struct gpio_chip *gc, unsigned offset,
return ret;
}
static int amd_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 amd_gpio_set_debounce(gc, offset, debounce);
}
#ifdef CONFIG_DEBUG_FS
static void amd_gpio_dbg_show(struct seq_file *s, struct gpio_chip *gc)
{
@ -186,7 +198,7 @@ static void amd_gpio_dbg_show(struct seq_file *s, struct gpio_chip *gc)
char *output_value;
char *output_enable;
for (bank = 0; bank < AMD_GPIO_TOTAL_BANKS; bank++) {
for (bank = 0; bank < gpio_dev->hwbank_num; bank++) {
seq_printf(s, "GPIO bank%d\t", bank);
switch (bank) {
@ -202,10 +214,14 @@ static void amd_gpio_dbg_show(struct seq_file *s, struct gpio_chip *gc)
i = 128;
pin_num = AMD_GPIO_PINS_BANK2 + i;
break;
case 3:
i = 192;
pin_num = AMD_GPIO_PINS_BANK3 + i;
break;
default:
return;
/* Illegal bank number, ignore */
continue;
}
for (; i < pin_num; i++) {
seq_printf(s, "pin%d\t", i);
spin_lock_irqsave(&gpio_dev->lock, flags);
@ -215,14 +231,14 @@ static void amd_gpio_dbg_show(struct seq_file *s, struct gpio_chip *gc)
if (pin_reg & BIT(INTERRUPT_ENABLE_OFF)) {
interrupt_enable = "interrupt is enabled|";
if (!(pin_reg & BIT(ACTIVE_LEVEL_OFF))
&& !(pin_reg & BIT(ACTIVE_LEVEL_OFF+1)))
if (!(pin_reg & BIT(ACTIVE_LEVEL_OFF)) &&
!(pin_reg & BIT(ACTIVE_LEVEL_OFF + 1)))
active_level = "Active low|";
else if (pin_reg & BIT(ACTIVE_LEVEL_OFF)
&& !(pin_reg & BIT(ACTIVE_LEVEL_OFF+1)))
else if (pin_reg & BIT(ACTIVE_LEVEL_OFF) &&
!(pin_reg & BIT(ACTIVE_LEVEL_OFF + 1)))
active_level = "Active high|";
else if (!(pin_reg & BIT(ACTIVE_LEVEL_OFF))
&& pin_reg & BIT(ACTIVE_LEVEL_OFF+1))
else if (!(pin_reg & BIT(ACTIVE_LEVEL_OFF)) &&
pin_reg & BIT(ACTIVE_LEVEL_OFF + 1))
active_level = "Active on both|";
else
active_level = "Unknow Active level|";
@ -246,17 +262,17 @@ static void amd_gpio_dbg_show(struct seq_file *s, struct gpio_chip *gc)
interrupt_mask =
"interrupt is masked|";
if (pin_reg & BIT(WAKE_CNTRL_OFF))
if (pin_reg & BIT(WAKE_CNTRL_OFF_S0I3))
wake_cntrl0 = "enable wakeup in S0i3 state|";
else
wake_cntrl0 = "disable wakeup in S0i3 state|";
if (pin_reg & BIT(WAKE_CNTRL_OFF))
if (pin_reg & BIT(WAKE_CNTRL_OFF_S3))
wake_cntrl1 = "enable wakeup in S3 state|";
else
wake_cntrl1 = "disable wakeup in S3 state|";
if (pin_reg & BIT(WAKE_CNTRL_OFF))
if (pin_reg & BIT(WAKE_CNTRL_OFF_S4))
wake_cntrl2 = "enable wakeup in S4/S5 state|";
else
wake_cntrl2 = "disable wakeup in S4/S5 state|";
@ -476,6 +492,7 @@ static struct irq_chip amd_gpio_irqchip = {
.irq_unmask = amd_gpio_irq_unmask,
.irq_eoi = amd_gpio_irq_eoi,
.irq_set_type = amd_gpio_irq_set_type,
.flags = IRQCHIP_SKIP_SET_WAKE,
};
static void amd_gpio_irq_handler(struct irq_desc *desc)
@ -758,18 +775,19 @@ static int amd_gpio_probe(struct platform_device *pdev)
gpio_dev->gc.direction_output = amd_gpio_direction_output;
gpio_dev->gc.get = amd_gpio_get_value;
gpio_dev->gc.set = amd_gpio_set_value;
gpio_dev->gc.set_debounce = amd_gpio_set_debounce;
gpio_dev->gc.set_config = amd_gpio_set_config;
gpio_dev->gc.dbg_show = amd_gpio_dbg_show;
gpio_dev->gc.base = 0;
gpio_dev->gc.base = -1;
gpio_dev->gc.label = pdev->name;
gpio_dev->gc.owner = THIS_MODULE;
gpio_dev->gc.parent = &pdev->dev;
gpio_dev->gc.ngpio = TOTAL_NUMBER_OF_PINS;
gpio_dev->gc.ngpio = resource_size(res) / 4;
#if defined(CONFIG_OF_GPIO)
gpio_dev->gc.of_node = pdev->dev.of_node;
#endif
gpio_dev->hwbank_num = gpio_dev->gc.ngpio / 64;
gpio_dev->groups = kerncz_groups;
gpio_dev->ngroups = ARRAY_SIZE(kerncz_groups);
@ -786,7 +804,7 @@ static int amd_gpio_probe(struct platform_device *pdev)
return ret;
ret = gpiochip_add_pin_range(&gpio_dev->gc, dev_name(&pdev->dev),
0, 0, TOTAL_NUMBER_OF_PINS);
0, 0, gpio_dev->gc.ngpio);
if (ret) {
dev_err(&pdev->dev, "Failed to add pin range\n");
goto out2;
@ -807,7 +825,6 @@ static int amd_gpio_probe(struct platform_device *pdev)
&amd_gpio_irqchip,
irq_base,
amd_gpio_irq_handler);
platform_set_drvdata(pdev, gpio_dev);
dev_dbg(&pdev->dev, "amd gpio driver loaded\n");

View File

@ -13,13 +13,12 @@
#ifndef _PINCTRL_AMD_H
#define _PINCTRL_AMD_H
#define TOTAL_NUMBER_OF_PINS 192
#define AMD_GPIO_PINS_PER_BANK 64
#define AMD_GPIO_TOTAL_BANKS 3
#define AMD_GPIO_PINS_BANK0 63
#define AMD_GPIO_PINS_BANK1 64
#define AMD_GPIO_PINS_BANK2 56
#define AMD_GPIO_PINS_BANK3 32
#define WAKE_INT_MASTER_REG 0xfc
#define EOI_MASK (1 << 29)
@ -35,7 +34,9 @@
#define ACTIVE_LEVEL_OFF 9
#define INTERRUPT_ENABLE_OFF 11
#define INTERRUPT_MASK_OFF 12
#define WAKE_CNTRL_OFF 13
#define WAKE_CNTRL_OFF_S0I3 13
#define WAKE_CNTRL_OFF_S3 14
#define WAKE_CNTRL_OFF_S4 15
#define PIN_STS_OFF 16
#define DRV_STRENGTH_SEL_OFF 17
#define PULL_UP_SEL_OFF 19
@ -93,6 +94,7 @@ struct amd_gpio {
u32 ngroups;
struct pinctrl_dev *pctrl;
struct gpio_chip gc;
unsigned int hwbank_num;
struct resource *res;
struct platform_device *pdev;
};

View File

@ -113,7 +113,6 @@ static int da850_pupd_pin_config_group_set(struct pinctrl_dev *pctldev,
struct da850_pupd_data *data = pinctrl_dev_get_drvdata(pctldev);
u32 ena, sel;
enum pin_config_param param;
u16 arg;
int i;
ena = readl(data->base + DA850_PUPD_ENA);
@ -121,7 +120,6 @@ static int da850_pupd_pin_config_group_set(struct pinctrl_dev *pctldev,
for (i = 0; i < num_configs; i++) {
param = pinconf_to_config_param(configs[i]);
arg = pinconf_to_config_argument(configs[i]);
switch (param) {
case PIN_CONFIG_BIAS_DISABLE:
@ -194,6 +192,7 @@ static const struct of_device_id da850_pupd_of_match[] = {
{ .compatible = "ti,da850-pupd" },
{ }
};
MODULE_DEVICE_TABLE(of, da850_pupd_of_match);
static struct platform_driver da850_pupd_driver = {
.driver = {

View File

@ -7,7 +7,7 @@
* by the Free Software Foundation.
*
* Copyright (C) 2012 Thomas Langer <thomas.langer@lantiq.com>
* Copyright (C) 2012 John Crispin <blogic@openwrt.org>
* Copyright (C) 2012 John Crispin <john@phrozen.org>
*/
#include <linux/gpio.h>

View File

@ -6,7 +6,7 @@
* it under the terms of the GNU General Public License version 2 as
* publishhed by the Free Software Foundation.
*
* Copyright (C) 2012 John Crispin <blogic@openwrt.org>
* Copyright (C) 2012 John Crispin <john@phrozen.org>
*/
#include <linux/module.h>

View File

@ -6,7 +6,7 @@
* it under the terms of the GNU General Public License version 2 as
* publishhed by the Free Software Foundation.
*
* Copyright (C) 2012 John Crispin <blogic@openwrt.org>
* Copyright (C) 2012 John Crispin <john@phrozen.org>
*/
#ifndef __PINCTRL_LANTIQ_H

View File

@ -904,7 +904,7 @@ static int lpc18xx_pconf_get(struct pinctrl_dev *pctldev, unsigned pin,
static int lpc18xx_pconf_set_usb1(struct pinctrl_dev *pctldev,
enum pin_config_param param,
u16 param_val, u32 *reg)
u32 param_val, u32 *reg)
{
switch (param) {
case PIN_CONFIG_LOW_POWER_MODE:
@ -932,7 +932,7 @@ static int lpc18xx_pconf_set_usb1(struct pinctrl_dev *pctldev,
static int lpc18xx_pconf_set_i2c0(struct pinctrl_dev *pctldev,
enum pin_config_param param,
u16 param_val, u32 *reg,
u32 param_val, u32 *reg,
unsigned pin)
{
u8 shift;
@ -982,7 +982,7 @@ static int lpc18xx_pconf_set_i2c0(struct pinctrl_dev *pctldev,
}
static int lpc18xx_pconf_set_gpio_pin_int(struct pinctrl_dev *pctldev,
u16 param_val, unsigned pin)
u32 param_val, unsigned pin)
{
struct lpc18xx_scu_data *scu = pinctrl_dev_get_drvdata(pctldev);
u32 val, reg_val, reg_offset = LPC18XX_SCU_PINTSEL0;
@ -1008,7 +1008,7 @@ static int lpc18xx_pconf_set_gpio_pin_int(struct pinctrl_dev *pctldev,
}
static int lpc18xx_pconf_set_pin(struct pinctrl_dev *pctldev, unsigned param,
u16 param_val, u32 *reg, unsigned pin,
u32 param_val, u32 *reg, unsigned pin,
struct lpc18xx_pin_caps *pin_cap)
{
switch (param) {
@ -1088,7 +1088,7 @@ static int lpc18xx_pconf_set(struct pinctrl_dev *pctldev, unsigned pin,
struct lpc18xx_scu_data *scu = pinctrl_dev_get_drvdata(pctldev);
struct lpc18xx_pin_caps *pin_cap;
enum pin_config_param param;
u16 param_val;
u32 param_val;
u32 reg;
int ret;
int i;

View File

@ -402,7 +402,7 @@ static int max77620_pinconf_set(struct pinctrl_dev *pctldev,
struct device *dev = mpci->dev;
struct max77620_fps_config *fps_config;
int param;
u16 param_val;
u32 param_val;
unsigned int val;
unsigned int pu_val;
unsigned int pd_val;

View File

@ -860,7 +860,7 @@ static int palmas_pinconf_set(struct pinctrl_dev *pctldev,
{
struct palmas_pctrl_chip_info *pci = pinctrl_dev_get_drvdata(pctldev);
enum pin_config_param param;
u16 param_val;
u32 param_val;
const struct palmas_pingroup *g;
const struct palmas_pin_info *opt;
int ret;

View File

@ -1441,7 +1441,7 @@ static int rockchip_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
struct rockchip_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
struct rockchip_pin_bank *bank = pin_to_bank(info, pin);
enum pin_config_param param;
u16 arg;
u32 arg;
int i;
int rc;

View File

@ -33,26 +33,11 @@
#include "core.h"
#include "devicetree.h"
#include "pinconf.h"
#include "pinmux.h"
#define DRIVER_NAME "pinctrl-single"
#define PCS_OFF_DISABLED ~0U
/**
* struct pcs_pingroup - pingroups for a function
* @np: pingroup device node pointer
* @name: pingroup name
* @gpins: array of the pins in the group
* @ngpins: number of pins in the group
* @node: list node
*/
struct pcs_pingroup {
struct device_node *np;
const char *name;
int *gpins;
int ngpins;
struct list_head node;
};
/**
* struct pcs_func_vals - mux function register offset and value pair
* @reg: register virtual address
@ -176,16 +161,10 @@ struct pcs_soc_data {
* @bits_per_mux: number of bits per mux
* @bits_per_pin: number of bits per pin
* @pins: physical pins on the SoC
* @pgtree: pingroup index radix tree
* @ftree: function index radix tree
* @pingroups: list of pingroups
* @functions: list of functions
* @gpiofuncs: list of gpio functions
* @irqs: list of interrupt registers
* @chip: chip container for this instance
* @domain: IRQ domain for this instance
* @ngroups: number of pingroups
* @nfuncs: number of functions
* @desc: pin controller descriptor
* @read: register read function to use
* @write: register write function to use
@ -213,16 +192,10 @@ struct pcs_device {
bool bits_per_mux;
unsigned bits_per_pin;
struct pcs_data pins;
struct radix_tree_root pgtree;
struct radix_tree_root ftree;
struct list_head pingroups;
struct list_head functions;
struct list_head gpiofuncs;
struct list_head irqs;
struct irq_chip chip;
struct irq_domain *domain;
unsigned ngroups;
unsigned nfuncs;
struct pinctrl_desc desc;
unsigned (*read)(void __iomem *reg);
void (*write)(unsigned val, void __iomem *reg);
@ -288,54 +261,6 @@ static void __maybe_unused pcs_writel(unsigned val, void __iomem *reg)
writel(val, reg);
}
static int pcs_get_groups_count(struct pinctrl_dev *pctldev)
{
struct pcs_device *pcs;
pcs = pinctrl_dev_get_drvdata(pctldev);
return pcs->ngroups;
}
static const char *pcs_get_group_name(struct pinctrl_dev *pctldev,
unsigned gselector)
{
struct pcs_device *pcs;
struct pcs_pingroup *group;
pcs = pinctrl_dev_get_drvdata(pctldev);
group = radix_tree_lookup(&pcs->pgtree, gselector);
if (!group) {
dev_err(pcs->dev, "%s could not find pingroup%i\n",
__func__, gselector);
return NULL;
}
return group->name;
}
static int pcs_get_group_pins(struct pinctrl_dev *pctldev,
unsigned gselector,
const unsigned **pins,
unsigned *npins)
{
struct pcs_device *pcs;
struct pcs_pingroup *group;
pcs = pinctrl_dev_get_drvdata(pctldev);
group = radix_tree_lookup(&pcs->pgtree, gselector);
if (!group) {
dev_err(pcs->dev, "%s could not find pingroup%i\n",
__func__, gselector);
return -EINVAL;
}
*pins = group->gpins;
*npins = group->ngpins;
return 0;
}
static void pcs_pin_dbg_show(struct pinctrl_dev *pctldev,
struct seq_file *s,
unsigned pin)
@ -369,67 +294,21 @@ static int pcs_dt_node_to_map(struct pinctrl_dev *pctldev,
struct pinctrl_map **map, unsigned *num_maps);
static const struct pinctrl_ops pcs_pinctrl_ops = {
.get_groups_count = pcs_get_groups_count,
.get_group_name = pcs_get_group_name,
.get_group_pins = pcs_get_group_pins,
.get_groups_count = pinctrl_generic_get_group_count,
.get_group_name = pinctrl_generic_get_group_name,
.get_group_pins = pinctrl_generic_get_group_pins,
.pin_dbg_show = pcs_pin_dbg_show,
.dt_node_to_map = pcs_dt_node_to_map,
.dt_free_map = pcs_dt_free_map,
};
static int pcs_get_functions_count(struct pinctrl_dev *pctldev)
{
struct pcs_device *pcs;
pcs = pinctrl_dev_get_drvdata(pctldev);
return pcs->nfuncs;
}
static const char *pcs_get_function_name(struct pinctrl_dev *pctldev,
unsigned fselector)
{
struct pcs_device *pcs;
struct pcs_function *func;
pcs = pinctrl_dev_get_drvdata(pctldev);
func = radix_tree_lookup(&pcs->ftree, fselector);
if (!func) {
dev_err(pcs->dev, "%s could not find function%i\n",
__func__, fselector);
return NULL;
}
return func->name;
}
static int pcs_get_function_groups(struct pinctrl_dev *pctldev,
unsigned fselector,
const char * const **groups,
unsigned * const ngroups)
{
struct pcs_device *pcs;
struct pcs_function *func;
pcs = pinctrl_dev_get_drvdata(pctldev);
func = radix_tree_lookup(&pcs->ftree, fselector);
if (!func) {
dev_err(pcs->dev, "%s could not find function%i\n",
__func__, fselector);
return -EINVAL;
}
*groups = func->pgnames;
*ngroups = func->npgnames;
return 0;
}
static int pcs_get_function(struct pinctrl_dev *pctldev, unsigned pin,
struct pcs_function **func)
{
struct pcs_device *pcs = pinctrl_dev_get_drvdata(pctldev);
struct pin_desc *pdesc = pin_desc_get(pctldev, pin);
const struct pinctrl_setting_mux *setting;
struct function_desc *function;
unsigned fselector;
/* If pin is not described in DTS & enabled, mux_setting is NULL. */
@ -437,7 +316,8 @@ static int pcs_get_function(struct pinctrl_dev *pctldev, unsigned pin,
if (!setting)
return -ENOTSUPP;
fselector = setting->func;
*func = radix_tree_lookup(&pcs->ftree, fselector);
function = pinmux_generic_get_function(pctldev, fselector);
*func = function->data;
if (!(*func)) {
dev_err(pcs->dev, "%s could not find function%i\n",
__func__, fselector);
@ -450,6 +330,7 @@ static int pcs_set_mux(struct pinctrl_dev *pctldev, unsigned fselector,
unsigned group)
{
struct pcs_device *pcs;
struct function_desc *function;
struct pcs_function *func;
int i;
@ -457,7 +338,8 @@ static int pcs_set_mux(struct pinctrl_dev *pctldev, unsigned fselector,
/* If function mask is null, needn't enable it. */
if (!pcs->fmask)
return 0;
func = radix_tree_lookup(&pcs->ftree, fselector);
function = pinmux_generic_get_function(pctldev, fselector);
func = function->data;
if (!func)
return -EINVAL;
@ -515,9 +397,9 @@ static int pcs_request_gpio(struct pinctrl_dev *pctldev,
}
static const struct pinmux_ops pcs_pinmux_ops = {
.get_functions_count = pcs_get_functions_count,
.get_function_name = pcs_get_function_name,
.get_function_groups = pcs_get_function_groups,
.get_functions_count = pinmux_generic_get_function_count,
.get_function_name = pinmux_generic_get_function_name,
.get_function_groups = pinmux_generic_get_function_groups,
.set_mux = pcs_set_mux,
.gpio_request_enable = pcs_request_gpio,
};
@ -622,7 +504,7 @@ static int pcs_pinconf_set(struct pinctrl_dev *pctldev,
struct pcs_device *pcs = pinctrl_dev_get_drvdata(pctldev);
struct pcs_function *func;
unsigned offset = 0, shift = 0, i, data, ret;
u16 arg;
u32 arg;
int j;
ret = pcs_get_function(pctldev, pin, &func);
@ -685,7 +567,7 @@ static int pcs_pinconf_group_get(struct pinctrl_dev *pctldev,
unsigned npins, old = 0;
int i, ret;
ret = pcs_get_group_pins(pctldev, group, &pins, &npins);
ret = pinctrl_generic_get_group_pins(pctldev, group, &pins, &npins);
if (ret)
return ret;
for (i = 0; i < npins; i++) {
@ -707,7 +589,7 @@ static int pcs_pinconf_group_set(struct pinctrl_dev *pctldev,
unsigned npins;
int i, ret;
ret = pcs_get_group_pins(pctldev, group, &pins, &npins);
ret = pinctrl_generic_get_group_pins(pctldev, group, &pins, &npins);
if (ret)
return ret;
for (i = 0; i < npins; i++) {
@ -859,77 +741,24 @@ static struct pcs_function *pcs_add_function(struct pcs_device *pcs,
unsigned npgnames)
{
struct pcs_function *function;
int res;
function = devm_kzalloc(pcs->dev, sizeof(*function), GFP_KERNEL);
if (!function)
return NULL;
function->name = name;
function->vals = vals;
function->nvals = nvals;
function->pgnames = pgnames;
function->npgnames = npgnames;
mutex_lock(&pcs->mutex);
list_add_tail(&function->node, &pcs->functions);
radix_tree_insert(&pcs->ftree, pcs->nfuncs, function);
pcs->nfuncs++;
mutex_unlock(&pcs->mutex);
res = pinmux_generic_add_function(pcs->pctl, name,
pgnames, npgnames,
function);
if (res)
return NULL;
return function;
}
static void pcs_remove_function(struct pcs_device *pcs,
struct pcs_function *function)
{
int i;
mutex_lock(&pcs->mutex);
for (i = 0; i < pcs->nfuncs; i++) {
struct pcs_function *found;
found = radix_tree_lookup(&pcs->ftree, i);
if (found == function)
radix_tree_delete(&pcs->ftree, i);
}
list_del(&function->node);
mutex_unlock(&pcs->mutex);
}
/**
* pcs_add_pingroup() - add a pingroup to the pingroup list
* @pcs: pcs driver instance
* @np: device node of the mux entry
* @name: name of the pingroup
* @gpins: array of the pins that belong to the group
* @ngpins: number of pins in the group
*/
static int pcs_add_pingroup(struct pcs_device *pcs,
struct device_node *np,
const char *name,
int *gpins,
int ngpins)
{
struct pcs_pingroup *pingroup;
pingroup = devm_kzalloc(pcs->dev, sizeof(*pingroup), GFP_KERNEL);
if (!pingroup)
return -ENOMEM;
pingroup->name = name;
pingroup->np = np;
pingroup->gpins = gpins;
pingroup->ngpins = ngpins;
mutex_lock(&pcs->mutex);
list_add_tail(&pingroup->node, &pcs->pingroups);
radix_tree_insert(&pcs->pgtree, pcs->ngroups, pingroup);
pcs->ngroups++;
mutex_unlock(&pcs->mutex);
return 0;
}
/**
* pcs_get_pin_by_offset() - get a pin index based on the register offset
* @pcs: pcs driver instance
@ -1100,10 +929,9 @@ static int pcs_parse_pinconf(struct pcs_device *pcs, struct device_node *np,
return 0;
}
static void pcs_free_pingroups(struct pcs_device *pcs);
/**
* smux_parse_one_pinctrl_entry() - parses a device tree mux entry
* @pctldev: pin controller device
* @pcs: pinctrl driver instance
* @np: device node of the mux entry
* @map: map entry
@ -1134,7 +962,7 @@ static int pcs_parse_one_pinctrl_entry(struct pcs_device *pcs,
rows = pinctrl_count_index_with_args(np, name);
if (rows <= 0) {
dev_err(pcs->dev, "Ivalid number of rows: %d\n", rows);
dev_err(pcs->dev, "Invalid number of rows: %d\n", rows);
return -EINVAL;
}
@ -1186,7 +1014,7 @@ static int pcs_parse_one_pinctrl_entry(struct pcs_device *pcs,
goto free_pins;
}
res = pcs_add_pingroup(pcs, np, np->name, pins, found);
res = pinctrl_generic_add_group(pcs->pctl, np->name, pins, found, pcs);
if (res < 0)
goto free_function;
@ -1205,10 +1033,10 @@ static int pcs_parse_one_pinctrl_entry(struct pcs_device *pcs,
return 0;
free_pingroups:
pcs_free_pingroups(pcs);
pinctrl_generic_remove_last_group(pcs->pctl);
*num_maps = 1;
free_function:
pcs_remove_function(pcs, function);
pinmux_generic_remove_last_function(pcs->pctl);
free_pins:
devm_kfree(pcs->dev, pins);
@ -1320,7 +1148,7 @@ static int pcs_parse_bits_in_pinctrl_entry(struct pcs_device *pcs,
goto free_pins;
}
res = pcs_add_pingroup(pcs, np, np->name, pins, found);
res = pinctrl_generic_add_group(pcs->pctl, np->name, pins, found, pcs);
if (res < 0)
goto free_function;
@ -1337,11 +1165,10 @@ static int pcs_parse_bits_in_pinctrl_entry(struct pcs_device *pcs,
return 0;
free_pingroups:
pcs_free_pingroups(pcs);
pinctrl_generic_remove_last_group(pcs->pctl);
*num_maps = 1;
free_function:
pcs_remove_function(pcs, function);
pinmux_generic_remove_last_function(pcs->pctl);
free_pins:
devm_kfree(pcs->dev, pins);
@ -1408,60 +1235,6 @@ free_map:
return ret;
}
/**
* pcs_free_funcs() - free memory used by functions
* @pcs: pcs driver instance
*/
static void pcs_free_funcs(struct pcs_device *pcs)
{
struct list_head *pos, *tmp;
int i;
mutex_lock(&pcs->mutex);
for (i = 0; i < pcs->nfuncs; i++) {
struct pcs_function *func;
func = radix_tree_lookup(&pcs->ftree, i);
if (!func)
continue;
radix_tree_delete(&pcs->ftree, i);
}
list_for_each_safe(pos, tmp, &pcs->functions) {
struct pcs_function *function;
function = list_entry(pos, struct pcs_function, node);
list_del(&function->node);
}
mutex_unlock(&pcs->mutex);
}
/**
* pcs_free_pingroups() - free memory used by pingroups
* @pcs: pcs driver instance
*/
static void pcs_free_pingroups(struct pcs_device *pcs)
{
struct list_head *pos, *tmp;
int i;
mutex_lock(&pcs->mutex);
for (i = 0; i < pcs->ngroups; i++) {
struct pcs_pingroup *pingroup;
pingroup = radix_tree_lookup(&pcs->pgtree, i);
if (!pingroup)
continue;
radix_tree_delete(&pcs->pgtree, i);
}
list_for_each_safe(pos, tmp, &pcs->pingroups) {
struct pcs_pingroup *pingroup;
pingroup = list_entry(pos, struct pcs_pingroup, node);
list_del(&pingroup->node);
}
mutex_unlock(&pcs->mutex);
}
/**
* pcs_irq_free() - free interrupt
* @pcs: pcs driver instance
@ -1490,8 +1263,7 @@ static void pcs_free_resources(struct pcs_device *pcs)
{
pcs_irq_free(pcs);
pinctrl_unregister(pcs->pctl);
pcs_free_funcs(pcs);
pcs_free_pingroups(pcs);
#if IS_BUILTIN(CONFIG_PINCTRL_SINGLE)
if (pcs->missing_nr_pinctrl_cells)
of_remove_property(pcs->np, pcs->missing_nr_pinctrl_cells);
@ -1885,8 +1657,6 @@ static int pcs_probe(struct platform_device *pdev)
pcs->np = np;
raw_spin_lock_init(&pcs->lock);
mutex_init(&pcs->mutex);
INIT_LIST_HEAD(&pcs->pingroups);
INIT_LIST_HEAD(&pcs->functions);
INIT_LIST_HEAD(&pcs->gpiofuncs);
soc = match->data;
pcs->flags = soc->flags;
@ -1947,8 +1717,6 @@ static int pcs_probe(struct platform_device *pdev)
return -ENODEV;
}
INIT_RADIX_TREE(&pcs->pgtree, GFP_KERNEL);
INIT_RADIX_TREE(&pcs->ftree, GFP_KERNEL);
platform_set_drvdata(pdev, pcs);
switch (pcs->width) {
@ -1979,10 +1747,9 @@ static int pcs_probe(struct platform_device *pdev)
if (ret < 0)
goto free;
pcs->pctl = pinctrl_register(&pcs->desc, pcs->dev, pcs);
if (IS_ERR(pcs->pctl)) {
ret = pinctrl_register_and_init(&pcs->desc, pcs->dev, pcs, &pcs->pctl);
if (ret) {
dev_err(pcs->dev, "could not register single pinctrl driver\n");
ret = PTR_ERR(pcs->pctl);
goto free;
}

View File

@ -424,41 +424,6 @@ static int sx150x_gpio_get(struct gpio_chip *chip, unsigned int offset)
return !!(value & BIT(offset));
}
static int sx150x_gpio_set_single_ended(struct gpio_chip *chip,
unsigned int offset,
enum single_ended_mode mode)
{
struct sx150x_pinctrl *pctl = gpiochip_get_data(chip);
int ret;
switch (mode) {
case LINE_MODE_PUSH_PULL:
if (pctl->data->model != SX150X_789 ||
sx150x_pin_is_oscio(pctl, offset))
return 0;
ret = regmap_write_bits(pctl->regmap,
pctl->data->pri.x789.reg_drain,
BIT(offset), 0);
break;
case LINE_MODE_OPEN_DRAIN:
if (pctl->data->model != SX150X_789 ||
sx150x_pin_is_oscio(pctl, offset))
return -ENOTSUPP;
ret = regmap_write_bits(pctl->regmap,
pctl->data->pri.x789.reg_drain,
BIT(offset), BIT(offset));
break;
default:
ret = -ENOTSUPP;
break;
}
return ret;
}
static int __sx150x_gpio_set(struct sx150x_pinctrl *pctl, unsigned int offset,
int value)
{
@ -811,16 +776,26 @@ static int sx150x_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
break;
case PIN_CONFIG_DRIVE_OPEN_DRAIN:
ret = sx150x_gpio_set_single_ended(&pctl->gpio,
pin, LINE_MODE_OPEN_DRAIN);
if (pctl->data->model != SX150X_789 ||
sx150x_pin_is_oscio(pctl, pin))
return -ENOTSUPP;
ret = regmap_write_bits(pctl->regmap,
pctl->data->pri.x789.reg_drain,
BIT(pin), BIT(pin));
if (ret < 0)
return ret;
break;
case PIN_CONFIG_DRIVE_PUSH_PULL:
ret = sx150x_gpio_set_single_ended(&pctl->gpio,
pin, LINE_MODE_PUSH_PULL);
if (pctl->data->model != SX150X_789 ||
sx150x_pin_is_oscio(pctl, pin))
return 0;
ret = regmap_write_bits(pctl->regmap,
pctl->data->pri.x789.reg_drain,
BIT(pin), 0);
if (ret < 0)
return ret;
@ -1178,7 +1153,7 @@ static int sx150x_probe(struct i2c_client *client,
pctl->gpio.direction_output = sx150x_gpio_direction_output;
pctl->gpio.get = sx150x_gpio_get;
pctl->gpio.set = sx150x_gpio_set;
pctl->gpio.set_single_ended = sx150x_gpio_set_single_ended;
pctl->gpio.set_config = gpiochip_generic_config;
pctl->gpio.parent = dev;
#ifdef CONFIG_OF_GPIO
pctl->gpio.of_node = dev->of_node;

View File

@ -6,7 +6,7 @@
* it under the terms of the GNU General Public License version 2 as
* publishhed by the Free Software Foundation.
*
* Copyright (C) 2012 John Crispin <blogic@openwrt.org>
* Copyright (C) 2012 John Crispin <john@phrozen.org>
* Copyright (C) 2015 Martin Schiller <mschiller@tdt.de>
*/

View File

@ -99,37 +99,24 @@ static int pin_request(struct pinctrl_dev *pctldev,
dev_dbg(pctldev->dev, "request pin %d (%s) for %s\n",
pin, desc->name, owner);
if (gpio_range) {
/* There's no need to support multiple GPIO requests */
if (desc->gpio_owner) {
dev_err(pctldev->dev,
"pin %s already requested by %s; cannot claim for %s\n",
desc->name, desc->gpio_owner, owner);
goto out;
}
if (ops->strict && desc->mux_usecount &&
strcmp(desc->mux_owner, owner)) {
dev_err(pctldev->dev,
"pin %s already requested by %s; cannot claim for %s\n",
desc->name, desc->mux_owner, owner);
goto out;
}
if ((!gpio_range || ops->strict) &&
desc->mux_usecount && strcmp(desc->mux_owner, owner)) {
dev_err(pctldev->dev,
"pin %s already requested by %s; cannot claim for %s\n",
desc->name, desc->mux_owner, owner);
goto out;
}
if ((gpio_range || ops->strict) && desc->gpio_owner) {
dev_err(pctldev->dev,
"pin %s already requested by %s; cannot claim for %s\n",
desc->name, desc->gpio_owner, owner);
goto out;
}
if (gpio_range) {
desc->gpio_owner = owner;
} else {
if (desc->mux_usecount && strcmp(desc->mux_owner, owner)) {
dev_err(pctldev->dev,
"pin %s already requested by %s; cannot claim for %s\n",
desc->name, desc->mux_owner, owner);
goto out;
}
if (ops->strict && desc->gpio_owner) {
dev_err(pctldev->dev,
"pin %s already requested by %s; cannot claim for %s\n",
desc->name, desc->gpio_owner, owner);
goto out;
}
desc->mux_usecount++;
if (desc->mux_usecount > 1)
return 0;
@ -695,3 +682,176 @@ void pinmux_init_device_debugfs(struct dentry *devroot,
}
#endif /* CONFIG_DEBUG_FS */
#ifdef CONFIG_GENERIC_PINMUX_FUNCTIONS
/**
* pinmux_generic_get_function_count() - returns number of functions
* @pctldev: pin controller device
*/
int pinmux_generic_get_function_count(struct pinctrl_dev *pctldev)
{
return pctldev->num_functions;
}
EXPORT_SYMBOL_GPL(pinmux_generic_get_function_count);
/**
* pinmux_generic_get_function_name() - returns the function name
* @pctldev: pin controller device
* @selector: function number
*/
const char *
pinmux_generic_get_function_name(struct pinctrl_dev *pctldev,
unsigned int selector)
{
struct function_desc *function;
function = radix_tree_lookup(&pctldev->pin_function_tree,
selector);
if (!function)
return NULL;
return function->name;
}
EXPORT_SYMBOL_GPL(pinmux_generic_get_function_name);
/**
* pinmux_generic_get_function_groups() - gets the function groups
* @pctldev: pin controller device
* @selector: function number
* @groups: array of pin groups
* @num_groups: number of pin groups
*/
int pinmux_generic_get_function_groups(struct pinctrl_dev *pctldev,
unsigned int selector,
const char * const **groups,
unsigned * const num_groups)
{
struct function_desc *function;
function = radix_tree_lookup(&pctldev->pin_function_tree,
selector);
if (!function) {
dev_err(pctldev->dev, "%s could not find function%i\n",
__func__, selector);
return -EINVAL;
}
*groups = function->group_names;
*num_groups = function->num_group_names;
return 0;
}
EXPORT_SYMBOL_GPL(pinmux_generic_get_function_groups);
/**
* pinmux_generic_get_function() - returns a function based on the number
* @pctldev: pin controller device
* @group_selector: function number
*/
struct function_desc *pinmux_generic_get_function(struct pinctrl_dev *pctldev,
unsigned int selector)
{
struct function_desc *function;
function = radix_tree_lookup(&pctldev->pin_function_tree,
selector);
if (!function)
return NULL;
return function;
}
EXPORT_SYMBOL_GPL(pinmux_generic_get_function);
/**
* pinmux_generic_get_function_groups() - gets the function groups
* @pctldev: pin controller device
* @name: name of the function
* @groups: array of pin groups
* @num_groups: number of pin groups
* @data: pin controller driver specific data
*/
int pinmux_generic_add_function(struct pinctrl_dev *pctldev,
const char *name,
const char **groups,
const unsigned int num_groups,
void *data)
{
struct function_desc *function;
function = devm_kzalloc(pctldev->dev, sizeof(*function), GFP_KERNEL);
if (!function)
return -ENOMEM;
function->name = name;
function->group_names = groups;
function->num_group_names = num_groups;
function->data = data;
radix_tree_insert(&pctldev->pin_function_tree, pctldev->num_functions,
function);
pctldev->num_functions++;
return 0;
}
EXPORT_SYMBOL_GPL(pinmux_generic_add_function);
/**
* pinmux_generic_remove_function() - removes a numbered function
* @pctldev: pin controller device
* @selector: function number
*
* Note that the caller must take care of locking.
*/
int pinmux_generic_remove_function(struct pinctrl_dev *pctldev,
unsigned int selector)
{
struct function_desc *function;
function = radix_tree_lookup(&pctldev->pin_function_tree,
selector);
if (!function)
return -ENOENT;
radix_tree_delete(&pctldev->pin_function_tree, selector);
devm_kfree(pctldev->dev, function);
pctldev->num_functions--;
return 0;
}
EXPORT_SYMBOL_GPL(pinmux_generic_remove_function);
/**
* pinmux_generic_free_functions() - removes all functions
* @pctldev: pin controller device
*
* Note that the caller must take care of locking.
*/
void pinmux_generic_free_functions(struct pinctrl_dev *pctldev)
{
struct radix_tree_iter iter;
struct function_desc *function;
unsigned long *indices;
void **slot;
int i = 0;
indices = devm_kzalloc(pctldev->dev, sizeof(*indices) *
pctldev->num_functions, GFP_KERNEL);
if (!indices)
return;
radix_tree_for_each_slot(slot, &pctldev->pin_function_tree, &iter, 0)
indices[i++] = iter.index;
for (i = 0; i < pctldev->num_functions; i++) {
function = radix_tree_lookup(&pctldev->pin_function_tree,
indices[i]);
radix_tree_delete(&pctldev->pin_function_tree, indices[i]);
devm_kfree(pctldev->dev, function);
}
pctldev->num_functions = 0;
}
#endif /* CONFIG_GENERIC_PINMUX_FUNCTIONS */

View File

@ -111,3 +111,59 @@ static inline void pinmux_init_device_debugfs(struct dentry *devroot,
}
#endif
#ifdef CONFIG_GENERIC_PINMUX_FUNCTIONS
/**
* struct function_desc - generic function descriptor
* @name: name of the function
* @group_names: array of pin group names
* @num_group_names: number of pin group names
* @data: pin controller driver specific data
*/
struct function_desc {
const char *name;
const char **group_names;
int num_group_names;
void *data;
};
int pinmux_generic_get_function_count(struct pinctrl_dev *pctldev);
const char *
pinmux_generic_get_function_name(struct pinctrl_dev *pctldev,
unsigned int selector);
int pinmux_generic_get_function_groups(struct pinctrl_dev *pctldev,
unsigned int selector,
const char * const **groups,
unsigned * const num_groups);
struct function_desc *pinmux_generic_get_function(struct pinctrl_dev *pctldev,
unsigned int selector);
int pinmux_generic_add_function(struct pinctrl_dev *pctldev,
const char *name,
const char **groups,
unsigned const num_groups,
void *data);
int pinmux_generic_remove_function(struct pinctrl_dev *pctldev,
unsigned int selector);
static inline int
pinmux_generic_remove_last_function(struct pinctrl_dev *pctldev)
{
return pinmux_generic_remove_function(pctldev,
pctldev->num_functions - 1);
}
void pinmux_generic_free_functions(struct pinctrl_dev *pctldev);
#else
static inline void pinmux_generic_free_functions(struct pinctrl_dev *pctldev)
{
}
#endif /* CONFIG_GENERIC_PINMUX_FUNCTIONS */

View File

@ -61,7 +61,7 @@ struct msm_pinctrl {
struct notifier_block restart_nb;
int irq;
spinlock_t lock;
raw_spinlock_t lock;
DECLARE_BITMAP(dual_edge_irqs, MAX_NR_GPIO);
DECLARE_BITMAP(enabled_irqs, MAX_NR_GPIO);
@ -153,14 +153,14 @@ static int msm_pinmux_set_mux(struct pinctrl_dev *pctldev,
if (WARN_ON(i == g->nfuncs))
return -EINVAL;
spin_lock_irqsave(&pctrl->lock, flags);
raw_spin_lock_irqsave(&pctrl->lock, flags);
val = readl(pctrl->regs + g->ctl_reg);
val &= ~mask;
val |= i << g->mux_bit;
writel(val, pctrl->regs + g->ctl_reg);
spin_unlock_irqrestore(&pctrl->lock, flags);
raw_spin_unlock_irqrestore(&pctrl->lock, flags);
return 0;
}
@ -323,14 +323,14 @@ static int msm_config_group_set(struct pinctrl_dev *pctldev,
break;
case PIN_CONFIG_OUTPUT:
/* set output value */
spin_lock_irqsave(&pctrl->lock, flags);
raw_spin_lock_irqsave(&pctrl->lock, flags);
val = readl(pctrl->regs + g->io_reg);
if (arg)
val |= BIT(g->out_bit);
else
val &= ~BIT(g->out_bit);
writel(val, pctrl->regs + g->io_reg);
spin_unlock_irqrestore(&pctrl->lock, flags);
raw_spin_unlock_irqrestore(&pctrl->lock, flags);
/* enable output */
arg = 1;
@ -351,12 +351,12 @@ static int msm_config_group_set(struct pinctrl_dev *pctldev,
return -EINVAL;
}
spin_lock_irqsave(&pctrl->lock, flags);
raw_spin_lock_irqsave(&pctrl->lock, flags);
val = readl(pctrl->regs + g->ctl_reg);
val &= ~(mask << bit);
val |= arg << bit;
writel(val, pctrl->regs + g->ctl_reg);
spin_unlock_irqrestore(&pctrl->lock, flags);
raw_spin_unlock_irqrestore(&pctrl->lock, flags);
}
return 0;
@ -384,13 +384,13 @@ static int msm_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
g = &pctrl->soc->groups[offset];
spin_lock_irqsave(&pctrl->lock, flags);
raw_spin_lock_irqsave(&pctrl->lock, flags);
val = readl(pctrl->regs + g->ctl_reg);
val &= ~BIT(g->oe_bit);
writel(val, pctrl->regs + g->ctl_reg);
spin_unlock_irqrestore(&pctrl->lock, flags);
raw_spin_unlock_irqrestore(&pctrl->lock, flags);
return 0;
}
@ -404,7 +404,7 @@ static int msm_gpio_direction_output(struct gpio_chip *chip, unsigned offset, in
g = &pctrl->soc->groups[offset];
spin_lock_irqsave(&pctrl->lock, flags);
raw_spin_lock_irqsave(&pctrl->lock, flags);
val = readl(pctrl->regs + g->io_reg);
if (value)
@ -417,7 +417,7 @@ static int msm_gpio_direction_output(struct gpio_chip *chip, unsigned offset, in
val |= BIT(g->oe_bit);
writel(val, pctrl->regs + g->ctl_reg);
spin_unlock_irqrestore(&pctrl->lock, flags);
raw_spin_unlock_irqrestore(&pctrl->lock, flags);
return 0;
}
@ -443,7 +443,7 @@ static void msm_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
g = &pctrl->soc->groups[offset];
spin_lock_irqsave(&pctrl->lock, flags);
raw_spin_lock_irqsave(&pctrl->lock, flags);
val = readl(pctrl->regs + g->io_reg);
if (value)
@ -452,7 +452,7 @@ static void msm_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
val &= ~BIT(g->out_bit);
writel(val, pctrl->regs + g->io_reg);
spin_unlock_irqrestore(&pctrl->lock, flags);
raw_spin_unlock_irqrestore(&pctrl->lock, flags);
}
#ifdef CONFIG_DEBUG_FS
@ -571,7 +571,7 @@ static void msm_gpio_irq_mask(struct irq_data *d)
g = &pctrl->soc->groups[d->hwirq];
spin_lock_irqsave(&pctrl->lock, flags);
raw_spin_lock_irqsave(&pctrl->lock, flags);
val = readl(pctrl->regs + g->intr_cfg_reg);
val &= ~BIT(g->intr_enable_bit);
@ -579,7 +579,7 @@ static void msm_gpio_irq_mask(struct irq_data *d)
clear_bit(d->hwirq, pctrl->enabled_irqs);
spin_unlock_irqrestore(&pctrl->lock, flags);
raw_spin_unlock_irqrestore(&pctrl->lock, flags);
}
static void msm_gpio_irq_unmask(struct irq_data *d)
@ -592,7 +592,7 @@ static void msm_gpio_irq_unmask(struct irq_data *d)
g = &pctrl->soc->groups[d->hwirq];
spin_lock_irqsave(&pctrl->lock, flags);
raw_spin_lock_irqsave(&pctrl->lock, flags);
val = readl(pctrl->regs + g->intr_status_reg);
val &= ~BIT(g->intr_status_bit);
@ -604,7 +604,7 @@ static void msm_gpio_irq_unmask(struct irq_data *d)
set_bit(d->hwirq, pctrl->enabled_irqs);
spin_unlock_irqrestore(&pctrl->lock, flags);
raw_spin_unlock_irqrestore(&pctrl->lock, flags);
}
static void msm_gpio_irq_ack(struct irq_data *d)
@ -617,7 +617,7 @@ static void msm_gpio_irq_ack(struct irq_data *d)
g = &pctrl->soc->groups[d->hwirq];
spin_lock_irqsave(&pctrl->lock, flags);
raw_spin_lock_irqsave(&pctrl->lock, flags);
val = readl(pctrl->regs + g->intr_status_reg);
if (g->intr_ack_high)
@ -629,7 +629,7 @@ static void msm_gpio_irq_ack(struct irq_data *d)
if (test_bit(d->hwirq, pctrl->dual_edge_irqs))
msm_gpio_update_dual_edge_pos(pctrl, g, d);
spin_unlock_irqrestore(&pctrl->lock, flags);
raw_spin_unlock_irqrestore(&pctrl->lock, flags);
}
static int msm_gpio_irq_set_type(struct irq_data *d, unsigned int type)
@ -642,7 +642,7 @@ static int msm_gpio_irq_set_type(struct irq_data *d, unsigned int type)
g = &pctrl->soc->groups[d->hwirq];
spin_lock_irqsave(&pctrl->lock, flags);
raw_spin_lock_irqsave(&pctrl->lock, flags);
/*
* For hw without possibility of detecting both edges
@ -716,7 +716,7 @@ static int msm_gpio_irq_set_type(struct irq_data *d, unsigned int type)
if (test_bit(d->hwirq, pctrl->dual_edge_irqs))
msm_gpio_update_dual_edge_pos(pctrl, g, d);
spin_unlock_irqrestore(&pctrl->lock, flags);
raw_spin_unlock_irqrestore(&pctrl->lock, flags);
if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
irq_set_handler_locked(d, handle_level_irq);
@ -732,11 +732,11 @@ static int msm_gpio_irq_set_wake(struct irq_data *d, unsigned int on)
struct msm_pinctrl *pctrl = gpiochip_get_data(gc);
unsigned long flags;
spin_lock_irqsave(&pctrl->lock, flags);
raw_spin_lock_irqsave(&pctrl->lock, flags);
irq_set_irq_wake(pctrl->irq, on);
spin_unlock_irqrestore(&pctrl->lock, flags);
raw_spin_unlock_irqrestore(&pctrl->lock, flags);
return 0;
}
@ -882,7 +882,7 @@ int msm_pinctrl_probe(struct platform_device *pdev,
pctrl->soc = soc_data;
pctrl->chip = msm_gpio_template;
spin_lock_init(&pctrl->lock);
raw_spin_lock_init(&pctrl->lock);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
pctrl->regs = devm_ioremap_resource(&pdev->dev, res);

View File

@ -193,9 +193,9 @@ static const struct pinctrl_pin_desc msm8660_pins[] = {
PINCTRL_PIN(171, "GPIO_171"),
PINCTRL_PIN(172, "GPIO_172"),
PINCTRL_PIN(173, "SDC1_CLK"),
PINCTRL_PIN(174, "SDC1_CMD"),
PINCTRL_PIN(175, "SDC1_DATA"),
PINCTRL_PIN(173, "SDC4_CLK"),
PINCTRL_PIN(174, "SDC4_CMD"),
PINCTRL_PIN(175, "SDC4_DATA"),
PINCTRL_PIN(176, "SDC3_CLK"),
PINCTRL_PIN(177, "SDC3_CMD"),
PINCTRL_PIN(178, "SDC3_DATA"),

View File

@ -24,11 +24,15 @@
#include <linux/irqdomain.h>
#include <linux/irq.h>
#include <linux/irqchip/chained_irq.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/io.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/regmap.h>
#include <linux/err.h>
#include <linux/soc/samsung/exynos-pmu.h>
#include <linux/soc/samsung/exynos-regs-pmu.h>
#include "pinctrl-samsung.h"
#include "pinctrl-exynos.h"
@ -528,10 +532,8 @@ static int exynos_eint_wkup_init(struct samsung_pinctrl_drv_data *d)
weint_data = devm_kzalloc(dev, bank->nr_pins
* sizeof(*weint_data), GFP_KERNEL);
if (!weint_data) {
dev_err(dev, "could not allocate memory for weint_data\n");
if (!weint_data)
return -ENOMEM;
}
for (idx = 0; idx < bank->nr_pins; ++idx) {
irq = irq_of_parse_and_map(bank->of_node, idx);
@ -559,10 +561,8 @@ static int exynos_eint_wkup_init(struct samsung_pinctrl_drv_data *d)
muxed_data = devm_kzalloc(dev, sizeof(*muxed_data)
+ muxed_banks*sizeof(struct samsung_pin_bank *), GFP_KERNEL);
if (!muxed_data) {
dev_err(dev, "could not allocate memory for muxed_data\n");
if (!muxed_data)
return -ENOMEM;
}
irq_set_chained_handler_and_data(irq, exynos_irq_demux_eint16_31,
muxed_data);
@ -644,6 +644,60 @@ static void exynos_pinctrl_resume(struct samsung_pinctrl_drv_data *drvdata)
exynos_pinctrl_resume_bank(drvdata, bank);
}
/* Retention control for S5PV210 are located at the end of clock controller */
#define S5P_OTHERS 0xE000
#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)
static void s5pv210_retention_disable(struct samsung_pinctrl_drv_data *drvdata)
{
void *clk_base = drvdata->retention_ctrl->priv;
u32 tmp;
tmp = __raw_readl(clk_base + S5P_OTHERS);
tmp |= (S5P_OTHERS_RET_IO | S5P_OTHERS_RET_CF | S5P_OTHERS_RET_MMC |
S5P_OTHERS_RET_UART);
__raw_writel(tmp, clk_base + S5P_OTHERS);
}
static struct samsung_retention_ctrl *
s5pv210_retention_init(struct samsung_pinctrl_drv_data *drvdata,
const struct samsung_retention_data *data)
{
struct samsung_retention_ctrl *ctrl;
struct device_node *np;
void *clk_base;
ctrl = devm_kzalloc(drvdata->dev, sizeof(*ctrl), GFP_KERNEL);
if (!ctrl)
return ERR_PTR(-ENOMEM);
np = of_find_compatible_node(NULL, NULL, "samsung,s5pv210-clock");
if (!np) {
pr_err("%s: failed to find clock controller DT node\n",
__func__);
return ERR_PTR(-ENODEV);
}
clk_base = of_iomap(np, 0);
if (!clk_base) {
pr_err("%s: failed to map clock registers\n", __func__);
return ERR_PTR(-EINVAL);
}
ctrl->priv = clk_base;
ctrl->disable = s5pv210_retention_disable;
return ctrl;
}
static const struct samsung_retention_data s5pv210_retention_data __initconst = {
.init = s5pv210_retention_init,
};
/* pin banks of s5pv210 pin-controller */
static const struct samsung_pin_bank_data s5pv210_pin_bank[] __initconst = {
EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpa0", 0x00),
@ -691,9 +745,58 @@ const struct samsung_pin_ctrl s5pv210_pin_ctrl[] __initconst = {
.eint_wkup_init = exynos_eint_wkup_init,
.suspend = exynos_pinctrl_suspend,
.resume = exynos_pinctrl_resume,
.retention_data = &s5pv210_retention_data,
},
};
/* Pad retention control code for accessing PMU regmap */
static atomic_t exynos_shared_retention_refcnt;
static void exynos_retention_enable(struct samsung_pinctrl_drv_data *drvdata)
{
if (drvdata->retention_ctrl->refcnt)
atomic_inc(drvdata->retention_ctrl->refcnt);
}
static void exynos_retention_disable(struct samsung_pinctrl_drv_data *drvdata)
{
struct samsung_retention_ctrl *ctrl = drvdata->retention_ctrl;
struct regmap *pmu_regs = ctrl->priv;
int i;
if (ctrl->refcnt && !atomic_dec_and_test(ctrl->refcnt))
return;
for (i = 0; i < ctrl->nr_regs; i++)
regmap_write(pmu_regs, ctrl->regs[i], ctrl->value);
}
static struct samsung_retention_ctrl *
exynos_retention_init(struct samsung_pinctrl_drv_data *drvdata,
const struct samsung_retention_data *data)
{
struct samsung_retention_ctrl *ctrl;
struct regmap *pmu_regs;
ctrl = devm_kzalloc(drvdata->dev, sizeof(*ctrl), GFP_KERNEL);
if (!ctrl)
return ERR_PTR(-ENOMEM);
pmu_regs = exynos_get_pmu_regmap();
if (IS_ERR(pmu_regs))
return ERR_CAST(pmu_regs);
ctrl->priv = pmu_regs;
ctrl->regs = data->regs;
ctrl->nr_regs = data->nr_regs;
ctrl->value = data->value;
ctrl->refcnt = data->refcnt;
ctrl->enable = exynos_retention_enable;
ctrl->disable = exynos_retention_disable;
return ctrl;
}
/* pin banks of exynos3250 pin-controller 0 */
static const struct samsung_pin_bank_data exynos3250_pin_banks0[] __initconst = {
EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpa0", 0x00),
@ -725,6 +828,30 @@ static const struct samsung_pin_bank_data exynos3250_pin_banks1[] __initconst =
EXYNOS_PIN_BANK_EINTW(8, 0xc60, "gpx3", 0x0c),
};
/*
* PMU pad retention groups for Exynos3250 doesn't match pin banks, so handle
* them all together
*/
static const u32 exynos3250_retention_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,
};
static const struct samsung_retention_data exynos3250_retention_data __initconst = {
.regs = exynos3250_retention_regs,
.nr_regs = ARRAY_SIZE(exynos3250_retention_regs),
.value = EXYNOS_WAKEUP_FROM_LOWPWR,
.refcnt = &exynos_shared_retention_refcnt,
.init = exynos_retention_init,
};
/*
* Samsung pinctrl driver data for Exynos3250 SoC. Exynos3250 SoC includes
* two gpio/pin-mux/pinconfig controllers.
@ -737,6 +864,7 @@ const struct samsung_pin_ctrl exynos3250_pin_ctrl[] __initconst = {
.eint_gpio_init = exynos_eint_gpio_init,
.suspend = exynos_pinctrl_suspend,
.resume = exynos_pinctrl_resume,
.retention_data = &exynos3250_retention_data,
}, {
/* pin-controller instance 1 data */
.pin_banks = exynos3250_pin_banks1,
@ -745,6 +873,7 @@ const struct samsung_pin_ctrl exynos3250_pin_ctrl[] __initconst = {
.eint_wkup_init = exynos_eint_wkup_init,
.suspend = exynos_pinctrl_suspend,
.resume = exynos_pinctrl_resume,
.retention_data = &exynos3250_retention_data,
},
};
@ -797,6 +926,36 @@ static const struct samsung_pin_bank_data exynos4210_pin_banks2[] __initconst =
EXYNOS_PIN_BANK_EINTN(7, 0x000, "gpz"),
};
/* PMU pad retention groups registers for Exynos4 (without audio) */
static const u32 exynos4_retention_regs[] = {
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,
};
static const struct samsung_retention_data exynos4_retention_data __initconst = {
.regs = exynos4_retention_regs,
.nr_regs = ARRAY_SIZE(exynos4_retention_regs),
.value = EXYNOS_WAKEUP_FROM_LOWPWR,
.refcnt = &exynos_shared_retention_refcnt,
.init = exynos_retention_init,
};
/* PMU retention control for audio pins can be tied to audio pin bank */
static const u32 exynos4_audio_retention_regs[] = {
S5P_PAD_RET_MAUDIO_OPTION,
};
static const struct samsung_retention_data exynos4_audio_retention_data __initconst = {
.regs = exynos4_audio_retention_regs,
.nr_regs = ARRAY_SIZE(exynos4_audio_retention_regs),
.value = EXYNOS_WAKEUP_FROM_LOWPWR,
.init = exynos_retention_init,
};
/*
* Samsung pinctrl driver data for Exynos4210 SoC. Exynos4210 SoC includes
* three gpio/pin-mux/pinconfig controllers.
@ -809,6 +968,7 @@ const struct samsung_pin_ctrl exynos4210_pin_ctrl[] __initconst = {
.eint_gpio_init = exynos_eint_gpio_init,
.suspend = exynos_pinctrl_suspend,
.resume = exynos_pinctrl_resume,
.retention_data = &exynos4_retention_data,
}, {
/* pin-controller instance 1 data */
.pin_banks = exynos4210_pin_banks1,
@ -817,10 +977,12 @@ const struct samsung_pin_ctrl exynos4210_pin_ctrl[] __initconst = {
.eint_wkup_init = exynos_eint_wkup_init,
.suspend = exynos_pinctrl_suspend,
.resume = exynos_pinctrl_resume,
.retention_data = &exynos4_retention_data,
}, {
/* pin-controller instance 2 data */
.pin_banks = exynos4210_pin_banks2,
.nr_banks = ARRAY_SIZE(exynos4210_pin_banks2),
.retention_data = &exynos4_audio_retention_data,
},
};
@ -894,6 +1056,7 @@ const struct samsung_pin_ctrl exynos4x12_pin_ctrl[] __initconst = {
.eint_gpio_init = exynos_eint_gpio_init,
.suspend = exynos_pinctrl_suspend,
.resume = exynos_pinctrl_resume,
.retention_data = &exynos4_retention_data,
}, {
/* pin-controller instance 1 data */
.pin_banks = exynos4x12_pin_banks1,
@ -902,6 +1065,7 @@ const struct samsung_pin_ctrl exynos4x12_pin_ctrl[] __initconst = {
.eint_wkup_init = exynos_eint_wkup_init,
.suspend = exynos_pinctrl_suspend,
.resume = exynos_pinctrl_resume,
.retention_data = &exynos4_retention_data,
}, {
/* pin-controller instance 2 data */
.pin_banks = exynos4x12_pin_banks2,
@ -909,6 +1073,7 @@ const struct samsung_pin_ctrl exynos4x12_pin_ctrl[] __initconst = {
.eint_gpio_init = exynos_eint_gpio_init,
.suspend = exynos_pinctrl_suspend,
.resume = exynos_pinctrl_resume,
.retention_data = &exynos4_audio_retention_data,
}, {
/* pin-controller instance 3 data */
.pin_banks = exynos4x12_pin_banks3,
@ -919,81 +1084,6 @@ const struct samsung_pin_ctrl exynos4x12_pin_ctrl[] __initconst = {
},
};
/* pin banks of exynos4415 pin-controller 0 */
static const struct samsung_pin_bank_data exynos4415_pin_banks0[] = {
EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpa0", 0x00),
EXYNOS_PIN_BANK_EINTG(6, 0x020, "gpa1", 0x04),
EXYNOS_PIN_BANK_EINTG(8, 0x040, "gpb", 0x08),
EXYNOS_PIN_BANK_EINTG(5, 0x060, "gpc0", 0x0c),
EXYNOS_PIN_BANK_EINTG(5, 0x080, "gpc1", 0x10),
EXYNOS_PIN_BANK_EINTG(4, 0x0A0, "gpd0", 0x14),
EXYNOS_PIN_BANK_EINTG(4, 0x0C0, "gpd1", 0x18),
EXYNOS_PIN_BANK_EINTG(8, 0x180, "gpf0", 0x30),
EXYNOS_PIN_BANK_EINTG(8, 0x1A0, "gpf1", 0x34),
EXYNOS_PIN_BANK_EINTG(1, 0x1C0, "gpf2", 0x38),
};
/* pin banks of exynos4415 pin-controller 1 */
static const struct samsung_pin_bank_data exynos4415_pin_banks1[] = {
EXYNOS_PIN_BANK_EINTG(8, 0x040, "gpk0", 0x08),
EXYNOS_PIN_BANK_EINTG(7, 0x060, "gpk1", 0x0c),
EXYNOS_PIN_BANK_EINTG(7, 0x080, "gpk2", 0x10),
EXYNOS_PIN_BANK_EINTG(7, 0x0A0, "gpk3", 0x14),
EXYNOS_PIN_BANK_EINTG(4, 0x0C0, "gpl0", 0x18),
EXYNOS_PIN_BANK_EINTN(6, 0x120, "mp00"),
EXYNOS_PIN_BANK_EINTN(4, 0x140, "mp01"),
EXYNOS_PIN_BANK_EINTN(6, 0x160, "mp02"),
EXYNOS_PIN_BANK_EINTN(8, 0x180, "mp03"),
EXYNOS_PIN_BANK_EINTN(8, 0x1A0, "mp04"),
EXYNOS_PIN_BANK_EINTN(8, 0x1C0, "mp05"),
EXYNOS_PIN_BANK_EINTN(8, 0x1E0, "mp06"),
EXYNOS_PIN_BANK_EINTG(8, 0x260, "gpm0", 0x24),
EXYNOS_PIN_BANK_EINTG(7, 0x280, "gpm1", 0x28),
EXYNOS_PIN_BANK_EINTG(5, 0x2A0, "gpm2", 0x2c),
EXYNOS_PIN_BANK_EINTG(8, 0x2C0, "gpm3", 0x30),
EXYNOS_PIN_BANK_EINTG(8, 0x2E0, "gpm4", 0x34),
EXYNOS_PIN_BANK_EINTW(8, 0xC00, "gpx0", 0x00),
EXYNOS_PIN_BANK_EINTW(8, 0xC20, "gpx1", 0x04),
EXYNOS_PIN_BANK_EINTW(8, 0xC40, "gpx2", 0x08),
EXYNOS_PIN_BANK_EINTW(8, 0xC60, "gpx3", 0x0c),
};
/* pin banks of exynos4415 pin-controller 2 */
static const struct samsung_pin_bank_data exynos4415_pin_banks2[] = {
EXYNOS_PIN_BANK_EINTG(7, 0x000, "gpz", 0x00),
EXYNOS_PIN_BANK_EINTN(2, 0x000, "etc1"),
};
/*
* Samsung pinctrl driver data for Exynos4415 SoC. Exynos4415 SoC includes
* three gpio/pin-mux/pinconfig controllers.
*/
const struct samsung_pin_ctrl exynos4415_pin_ctrl[] = {
{
/* pin-controller instance 0 data */
.pin_banks = exynos4415_pin_banks0,
.nr_banks = ARRAY_SIZE(exynos4415_pin_banks0),
.eint_gpio_init = exynos_eint_gpio_init,
.suspend = exynos_pinctrl_suspend,
.resume = exynos_pinctrl_resume,
}, {
/* pin-controller instance 1 data */
.pin_banks = exynos4415_pin_banks1,
.nr_banks = ARRAY_SIZE(exynos4415_pin_banks1),
.eint_gpio_init = exynos_eint_gpio_init,
.eint_wkup_init = exynos_eint_wkup_init,
.suspend = exynos_pinctrl_suspend,
.resume = exynos_pinctrl_resume,
}, {
/* pin-controller instance 2 data */
.pin_banks = exynos4415_pin_banks2,
.nr_banks = ARRAY_SIZE(exynos4415_pin_banks2),
.eint_gpio_init = exynos_eint_gpio_init,
.suspend = exynos_pinctrl_suspend,
.resume = exynos_pinctrl_resume,
},
};
/* pin banks of exynos5250 pin-controller 0 */
static const struct samsung_pin_bank_data exynos5250_pin_banks0[] __initconst = {
EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpa0", 0x00),
@ -1063,6 +1153,7 @@ const struct samsung_pin_ctrl exynos5250_pin_ctrl[] __initconst = {
.eint_wkup_init = exynos_eint_wkup_init,
.suspend = exynos_pinctrl_suspend,
.resume = exynos_pinctrl_resume,
.retention_data = &exynos4_retention_data,
}, {
/* pin-controller instance 1 data */
.pin_banks = exynos5250_pin_banks1,
@ -1070,6 +1161,7 @@ const struct samsung_pin_ctrl exynos5250_pin_ctrl[] __initconst = {
.eint_gpio_init = exynos_eint_gpio_init,
.suspend = exynos_pinctrl_suspend,
.resume = exynos_pinctrl_resume,
.retention_data = &exynos4_retention_data,
}, {
/* pin-controller instance 2 data */
.pin_banks = exynos5250_pin_banks2,
@ -1084,6 +1176,7 @@ const struct samsung_pin_ctrl exynos5250_pin_ctrl[] __initconst = {
.eint_gpio_init = exynos_eint_gpio_init,
.suspend = exynos_pinctrl_suspend,
.resume = exynos_pinctrl_resume,
.retention_data = &exynos4_audio_retention_data,
},
};
@ -1310,6 +1403,30 @@ static const struct samsung_pin_bank_data exynos5420_pin_banks4[] __initconst =
EXYNOS_PIN_BANK_EINTG(7, 0x000, "gpz", 0x00),
};
/* PMU pad retention groups registers for Exynos5420 (without audio) */
static const u32 exynos5420_retention_regs[] = {
EXYNOS_PAD_RET_DRAM_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,
};
static const struct samsung_retention_data exynos5420_retention_data __initconst = {
.regs = exynos5420_retention_regs,
.nr_regs = ARRAY_SIZE(exynos5420_retention_regs),
.value = EXYNOS_WAKEUP_FROM_LOWPWR,
.refcnt = &exynos_shared_retention_refcnt,
.init = exynos_retention_init,
};
/*
* Samsung pinctrl driver data for Exynos5420 SoC. Exynos5420 SoC includes
* four gpio/pin-mux/pinconfig controllers.
@ -1321,114 +1438,119 @@ const struct samsung_pin_ctrl exynos5420_pin_ctrl[] __initconst = {
.nr_banks = ARRAY_SIZE(exynos5420_pin_banks0),
.eint_gpio_init = exynos_eint_gpio_init,
.eint_wkup_init = exynos_eint_wkup_init,
.retention_data = &exynos5420_retention_data,
}, {
/* pin-controller instance 1 data */
.pin_banks = exynos5420_pin_banks1,
.nr_banks = ARRAY_SIZE(exynos5420_pin_banks1),
.eint_gpio_init = exynos_eint_gpio_init,
.retention_data = &exynos5420_retention_data,
}, {
/* pin-controller instance 2 data */
.pin_banks = exynos5420_pin_banks2,
.nr_banks = ARRAY_SIZE(exynos5420_pin_banks2),
.eint_gpio_init = exynos_eint_gpio_init,
.retention_data = &exynos5420_retention_data,
}, {
/* pin-controller instance 3 data */
.pin_banks = exynos5420_pin_banks3,
.nr_banks = ARRAY_SIZE(exynos5420_pin_banks3),
.eint_gpio_init = exynos_eint_gpio_init,
.retention_data = &exynos5420_retention_data,
}, {
/* pin-controller instance 4 data */
.pin_banks = exynos5420_pin_banks4,
.nr_banks = ARRAY_SIZE(exynos5420_pin_banks4),
.eint_gpio_init = exynos_eint_gpio_init,
.retention_data = &exynos4_audio_retention_data,
},
};
/* pin banks of exynos5433 pin-controller - ALIVE */
static const struct samsung_pin_bank_data exynos5433_pin_banks0[] = {
EXYNOS5433_PIN_BANK_EINTW(8, 0x000, "gpa0", 0x00),
EXYNOS5433_PIN_BANK_EINTW(8, 0x020, "gpa1", 0x04),
EXYNOS5433_PIN_BANK_EINTW(8, 0x040, "gpa2", 0x08),
EXYNOS5433_PIN_BANK_EINTW(8, 0x060, "gpa3", 0x0c),
EXYNOS5433_PIN_BANK_EINTW_EXT(8, 0x020, "gpf1", 0x1004, 1),
EXYNOS5433_PIN_BANK_EINTW_EXT(4, 0x040, "gpf2", 0x1008, 1),
EXYNOS5433_PIN_BANK_EINTW_EXT(4, 0x060, "gpf3", 0x100c, 1),
EXYNOS5433_PIN_BANK_EINTW_EXT(8, 0x080, "gpf4", 0x1010, 1),
EXYNOS5433_PIN_BANK_EINTW_EXT(8, 0x0a0, "gpf5", 0x1014, 1),
static const struct samsung_pin_bank_data exynos5433_pin_banks0[] __initconst = {
EXYNOS_PIN_BANK_EINTW(8, 0x000, "gpa0", 0x00),
EXYNOS_PIN_BANK_EINTW(8, 0x020, "gpa1", 0x04),
EXYNOS_PIN_BANK_EINTW(8, 0x040, "gpa2", 0x08),
EXYNOS_PIN_BANK_EINTW(8, 0x060, "gpa3", 0x0c),
EXYNOS_PIN_BANK_EINTW_EXT(8, 0x020, "gpf1", 0x1004, 1),
EXYNOS_PIN_BANK_EINTW_EXT(4, 0x040, "gpf2", 0x1008, 1),
EXYNOS_PIN_BANK_EINTW_EXT(4, 0x060, "gpf3", 0x100c, 1),
EXYNOS_PIN_BANK_EINTW_EXT(8, 0x080, "gpf4", 0x1010, 1),
EXYNOS_PIN_BANK_EINTW_EXT(8, 0x0a0, "gpf5", 0x1014, 1),
};
/* pin banks of exynos5433 pin-controller - AUD */
static const struct samsung_pin_bank_data exynos5433_pin_banks1[] = {
EXYNOS5433_PIN_BANK_EINTG(7, 0x000, "gpz0", 0x00),
EXYNOS5433_PIN_BANK_EINTG(4, 0x020, "gpz1", 0x04),
static const struct samsung_pin_bank_data exynos5433_pin_banks1[] __initconst = {
EXYNOS_PIN_BANK_EINTG(7, 0x000, "gpz0", 0x00),
EXYNOS_PIN_BANK_EINTG(4, 0x020, "gpz1", 0x04),
};
/* pin banks of exynos5433 pin-controller - CPIF */
static const struct samsung_pin_bank_data exynos5433_pin_banks2[] = {
EXYNOS5433_PIN_BANK_EINTG(2, 0x000, "gpv6", 0x00),
static const struct samsung_pin_bank_data exynos5433_pin_banks2[] __initconst = {
EXYNOS_PIN_BANK_EINTG(2, 0x000, "gpv6", 0x00),
};
/* pin banks of exynos5433 pin-controller - eSE */
static const struct samsung_pin_bank_data exynos5433_pin_banks3[] = {
EXYNOS5433_PIN_BANK_EINTG(3, 0x000, "gpj2", 0x00),
static const struct samsung_pin_bank_data exynos5433_pin_banks3[] __initconst = {
EXYNOS_PIN_BANK_EINTG(3, 0x000, "gpj2", 0x00),
};
/* pin banks of exynos5433 pin-controller - FINGER */
static const struct samsung_pin_bank_data exynos5433_pin_banks4[] = {
EXYNOS5433_PIN_BANK_EINTG(4, 0x000, "gpd5", 0x00),
static const struct samsung_pin_bank_data exynos5433_pin_banks4[] __initconst = {
EXYNOS_PIN_BANK_EINTG(4, 0x000, "gpd5", 0x00),
};
/* pin banks of exynos5433 pin-controller - FSYS */
static const struct samsung_pin_bank_data exynos5433_pin_banks5[] = {
EXYNOS5433_PIN_BANK_EINTG(6, 0x000, "gph1", 0x00),
EXYNOS5433_PIN_BANK_EINTG(7, 0x020, "gpr4", 0x04),
EXYNOS5433_PIN_BANK_EINTG(5, 0x040, "gpr0", 0x08),
EXYNOS5433_PIN_BANK_EINTG(8, 0x060, "gpr1", 0x0c),
EXYNOS5433_PIN_BANK_EINTG(2, 0x080, "gpr2", 0x10),
EXYNOS5433_PIN_BANK_EINTG(8, 0x0a0, "gpr3", 0x14),
static const struct samsung_pin_bank_data exynos5433_pin_banks5[] __initconst = {
EXYNOS_PIN_BANK_EINTG(6, 0x000, "gph1", 0x00),
EXYNOS_PIN_BANK_EINTG(7, 0x020, "gpr4", 0x04),
EXYNOS_PIN_BANK_EINTG(5, 0x040, "gpr0", 0x08),
EXYNOS_PIN_BANK_EINTG(8, 0x060, "gpr1", 0x0c),
EXYNOS_PIN_BANK_EINTG(2, 0x080, "gpr2", 0x10),
EXYNOS_PIN_BANK_EINTG(8, 0x0a0, "gpr3", 0x14),
};
/* pin banks of exynos5433 pin-controller - IMEM */
static const struct samsung_pin_bank_data exynos5433_pin_banks6[] = {
EXYNOS5433_PIN_BANK_EINTG(8, 0x000, "gpf0", 0x00),
static const struct samsung_pin_bank_data exynos5433_pin_banks6[] __initconst = {
EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpf0", 0x00),
};
/* pin banks of exynos5433 pin-controller - NFC */
static const struct samsung_pin_bank_data exynos5433_pin_banks7[] = {
EXYNOS5433_PIN_BANK_EINTG(3, 0x000, "gpj0", 0x00),
static const struct samsung_pin_bank_data exynos5433_pin_banks7[] __initconst = {
EXYNOS_PIN_BANK_EINTG(3, 0x000, "gpj0", 0x00),
};
/* pin banks of exynos5433 pin-controller - PERIC */
static const struct samsung_pin_bank_data exynos5433_pin_banks8[] = {
EXYNOS5433_PIN_BANK_EINTG(6, 0x000, "gpv7", 0x00),
EXYNOS5433_PIN_BANK_EINTG(5, 0x020, "gpb0", 0x04),
EXYNOS5433_PIN_BANK_EINTG(8, 0x040, "gpc0", 0x08),
EXYNOS5433_PIN_BANK_EINTG(2, 0x060, "gpc1", 0x0c),
EXYNOS5433_PIN_BANK_EINTG(6, 0x080, "gpc2", 0x10),
EXYNOS5433_PIN_BANK_EINTG(8, 0x0a0, "gpc3", 0x14),
EXYNOS5433_PIN_BANK_EINTG(2, 0x0c0, "gpg0", 0x18),
EXYNOS5433_PIN_BANK_EINTG(4, 0x0e0, "gpd0", 0x1c),
EXYNOS5433_PIN_BANK_EINTG(6, 0x100, "gpd1", 0x20),
EXYNOS5433_PIN_BANK_EINTG(8, 0x120, "gpd2", 0x24),
EXYNOS5433_PIN_BANK_EINTG(5, 0x140, "gpd4", 0x28),
EXYNOS5433_PIN_BANK_EINTG(2, 0x160, "gpd8", 0x2c),
EXYNOS5433_PIN_BANK_EINTG(7, 0x180, "gpd6", 0x30),
EXYNOS5433_PIN_BANK_EINTG(3, 0x1a0, "gpd7", 0x34),
EXYNOS5433_PIN_BANK_EINTG(5, 0x1c0, "gpg1", 0x38),
EXYNOS5433_PIN_BANK_EINTG(2, 0x1e0, "gpg2", 0x3c),
EXYNOS5433_PIN_BANK_EINTG(8, 0x200, "gpg3", 0x40),
static const struct samsung_pin_bank_data exynos5433_pin_banks8[] __initconst = {
EXYNOS_PIN_BANK_EINTG(6, 0x000, "gpv7", 0x00),
EXYNOS_PIN_BANK_EINTG(5, 0x020, "gpb0", 0x04),
EXYNOS_PIN_BANK_EINTG(8, 0x040, "gpc0", 0x08),
EXYNOS_PIN_BANK_EINTG(2, 0x060, "gpc1", 0x0c),
EXYNOS_PIN_BANK_EINTG(6, 0x080, "gpc2", 0x10),
EXYNOS_PIN_BANK_EINTG(8, 0x0a0, "gpc3", 0x14),
EXYNOS_PIN_BANK_EINTG(2, 0x0c0, "gpg0", 0x18),
EXYNOS_PIN_BANK_EINTG(4, 0x0e0, "gpd0", 0x1c),
EXYNOS_PIN_BANK_EINTG(6, 0x100, "gpd1", 0x20),
EXYNOS_PIN_BANK_EINTG(8, 0x120, "gpd2", 0x24),
EXYNOS_PIN_BANK_EINTG(5, 0x140, "gpd4", 0x28),
EXYNOS_PIN_BANK_EINTG(2, 0x160, "gpd8", 0x2c),
EXYNOS_PIN_BANK_EINTG(7, 0x180, "gpd6", 0x30),
EXYNOS_PIN_BANK_EINTG(3, 0x1a0, "gpd7", 0x34),
EXYNOS_PIN_BANK_EINTG(5, 0x1c0, "gpg1", 0x38),
EXYNOS_PIN_BANK_EINTG(2, 0x1e0, "gpg2", 0x3c),
EXYNOS_PIN_BANK_EINTG(8, 0x200, "gpg3", 0x40),
};
/* pin banks of exynos5433 pin-controller - TOUCH */
static const struct samsung_pin_bank_data exynos5433_pin_banks9[] = {
EXYNOS5433_PIN_BANK_EINTG(3, 0x000, "gpj1", 0x00),
static const struct samsung_pin_bank_data exynos5433_pin_banks9[] __initconst = {
EXYNOS_PIN_BANK_EINTG(3, 0x000, "gpj1", 0x00),
};
/*
* Samsung pinctrl driver data for Exynos5433 SoC. Exynos5433 SoC includes
* ten gpio/pin-mux/pinconfig controllers.
*/
const struct samsung_pin_ctrl exynos5433_pin_ctrl[] = {
const struct samsung_pin_ctrl exynos5433_pin_ctrl[] __initconst = {
{
/* pin-controller instance 0 data */
.pin_banks = exynos5433_pin_banks0,

View File

@ -489,10 +489,8 @@ static int s3c64xx_eint_gpio_init(struct samsung_pinctrl_drv_data *d)
data = devm_kzalloc(dev, sizeof(*data)
+ nr_domains * sizeof(*data->domains), GFP_KERNEL);
if (!data) {
dev_err(dev, "failed to allocate handler data\n");
if (!data)
return -ENOMEM;
}
data->drvdata = d;
bank = d->pin_banks;
@ -715,10 +713,8 @@ static int s3c64xx_eint_eint0_init(struct samsung_pinctrl_drv_data *d)
return -ENODEV;
data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
if (!data) {
dev_err(dev, "could not allocate memory for wkup eint data\n");
if (!data)
return -ENOMEM;
}
data->drvdata = d;
for (i = 0; i < NUM_EINT0_IRQ; ++i) {
@ -751,10 +747,8 @@ static int s3c64xx_eint_eint0_init(struct samsung_pinctrl_drv_data *d)
ddata = devm_kzalloc(dev,
sizeof(*ddata) + nr_eints, GFP_KERNEL);
if (!ddata) {
dev_err(dev, "failed to allocate domain data\n");
if (!ddata)
return -ENOMEM;
}
ddata->bank = bank;
bank->irq_domain = irq_domain_add_linear(bank->of_node,

Some files were not shown because too many files have changed in this diff Show More