Commit bd698cf6 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'pinctrl-v3.16-1' of...

Merge tag 'pinctrl-v3.16-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl into next

Pull pin control changes from Linus Walleij:
 "This is the bulk of pin control changes for the v3.16 development
  cycle:

   - Antoine Tenart made the get_group_pins() vtable entry optional.

   - Antoine also provides an entirely new driver for the Marvell Berlin
     SoC.  This is unrelated to the existing MVEBU hardware driver and
     warrants its own separate driver.

   - reflected from the GPIO subsystem there is a number of refactorings
     to make pin control drivers with gpiochips use the new gpiolib
     irqchip helpers.  The following drivers were converted to use the
     new infrastructure:
       * ST Microelectronics STiH416 and friends
       * The Atmel AT91
       * The CSR SiRF (Prima2)
       * The Qualcomm MSM series

   - massive improvements in the Qualcomm MSM driver from Bjorn
     Andersson, Andy Gross and Kumar Gala.  Among those new support for
     the IPQ8064 and MSM8x74 SoC variants.

   - support for the Freescale i.MX6 SoloX SoC variant.

   - massive improvements in the Allwinner sunxi driver from Boris
     Brezillon, Maxime Ripard and Chen-Yu Tsai.

   - Renesas PFC updates from Laurent Pinchart, Kuninori Morimoto,
     Wolfram Sang and Magnus Damm.

   - Cleanups and refactorings of the nVidia Tegra driver from Stepgen
     Warren.

   - the Exynos driver now supports the Exynos3250 SoC.

   - Intel BayTrail updates from Jin Yao, Mika Westerberg.

   - the MVEBU driver now supports the Orion5x SoC variants, which is
     part of the effort of getting rid of the old Marvell kludges in
     arch/arm/mach-orion5x

   - Rockchip driver updates from Heiko Stuebner.

   - a ton of cleanups and janitorial patches from Axel Lin.

   - some minor fixes and improvements here and there"

* tag 'pinctrl-v3.16-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl: (93 commits)
  pinctrl: sirf: fix a bad conflict resolution
  pinctrl: msm: Add more MSM8X74 pin definitions
  pinctrl: qcom: ipq8064: Fix naming convention
  pinctrl: msm: Add missing sdc1 and sdc3 groups
  pinctrl: sirf: switch to using allocated state container
  pinctrl: Enable "power-source" to be extracted from DT files
  pinctrl: sunxi: create irq/pin mapping during init
  pinctrl: pinconf-generic: Use kmemdup instead of kmalloc + memcpy
  pinctrl: berlin: Use devm_ioremap_resource()
  pinctrl: sirf: fix typo for GPIO bank number
  pinctrl: sunxi: depend on RESET_CONTROLLER
  pinctrl: sunxi: fix pin numbers passed to register offset helpers
  pinctrl: add pinctrl driver for imx6sx
  pinctrl/at91: Fix lockup when IRQ on PIOC and PIOD occurs
  pinctrl: msm: switch to using generic GPIO irqchip helpers
  pinctrl: sunxi: Fix multiple registration issue
  pinctrl: sunxi: Fix recursive dependency
  pinctrl: berlin: add the BG2CD pinctrl driver
  pinctrl: berlin: add the BG2 pinctrl driver
  pinctrl: berlin: add the BG2Q pinctrl driver
  ...
parents f4562052 29c7f1f5
......@@ -6,8 +6,13 @@ the first two functions being GPIO in and out. The configuration on
the pins includes drive strength and pull-up.
Required properties:
- compatible: "allwinner,<soc>-pinctrl". Supported SoCs for now are:
sun5i-a13.
- compatible: Should be one of the followings (depending on you SoC):
"allwinner,sun4i-a10-pinctrl"
"allwinner,sun5i-a10s-pinctrl"
"allwinner,sun5i-a13-pinctrl"
"allwinner,sun6i-a31-pinctrl"
"allwinner,sun6i-a31-r-pinctrl"
"allwinner,sun7i-a20-pinctrl"
- reg: Should contain the register physical address and length for the
pin controller.
......
* Freescale i.MX6 SoloX IOMUX Controller
Please refer to fsl,imx-pinctrl.txt in this directory for common binding part
and usage.
Required properties:
- compatible: "fsl,imx6sx-iomuxc"
- fsl,pins: each entry consists of 6 integers and represents the mux and config
setting for one pin. The first 5 integers <mux_reg conf_reg input_reg mux_val
input_val> are specified using a PIN_FUNC_ID macro, which can be found in
imx6sx-pinfunc.h under device tree source folder. The last integer CONFIG is
the pad setting value like pull-up on this pin. Please refer to i.MX6 SoloX
Reference Manual for detailed CONFIG settings.
CONFIG bits definition:
PAD_CTL_HYS (1 << 16)
PAD_CTL_PUS_100K_DOWN (0 << 14)
PAD_CTL_PUS_47K_UP (1 << 14)
PAD_CTL_PUS_100K_UP (2 << 14)
PAD_CTL_PUS_22K_UP (3 << 14)
PAD_CTL_PUE (1 << 13)
PAD_CTL_PKE (1 << 12)
PAD_CTL_ODE (1 << 11)
PAD_CTL_SPEED_LOW (0 << 6)
PAD_CTL_SPEED_MED (1 << 6)
PAD_CTL_SPEED_HIGH (3 << 6)
PAD_CTL_DSE_DISABLE (0 << 3)
PAD_CTL_DSE_260ohm (1 << 3)
PAD_CTL_DSE_130ohm (2 << 3)
PAD_CTL_DSE_87ohm (3 << 3)
PAD_CTL_DSE_65ohm (4 << 3)
PAD_CTL_DSE_52ohm (5 << 3)
PAD_CTL_DSE_43ohm (6 << 3)
PAD_CTL_DSE_37ohm (7 << 3)
PAD_CTL_SRE_FAST (1 << 0)
PAD_CTL_SRE_SLOW (0 << 0)
* Marvell Orion SoC pinctrl driver for mpp
Please refer to marvell,mvebu-pinctrl.txt in this directory for common binding
part and usage.
Required properties:
- compatible: "marvell,88f5181l-pinctrl", "marvell,88f5182-pinctrl",
"marvell,88f5281-pinctrl"
- reg: two register areas, the first one describing the first two
contiguous MPP registers, and the second one describing the single
final MPP register, separated from the previous one.
Available mpp pins/groups and functions:
Note: brackets (x) are not part of the mpp name for marvell,function and given
only for more detailed description in this document.
* Marvell Orion 88f5181l
name pins functions
================================================================================
mpp0 0 pcie(rstout), pci(req2), gpio
mpp1 1 gpio, pci(gnt2)
mpp2 2 gpio, pci(req3), pci-1(pme)
mpp3 3 gpio, pci(gnt3)
mpp4 4 gpio, pci(req4)
mpp5 5 gpio, pci(gnt4)
mpp6 6 gpio, pci(req5), pci-1(clk)
mpp7 7 gpio, pci(gnt5), pci-1(clk)
mpp8 8 gpio, ge(col)
mpp9 9 gpio, ge(rxerr)
mpp10 10 gpio, ge(crs)
mpp11 11 gpio, ge(txerr)
mpp12 12 gpio, ge(txd4)
mpp13 13 gpio, ge(txd5)
mpp14 14 gpio, ge(txd6)
mpp15 15 gpio, ge(txd7)
mpp16 16 ge(rxd4)
mpp17 17 ge(rxd5)
mpp18 18 ge(rxd6)
mpp19 19 ge(rxd7)
* Marvell Orion 88f5182
name pins functions
================================================================================
mpp0 0 pcie(rstout), pci(req2), gpio
mpp1 1 gpio, pci(gnt2)
mpp2 2 gpio, pci(req3), pci-1(pme)
mpp3 3 gpio, pci(gnt3)
mpp4 4 gpio, pci(req4), bootnand(re), sata0(prsnt)
mpp5 5 gpio, pci(gnt4), bootnand(we), sata1(prsnt)
mpp6 6 gpio, pci(req5), nand(re0), sata0(act)
mpp7 7 gpio, pci(gnt5), nand(we0), sata1(act)
mpp8 8 gpio, ge(col)
mpp9 9 gpio, ge(rxerr)
mpp10 10 gpio, ge(crs)
mpp11 11 gpio, ge(txerr)
mpp12 12 gpio, ge(txd4), nand(re1), sata0(ledprsnt)
mpp13 13 gpio, ge(txd5), nand(we1), sata1(ledprsnt)
mpp14 14 gpio, ge(txd6), nand(re2), sata0(ledact)
mpp15 15 gpio, ge(txd7), nand(we2), sata1(ledact)
mpp16 16 uart1(rxd), ge(rxd4), gpio
mpp17 17 uart1(txd), ge(rxd5), gpio
mpp18 18 uart1(cts), ge(rxd6), gpio
mpp19 19 uart1(rts), ge(rxd7), gpio
* Marvell Orion 88f5281
name pins functions
================================================================================
mpp0 0 pcie(rstout), pci(req2), gpio
mpp1 1 gpio, pci(gnt2)
mpp2 2 gpio, pci(req3), pci(pme)
mpp3 3 gpio, pci(gnt3)
mpp4 4 gpio, pci(req4), bootnand(re)
mpp5 5 gpio, pci(gnt4), bootnand(we)
mpp6 6 gpio, pci(req5), nand(re0)
mpp7 7 gpio, pci(gnt5), nand(we0)
mpp8 8 gpio, ge(col)
mpp9 9 gpio, ge(rxerr)
mpp10 10 gpio, ge(crs)
mpp11 11 gpio, ge(txerr)
mpp12 12 gpio, ge(txd4), nand(re1)
mpp13 13 gpio, ge(txd5), nand(we1)
mpp14 14 gpio, ge(txd6), nand(re2)
mpp15 15 gpio, ge(txd7), nand(we2)
mpp16 16 uart1(rxd), ge(rxd4)
mpp17 17 uart1(txd), ge(rxd5)
mpp18 18 uart1(cts), ge(rxd6)
mpp19 19 uart1(rts), ge(rxd7)
......@@ -156,6 +156,7 @@ input-disable - disable input on pin (no effect on output)
input-schmitt-enable - enable schmitt-trigger mode
input-schmitt-disable - disable schmitt-trigger mode
input-debounce - debounce mode with debound time X
power-source - select between different power supplies
low-power-enable - enable low power mode
low-power-disable - disable low power mode
output-low - set the pin to output mode with low level
......
Qualcomm APQ8064 TLMM block
Required properties:
- compatible: "qcom,apq8064-pinctrl"
- reg: Should be the base address and length of the TLMM block.
- interrupts: Should be the parent IRQ of the TLMM block.
- interrupt-controller: Marks the device node as an interrupt controller.
- #interrupt-cells: Should be two.
- gpio-controller: Marks the device node as a GPIO controller.
- #gpio-cells : Should be two.
The first cell is the gpio pin number and the
second cell is used for optional parameters.
Please refer to ../gpio/gpio.txt and ../interrupt-controller/interrupts.txt for
a general description of GPIO and interrupt bindings.
Please refer to pinctrl-bindings.txt in this directory for details of the
common pinctrl bindings used by client devices, including the meaning of the
phrase "pin configuration node".
Qualcomm's pin configuration nodes act as a container for an abitrary number of
subnodes. Each of these subnodes represents some desired configuration for a
pin, a group, or a list of pins or groups. This configuration can include the
mux function to select on those pin(s)/group(s), and various pin configuration
parameters, such as pull-up, drive strength, etc.
The name of each subnode is not important; all subnodes should be enumerated
and processed purely based on their content.
Each subnode only affects those parameters that are explicitly listed. In
other words, a subnode that lists a mux function but no pin configuration
parameters implies no information about any pin configuration parameters.
Similarly, a pin subnode that describes a pullup parameter implies no
information about e.g. the mux function.
The following generic properties as defined in pinctrl-bindings.txt are valid
to specify in a pin configuration subnode:
pins, function, bias-disable, bias-pull-down, bias-pull,up, drive-strength,
output-low, output-high.
Non-empty subnodes must specify the 'pins' property.
Valid values for pins are:
gpio0-gpio89
Valid values for function are:
cam_mclk, codec_mic_i2s, codec_spkr_i2s, gsbi1, gsbi2, gsbi3, gsbi4,
gsbi4_cam_i2c, gsbi5, gsbi5_spi_cs1, gsbi5_spi_cs2, gsbi5_spi_cs3, gsbi6,
gsbi6_spi_cs1, gsbi6_spi_cs2, gsbi6_spi_cs3, gsbi7, gsbi7_spi_cs1,
gsbi7_spi_cs2, gsbi7_spi_cs3, gsbi_cam_i2c, hdmi, mi2s, riva_bt, riva_fm,
riva_wlan, sdc2, sdc4, slimbus, spkr_i2s, tsif1, tsif2, usb2_hsic,
Example:
msmgpio: pinctrl@800000 {
compatible = "qcom,apq8064-pinctrl";
reg = <0x800000 0x4000>;
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
interrupts = <0 32 0x4>;
pinctrl-names = "default";
pinctrl-0 = <&gsbi5_uart_default>;
gsbi5_uart_default: gsbi5_uart_default {
mux {
pins = "gpio51", "gpio52";
function = "gsbi5";
};
tx {
pins = "gpio51";
drive-strength = <4>;
bias-disable;
};
rx {
pins = "gpio52";
drive-strength = <2>;
bias-pull-up;
};
};
};
Qualcomm IPQ8064 TLMM block
Required properties:
- compatible: "qcom,ipq8064-pinctrl"
- reg: Should be the base address and length of the TLMM block.
- interrupts: Should be the parent IRQ of the TLMM block.
- interrupt-controller: Marks the device node as an interrupt controller.
- #interrupt-cells: Should be two.
- gpio-controller: Marks the device node as a GPIO controller.
- #gpio-cells : Should be two.
The first cell is the gpio pin number and the
second cell is used for optional parameters.
Please refer to ../gpio/gpio.txt and ../interrupt-controller/interrupts.txt for
a general description of GPIO and interrupt bindings.
Please refer to pinctrl-bindings.txt in this directory for details of the
common pinctrl bindings used by client devices, including the meaning of the
phrase "pin configuration node".
Qualcomm's pin configuration nodes act as a container for an abitrary number of
subnodes. Each of these subnodes represents some desired configuration for a
pin, a group, or a list of pins or groups. This configuration can include the
mux function to select on those pin(s)/group(s), and various pin configuration
parameters, such as pull-up, drive strength, etc.
The name of each subnode is not important; all subnodes should be enumerated
and processed purely based on their content.
Each subnode only affects those parameters that are explicitly listed. In
other words, a subnode that lists a mux function but no pin configuration
parameters implies no information about any pin configuration parameters.
Similarly, a pin subnode that describes a pullup parameter implies no
information about e.g. the mux function.
The following generic properties as defined in pinctrl-bindings.txt are valid
to specify in a pin configuration subnode:
pins, function, bias-disable, bias-pull-down, bias-pull,up, drive-strength,
output-low, output-high.
Non-empty subnodes must specify the 'pins' property.
Valid values for qcom,pins are:
gpio0-gpio68
Supports mux, bias, and drive-strength
sdc3_clk, sdc3_cmd, sdc3_data
Supports bias and drive-strength
Valid values for function are:
mdio, mi2s, pdm, ssbi, spmi, audio_pcm, gsbi1, gsbi2, gsbi4, gsbi5,
gsbi5_spi_cs1, gsbi5_spi_cs2, gsbi5_spi_cs3, gsbi6, gsbi7, nss_spi, sdc1,
spdif, nand, tsif1, tsif2, usb_fs_n, usb_fs, usb2_hsic, rgmii2, sata,
pcie1_rst, pcie1_prsnt, pcie1_pwren_n, pcie1_pwren, pcie1_pwrflt,
pcie1_clk_req, pcie2_rst, pcie2_prsnt, pcie2_pwren_n, pcie2_pwren,
pcie2_pwrflt, pcie2_clk_req, pcie3_rst, pcie3_prsnt, pcie3_pwren_n,
pcie3_pwren, pcie3_pwrflt, pcie3_clk_req, ps_hold
Example:
pinmux: pinctrl@800000 {
compatible = "qcom,ipq8064-pinctrl";
reg = <0x800000 0x4000>;
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
interrupts = <0 32 0x4>;
pinctrl-names = "default";
pinctrl-0 = <&gsbi5_uart_default>;
gsbi5_uart_default: gsbi5_uart_default {
mux {
pins = "gpio18", "gpio19";
function = "gsbi5";
};
tx {
pins = "gpio18";
drive-strength = <4>;
bias-disable;
};
rx {
pins = "gpio19";
drive-strength = <2>;
bias-pull-up;
};
};
};
......@@ -50,7 +50,27 @@ Valid values for pins are:
Supports bias and drive-strength
Valid values for function are:
blsp_i2c2, blsp_i2c6, blsp_i2c11, blsp_spi1, blsp_uart2, blsp_uart8, slimbus
cci_i2c0, cci_i2c1, uim1, uim2, uim_batt_alarm,
blsp_uim1, blsp_uart1, blsp_i2c1, blsp_spi1,
blsp_uim2, blsp_uart2, blsp_i2c2, blsp_spi2,
blsp_uim3, blsp_uart3, blsp_i2c3, blsp_spi3,
blsp_uim4, blsp_uart4, blsp_i2c4, blsp_spi4,
blsp_uim5, blsp_uart5, blsp_i2c5, blsp_spi5,
blsp_uim6, blsp_uart6, blsp_i2c6, blsp_spi6,
blsp_uim7, blsp_uart7, blsp_i2c7, blsp_spi7,
blsp_uim8, blsp_uart8, blsp_i2c8, blsp_spi8,
blsp_uim9, blsp_uart9, blsp_i2c9, blsp_spi9,
blsp_uim10, blsp_uart10, blsp_i2c10, blsp_spi10,
blsp_uim11, blsp_uart11, blsp_i2c11, blsp_spi11,
blsp_uim12, blsp_uart12, blsp_i2c12, blsp_spi12,
blsp_spi1_cs1, blsp_spi2_cs2, blsp_spi_cs3, blsp_spi2_cs1, blsp_spi2_cs2
blsp_spi2_cs3, blsp_spi10_cs1, blsp_spi10_cs2, blsp_spi10_cs3,
sdc3, sdc4, gcc_gp_clk1, gcc_gp_clk2, gcc_gp_clk3, cci_timer0, cci_timer1,
cci_timer2, cci_timer3, cci_async_in0, cci_async_in1, cci_async_in2,
cam_mckl0, cam_mclk1, cam_mclk2, cam_mclk3, mdp_vsync, hdmi_cec, hdmi_ddc,
hdmi_hpd, edp_hpd, gp_pdm0, gp_pdm1, gp_pdm2, gp_pdm3, gp0_clk, gp1_clk,
gp_mn, tsif1, tsif2, hsic, grfc, audio_ref_clk, qua_mi2s, pri_mi2s, spkr_mi2s,
ter_mi2s, sec_mi2s, bt, fm, wlan, slimbus
(Note that this is not yet the complete list of functions)
......
......@@ -21,13 +21,23 @@ defined as gpio sub-nodes of the pinmux controller.
Required properties for iomux controller:
- compatible: one of "rockchip,rk2928-pinctrl", "rockchip,rk3066a-pinctrl"
"rockchip,rk3066b-pinctrl", "rockchip,rk3188-pinctrl"
- rockchip,grf: phandle referencing a syscon providing the
"general register files"
Optional properties for iomux controller:
- rockchip,pmu: phandle referencing a syscon providing the pmu registers
as some SoCs carry parts of the iomux controller registers there.
Required for at least rk3188 and rk3288.
Deprecated properties for iomux controller:
- reg: first element is the general register space of the iomux controller
second element is the separate pull register space of the rk3188
It should be large enough to contain also separate pull registers.
second element is the separate pull register space of the rk3188.
Use rockchip,grf and rockchip,pmu described above instead.
Required properties for gpio sub nodes:
- compatible: "rockchip,gpio-bank", "rockchip,rk3188-gpio-bank0"
- reg: register of the gpio bank (different than the iomux registerset)
second element: separate pull register for rk3188 bank0
- interrupts: base interrupt of the gpio bank in the interrupt controller
- clocks: clock that drives this bank
- gpio-controller: identifies the node as a gpio controller and pin bank.
......@@ -39,6 +49,10 @@ Required properties for gpio sub nodes:
cells should use the standard two-cell scheme described in
bindings/interrupt-controller/interrupts.txt
Deprecated properties for gpio sub nodes:
- reg: second element: separate pull register for rk3188 bank0, use
rockchip,pmu described above instead
Required properties for pin configuration node:
- rockchip,pins: 3 integers array, represents a group of pins mux and config
setting. The format is rockchip,pins = <PIN_BANK PIN_BANK_IDX MUX &phandle>.
......@@ -54,7 +68,8 @@ Examples:
pinctrl@20008000 {
compatible = "rockchip,rk3066a-pinctrl";
reg = <0x20008000 0x150>;
rockchip,grf = <&grf>;
#address-cells = <1>;
#size-cells = <1>;
ranges;
......@@ -103,16 +118,15 @@ Example for rk3188:
pinctrl@20008000 {
compatible = "rockchip,rk3188-pinctrl";
reg = <0x20008000 0xa0>,
<0x20008164 0x1a0>;
rockchip,grf = <&grf>;
rockchip,pmu = <&pmu>;
#address-cells = <1>;
#size-cells = <1>;
ranges;
gpio0: gpio0@0x2000a000 {
compatible = "rockchip,rk3188-gpio-bank0";
reg = <0x2000a000 0x100>,
<0x20004064 0x8>;
reg = <0x2000a000 0x100>;
interrupts = <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clk_gates8 9>;
......
......@@ -1629,9 +1629,9 @@ config ARCH_NR_GPIO
int
default 1024 if ARCH_SHMOBILE || ARCH_TEGRA
default 512 if ARCH_EXYNOS || ARCH_KEYSTONE || SOC_OMAP5 || SOC_DRA7XX || ARCH_S3C24XX || ARCH_S3C64XX
default 416 if ARCH_SUNXI
default 392 if ARCH_U8500
default 352 if ARCH_VT8500
default 288 if ARCH_SUNXI
default 264 if MACH_H4700
default 0
help
......
......@@ -180,6 +180,7 @@ static const struct acpi_device_id acpi_lpss_device_ids[] = {
{ "80860F14", (unsigned long)&byt_sdio_dev_desc },
{ "80860F41", (unsigned long)&byt_i2c_dev_desc },
{ "INT33B2", },
{ "INT33FC", },
{ "INT3430", (unsigned long)&lpt_dev_desc },
{ "INT3431", (unsigned long)&lpt_dev_desc },
......
......@@ -84,6 +84,9 @@ config PINCTRL_AT91
depends on ARCH_AT91
select PINMUX
select PINCONF
select GPIOLIB
select OF_GPIO
select GPIOLIB_IRQCHIP
help
Say Y here to enable the at91 pinctrl driver
......@@ -185,6 +188,13 @@ config PINCTRL_IMX6SL
help
Say Y here to enable the imx6sl pinctrl driver
config PINCTRL_IMX6SX
bool "IMX6SX pinctrl driver"
depends on SOC_IMX6SX
select PINCTRL_IMX
help
Say Y here to enable the imx6sx pinctrl driver
config PINCTRL_VF610
bool "Freescale Vybrid VF610 pinctrl driver"
depends on SOC_VF610
......@@ -221,10 +231,27 @@ config PINCTRL_MSM
select PINMUX
select PINCONF
select GENERIC_PINCONF
select GPIOLIB_IRQCHIP
config PINCTRL_APQ8064
tristate "Qualcomm APQ8064 pin controller driver"
depends on GPIOLIB && OF
select PINCTRL_MSM
help
This is the pinctrl, pinmux, pinconf and gpiolib driver for the
Qualcomm TLMM block found in the Qualcomm APQ8064 platform.
config PINCTRL_IPQ8064
tristate "Qualcomm IPQ8064 pin controller driver"
depends on GPIOLIB && OF
select PINCTRL_MSM
help
This is the pinctrl, pinmux, pinconf and gpiolib driver for the
Qualcomm TLMM block found in the Qualcomm IPQ8064 platform.
config PINCTRL_MSM8X74
tristate "Qualcomm 8x74 pin controller driver"
depends on GPIOLIB && OF
depends on GPIOLIB && OF && (ARCH_QCOM || COMPILE_TEST)
select PINCTRL_MSM
help
This is the pinctrl, pinmux, pinconf and gpiolib driver for the
......@@ -256,6 +283,7 @@ config PINCTRL_ROCKCHIP
select PINMUX
select GENERIC_PINCONF
select GENERIC_IRQ_CHIP
select MFD_SYSCON
config PINCTRL_SINGLE
tristate "One-register-per-pin type device tree based pinctrl driver"
......@@ -270,17 +298,14 @@ config PINCTRL_SIRF
bool "CSR SiRFprimaII/SiRFmarco pin controller driver"
depends on ARCH_SIRF
select PINMUX
config PINCTRL_SUNXI
bool
select PINMUX
select GENERIC_PINCONF
select GPIOLIB_IRQCHIP
config PINCTRL_ST
bool
depends on OF
select PINMUX
select PINCONF
select GPIOLIB_IRQCHIP
config PINCTRL_TEGRA
bool
......@@ -368,9 +393,11 @@ config PINCTRL_S3C64XX
depends on ARCH_S3C64XX
select PINCTRL_SAMSUNG
source "drivers/pinctrl/berlin/Kconfig"
source "drivers/pinctrl/mvebu/Kconfig"
source "drivers/pinctrl/sh-pfc/Kconfig"
source "drivers/pinctrl/spear/Kconfig"
source "drivers/pinctrl/sunxi/Kconfig"
source "drivers/pinctrl/vt8500/Kconfig"
config PINCTRL_XWAY
......
......@@ -32,12 +32,15 @@ obj-$(CONFIG_PINCTRL_IMX53) += pinctrl-imx53.o
obj-$(CONFIG_PINCTRL_IMX6Q) += pinctrl-imx6q.o
obj-$(CONFIG_PINCTRL_IMX6Q) += pinctrl-imx6dl.o
obj-$(CONFIG_PINCTRL_IMX6SL) += pinctrl-imx6sl.o
obj-$(CONFIG_PINCTRL_IMX6SX) += pinctrl-imx6sx.o
obj-$(CONFIG_PINCTRL_FALCON) += pinctrl-falcon.o
obj-$(CONFIG_PINCTRL_MXS) += pinctrl-mxs.o
obj-$(CONFIG_PINCTRL_IMX23) += pinctrl-imx23.o
obj-$(CONFIG_PINCTRL_IMX25) += pinctrl-imx25.o
obj-$(CONFIG_PINCTRL_IMX28) += pinctrl-imx28.o
obj-$(CONFIG_PINCTRL_MSM) += pinctrl-msm.o
obj-$(CONFIG_PINCTRL_APQ8064) += pinctrl-apq8064.o
obj-$(CONFIG_PINCTRL_IPQ8064) += pinctrl-ipq8064.o
obj-$(CONFIG_PINCTRL_MSM8X74) += pinctrl-msm8x74.o
obj-$(CONFIG_PINCTRL_NOMADIK) += pinctrl-nomadik.o
obj-$(CONFIG_PINCTRL_STN8815) += pinctrl-nomadik-stn8815.o
......@@ -47,7 +50,6 @@ obj-$(CONFIG_PINCTRL_PALMAS) += pinctrl-palmas.o
obj-$(CONFIG_PINCTRL_ROCKCHIP) += pinctrl-rockchip.o
obj-$(CONFIG_PINCTRL_SINGLE) += pinctrl-single.o
obj-$(CONFIG_PINCTRL_SIRF) += sirf/
obj-$(CONFIG_PINCTRL_SUNXI) += pinctrl-sunxi.o
obj-$(CONFIG_PINCTRL_TEGRA) += pinctrl-tegra.o
obj-$(CONFIG_PINCTRL_TEGRA20) += pinctrl-tegra20.o
obj-$(CONFIG_PINCTRL_TEGRA30) += pinctrl-tegra30.o
......@@ -68,8 +70,10 @@ obj-$(CONFIG_PINCTRL_TB10X) += pinctrl-tb10x.o
obj-$(CONFIG_PINCTRL_ST) += pinctrl-st.o
obj-$(CONFIG_PINCTRL_VF610) += pinctrl-vf610.o
obj-$(CONFIG_ARCH_BERLIN) += berlin/
obj-$(CONFIG_PLAT_ORION) += mvebu/
obj-$(CONFIG_ARCH_SHMOBILE) += sh-pfc/
obj-$(CONFIG_SUPERH) += sh-pfc/
obj-$(CONFIG_PLAT_SPEAR) += spear/
obj-$(CONFIG_ARCH_VT8500) += vt8500/
obj-$(CONFIG_ARCH_SUNXI) += sunxi/
if ARCH_BERLIN
config PINCTRL_BERLIN
bool
select PINMUX
select REGMAP_MMIO
config PINCTRL_BERLIN_BG2
bool
select PINCTRL_BERLIN
config PINCTRL_BERLIN_BG2CD
bool
select PINCTRL_BERLIN
config PINCTRL_BERLIN_BG2Q
bool
select PINCTRL_BERLIN
endif
obj-$(CONFIG_PINCTRL_BERLIN) += berlin.o
obj-$(CONFIG_PINCTRL_BERLIN_BG2) += berlin-bg2.o
obj-$(CONFIG_PINCTRL_BERLIN_BG2CD) += berlin-bg2cd.o
obj-$(CONFIG_PINCTRL_BERLIN_BG2Q) += berlin-bg2q.o
This diff is collapsed.
/*
* Marvell Berlin BG2CD pinctrl driver.
*
* Copyright (C) 2014 Marvell Technology Group Ltd.
*
* Antoine Ténart <antoine.tenart@free-electrons.com>
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include "berlin.h"
static const struct berlin_desc_group berlin2cd_soc_pinctrl_groups[] = {
/* G */
BERLIN_PINCTRL_GROUP("G0", 0x00, 0x1, 0x00,
BERLIN_PINCTRL_FUNCTION(0x0, "jtag"),
BERLIN_PINCTRL_FUNCTION(0x1, "gpio"),
BERLIN_PINCTRL_FUNCTION(0x2, "led"),
BERLIN_PINCTRL_FUNCTION(0x3, "pwm")),
BERLIN_PINCTRL_GROUP("G1", 0x00, 0x2, 0x01,
BERLIN_PINCTRL_FUNCTION(0x0, "gpio"),
BERLIN_PINCTRL_FUNCTION(0x1, "sd0"),
BERLIN_PINCTRL_FUNCTION(0x6, "usb0_dbg"),
BERLIN_PINCTRL_FUNCTION(0x7, "usb1_dbg")),
BERLIN_PINCTRL_GROUP("G2", 0x00, 0x2, 0x02,
BERLIN_PINCTRL_FUNCTION(0x0, "gpio"),
BERLIN_PINCTRL_FUNCTION(0x1, "sd0"),
BERLIN_PINCTRL_FUNCTION(0x2, "fe"),
BERLIN_PINCTRL_FUNCTION(0x3, "pll"),
BERLIN_PINCTRL_FUNCTION(0x6, "usb0_dbg"),
BERLIN_PINCTRL_FUNCTION(0x7, "usb1_dbg")),
BERLIN_PINCTRL_GROUP("G3", 0x00, 0x2, 0x04,
BERLIN_PINCTRL_FUNCTION(0x0, "gpio"),
BERLIN_PINCTRL_FUNCTION(0x1, "sd0"),
BERLIN_PINCTRL_FUNCTION(0x2, "twsi2"),
BERLIN_PINCTRL_FUNCTION(0x3, "pll"),
BERLIN_PINCTRL_FUNCTION(0x4, "fe"),
BERLIN_PINCTRL_FUNCTION(0x6, "usb0_dbg"),
BERLIN_PINCTRL_FUNCTION(0x7, "usb1_dbg")),
BERLIN_PINCTRL_GROUP("G4", 0x00, 0x2, 0x06,
BERLIN_PINCTRL_FUNCTION(0x0, "gpio"),
BERLIN_PINCTRL_FUNCTION(0x1, "sd0"),
BERLIN_PINCTRL_FUNCTION(0x2, "twsi3"),
BERLIN_PINCTRL_FUNCTION(0x3, "pll"),
BERLIN_PINCTRL_FUNCTION(0x4, "pwm"),
BERLIN_PINCTRL_FUNCTION(0x6, "usb0_dbg"),
BERLIN_PINCTRL_FUNCTION(0x7, "usb1_dbg")),
BERLIN_PINCTRL_GROUP("G5", 0x00, 0x3, 0x08,
BERLIN_PINCTRL_FUNCTION(0x0, "gpio"),
BERLIN_PINCTRL_FUNCTION(0x1, "sd0"),
BERLIN_PINCTRL_FUNCTION(0x2, "twsi3"),
BERLIN_PINCTRL_FUNCTION(0x3, "arc"),
BERLIN_PINCTRL_FUNCTION(0x4, "pwm"),
BERLIN_PINCTRL_FUNCTION(0x6, "usb0_dbg"),
BERLIN_PINCTRL_FUNCTION(0x7, "usb1_dbg")),
BERLIN_PINCTRL_GROUP("G6", 0x00, 0x2, 0x0b,
BERLIN_PINCTRL_FUNCTION(0x0, "uart0"), /* RX/TX */
BERLIN_PINCTRL_FUNCTION(0x1, "gpio")),
BERLIN_PINCTRL_GROUP("G7", 0x00, 0x3, 0x0d,
BERLIN_PINCTRL_FUNCTION(0x0, "eddc"),
BERLIN_PINCTRL_FUNCTION(0x1, "twsi1"),
BERLIN_PINCTRL_FUNCTION(0x2, "gpio")),
BERLIN_PINCTRL_GROUP("G8", 0x00, 0x3, 0x10,
BERLIN_PINCTRL_FUNCTION(0x0, "ss0"),
BERLIN_PINCTRL_FUNCTION(0x1, "gpio")),
BERLIN_PINCTRL_GROUP("G9", 0x00, 0x3, 0x13,
BERLIN_PINCTRL_FUNCTION(0x0, "gpio"),
BERLIN_PINCTRL_FUNCTION(0x1, "spi1"),
BERLIN_PINCTRL_FUNCTION(0x2, "twsi0")),
BERLIN_PINCTRL_GROUP("G10", 0x00, 0x2, 0x16,
BERLIN_PINCTRL_FUNCTION(0x0, "spi1"),
BERLIN_PINCTRL_FUNCTION(0x1, "gpio")),
BERLIN_PINCTRL_GROUP("G11", 0x00, 0x2, 0x18,
BERLIN_PINCTRL_FUNCTION(0x0, "spi1"),
BERLIN_PINCTRL_FUNCTION(0x1, "gpio")),
BERLIN_PINCTRL_GROUP("G12", 0x00, 0x3, 0x1a,
BERLIN_PINCTRL_FUNCTION(0x0, "usb1"),
BERLIN_PINCTRL_FUNCTION(0x1, "gpio")),
BERLIN_PINCTRL_GROUP("G13", 0x04, 0x3, 0x00,
BERLIN_PINCTRL_FUNCTION(0x0, "nand"),
BERLIN_PINCTRL_FUNCTION(0x1, "usb0_dbg"),
BERLIN_PINCTRL_FUNCTION(0x2, "usb1_dbg")),
BERLIN_PINCTRL_GROUP("G14", 0x04, 0x1, 0x03,
BERLIN_PINCTRL_FUNCTION(0x0, "nand"),
BERLIN_PINCTRL_FUNCTION(0x1, "gpio")),
BERLIN_PINCTRL_GROUP("G15", 0x04, 0x2, 0x04,
BERLIN_PINCTRL_FUNCTION(0x0, "jtag"),
BERLIN_PINCTRL_FUNCTION(0x1, "gpio")),
BERLIN_PINCTRL_GROUP("G16", 0x04, 0x3, 0x06,
BERLIN_PINCTRL_FUNCTION_UNKNOWN),
BERLIN_PINCTRL_GROUP("G17", 0x04, 0x3, 0x09,
BERLIN_PINCTRL_FUNCTION_UNKNOWN),
BERLIN_PINCTRL_GROUP("G18", 0x04, 0x1, 0x0c,
BERLIN_PINCTRL_FUNCTION_UNKNOWN),
BERLIN_PINCTRL_GROUP("G19", 0x04, 0x1, 0x0d,
BERLIN_PINCTRL_FUNCTION_UNKNOWN),
BERLIN_PINCTRL_GROUP("G20", 0x04, 0x1, 0x0e,
BERLIN_PINCTRL_FUNCTION_UNKNOWN),
BERLIN_PINCTRL_GROUP("G21", 0x04, 0x3, 0x0f,
BERLIN_PINCTRL_FUNCTION_UNKNOWN),
BERLIN_PINCTRL_GROUP("G22", 0x04, 0x3, 0x12,
BERLIN_PINCTRL_FUNCTION_UNKNOWN),
BERLIN_PINCTRL_GROUP("G23", 0x04, 0x3, 0x15,
BERLIN_PINCTRL_FUNCTION_UNKNOWN),
BERLIN_PINCTRL_GROUP("G24", 0x04, 0x2, 0x18,
BERLIN_PINCTRL_FUNCTION_UNKNOWN),
BERLIN_PINCTRL_GROUP("G25", 0x04, 0x2, 0x1a,
BERLIN_PINCTRL_FUNCTION_UNKNOWN),
BERLIN_PINCTRL_GROUP("G26", 0x04, 0x1, 0x1c,
BERLIN_PINCTRL_FUNCTION_UNKNOWN),
BERLIN_PINCTRL_GROUP("G27", 0x04, 0x1, 0x1d,
BERLIN_PINCTRL_FUNCTION_UNKNOWN),
BERLIN_PINCTRL_GROUP("G28", 0x04, 0x2, 0x1e,
BERLIN_PINCTRL_FUNCTION_UNKNOWN),
};
static const struct berlin_desc_group berlin2cd_sysmgr_pinctrl_groups[] = {
/* GSM */
BERLIN_PINCTRL_GROUP("GSM0", 0x40, 0x2, 0x00,
BERLIN_PINCTRL_FUNCTION_UNKNOWN),
BERLIN_PINCTRL_GROUP("GSM1", 0x40, 0x2, 0x02,
BERLIN_PINCTRL_FUNCTION_UNKNOWN),
BERLIN_PINCTRL_GROUP("GSM2", 0x40, 0x2, 0x04,
BERLIN_PINCTRL_FUNCTION_UNKNOWN),
BERLIN_PINCTRL_GROUP("GSM3", 0x40, 0x2, 0x06,
BERLIN_PINCTRL_FUNCTION_UNKNOWN),
BERLIN_PINCTRL_GROUP("GSM4", 0x40, 0x2, 0x08,
BERLIN_PINCTRL_FUNCTION_UNKNOWN),
BERLIN_PINCTRL_GROUP("GSM5", 0x40, 0x2, 0x0a,
BERLIN_PINCTRL_FUNCTION_UNKNOWN),
BERLIN_PINCTRL_GROUP("GSM6", 0x40, 0x2, 0x0c,
BERLIN_PINCTRL_FUNCTION_UNKNOWN),
BERLIN_PINCTRL_GROUP("GSM7", 0x40, 0x1, 0x0e,
BERLIN_PINCTRL_FUNCTION_UNKNOWN),
BERLIN_PINCTRL_GROUP("GSM8", 0x40, 0x1, 0x0f,
BERLIN_PINCTRL_FUNCTION_UNKNOWN),
BERLIN_PINCTRL_GROUP("GSM9", 0x40, 0x1, 0x10,
BERLIN_PINCTRL_FUNCTION_UNKNOWN),
BERLIN_PINCTRL_GROUP("GSM10", 0x40, 0x1, 0x11,
BERLIN_PINCTRL_FUNCTION_UNKNOWN),
BERLIN_PINCTRL_GROUP("GSM11", 0x40, 0x1, 0x12,
BERLIN_PINCTRL_FUNCTION_UNKNOWN),
};
static const struct berlin_pinctrl_desc berlin2cd_soc_pinctrl_data = {
.groups = berlin2cd_soc_pinctrl_groups,
.ngroups = ARRAY_SIZE(berlin2cd_soc_pinctrl_groups),
};
static const struct berlin_pinctrl_desc berlin2cd_sysmgr_pinctrl_data = {
.groups = berlin2cd_sysmgr_pinctrl_groups,
.ngroups = ARRAY_SIZE(berlin2cd_sysmgr_pinctrl_groups),
};
static const struct of_device_id berlin2cd_pinctrl_match[] = {
{
.compatible = "marvell,berlin2cd-chip-ctrl",
.data = &berlin2cd_soc_pinctrl_data
},
{
.compatible = "marvell,berlin2cd-system-ctrl",
.data = &berlin2cd_sysmgr_pinctrl_data
},
{}
};
MODULE_DEVICE_TABLE(of, berlin2cd_pinctrl_match);
static int berlin2cd_pinctrl_probe(struct platform_device *pdev)
{
const struct of_device_id *match =
of_match_device(berlin2cd_pinctrl_match, &pdev->dev);
struct regmap_config *rmconfig;
struct regmap *regmap;
struct resource *res;
void __iomem *base;
rmconfig = devm_kzalloc(&pdev->dev, sizeof(*rmconfig), GFP_KERNEL);
if (!rmconfig)
return -ENOMEM;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(base))
return PTR_ERR(base);
rmconfig->reg_bits = 32,
rmconfig->val_bits = 32,
rmconfig->reg_stride = 4,
rmconfig->max_register = resource_size(res);
regmap = devm_regmap_init_mmio(&pdev->dev, base, rmconfig);
if (IS_ERR(regmap))
return PTR_ERR(regmap);
return berlin_pinctrl_probe(pdev, match->data);
}
static struct platform_driver berlin2cd_pinctrl_driver = {
.probe = berlin2cd_pinctrl_probe,
.driver = {
.name = "berlin-bg2cd-pinctrl",
.owner = THIS_MODULE,
.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");
This diff is collapsed.
/*
* Marvell Berlin SoC pinctrl core driver
*
* Copyright (C) 2014 Marvell Technology Group Ltd.
*
* Antoine Ténart <antoine.tenart@free-electrons.com>
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
#include <linux/io.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_device.h>
#include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/pinmux.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/slab.h>
#include "../core.h"
#include "../pinctrl-utils.h"
#include "berlin.h"
struct berlin_pinctrl {
struct regmap *regmap;
struct device *dev;
const struct berlin_pinctrl_desc *desc;
struct berlin_pinctrl_function *functions;
unsigned nfunctions;
struct pinctrl_dev *pctrl_dev;
};
static int berlin_pinctrl_get_group_count(struct pinctrl_dev *pctrl_dev)
{
struct berlin_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctrl_dev);
return pctrl->desc->ngroups;
}
static const char *berlin_pinctrl_get_group_name(struct pinctrl_dev *pctrl_dev,
unsigned group)
{
struct berlin_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctrl_dev);
return pctrl->desc->groups[group].name;
}
static int berlin_pinctrl_dt_node_to_map(struct pinctrl_dev *pctrl_dev,
struct device_node *node,
struct pinctrl_map **map,
unsigned *num_maps)
{
struct berlin_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctrl_dev);
struct property *prop;
const char *function_name, *group_name;
unsigned reserved_maps = 0;
int ret, ngroups;
*map = NULL;
*num_maps = 0;
ret = of_property_read_string(node, "function", &function_name);
if (ret) {
dev_err(pctrl->dev,
"missing function property in node %s\n",
node->name);
return -EINVAL;
}
ngroups = of_property_count_strings(node, "groups");
if (ngroups < 0) {
dev_err(pctrl->dev,
"missing groups property in node %s\n",
node->name);
return -EINVAL;
}
ret = pinctrl_utils_reserve_map(pctrl_dev, map, &reserved_maps,
num_maps, ngroups);
if (ret) {
dev_err(pctrl->dev, "can't reserve map: %d\n", ret);
return ret;
}
of_property_for_each_string(node, "groups", prop, group_name) {
ret = pinctrl_utils_add_map_mux(pctrl_dev, map, &reserved_maps,
num_maps, group_name,
function_name);
if (ret) {
dev_err(pctrl->dev, "can't add map: %d\n", ret);
return ret;
}
}
return 0;
}
static void berlin_pinctrl_dt_free_map(struct pinctrl_dev *pctrl_dev,
struct pinctrl_map *map,
unsigned nmaps)
{
int i;
for (i = 0; i < nmaps; i++) {
if (map[i].type == PIN_MAP_TYPE_MUX_GROUP) {
kfree(map[i].data.mux.group);
/* a function can be applied to multiple groups */
if (i == 0)
kfree(map[i].data.mux.function);
}
}
kfree(map);
}
static const struct pinctrl_ops berlin_pinctrl_ops = {
.get_groups_count = &berlin_pinctrl_get_group_count,
.get_group_name = &berlin_pinctrl_get_group_name,
.dt_node_to_map = &berlin_pinctrl_dt_node_to_map,
.dt_free_map = &berlin_pinctrl_dt_free_map,
};
static int berlin_pinmux_get_functions_count(struct pinctrl_dev *pctrl_dev)
{
struct berlin_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctrl_dev);
return pctrl->nfunctions;
}
static const char *berlin_pinmux_get_function_name(struct pinctrl_dev *pctrl_dev,
unsigned function)
{
struct berlin_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctrl_dev);
return pctrl->functions[function].name;
}
static int berlin_pinmux_get_function_groups(struct pinctrl_dev *pctrl_dev,
unsigned function,
const char * const **groups,
unsigned * const num_groups)
{
struct berlin_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctrl_dev);
*groups = pctrl->functions[function].groups;
*num_groups = pctrl->functions[function].ngroups;
return 0;
}
static struct berlin_desc_function *
berlin_pinctrl_find_function_by_name(struct berlin_pinctrl *pctrl,
const struct berlin_desc_group *group,
const char *fname)
{
struct berlin_desc_function *function = group->functions;
while (function->name) {
if (!strcmp(function->name, fname))
return function;
function++;
}
return NULL;
}
static int berlin_pinmux_enable(struct pinctrl_dev *pctrl_dev,
unsigned function,
unsigned group)
{
struct berlin_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctrl_dev);
const struct berlin_desc_group *group_desc = pctrl->desc->groups + group;
struct berlin_pinctrl_function *func = pctrl->functions + function;
struct berlin_desc_function *function_desc =
berlin_pinctrl_find_function_by_name(pctrl, group_desc,
func->name);
u32 mask, val;
if (!function_desc)
return -EINVAL;
mask = GENMASK(group_desc->lsb + group_desc->bit_width - 1,
group_desc->lsb);
val = function_desc->muxval << group_desc->lsb;
regmap_update_bits(pctrl->regmap, group_desc->offset, mask, val);
return 0;
}
static const struct pinmux_ops berlin_pinmux_ops = {
.get_functions_count = &berlin_pinmux_get_functions_count,
.get_function_name = &berlin_pinmux_get_function_name,
.get_function_groups = &berlin_pinmux_get_function_groups,
.enable = &berlin_pinmux_enable,
};
static int berlin_pinctrl_add_function(struct berlin_pinctrl *pctrl,
const char *name)
{
struct berlin_pinctrl_function *function = pctrl->functions;
while (function->name) {
if (!strcmp(function->name, name)) {
function->ngroups++;
return -EEXIST;
}
function++;
}
function->name = name;
function->ngroups = 1;
pctrl->nfunctions++;
return 0;
}
static int berlin_pinctrl_build_state(struct platform_device *pdev)
{
struct berlin_pinctrl *pctrl = platform_get_drvdata(pdev);
struct berlin_desc_group const *desc_group;
struct berlin_desc_function const *desc_function;
int i, max_functions = 0;
pctrl->nfunctions = 0;
for (i = 0; i < pctrl->desc->ngroups; i++) {
desc_group = pctrl->desc->groups + i;
/* compute the maxiumum number of functions a group can have */
max_functions += 1 << (desc_group->bit_width + 1);
}
/* we will reallocate later */
pctrl->functions = devm_kzalloc(&pdev->dev,
max_functions * sizeof(*pctrl->functions),
GFP_KERNEL);
if (!pctrl->functions)
return -ENOMEM;
/* register all functions */
for (i = 0; i < pctrl->desc->ngroups; i++) {
desc_group = pctrl->desc->groups + i;
desc_function = desc_group->functions;
while (desc_function->name) {
berlin_pinctrl_add_function(pctrl, desc_function->name);
desc_function++;
}
}
pctrl->functions = krealloc(pctrl->functions,
pctrl->nfunctions * sizeof(*pctrl->functions),
GFP_KERNEL);
/* map functions to theirs groups */
for (i = 0; i < pctrl->desc->ngroups; i++) {
desc_group = pctrl->desc->groups + i;
desc_function = desc_group->functions;
while (desc_function->name) {
struct berlin_pinctrl_function
*function = pctrl->functions;
const char **groups;
bool found = false;
while (function->name) {
if (!strcmp(desc_function->name, function->name)) {
found = true;
break;
}
function++;
}
if (!found)
return -EINVAL;
if (!function->groups) {
function->groups =
devm_kzalloc(&pdev->dev,
function->ngroups * sizeof(char *),
GFP_KERNEL);
if (!function->groups)
return -ENOMEM;
}
groups = function->groups;
while (*groups)
groups++;
*groups = desc_group->name;
desc_function++;
}
}
return 0;
}
static struct pinctrl_desc berlin_pctrl_desc = {
.name = "berlin-pinctrl",
.pctlops = &berlin_pinctrl_ops,
.pmxops = &berlin_pinmux_ops,
.owner = THIS_MODULE,
};
int berlin_pinctrl_probe(struct platform_device *pdev,
const struct berlin_pinctrl_desc *desc)
{
struct device *dev = &pdev->dev;
struct berlin_pinctrl *pctrl;
struct regmap *regmap;
int ret;
regmap = dev_get_regmap(&pdev->dev, NULL);
if (!regmap)
return PTR_ERR(regmap);
pctrl = devm_kzalloc(dev, sizeof(*pctrl), GFP_KERNEL);
if (!pctrl)
return -ENOMEM;
platform_set_drvdata(pdev, pctrl);
pctrl->regmap = regmap;
pctrl->dev = &pdev->dev;
pctrl->desc = desc;
ret = berlin_pinctrl_build_state(pdev);
if (ret) {
dev_err(dev, "cannot build driver state: %d\n", ret);
return ret;
}
pctrl->pctrl_dev = pinctrl_register(&berlin_pctrl_desc, dev, pctrl);
if (!pctrl->pctrl_dev) {
dev_err(dev, "failed to register pinctrl driver\n");
return -EINVAL;
}
return 0;
}
/*
* Marvell Berlin SoC pinctrl driver.
*
* Copyright (C) 2014 Marvell Technology Group Ltd.
*
* Antoine Ténart <antoine.tenart@free-electrons.com>
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
#ifndef __PINCTRL_BERLIN_H
#define __PINCTRL_BERLIN_H
struct berlin_desc_function {
const char *name;
u8 muxval;
};
struct berlin_desc_group {
const char *name;
u8 offset;
u8 bit_width;
u8 lsb;
struct berlin_desc_function *functions;
};
struct berlin_pinctrl_desc {
const struct berlin_desc_group *groups;
unsigned ngroups;
};
struct berlin_pinctrl_function {
const char *name;
const char **groups;
unsigned ngroups;
};
#define BERLIN_PINCTRL_GROUP(_name, _offset, _width, _lsb, ...) \
{ \
.name = _name, \
.offset = _offset, \
.bit_width = _width, \
.lsb = _lsb, \
.functions = (struct berlin_desc_function[]){ \
__VA_ARGS__, { } }, \
}
#define BERLIN_PINCTRL_FUNCTION(_muxval, _name) \
{ \
.name = _name, \
.muxval = _muxval, \
}
#define BERLIN_PINCTRL_FUNCTION_UNKNOWN {}
int berlin_pinctrl_probe(struct platform_device *pdev,
const struct berlin_pinctrl_desc *desc);
#endif /* __PINCTRL_BERLIN_H */
......@@ -468,6 +468,9 @@ int pinctrl_get_group_pins(struct pinctrl_dev *pctldev, const char *pin_group,
const struct pinctrl_ops *pctlops = pctldev->desc->pctlops;
int gs;
if (!pctlops->get_group_pins)
return -EINVAL;
gs = pinctrl_get_group_selector(pctldev, pin_group);
if (gs < 0)
return gs;
......@@ -1362,15 +1365,16 @@ static int pinctrl_groups_show(struct seq_file *s, void *what)
seq_puts(s, "registered pin groups:\n");
while (selector < ngroups) {
const unsigned *pins;
unsigned num_pins;
const unsigned *pins = NULL;
unsigned num_pins = 0;
const char *gname = ops->get_group_name(pctldev, selector);
const char *pname;
int ret;
int ret = 0;
int i;
ret = ops->get_group_pins(pctldev, selector,
&pins, &num_pins);
if (ops->get_group_pins)
ret = ops->get_group_pins(pctldev, selector,
&pins, &num_pins);
if (ret)
seq_printf(s, "%s [ERROR GETTING PINS]\n",
gname);
......@@ -1694,8 +1698,7 @@ static int pinctrl_check_ops(struct pinctrl_dev *pctldev)
if (!ops ||
!ops->get_groups_count ||
!ops->get_group_name ||
!ops->get_group_pins)
!ops->get_group_name)
return -EINVAL;
if (ops->dt_node_to_map && !ops->dt_free_map)
......
......@@ -30,4 +30,8 @@ config PINCTRL_ARMADA_XP
bool
select PINCTRL_MVEBU
config PINCTRL_ORION
bool
select PINCTRL_MVEBU
endif
......@@ -5,3 +5,4 @@ obj-$(CONFIG_PINCTRL_ARMADA_370) += pinctrl-armada-370.o
obj-$(CONFIG_PINCTRL_ARMADA_375) += pinctrl-armada-375.o
obj-$(CONFIG_PINCTRL_ARMADA_38X) += pinctrl-armada-38x.o
obj-$(CONFIG_PINCTRL_ARMADA_XP) += pinctrl-armada-xp.o
obj-$(CONFIG_PINCTRL_ORION) += pinctrl-orion.o
/*
* Marvell Orion pinctrl driver based on mvebu pinctrl core
*
* Author: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* The first 16 MPP pins on Orion are easy to handle: they are
* configured through 2 consecutive registers, located at the base
* address of the MPP device.
*
* However the last 4 MPP pins are handled by a register at offset
* 0x50 from the base address, so it is not consecutive with the first
* two registers.
*/
#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>
#include <linux/of_device.h>
#include <linux/pinctrl/pinctrl.h>
#include "pinctrl-mvebu.h"
static void __iomem *mpp_base;
static void __iomem *high_mpp_base;
static int orion_mpp_ctrl_get(unsigned pid, unsigned long *config)
{
unsigned shift = (pid % MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;
if (pid < 16) {
unsigned off = (pid / MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;
*config = (readl(mpp_base + off) >> shift) & MVEBU_MPP_MASK;
}
else {
*config = (readl(high_mpp_base) >> shift) & MVEBU_MPP_MASK;
}
return 0;
}
static int orion_mpp_ctrl_set(unsigned pid, unsigned long config)
{
unsigned shift = (pid % MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;
if (pid < 16) {
unsigned off = (pid / MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;
u32 reg = readl(mpp_base + off) & ~(MVEBU_MPP_MASK << shift);
writel(reg | (config << shift), mpp_base + off);
}
else {
u32 reg = readl(high_mpp_base) & ~(MVEBU_MPP_MASK << shift);
writel(reg | (config << shift), high_mpp_base);
}
return 0;
}
#define V(f5181l, f5182, f5281) \
((f5181l << 0) | (f5182 << 1) | (f5281 << 2))
enum orion_variant {
V_5181L = V(1, 0, 0),
V_5182 = V(0, 1, 0),
V_5281 = V(0, 0, 1),
V_ALL = V(1, 1, 1),
};
static struct mvebu_mpp_mode orion_mpp_modes[] = {
MPP_MODE(0,
MPP_VAR_FUNCTION(0x0, "pcie", "rstout", V_ALL),
MPP_VAR_FUNCTION(0x2, "pci", "req2", V_ALL),
MPP_VAR_FUNCTION(0x3, "gpio", NULL, V_ALL)),
MPP_MODE(1,
MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_ALL),
MPP_VAR_FUNCTION(0x2, "pci", "gnt2", V_ALL)),
MPP_MODE(2,
MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_ALL),
MPP_VAR_FUNCTION(0x2, "pci", "req3", V_ALL),
MPP_VAR_FUNCTION(0x3, "pci-1", "pme", V_ALL)),
MPP_MODE(3,
MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_ALL),
MPP_VAR_FUNCTION(0x2, "pci", "gnt3", V_ALL)),
MPP_MODE(4,
MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_ALL),
MPP_VAR_FUNCTION(0x2, "pci", "req4", V_ALL),
MPP_VAR_FUNCTION(0x4, "bootnand", "re", V_5182 | V_5281),
MPP_VAR_FUNCTION(0x5, "sata0", "prsnt", V_5182)),
MPP_MODE(5,
MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_ALL),
MPP_VAR_FUNCTION(0x2, "pci", "gnt4", V_ALL),
MPP_VAR_FUNCTION(0x4, "bootnand", "we", V_5182 | V_5281),
MPP_VAR_FUNCTION(0x5, "sata1", "prsnt", V_5182)),
MPP_MODE(6,
MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_ALL),
MPP_VAR_FUNCTION(0x2, "pci", "req5", V_ALL),
MPP_VAR_FUNCTION(0x4, "nand", "re0", V_5182 | V_5281),
MPP_VAR_FUNCTION(0x5, "pci-1", "clk", V_5181L),
MPP_VAR_FUNCTION(0x5, "sata0", "act", V_5182)),
MPP_MODE(7,
MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_ALL),
MPP_VAR_FUNCTION(0x2, "pci", "gnt5", V_ALL),
MPP_VAR_FUNCTION(0x4, "nand", "we0", V_5182 | V_5281),
MPP_VAR_FUNCTION(0x5, "pci-1", "clk", V_5181L),
MPP_VAR_FUNCTION(0x5, "sata1", "act", V_5182)),
MPP_MODE(8,
MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_ALL),
MPP_VAR_FUNCTION(0x1, "ge", "col", V_ALL)),
MPP_MODE(9,
MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_ALL),
MPP_VAR_FUNCTION(0x1, "ge", "rxerr", V_ALL)),
MPP_MODE(10,
MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_ALL),
MPP_VAR_FUNCTION(0x1, "ge", "crs", V_ALL)),
MPP_MODE(11,
MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_ALL),
MPP_VAR_FUNCTION(0x1, "ge", "txerr", V_ALL)),
MPP_MODE(12,
MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_ALL),
MPP_VAR_FUNCTION(0x1, "ge", "txd4", V_ALL),
MPP_VAR_FUNCTION(0x4, "nand", "re1", V_5182 | V_5281),
MPP_VAR_FUNCTION(0x5, "sata0", "ledprsnt", V_5182)),
MPP_MODE(13,
MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_ALL),
MPP_VAR_FUNCTION(0x1, "ge", "txd5", V_ALL),
MPP_VAR_FUNCTION(0x4, "nand", "we1", V_5182 | V_5281),
MPP_VAR_FUNCTION(0x5, "sata1", "ledprsnt", V_5182)),
MPP_MODE(14,
MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_ALL),
MPP_VAR_FUNCTION(0x1, "ge", "txd6", V_ALL),
MPP_VAR_FUNCTION(0x4, "nand", "re2", V_5182 | V_5281),
MPP_VAR_FUNCTION(0x5, "sata0", "ledact", V_5182)),
MPP_MODE(15,
MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_ALL),
MPP_VAR_FUNCTION(0x1, "ge", "txd7", V_ALL),
MPP_VAR_FUNCTION(0x4, "nand", "we2", V_5182 | V_5281),
MPP_VAR_FUNCTION(0x5, "sata1", "ledact", V_5182)),
MPP_MODE(16,
MPP_VAR_FUNCTION(0x0, "uart1", "rxd", V_5182 | V_5281),
MPP_VAR_FUNCTION(0x1, "ge", "rxd4", V_ALL),
MPP_VAR_FUNCTION(0x5, "gpio", NULL, V_5182)),
MPP_MODE(17,
MPP_VAR_FUNCTION(0x0, "uart1", "txd", V_5182 | V_5281),
MPP_VAR_FUNCTION(0x1, "ge", "rxd5", V_ALL),
MPP_VAR_FUNCTION(0x5, "gpio", NULL, V_5182)),
MPP_MODE(18,
MPP_VAR_FUNCTION(0x0, "uart1", "cts", V_5182 | V_5281),
MPP_VAR_FUNCTION(0x1, "ge", "rxd6", V_ALL),
MPP_VAR_FUNCTION(0x5, "gpio", NULL, V_5182)),
MPP_MODE(19,
MPP_VAR_FUNCTION(0x0, "uart1", "rts", V_5182 | V_5281),
MPP_VAR_FUNCTION(0x1, "ge", "rxd7", V_ALL),
MPP_VAR_FUNCTION(0x5, "gpio", NULL, V_5182)),
};
static struct mvebu_mpp_ctrl orion_mpp_controls[] = {
MPP_FUNC_CTRL(0, 19, NULL, orion_mpp_ctrl),
};
static struct pinctrl_gpio_range mv88f5181l_gpio_ranges[] = {
MPP_GPIO_RANGE(0, 0, 0, 16),
};
static struct pinctrl_gpio_range mv88f5182_gpio_ranges[] = {
MPP_GPIO_RANGE(0, 0, 0, 19),
};
static struct pinctrl_gpio_range mv88f5281_gpio_ranges[] = {
MPP_GPIO_RANGE(0, 0, 0, 16),
};
static struct mvebu_pinctrl_soc_info mv88f5181l_info = {
.variant = V_5181L,
.controls = orion_mpp_controls,
.ncontrols = ARRAY_SIZE(orion_mpp_controls),
.modes = orion_mpp_modes,
.nmodes = ARRAY_SIZE(orion_mpp_modes),
.gpioranges = mv88f5181l_gpio_ranges,
.ngpioranges = ARRAY_SIZE(mv88f5181l_gpio_ranges),
};
static struct mvebu_pinctrl_soc_info mv88f5182_info = {
.variant = V_5182,
.controls = orion_mpp_controls,
.ncontrols = ARRAY_SIZE(orion_mpp_controls),
.modes = orion_mpp_modes,
.nmodes = ARRAY_SIZE(orion_mpp_modes),
.gpioranges = mv88f5182_gpio_ranges,
.ngpioranges = ARRAY_SIZE(mv88f5182_gpio_ranges),
};
static struct mvebu_pinctrl_soc_info mv88f5281_info = {
.variant = V_5281,
.controls = orion_mpp_controls,
.ncontrols = ARRAY_SIZE(orion_mpp_controls),
.modes = orion_mpp_modes,
.nmodes = ARRAY_SIZE(orion_mpp_modes),
.gpioranges = mv88f5281_gpio_ranges,
.ngpioranges = ARRAY_SIZE(mv88f5281_gpio_ranges),
};
/*
* There are multiple variants of the Orion SoCs, but in terms of pin
* muxing, they are identical.
*/
static struct of_device_id orion_pinctrl_of_match[] = {
{ .compatible = "marvell,88f5181l-pinctrl", .data = &mv88f5181l_info },
{ .compatible = "marvell,88f5182-pinctrl", .data = &mv88f5182_info },
{ .compatible = "marvell,88f5281-pinctrl", .data = &mv88f5281_info },
{ }
};
static int orion_pinctrl_probe(struct platform_device *pdev)
{
const struct of_device_id *match =
of_match_device(orion_pinctrl_of_match, &pdev->dev);
struct resource *res;
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);
res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
high_mpp_base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(high_mpp_base))
return PTR_ERR(high_mpp_base);
return mvebu_pinctrl_probe(pdev);
}
static int orion_pinctrl_remove(struct platform_device *pdev)
{
return mvebu_pinctrl_remove(pdev);
}
static struct platform_driver orion_pinctrl_driver = {
.driver = {
.name = "orion-pinctrl",
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(orion_pinctrl_of_match),
},
.probe = orion_pinctrl_probe,
.remove = orion_pinctrl_remove,
};
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");
......@@ -166,6 +166,7 @@ static struct pinconf_generic_dt_params dt_params[] = {
{ "input-schmitt-enable", PIN_CONFIG_INPUT_SCHMITT_ENABLE, 1 },
{ "input-schmitt-disable", PIN_CONFIG_INPUT_SCHMITT_ENABLE, 0 },
{ "input-debounce", PIN_CONFIG_INPUT_DEBOUNCE, 0 },
{ "power-source", PIN_CONFIG_POWER_SOURCE, 0 },
{ "low-power-enable", PIN_CONFIG_LOW_POWER_MODE, 1 },
{ "low-power-disable", PIN_CONFIG_LOW_POWER_MODE, 0 },
{ "output-low", PIN_CONFIG_OUTPUT, 0, },
......@@ -228,13 +229,12 @@ int pinconf_generic_parse_dt_config(struct device_node *np,
* Now limit the number of configs to the real number of
* found properties.
*/
*configs = kzalloc(ncfg * sizeof(unsigned long), GFP_KERNEL);
*configs = kmemdup(cfg, ncfg * sizeof(unsigned long), GFP_KERNEL);
if (!*configs) {
ret = -ENOMEM;
goto out;
}
memcpy(*configs, cfg, ncfg * sizeof(unsigned long));
*nconfigs = ncfg;
out:
......
......@@ -927,7 +927,7 @@ static int adi_gpio_irq_map(struct irq_domain *d, unsigned int irq,
return 0;
}
const struct irq_domain_ops adi_gpio_irq_domain_ops = {
static const struct irq_domain_ops adi_gpio_irq_domain_ops = {
.map = adi_gpio_irq_map,
.xlate = irq_domain_xlate_onecell,
};
......
This diff is collapsed.
......@@ -16,9 +16,6 @@
#include <linux/of_irq.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/irqdomain.h>
#include <linux/irqchip/chained_irq.h>
#include <linux/io.h>
#include <linux/gpio.h>
#include <linux/pinctrl/machine.h>
......@@ -47,7 +44,6 @@ struct at91_gpio_chip {
int pioc_idx; /* PIO bank index */
void __iomem *regbase; /* PIO bank virtual address */
struct clk *clock; /* associated clock */
struct irq_domain *domain; /* associated irq domain */
struct at91_pinctrl_mux_ops *ops; /* ops */
};
......@@ -1192,21 +1188,6 @@ static int at91_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
return 0;
}
static int at91_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
{
struct at91_gpio_chip *at91_gpio = to_at91_gpio_chip(chip);
int virq;
if (offset < chip->ngpio)
virq = irq_create_mapping(at91_gpio->domain, offset);
else
virq = -ENXIO;
dev_dbg(chip->dev, "%s: request IRQ for GPIO %d, return %d\n",
chip->label, offset + chip->base, virq);
return virq;
}
#ifdef CONFIG_DEBUG_FS
static void at91_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
{
......@@ -1216,8 +1197,7 @@ static void at91_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
void __iomem *pio = at91_gpio->regbase;
for (i = 0; i < chip->ngpio; i++) {
unsigned pin = chip->base + i;
unsigned mask = pin_to_mask(pin);
unsigned mask = pin_to_mask(i);
const char *gpio_label;
u32 pdsr;
......@@ -1336,6 +1316,11 @@ static int alt_gpio_irq_type(struct irq_data *d, unsigned type)
return 0;
}
static void gpio_irq_ack(struct irq_data *d)
{
/* the interrupt is already cleared before by reading ISR */
}
static unsigned int gpio_irq_startup(struct irq_data *d)
{
struct at91_gpio_chip *at91_gpio = irq_data_get_irq_chip_data(d);
......@@ -1435,6 +1420,7 @@ void at91_pinctrl_gpio_resume(void)
static struct irq_chip gpio_irqchip = {
.name = "GPIO",
.irq_ack = gpio_irq_ack,
.irq_startup = gpio_irq_startup,
.irq_shutdown = gpio_irq_shutdown,
.irq_disable = gpio_irq_mask,
......@@ -1446,9 +1432,11 @@ static struct irq_chip gpio_irqchip = {
static void gpio_irq_handler(unsigned irq, struct irq_desc *desc)
{
struct irq_chip *chip = irq_desc_get_chip(desc);
struct irq_data *idata = irq_desc_get_irq_data(desc);
struct at91_gpio_chip *at91_gpio = irq_data_get_irq_chip_data(idata);
struct irq_chip *chip = irq_get_chip(irq);
struct gpio_chip *gpio_chip = irq_desc_get_handler_data(desc);
struct at91_gpio_chip *at91_gpio = container_of(gpio_chip,
struct at91_gpio_chip, chip);
void __iomem *pio = at91_gpio->regbase;
unsigned long isr;
int n;
......@@ -1465,85 +1453,25 @@ static void gpio_irq_handler(unsigned irq, struct irq_desc *desc)
break;
at91_gpio = at91_gpio->next;
pio = at91_gpio->regbase;
gpio_chip = &at91_gpio->chip;
continue;
}
for_each_set_bit(n, &isr, BITS_PER_LONG) {
generic_handle_irq(irq_find_mapping(at91_gpio->domain, n));
generic_handle_irq(irq_find_mapping(
gpio_chip->irqdomain, n));
}
}
chained_irq_exit(chip, desc);
/* now it may re-trigger */
}
/*
* This lock class tells lockdep that GPIO irqs are in a different
* category than their parents, so it won't report false recursion.
*/
static struct lock_class_key gpio_lock_class;
static int at91_gpio_irq_map(struct irq_domain *h, unsigned int virq,
irq_hw_number_t hw)
{
struct at91_gpio_chip *at91_gpio = h->host_data;
void __iomem *pio = at91_gpio->regbase;
u32 mask = 1 << hw;
irq_set_lockdep_class(virq, &gpio_lock_class);
/*
* Can use the "simple" and not "edge" handler since it's
* shorter, and the AIC handles interrupts sanely.
*/
irq_set_chip(virq, &gpio_irqchip);
if ((at91_gpio->ops == &at91sam9x5_ops) &&
(readl_relaxed(pio + PIO_AIMMR) & mask) &&
(readl_relaxed(pio + PIO_ELSR) & mask))
irq_set_handler(virq, handle_level_irq);
else
irq_set_handler(virq, handle_simple_irq);
set_irq_flags(virq, IRQF_VALID);
irq_set_chip_data(virq, at91_gpio);
return 0;
}
static int at91_gpio_irq_domain_xlate(struct irq_domain *d,
struct device_node *ctrlr,
const u32 *intspec, unsigned int intsize,
irq_hw_number_t *out_hwirq,
unsigned int *out_type)
{
struct at91_gpio_chip *at91_gpio = d->host_data;
int ret;
int pin = at91_gpio->chip.base + intspec[0];
if (WARN_ON(intsize < 2))
return -EINVAL;
*out_hwirq = intspec[0];
*out_type = intspec[1] & IRQ_TYPE_SENSE_MASK;
ret = gpio_request(pin, ctrlr->full_name);
if (ret)
return ret;
ret = gpio_direction_input(pin);
if (ret)
return ret;
return 0;
}
static struct irq_domain_ops at91_gpio_ops = {
.map = at91_gpio_irq_map,
.xlate = at91_gpio_irq_domain_xlate,
};
static int at91_gpio_of_irq_setup(struct device_node *node,
struct at91_gpio_chip *at91_gpio)
{
struct at91_gpio_chip *prev = NULL;
struct at91_gpio_chip *prev = NULL;
struct irq_data *d = irq_get_irq_data(at91_gpio->pioc_virq);
int ret;
at91_gpio->pioc_hwirq = irqd_to_hwirq(d);
......@@ -1553,10 +1481,17 @@ static int at91_gpio_of_irq_setup(struct device_node *node,
/* Disable irqs of this PIO controller */
writel_relaxed(~0, at91_gpio->regbase + PIO_IDR);
/* Setup irq domain */
at91_gpio->domain = irq_domain_add_linear(node, at91_gpio->chip.ngpio,
&at91_gpio_ops, at91_gpio);
if (!at91_gpio->domain)
/*
* Let the generic code handle this edge IRQ, the the chained
* handler will perform the actual work of handling the parent
* interrupt.
*/
ret = gpiochip_irqchip_add(&at91_gpio->chip,
&gpio_irqchip,
0,
handle_edge_irq,
IRQ_TYPE_EDGE_BOTH);
if (ret)
panic("at91_gpio.%d: couldn't allocate irq domain (DT).\n",
at91_gpio->pioc_idx);
......@@ -1571,8 +1506,11 @@ static int at91_gpio_of_irq_setup(struct device_node *node,
if (prev && prev->next == at91_gpio)
return 0;
irq_set_chip_data(at91_gpio->pioc_virq, at91_gpio);
irq_set_chained_handler(at91_gpio->pioc_virq, gpio_irq_handler);
/* Then register the chain on the parent IRQ */
gpiochip_set_chained_irqchip(&at91_gpio->chip,
&gpio_irqchip,
at91_gpio->pioc_virq,
gpio_irq_handler);
return 0;
}
......@@ -1586,7 +1524,6 @@ static struct gpio_chip at91_gpio_template = {
.get = at91_gpio_get,
.direction_output = at91_gpio_direction_output,
.set = at91_gpio_set,
.to_irq = at91_gpio_to_irq,
.dbg_show = at91_gpio_dbg_show,
.can_sleep = false,
.ngpio = MAX_NB_GPIO_PER_BANK,
......
......@@ -43,9 +43,20 @@
#define BYT_INT_STAT_REG 0x800
/* BYT_CONF0_REG register bits */
#define BYT_IODEN BIT(31)
#define BYT_TRIG_NEG BIT(26)
#define BYT_TRIG_POS BIT(25)
#define BYT_TRIG_LVL BIT(24)
#define BYT_PULL_STR_SHIFT 9
#define BYT_PULL_STR_MASK (3 << BYT_PULL_STR_SHIFT)
#define BYT_PULL_STR_2K (0 << BYT_PULL_STR_SHIFT)
#define BYT_PULL_STR_10K (1 << BYT_PULL_STR_SHIFT)
#define BYT_PULL_STR_20K (2 << BYT_PULL_STR_SHIFT)
#define BYT_PULL_STR_40K (3 << BYT_PULL_STR_SHIFT)
#define BYT_PULL_ASSIGN_SHIFT 7
#define BYT_PULL_ASSIGN_MASK (3 << BYT_PULL_ASSIGN_SHIFT)
#define BYT_PULL_ASSIGN_UP (1 << BYT_PULL_ASSIGN_SHIFT)
#define BYT_PULL_ASSIGN_DOWN (2 << BYT_PULL_ASSIGN_SHIFT)
#define BYT_PIN_MUX 0x07
/* BYT_VAL_REG register bits */
......@@ -321,6 +332,8 @@ static void byt_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
spin_lock_irqsave(&vg->lock, flags);
for (i = 0; i < vg->chip.ngpio; i++) {
const char *pull_str = NULL;
const char *pull = NULL;
const char *label;
offs = vg->range->pins[i] * 16;
conf0 = readl(vg->reg_base + offs + BYT_CONF0_REG);
......@@ -330,8 +343,32 @@ static void byt_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
if (!label)
label = "Unrequested";
switch (conf0 & BYT_PULL_ASSIGN_MASK) {
case BYT_PULL_ASSIGN_UP:
pull = "up";
break;
case BYT_PULL_ASSIGN_DOWN:
pull = "down";
break;
}
switch (conf0 & BYT_PULL_STR_MASK) {
case BYT_PULL_STR_2K:
pull_str = "2k";
break;
case BYT_PULL_STR_10K:
pull_str = "10k";
break;
case BYT_PULL_STR_20K:
pull_str = "20k";
break;
case BYT_PULL_STR_40K:
pull_str = "40k";
break;
}
seq_printf(s,
" gpio-%-3d (%-20.20s) %s %s %s pad-%-3d offset:0x%03x mux:%d %s%s%s\n",
" gpio-%-3d (%-20.20s) %s %s %s pad-%-3d offset:0x%03x mux:%d %s%s%s",
i,
label,
val & BYT_INPUT_EN ? " " : "in",
......@@ -339,9 +376,19 @@ static void byt_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
val & BYT_LEVEL ? "hi" : "lo",
vg->range->pins[i], offs,
conf0 & 0x7,
conf0 & BYT_TRIG_NEG ? " fall" : "",
conf0 & BYT_TRIG_POS ? " rise" : "",
conf0 & BYT_TRIG_LVL ? " level" : "");
conf0 & BYT_TRIG_NEG ? " fall" : " ",
conf0 & BYT_TRIG_POS ? " rise" : " ",
conf0 & BYT_TRIG_LVL ? " level" : " ");
if (pull && pull_str)
seq_printf(s, " %-4s %-3s", pull, pull_str);
else
seq_puts(s, " ");
if (conf0 & BYT_IODEN)
seq_puts(s, " open-drain");
seq_puts(s, "\n");
}
spin_unlock_irqrestore(&vg->lock, flags);
}
......@@ -527,12 +574,6 @@ static int byt_gpio_probe(struct platform_device *pdev)
gc->can_sleep = false;
gc->dev = dev;
ret = gpiochip_add(gc);
if (ret) {
dev_err(&pdev->dev, "failed adding byt-gpio chip\n");
return ret;
}
/* set up interrupts */
irq_rc = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (irq_rc && irq_rc->start) {
......@@ -550,6 +591,12 @@ static int byt_gpio_probe(struct platform_device *pdev)
irq_set_chained_handler(hwirq, byt_gpio_irq_handler);
}
ret = gpiochip_add(gc);
if (ret) {
dev_err(&pdev->dev, "failed adding byt-gpio chip\n");
return ret;
}
pm_runtime_enable(dev);
return 0;
......@@ -572,6 +619,7 @@ static const struct dev_pm_ops byt_gpio_pm_ops = {
static const struct acpi_device_id byt_gpio_acpi_match[] = {
{ "INT33B2", 0 },
{ "INT33FC", 0 },
{ }
};
MODULE_DEVICE_TABLE(acpi, byt_gpio_acpi_match);
......
......@@ -718,6 +718,73 @@ struct samsung_pin_ctrl s5pv210_pin_ctrl[] = {
},
};
/* pin banks of exynos3250 pin-controller 0 */
static struct samsung_pin_bank exynos3250_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),
};
/* pin banks of exynos3250 pin-controller 1 */
static struct samsung_pin_bank exynos3250_pin_banks1[] = {
EXYNOS_PIN_BANK_EINTN(8, 0x120, "gpe0"),
EXYNOS_PIN_BANK_EINTN(8, 0x140, "gpe1"),
EXYNOS_PIN_BANK_EINTN(3, 0x180, "gpe2"),
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(4, 0x0c0, "gpl0", 0x18),
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),
};
/*
* Samsung pinctrl driver data for Exynos3250 SoC. Exynos3250 SoC includes
* two gpio/pin-mux/pinconfig controllers.
*/
struct samsung_pin_ctrl exynos3250_pin_ctrl[] = {
{
/* pin-controller instance 0 data */
.pin_banks = exynos3250_pin_banks0,
.nr_banks = ARRAY_SIZE(exynos3250_pin_banks0),
.geint_con = EXYNOS_GPIO_ECON_OFFSET,
.geint_mask = EXYNOS_GPIO_EMASK_OFFSET,
.geint_pend = EXYNOS_GPIO_EPEND_OFFSET,
.svc = EXYNOS_SVC_OFFSET,
.eint_gpio_init = exynos_eint_gpio_init,
.suspend = exynos_pinctrl_suspend,
.resume = exynos_pinctrl_resume,
.label = "exynos3250-gpio-ctrl0",
}, {
/* pin-controller instance 1 data */
.pin_banks = exynos3250_pin_banks1,
.nr_banks = ARRAY_SIZE(exynos3250_pin_banks1),
.geint_con = EXYNOS_GPIO_ECON_OFFSET,
.geint_mask = EXYNOS_GPIO_EMASK_OFFSET,
.geint_pend = EXYNOS_GPIO_EPEND_OFFSET,
.weint_con = EXYNOS_WKUP_ECON_OFFSET,
.weint_mask = EXYNOS_WKUP_EMASK_OFFSET,
.weint_pend = EXYNOS_WKUP_EPEND_OFFSET,
.svc = EXYNOS_SVC_OFFSET,
.eint_gpio_init = exynos_eint_gpio_init,
.eint_wkup_init = exynos_eint_wkup_init,
.suspend = exynos_pinctrl_suspend,
.resume = exynos_pinctrl_resume,
.label = "exynos3250-gpio-ctrl1",
},
};
/* pin banks of exynos4210 pin-controller 0 */
static struct samsung_pin_bank exynos4210_pin_banks0[] = {
EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpa0", 0x00),
......
......@@ -491,7 +491,7 @@ static int imx_pinctrl_parse_groups(struct device_node *np,
pin->mux_mode |= IOMUXC_CONFIG_SION;
pin->config = config & ~IMX_PAD_SION;
dev_dbg(info->dev, "%s: %d 0x%08lx", info->pins[pin_id].name,
dev_dbg(info->dev, "%s: 0x%x 0x%08lx", info->pins[pin_id].name,
pin->mux_mode, pin->config);
}
......
This diff is collapsed.
This diff is collapsed.
......@@ -10,6 +10,7 @@
*/
#ifndef __PINCTRL_LANTIQ_H
#define __PINCTRL_LANTIQ_H
#include <linux/clkdev.h>
#include <linux/pinctrl/pinctrl.h>
......
......@@ -13,7 +13,6 @@
*/
#include <linux/err.h>
#include <linux/irqdomain.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/of.h>
......@@ -26,8 +25,6 @@
#include <linux/slab.h>
#include <linux/gpio.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/irqchip/chained_irq.h>
#include <linux/spinlock.h>
#include "core.h"
......@@ -41,7 +38,6 @@
* struct msm_pinctrl - state for a pinctrl-msm device
* @dev: device handle.
* @pctrl: pinctrl handle.
* @domain: irqdomain handle.
* @chip: gpiochip handle.
* @irq: parent irq for the TLMM irq_chip.
* @lock: Spinlock to protect register resources as well
......@@ -55,7 +51,6 @@
struct msm_pinctrl {
struct device *dev;
struct pinctrl_dev *pctrl;
struct irq_domain *domain;
struct gpio_chip chip;
int irq;
......@@ -68,6 +63,11 @@ struct msm_pinctrl {
void __iomem *regs;
};
static inline struct msm_pinctrl *to_msm_pinctrl(struct gpio_chip *gc)
{
return container_of(gc, struct msm_pinctrl, chip);
}
static int msm_get_groups_count(struct pinctrl_dev *pctldev)
{
struct msm_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
......@@ -145,12 +145,12 @@ static int msm_pinmux_enable(struct pinctrl_dev *pctldev,
if (WARN_ON(g->mux_bit < 0))
return -EINVAL;
for (i = 0; i < ARRAY_SIZE(g->funcs); i++) {
for (i = 0; i < g->nfuncs; i++) {
if (g->funcs[i] == function)
break;
}
if (WARN_ON(i == ARRAY_SIZE(g->funcs)))
if (WARN_ON(i == g->nfuncs))
return -EINVAL;
spin_lock_irqsave(&pctrl->lock, flags);
......@@ -480,13 +480,6 @@ static void msm_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
spin_unlock_irqrestore(&pctrl->lock, flags);
}
static int msm_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
{
struct msm_pinctrl *pctrl = container_of(chip, struct msm_pinctrl, chip);
return irq_find_mapping(pctrl->domain, offset);
}
static int msm_gpio_request(struct gpio_chip *chip, unsigned offset)
{
int gpio = chip->base + offset;
......@@ -556,7 +549,6 @@ static struct gpio_chip msm_gpio_template = {
.direction_output = msm_gpio_direction_output,
.get = msm_gpio_get,
.set = msm_gpio_set,
.to_irq = msm_gpio_to_irq,
.request = msm_gpio_request,
.free = msm_gpio_free,
.dbg_show = msm_gpio_dbg_show,
......@@ -608,12 +600,12 @@ static void msm_gpio_update_dual_edge_pos(struct msm_pinctrl *pctrl,
static void msm_gpio_irq_mask(struct irq_data *d)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct msm_pinctrl *pctrl = to_msm_pinctrl(gc);
const struct msm_pingroup *g;
struct msm_pinctrl *pctrl;
unsigned long flags;
u32 val;
pctrl = irq_data_get_irq_chip_data(d);
g = &pctrl->soc->groups[d->hwirq];
spin_lock_irqsave(&pctrl->lock, flags);
......@@ -629,12 +621,12 @@ static void msm_gpio_irq_mask(struct irq_data *d)
static void msm_gpio_irq_unmask(struct irq_data *d)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct msm_pinctrl *pctrl = to_msm_pinctrl(gc);
const struct msm_pingroup *g;
struct msm_pinctrl *pctrl;
unsigned long flags;
u32 val;
pctrl = irq_data_get_irq_chip_data(d);
g = &pctrl->soc->groups[d->hwirq];
spin_lock_irqsave(&pctrl->lock, flags);
......@@ -654,12 +646,12 @@ static void msm_gpio_irq_unmask(struct irq_data *d)
static void msm_gpio_irq_ack(struct irq_data *d)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct msm_pinctrl *pctrl = to_msm_pinctrl(gc);
const struct msm_pingroup *g;
struct msm_pinctrl *pctrl;
unsigned long flags;
u32 val;
pctrl = irq_data_get_irq_chip_data(d);
g = &pctrl->soc->groups[d->hwirq];
spin_lock_irqsave(&pctrl->lock, flags);
......@@ -681,12 +673,12 @@ static void msm_gpio_irq_ack(struct irq_data *d)
static int msm_gpio_irq_set_type(struct irq_data *d, unsigned int type)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct msm_pinctrl *pctrl = to_msm_pinctrl(gc);
const struct msm_pingroup *g;
struct msm_pinctrl *pctrl;
unsigned long flags;
u32 val;
pctrl = irq_data_get_irq_chip_data(d);
g = &pctrl->soc->groups[d->hwirq];
spin_lock_irqsave(&pctrl->lock, flags);
......@@ -775,11 +767,10 @@ static int msm_gpio_irq_set_type(struct irq_data *d, unsigned int type)
static int msm_gpio_irq_set_wake(struct irq_data *d, unsigned int on)
{
struct msm_pinctrl *pctrl;
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct msm_pinctrl *pctrl = to_msm_pinctrl(gc);
unsigned long flags;
pctrl = irq_data_get_irq_chip_data(d);
spin_lock_irqsave(&pctrl->lock, flags);
irq_set_irq_wake(pctrl->irq, on);
......@@ -789,25 +780,6 @@ static int msm_gpio_irq_set_wake(struct irq_data *d, unsigned int on)
return 0;
}
static int msm_gpio_irq_reqres(struct irq_data *d)
{
struct msm_pinctrl *pctrl = irq_data_get_irq_chip_data(d);
if (gpio_lock_as_irq(&pctrl->chip, d->hwirq)) {
dev_err(pctrl->dev, "unable to lock HW IRQ %lu for IRQ\n",
d->hwirq);
return -EINVAL;
}
return 0;
}
static void msm_gpio_irq_relres(struct irq_data *d)
{
struct msm_pinctrl *pctrl = irq_data_get_irq_chip_data(d);
gpio_unlock_as_irq(&pctrl->chip, d->hwirq);
}
static struct irq_chip msm_gpio_irq_chip = {
.name = "msmgpio",
.irq_mask = msm_gpio_irq_mask,
......@@ -815,14 +787,13 @@ static struct irq_chip msm_gpio_irq_chip = {
.irq_ack = msm_gpio_irq_ack,
.irq_set_type = msm_gpio_irq_set_type,
.irq_set_wake = msm_gpio_irq_set_wake,
.irq_request_resources = msm_gpio_irq_reqres,
.irq_release_resources = msm_gpio_irq_relres,
};
static void msm_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
{
struct gpio_chip *gc = irq_desc_get_handler_data(desc);
const struct msm_pingroup *g;
struct msm_pinctrl *pctrl = irq_desc_get_handler_data(desc);
struct msm_pinctrl *pctrl = to_msm_pinctrl(gc);
struct irq_chip *chip = irq_get_chip(irq);
int irq_pin;
int handled = 0;
......@@ -839,7 +810,7 @@ static void msm_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
g = &pctrl->soc->groups[i];
val = readl(pctrl->regs + g->intr_status_reg);
if (val & BIT(g->intr_status_bit)) {
irq_pin = irq_find_mapping(pctrl->domain, i);
irq_pin = irq_find_mapping(gc->irqdomain, i);
generic_handle_irq(irq_pin);
handled++;
}
......@@ -852,19 +823,10 @@ static void msm_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
chained_irq_exit(chip, desc);
}
/*
* This lock class tells lockdep that GPIO irqs are in a different
* category than their parents, so it won't report false recursion.
*/
static struct lock_class_key gpio_lock_class;
static int msm_gpio_init(struct msm_pinctrl *pctrl)
{
struct gpio_chip *chip;
int irq;
int ret;
int i;
int r;
unsigned ngpio = pctrl->soc->ngpios;
if (WARN_ON(ngpio > MAX_NR_GPIO))
......@@ -890,23 +852,18 @@ static int msm_gpio_init(struct msm_pinctrl *pctrl)
return ret;
}
pctrl->domain = irq_domain_add_linear(pctrl->dev->of_node, chip->ngpio,
&irq_domain_simple_ops, NULL);
if (!pctrl->domain) {
dev_err(pctrl->dev, "Failed to register irq domain\n");
r = gpiochip_remove(&pctrl->chip);
ret = gpiochip_irqchip_add(chip,
&msm_gpio_irq_chip,
0,
handle_edge_irq,
IRQ_TYPE_NONE);
if (ret) {
dev_err(pctrl->dev, "Failed to add irqchip to gpiochip\n");
return -ENOSYS;
}
for (i = 0; i < chip->ngpio; i++) {
irq = irq_create_mapping(pctrl->domain, i);
irq_set_lockdep_class(irq, &gpio_lock_class);
irq_set_chip_and_handler(irq, &msm_gpio_irq_chip, handle_edge_irq);
irq_set_chip_data(irq, pctrl);
}
irq_set_handler_data(pctrl->irq, pctrl);
irq_set_chained_handler(pctrl->irq, msm_gpio_irq_handler);
gpiochip_set_chained_irqchip(chip, &msm_gpio_irq_chip, pctrl->irq,
msm_gpio_irq_handler);
return 0;
}
......@@ -974,8 +931,6 @@ int msm_pinctrl_remove(struct platform_device *pdev)
return ret;
}
irq_set_chained_handler(pctrl->irq, NULL);
irq_domain_remove(pctrl->domain);
pinctrl_unregister(pctrl->pctrl);
return 0;
......
......@@ -65,7 +65,8 @@ struct msm_pingroup {
const unsigned *pins;
unsigned npins;
unsigned funcs[8];
unsigned *funcs;
unsigned nfuncs;
s16 ctl_reg;
s16 io_reg;
......
This diff is collapsed.
This diff is collapsed.
......@@ -1114,6 +1114,8 @@ static struct syscore_ops samsung_pinctrl_syscore_ops = {
static const struct of_device_id samsung_pinctrl_dt_match[] = {
#ifdef CONFIG_PINCTRL_EXYNOS
{ .compatible = "samsung,exynos3250-pinctrl",
.data = (void *)exynos3250_pin_ctrl },
{ .compatible = "samsung,exynos4210-pinctrl",
.data = (void *)exynos4210_pin_ctrl },
{ .compatible = "samsung,exynos4x12-pinctrl",
......
......@@ -251,6 +251,7 @@ struct samsung_pmx_func {
};
/* list of all exported SoC specific data */
extern struct samsung_pin_ctrl exynos3250_pin_ctrl[];
extern struct samsung_pin_ctrl exynos4210_pin_ctrl[];
extern struct samsung_pin_ctrl exynos4x12_pin_ctrl[];
extern struct samsung_pin_ctrl exynos5250_pin_ctrl[];
......
......@@ -13,10 +13,6 @@
#include <linux/slab.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/irq.h>
#include <linux/irqdesc.h>
#include <linux/irqdomain.h>
#include <linux/irqchip/chained_irq.h>
#include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/of_gpio.h>
......@@ -242,13 +238,13 @@ struct st_pio_control {
};
struct st_pctl_data {
enum st_retime_style rt_style;
unsigned int *input_delays;
int ninput_delays;
unsigned int *output_delays;
int noutput_delays;
const enum st_retime_style rt_style;
const unsigned int *input_delays;
const int ninput_delays;
const unsigned int *output_delays;
const int noutput_delays;
/* register offset information */
int alt, oe, pu, od, rt;
const int alt, oe, pu, od, rt;
};
struct st_pinconf {
......@@ -321,7 +317,6 @@ struct st_gpio_bank {
struct pinctrl_gpio_range range;
void __iomem *base;
struct st_pio_control pc;
struct irq_domain *domain;
unsigned long irq_edge_conf;
spinlock_t lock;
};
......@@ -342,15 +337,15 @@ struct st_pinctrl {
/* SOC specific data */
/* STiH415 data */
static unsigned int stih415_input_delays[] = {0, 500, 1000, 1500};
static unsigned int stih415_output_delays[] = {0, 1000, 2000, 3000};
static const unsigned int stih415_input_delays[] = {0, 500, 1000, 1500};
static const unsigned int stih415_output_delays[] = {0, 1000, 2000, 3000};
#define STIH415_PCTRL_COMMON_DATA \
.rt_style = st_retime_style_packed, \
.input_delays = stih415_input_delays, \
.ninput_delays = 4, \
.ninput_delays = ARRAY_SIZE(stih415_input_delays), \
.output_delays = stih415_output_delays, \
.noutput_delays = 4
.noutput_delays = ARRAY_SIZE(stih415_output_delays)
static const struct st_pctl_data stih415_sbc_data = {
STIH415_PCTRL_COMMON_DATA,
......@@ -378,8 +373,8 @@ static const struct st_pctl_data stih415_right_data = {
};
/* STiH416 data */
static unsigned int stih416_delays[] = {0, 300, 500, 750, 1000, 1250, 1500,
1750, 2000, 2250, 2500, 2750, 3000, 3250 };
static const unsigned int stih416_delays[] = {0, 300, 500, 750, 1000, 1250,
1500, 1750, 2000, 2250, 2500, 2750, 3000, 3250 };
static const struct st_pctl_data stih416_data = {
.rt_style = st_retime_style_dedicated,
......@@ -468,7 +463,7 @@ static void st_pctl_set_function(struct st_pio_control *pc,
static unsigned long st_pinconf_delay_to_bit(unsigned int delay,
const struct st_pctl_data *data, unsigned long config)
{
unsigned int *delay_times;
const unsigned int *delay_times;
int num_delay_times, i, closest_index = -1;
unsigned int closest_divergence = UINT_MAX;
......@@ -501,7 +496,7 @@ static unsigned long st_pinconf_delay_to_bit(unsigned int delay,
static unsigned long st_pinconf_bit_to_delay(unsigned int index,
const struct st_pctl_data *data, unsigned long output)
{
unsigned int *delay_times;
const unsigned int *delay_times;
int num_delay_times;
if (output) {
......@@ -1285,58 +1280,26 @@ static int st_pctl_parse_functions(struct device_node *np,
return 0;
}
static int st_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
{
struct st_gpio_bank *bank = gpio_chip_to_bank(chip);
int irq = -ENXIO;
if (offset < chip->ngpio)
irq = irq_find_mapping(bank->domain, offset);
dev_info(chip->dev, "%s: request IRQ for GPIO %d, return %d\n",
chip->label, offset + chip->base, irq);
return irq;
}
static void st_gpio_irq_mask(struct irq_data *d)
{
struct st_gpio_bank *bank = irq_data_get_irq_chip_data(d);
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct st_gpio_bank *bank = gpio_chip_to_bank(gc);
writel(BIT(d->hwirq), bank->base + REG_PIO_CLR_PMASK);
}
static void st_gpio_irq_unmask(struct irq_data *d)
{
struct st_gpio_bank *bank = irq_data_get_irq_chip_data(d);
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct st_gpio_bank *bank = gpio_chip_to_bank(gc);
writel(BIT(d->hwirq), bank->base + REG_PIO_SET_PMASK);
}
static unsigned int st_gpio_irq_startup(struct irq_data *d)
{
struct st_gpio_bank *bank = irq_data_get_irq_chip_data(d);
if (gpio_lock_as_irq(&bank->gpio_chip, d->hwirq))
dev_err(bank->gpio_chip.dev,
"unable to lock HW IRQ %lu for IRQ\n",
d->hwirq);
st_gpio_irq_unmask(d);
return 0;
}
static void st_gpio_irq_shutdown(struct irq_data *d)
{
struct st_gpio_bank *bank = irq_data_get_irq_chip_data(d);
st_gpio_irq_mask(d);
gpio_unlock_as_irq(&bank->gpio_chip, d->hwirq);
}
static int st_gpio_irq_set_type(struct irq_data *d, unsigned type)
{
struct st_gpio_bank *bank = irq_data_get_irq_chip_data(d);
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct st_gpio_bank *bank = gpio_chip_to_bank(gc);
unsigned long flags;
int comp, pin = d->hwirq;
u32 val;
......@@ -1440,7 +1403,7 @@ static void __gpio_irq_handler(struct st_gpio_bank *bank)
continue;
}
generic_handle_irq(irq_find_mapping(bank->domain, n));
generic_handle_irq(irq_find_mapping(bank->gpio_chip.irqdomain, n));
}
}
}
......@@ -1449,7 +1412,8 @@ static void st_gpio_irq_handler(unsigned irq, struct irq_desc *desc)
{
/* interrupt dedicated per bank */
struct irq_chip *chip = irq_get_chip(irq);
struct st_gpio_bank *bank = irq_get_handler_data(irq);
struct gpio_chip *gc = irq_desc_get_handler_data(desc);
struct st_gpio_bank *bank = gpio_chip_to_bank(gc);
chained_irq_enter(chip, desc);
__gpio_irq_handler(bank);
......@@ -1483,7 +1447,6 @@ static struct gpio_chip st_gpio_template = {
.ngpio = ST_GPIO_PINS_PER_BANK,
.of_gpio_n_cells = 1,
.of_xlate = st_gpio_xlate,
.to_irq = st_gpio_to_irq,
};
static struct irq_chip st_gpio_irqchip = {
......@@ -1491,26 +1454,6 @@ static struct irq_chip st_gpio_irqchip = {
.irq_mask = st_gpio_irq_mask,
.irq_unmask = st_gpio_irq_unmask,
.irq_set_type = st_gpio_irq_set_type,
.irq_startup = st_gpio_irq_startup,
.irq_shutdown = st_gpio_irq_shutdown,
};
static int st_gpio_irq_domain_map(struct irq_domain *h,
unsigned int virq, irq_hw_number_t hw)
{
struct st_gpio_bank *bank = h->host_data;
irq_set_chip(virq, &st_gpio_irqchip);
irq_set_handler(virq, handle_simple_irq);
set_irq_flags(virq, IRQF_VALID);
irq_set_chip_data(virq, bank);
return 0;
}
static struct irq_domain_ops st_gpio_irq_ops = {
.map = st_gpio_irq_domain_map,
.xlate = irq_domain_xlate_twocell,
};
static int st_gpiolib_register_bank(struct st_pinctrl *info,
......@@ -1521,7 +1464,7 @@ static int st_gpiolib_register_bank(struct st_pinctrl *info,
struct device *dev = info->dev;
int bank_num = of_alias_get_id(np, "gpio");
struct resource res, irq_res;
int gpio_irq = 0, err, i;
int gpio_irq = 0, err;
if (of_address_to_resource(np, 0, &res))
return -ENODEV;
......@@ -1534,6 +1477,7 @@ static int st_gpiolib_register_bank(struct st_pinctrl *info,
bank->gpio_chip.base = bank_num * ST_GPIO_PINS_PER_BANK;
bank->gpio_chip.ngpio = ST_GPIO_PINS_PER_BANK;
bank->gpio_chip.of_node = np;
bank->gpio_chip.dev = dev;
spin_lock_init(&bank->lock);
of_property_read_string(np, "st,bank-name", &range->name);
......@@ -1571,26 +1515,18 @@ static int st_gpiolib_register_bank(struct st_pinctrl *info,
if (of_irq_to_resource(np, 0, &irq_res)) {
gpio_irq = irq_res.start;
irq_set_chained_handler(gpio_irq, st_gpio_irq_handler);
irq_set_handler_data(gpio_irq, bank);
gpiochip_set_chained_irqchip(&bank->gpio_chip, &st_gpio_irqchip,
gpio_irq, st_gpio_irq_handler);
}
if (info->irqmux_base > 0 || gpio_irq > 0) {
/* Setup IRQ domain */
bank->domain = irq_domain_add_linear(np,
ST_GPIO_PINS_PER_BANK,
&st_gpio_irq_ops, bank);
if (!bank->domain) {
dev_err(dev, "Failed to add irq domain for %s\n",
np->full_name);
} else {
for (i = 0; i < ST_GPIO_PINS_PER_BANK; i++) {
if (irq_create_mapping(bank->domain, i) < 0)
dev_err(dev,
"Failed to map IRQ %i\n", i);
}
err = gpiochip_irqchip_add(&bank->gpio_chip, &st_gpio_irqchip,
0, handle_simple_irq,
IRQ_TYPE_LEVEL_LOW);
if (err) {
dev_info(dev, "could not add irqchip\n");
return err;
}
} else {
dev_info(dev, "No IRQ support for %s bank\n", np->full_name);
}
......
This diff is collapsed.
This diff is collapsed.
......@@ -295,17 +295,11 @@ static void tegra_pinctrl_disable(struct pinctrl_dev *pctldev,
{
struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
const struct tegra_pingroup *g;
u32 val;
g = &pmx->soc->groups[group];
if (WARN_ON(g->mux_reg < 0))
return;
val = pmx_readl(pmx, g->mux_bank, g->mux_reg);
val &= ~(0x3 << g->mux_bit);
val |= g->func_safe << g->mux_bit;
pmx_writel(pmx, val, g->mux_bank, g->mux_reg);
}
static const struct pinmux_ops tegra_pinmux_ops = {
......@@ -336,32 +330,32 @@ static int tegra_pinconf_reg(struct tegra_pmx *pmx,
*width = 1;
break;
case TEGRA_PINCONF_PARAM_ENABLE_INPUT:
*bank = g->einput_bank;
*reg = g->einput_reg;
*bank = g->mux_bank;
*reg = g->mux_reg;
*bit = g->einput_bit;
*width = 1;
break;
case TEGRA_PINCONF_PARAM_OPEN_DRAIN:
*bank = g->odrain_bank;
*reg = g->odrain_reg;
*bank = g->mux_bank;
*reg = g->mux_reg;
*bit = g->odrain_bit;
*width = 1;
break;
case TEGRA_PINCONF_PARAM_LOCK:
*bank = g->lock_bank;
*reg = g->lock_reg;
*bank = g->mux_bank;
*reg = g->mux_reg;
*bit = g->lock_bit;
*width = 1;
break;
case TEGRA_PINCONF_PARAM_IORESET:
*bank = g->ioreset_bank;
*reg = g->ioreset_reg;
*bank = g->mux_bank;
*reg = g->mux_reg;
*bit = g->ioreset_bit;
*width = 1;
break;
case TEGRA_PINCONF_PARAM_RCV_SEL:
*bank = g->rcv_sel_bank;
*reg = g->rcv_sel_reg;
*bank = g->mux_bank;
*reg = g->mux_reg;
*bit = g->rcv_sel_bit;
*width = 1;
break;
......@@ -408,8 +402,8 @@ static int tegra_pinconf_reg(struct tegra_pmx *pmx,
*width = g->slwr_width;
break;
case TEGRA_PINCONF_PARAM_DRIVE_TYPE:
*bank = g->drvtype_bank;
*reg = g->drvtype_reg;
*bank = g->drv_bank;
*reg = g->drv_reg;
*bit = g->drvtype_bit;
*width = 2;
break;
......@@ -418,11 +412,22 @@ static int tegra_pinconf_reg(struct tegra_pmx *pmx,
return -ENOTSUPP;
}
if (*reg < 0) {
if (report_err)
if (*reg < 0 || *bit > 31) {
if (report_err) {
const char *prop = "unknown";
int i;
for (i = 0; i < ARRAY_SIZE(cfg_params); i++) {
if (cfg_params[i].param == param) {
prop = cfg_params[i].property;
break;
}
}
dev_err(pmx->dev,
"Config param %04x not supported on group %s\n",
param, g->name);
"Config param %04x (%s) not supported on group %s\n",
param, prop, g->name);
}
return -ENOTSUPP;
}
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -391,14 +391,16 @@ int pinmux_enable_setting(struct pinctrl_setting const *setting)
struct pinctrl_dev *pctldev = setting->pctldev;
const struct pinctrl_ops *pctlops = pctldev->desc->pctlops;
const struct pinmux_ops *ops = pctldev->desc->pmxops;
int ret;
const unsigned *pins;
unsigned num_pins;
int ret = 0;
const unsigned *pins = NULL;
unsigned num_pins = 0;
int i;
struct pin_desc *desc;
ret = pctlops->get_group_pins(pctldev, setting->data.mux.group,
&pins, &num_pins);
if (pctlops->get_group_pins)
ret = pctlops->get_group_pins(pctldev, setting->data.mux.group,
&pins, &num_pins);
if (ret) {
const char *gname;
......@@ -470,14 +472,15 @@ void pinmux_disable_setting(struct pinctrl_setting const *setting)
struct pinctrl_dev *pctldev = setting->pctldev;
const struct pinctrl_ops *pctlops = pctldev->desc->pctlops;
const struct pinmux_ops *ops = pctldev->desc->pmxops;
int ret;
const unsigned *pins;
unsigned num_pins;
int ret = 0;
const unsigned *pins = NULL;
unsigned num_pins = 0;
int i;
struct pin_desc *desc;
ret = pctlops->get_group_pins(pctldev, setting->data.mux.group,
&pins, &num_pins);
if (pctlops->get_group_pins)
ret = pctlops->get_group_pins(pctldev, setting->data.mux.group,
&pins, &num_pins);
if (ret) {
const char *gname;
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment