forked from luck/tmp_suning_uos_patched
Pin control changes for the v3.11 kernel cycle:
- A large slew of improvements of the Genric pin configuration support, and deployment in four different platforms: Rockchip, Super-H PFC, ABx500 and TZ1090. Support BIAS_BUS_HOLD, get device tree parsing and debugfs support into shape. - We also have device tree support with generic naming conventions for the generic pin configuration. - Delete the unused and confusing direct pinconf API. Now state transitions is *the* way to control pins and multiplexing. - New drivers for Rockchip, TZ1090, and TZ1090 PDC. - Two pin control states related to power management are now handled in the device core: "sleep" and "idle", removing a lot of boilerplate code in drivers. We do not yet know if this is the final word for pin PM, but it already make things a lot easier to handle. - Handle sparse GPIO ranges passing a list of disparate pins, and utilize these in the new BayTrail (x86 Atom SoC) driver. - Make the sunxi (AllWinner) driver handle external interrupts. - Make it possible for pinctrl-single to handle the case where several pins are managed by a single register, and augment it to handle sleep modes. - Cleanups and improvements for the abx500 drivers. - Move Sirf pin control drivers to their own directory, support save/restore of context and add support for the SiRFatlas6 SoC. - PMU muxing for the Dove pinctrl driver. - Finalization and support for VF610 in the i.MX6 pinctrl driver. - Smoothen out various Exynos rough edges. - Generic cleanups of various kinds. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.10 (GNU/Linux) iQIcBAABAgAGBQJR0Z07AAoJEEEQszewGV1zx+oP/j+bh39e1Fc8ySFNvpwLFFRb EbQZx21XsK+d4fUVYQJ1IBh3e5FTqkmvHarbO1aNttqyk7eN5P4EFb3dLExIX+81 6SJYtldH5ZdvLpJNvSXAX6fUjTD1CtBCDs5z5AvDQjqUArQ2tKlzJJgFXW8MSd3B 5hd7XdU5g30GbVzFwrPbVUZwRM12YVs/HACkP6uFqDjB8KX6nXpETlqeeFW+ApvW RPT7iN/CsFls7gl6mHsPvScdfXar0ilZfu0hTf3EmhlVK1/iPOV6aqAF9z4j2Yxf ICL/x3phJ0Q7yNeZslif0KN3iJnrRGbdNvBi6wim35Ds5Uf3lY2SAhSvxNmkjT8n DB9oBTvQzr5OEv8fstWJAT+BWIdZ6Z91IqJ5Gy40A91oVUU9NDDBR3ur2gIneEUz 51kOUhucCzpiht5A/7djAx6MYYOEUwjGNzjOs7tGcxCxz4+Rb2DbAXZ3Cew45ddh 1QsfL3588A0DTp7ccw7f4QwYveX/cquzia/MD8AtdrUSYFEPfkexEo540/VqMl8j aMJ8Uuca9GSnyXDk+ziwkzLg2DjTw+p+6IygNr2GLrXFH2LTAKRpz/SidyLArDsw 0sTFan0sdU3497rHX5Xc8yCyDY4sXCdQm3/er+TE+Z7V2dS99GuEysCAInIdvM1I Wupqaxw4A25YSmbRFVpR =EbAf -----END PGP SIGNATURE----- Merge tag 'pinctrl-for-v3.11-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl Pull pin control changes from Linus Walleij: - A large slew of improvements of the Genric pin configuration support, and deployment in four different platforms: Rockchip, Super-H PFC, ABx500 and TZ1090. Support BIAS_BUS_HOLD, get device tree parsing and debugfs support into shape. - We also have device tree support with generic naming conventions for the generic pin configuration. - Delete the unused and confusing direct pinconf API. Now state transitions is *the* way to control pins and multiplexing. - New drivers for Rockchip, TZ1090, and TZ1090 PDC. - Two pin control states related to power management are now handled in the device core: "sleep" and "idle", removing a lot of boilerplate code in drivers. We do not yet know if this is the final word for pin PM, but it already make things a lot easier to handle. - Handle sparse GPIO ranges passing a list of disparate pins, and utilize these in the new BayTrail (x86 Atom SoC) driver. - Make the sunxi (AllWinner) driver handle external interrupts. - Make it possible for pinctrl-single to handle the case where several pins are managed by a single register, and augment it to handle sleep modes. - Cleanups and improvements for the abx500 drivers. - Move Sirf pin control drivers to their own directory, support save/restore of context and add support for the SiRFatlas6 SoC. - PMU muxing for the Dove pinctrl driver. - Finalization and support for VF610 in the i.MX6 pinctrl driver. - Smoothen out various Exynos rough edges. - Generic cleanups of various kinds. * tag 'pinctrl-for-v3.11-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl: (82 commits) pinctrl: vt8500: wmt: remove redundant dev_err call in wmt_pinctrl_probe() pinctrl: remove bindings for pinconf options needing more thought pinctrl: remove slew-rate parameter from tz1090 pinctrl: set unit for debounce time pinconfig to usec pinctrl: more clarifications for generic pull configs pinctrl: rip out the direct pinconf API pinctrl-tz1090-pdc: add TZ1090 PDC pinctrl driver pinctrl-tz1090: add TZ1090 pinctrl driver pinctrl: samsung: Staticize drvdata_list pinctrl: rockchip: Add missing irq_gc_unlock() call before return error pinctrl: abx500: rework error path pinctrl: abx500: suppress hardcoded value pinctrl: abx500: factorize code pinctrl: abx500: fix abx500_gpio_get() pinctrl: abx500: fix abx500_pin_config_set() pinctrl: abx500: Add device tree support sh-pfc: Guard DT parsing with #ifdef CONFIG_OF pinctrl: add Intel BayTrail GPIO/pinctrl support pinctrl: fix pinconf_ops::pin_config_dbg_parse_modify kerneldoc pinctrl: Staticize local symbols ... Conflicts: drivers/net/ethernet/ti/davinci_mdio.c drivers/pinctrl/Makefile
This commit is contained in:
commit
3dbde57ad9
|
@ -0,0 +1,41 @@
|
|||
Freescale Vybrid VF610 IOMUX Controller
|
||||
|
||||
Please refer to fsl,imx-pinctrl.txt in this directory for common binding part
|
||||
and usage.
|
||||
|
||||
Required properties:
|
||||
- compatible: "fsl,vf610-iomuxc"
|
||||
- fsl,pins: two integers array, represents a group of pins mux and config
|
||||
setting. The format is fsl,pins = <PIN_FUNC_ID CONFIG>, PIN_FUNC_ID is
|
||||
a pin working on a specific function, CONFIG is the pad setting value
|
||||
such as pull-up, speed, ode for this pin. Please refer to Vybrid VF610
|
||||
datasheet for the valid pad config settings.
|
||||
|
||||
CONFIG bits definition:
|
||||
PAD_CTL_SPEED_LOW (1 << 12)
|
||||
PAD_CTL_SPEED_MED (2 << 12)
|
||||
PAD_CTL_SPEED_HIGH (3 << 12)
|
||||
PAD_CTL_SRE_FAST (1 << 11)
|
||||
PAD_CTL_SRE_SLOW (0 << 11)
|
||||
PAD_CTL_ODE (1 << 10)
|
||||
PAD_CTL_HYS (1 << 9)
|
||||
PAD_CTL_DSE_DISABLE (0 << 6)
|
||||
PAD_CTL_DSE_150ohm (1 << 6)
|
||||
PAD_CTL_DSE_75ohm (2 << 6)
|
||||
PAD_CTL_DSE_50ohm (3 << 6)
|
||||
PAD_CTL_DSE_37ohm (4 << 6)
|
||||
PAD_CTL_DSE_30ohm (5 << 6)
|
||||
PAD_CTL_DSE_25ohm (6 << 6)
|
||||
PAD_CTL_DSE_20ohm (7 << 6)
|
||||
PAD_CTL_PUS_100K_DOWN (0 << 4)
|
||||
PAD_CTL_PUS_47K_UP (1 << 4)
|
||||
PAD_CTL_PUS_100K_UP (2 << 4)
|
||||
PAD_CTL_PUS_22K_UP (3 << 4)
|
||||
PAD_CTL_PKE (1 << 3)
|
||||
PAD_CTL_PUE (1 << 2)
|
||||
PAD_CTL_OBE_ENABLE (1 << 1)
|
||||
PAD_CTL_IBE_ENABLE (1 << 0)
|
||||
PAD_CTL_OBE_IBE_ENABLE (3 << 0)
|
||||
|
||||
Please refer to vf610-pinfunc.h in device tree source folder
|
||||
for all available PIN_FUNC_ID for Vybrid VF610.
|
|
@ -0,0 +1,127 @@
|
|||
ImgTec TZ1090 PDC pin controller
|
||||
|
||||
Required properties:
|
||||
- compatible: "img,tz1090-pdc-pinctrl"
|
||||
- reg: Should contain the register physical address and length of the
|
||||
SOC_GPIO_CONTROL registers in the PDC register region.
|
||||
|
||||
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".
|
||||
|
||||
TZ1090-PDC'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. For this reason, even seemingly boolean
|
||||
values are actually tristates in this binding: unspecified, off, or on.
|
||||
Unspecified is represented as an absent property, and off/on are represented as
|
||||
integer values 0 and 1.
|
||||
|
||||
Required subnode-properties:
|
||||
- tz1090,pins : An array of strings. Each string contains the name of a pin or
|
||||
group. Valid values for these names are listed below.
|
||||
|
||||
Optional subnode-properties:
|
||||
- tz1090,function: A string containing the name of the function to mux to the
|
||||
pin or group. Valid values for function names are listed below, including
|
||||
which pingroups can be muxed to them.
|
||||
- supported generic pinconfig properties (for further details see
|
||||
Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt):
|
||||
- bias-disable
|
||||
- bias-high-impedance
|
||||
- bias-bus-hold
|
||||
- bias-pull-up
|
||||
- bias-pull-down
|
||||
- input-schmitt-enable
|
||||
- input-schmitt-disable
|
||||
- drive-strength: Integer, control drive strength of pins in mA.
|
||||
2: 2mA
|
||||
4: 4mA
|
||||
8: 8mA
|
||||
12: 12mA
|
||||
- low-power-enable: Flag, power-on-start weak pull-down for invalid power.
|
||||
- low-power-disable: Flag, power-on-start weak pull-down disabled.
|
||||
|
||||
Note that many of these properties are only valid for certain specific pins
|
||||
or groups. See the TZ1090 TRM for complete details regarding which groups
|
||||
support which functionality. The Linux pinctrl driver may also be a useful
|
||||
reference.
|
||||
|
||||
Valid values for pin and group names are:
|
||||
|
||||
pins:
|
||||
|
||||
These all support bias-high-impediance, bias-pull-up, bias-pull-down, and
|
||||
bias-bus-hold (which can also be provided to any of the groups below to set
|
||||
it for all gpio pins in that group).
|
||||
|
||||
gpio0, gpio1, sys_wake0, sys_wake1, sys_wake2, ir_data, ext_power.
|
||||
|
||||
mux groups:
|
||||
|
||||
These all support function.
|
||||
|
||||
gpio0
|
||||
pins: gpio0.
|
||||
function: ir_mod_stable_out.
|
||||
gpio1
|
||||
pins: gpio1.
|
||||
function: ir_mod_power_out.
|
||||
|
||||
drive groups:
|
||||
|
||||
These support input-schmitt-enable, input-schmitt-disable,
|
||||
drive-strength, low-power-enable, and low-power-disable.
|
||||
|
||||
pdc
|
||||
pins: gpio0, gpio1, sys_wake0, sys_wake1, sys_wake2, ir_data,
|
||||
ext_power.
|
||||
|
||||
Example:
|
||||
|
||||
pinctrl_pdc: pinctrl@02006500 {
|
||||
#gpio-range-cells = <3>;
|
||||
compatible = "img,tz1090-pdc-pinctrl";
|
||||
reg = <0x02006500 0x100>;
|
||||
};
|
||||
|
||||
Example board file extracts:
|
||||
|
||||
&pinctrl_pdc {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&syswake_default>;
|
||||
|
||||
syswake_default: syswakes {
|
||||
syswake_cfg {
|
||||
tz1090,pins = "sys_wake0",
|
||||
"sys_wake1",
|
||||
"sys_wake2";
|
||||
pull-up;
|
||||
};
|
||||
};
|
||||
irmod_default: irmod {
|
||||
gpio0_cfg {
|
||||
tz1090,pins = "gpio0";
|
||||
tz1090,function = "ir_mod_stable_out";
|
||||
};
|
||||
gpio1_cfg {
|
||||
tz1090,pins = "gpio1";
|
||||
tz1090,function = "ir_mod_power_out";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
ir: ir@02006200 {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&irmod_default>;
|
||||
};
|
227
Documentation/devicetree/bindings/pinctrl/img,tz1090-pinctrl.txt
Normal file
227
Documentation/devicetree/bindings/pinctrl/img,tz1090-pinctrl.txt
Normal file
|
@ -0,0 +1,227 @@
|
|||
ImgTec TZ1090 pin controller
|
||||
|
||||
Required properties:
|
||||
- compatible: "img,tz1090-pinctrl"
|
||||
- reg: Should contain the register physical address and length of the pad
|
||||
configuration registers (CR_PADS_* and CR_IF_CTL0).
|
||||
|
||||
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".
|
||||
|
||||
TZ1090'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. For this reason, even seemingly boolean
|
||||
values are actually tristates in this binding: unspecified, off, or on.
|
||||
Unspecified is represented as an absent property, and off/on are represented as
|
||||
integer values 0 and 1.
|
||||
|
||||
Required subnode-properties:
|
||||
- tz1090,pins : An array of strings. Each string contains the name of a pin or
|
||||
group. Valid values for these names are listed below.
|
||||
|
||||
Optional subnode-properties:
|
||||
- tz1090,function: A string containing the name of the function to mux to the
|
||||
pin or group. Valid values for function names are listed below, including
|
||||
which pingroups can be muxed to them.
|
||||
- supported generic pinconfig properties (for further details see
|
||||
Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt):
|
||||
- bias-disable
|
||||
- bias-high-impedance
|
||||
- bias-bus-hold
|
||||
- bias-pull-up
|
||||
- bias-pull-down
|
||||
- input-schmitt-enable
|
||||
- input-schmitt-disable
|
||||
- drive-strength: Integer, control drive strength of pins in mA.
|
||||
2: 2mA
|
||||
4: 4mA
|
||||
8: 8mA
|
||||
12: 12mA
|
||||
|
||||
|
||||
Note that many of these properties are only valid for certain specific pins
|
||||
or groups. See the TZ1090 TRM for complete details regarding which groups
|
||||
support which functionality. The Linux pinctrl driver may also be a useful
|
||||
reference.
|
||||
|
||||
Valid values for pin and group names are:
|
||||
|
||||
gpio pins:
|
||||
|
||||
These all support bias-high-impediance, bias-pull-up, bias-pull-down, and
|
||||
bias-bus-hold (which can also be provided to any of the groups below to set
|
||||
it for all pins in that group).
|
||||
|
||||
They also all support the some form of muxing. Any pins which are contained
|
||||
in one of the mux groups (see below) can be muxed only to the functions
|
||||
supported by the mux group. All other pins can be muxed to the "perip"
|
||||
function which which enables them with their intended peripheral.
|
||||
|
||||
Different pins in the same mux group cannot be muxed to different functions,
|
||||
however it is possible to mux only a subset of the pins in a mux group to a
|
||||
particular function and leave the remaining pins unmuxed. This is useful if
|
||||
the board connects certain pins in a group to other devices to be controlled
|
||||
by GPIO, and you don't want the usual peripheral to have any control of the
|
||||
pin.
|
||||
|
||||
ant_sel0, ant_sel1, gain0, gain1, gain2, gain3, gain4, gain5, gain6, gain7,
|
||||
i2s_bclk_out, i2s_din, i2s_dout0, i2s_dout1, i2s_dout2, i2s_lrclk_out,
|
||||
i2s_mclk, pa_on, pdm_a, pdm_b, pdm_c, pdm_d, pll_on, rx_hp, rx_on,
|
||||
scb0_sclk, scb0_sdat, scb1_sclk, scb1_sdat, scb2_sclk, scb2_sdat, sdh_cd,
|
||||
sdh_clk_in, sdh_wp, sdio_clk, sdio_cmd, sdio_d0, sdio_d1, sdio_d2, sdio_d3,
|
||||
spi0_cs0, spi0_cs1, spi0_cs2, spi0_din, spi0_dout, spi0_mclk, spi1_cs0,
|
||||
spi1_cs1, spi1_cs2, spi1_din, spi1_dout, spi1_mclk, tft_blank_ls, tft_blue0,
|
||||
tft_blue1, tft_blue2, tft_blue3, tft_blue4, tft_blue5, tft_blue6, tft_blue7,
|
||||
tft_green0, tft_green1, tft_green2, tft_green3, tft_green4, tft_green5,
|
||||
tft_green6, tft_green7, tft_hsync_nr, tft_panelclk, tft_pwrsave, tft_red0,
|
||||
tft_red1, tft_red2, tft_red3, tft_red4, tft_red5, tft_red6, tft_red7,
|
||||
tft_vd12acb, tft_vdden_gd, tft_vsync_ns, tx_on, uart0_cts, uart0_rts,
|
||||
uart0_rxd, uart0_txd, uart1_rxd, uart1_txd.
|
||||
|
||||
bias-high-impediance: supported.
|
||||
bias-pull-up: supported.
|
||||
bias-pull-down: supported.
|
||||
bias-bus-hold: supported.
|
||||
function: perip or those supported by pin's mux group.
|
||||
|
||||
other pins:
|
||||
|
||||
These other pins are part of various pin groups below, but can't be
|
||||
controlled as GPIOs. They do however support bias-high-impediance,
|
||||
bias-pull-up, bias-pull-down, and bias-bus-hold (which can also be provided
|
||||
to any of the groups below to set it for all pins in that group).
|
||||
|
||||
clk_out0, clk_out1, tck, tdi, tdo, tms, trst.
|
||||
|
||||
bias-high-impediance: supported.
|
||||
bias-pull-up: supported.
|
||||
bias-pull-down: supported.
|
||||
bias-bus-hold: supported.
|
||||
|
||||
mux groups:
|
||||
|
||||
These all support function, and some support drive configs.
|
||||
|
||||
afe
|
||||
pins: tx_on, rx_on, pll_on, pa_on, rx_hp, ant_sel0,
|
||||
ant_sel1, gain0, gain1, gain2, gain3, gain4,
|
||||
gain5, gain6, gain7.
|
||||
function: afe, ts_out_0.
|
||||
input-schmitt-enable: supported.
|
||||
input-schmitt-disable: supported.
|
||||
drive-strength: supported.
|
||||
pdm_d
|
||||
pins: pdm_d.
|
||||
function: pdm_dac, usb_vbus.
|
||||
sdh
|
||||
pins: sdh_cd, sdh_wp, sdh_clk_in.
|
||||
function: sdh, sdio.
|
||||
sdio
|
||||
pins: sdio_clk, sdio_cmd, sdio_d0, sdio_d1, sdio_d2,
|
||||
sdio_d3.
|
||||
function: sdio, sdh.
|
||||
spi1_cs2
|
||||
pins: spi1_cs2.
|
||||
function: spi1_cs2, usb_vbus.
|
||||
tft
|
||||
pins: tft_red0, tft_red1, tft_red2, tft_red3,
|
||||
tft_red4, tft_red5, tft_red6, tft_red7,
|
||||
tft_green0, tft_green1, tft_green2, tft_green3,
|
||||
tft_green4, tft_green5, tft_green6, tft_green7,
|
||||
tft_blue0, tft_blue1, tft_blue2, tft_blue3,
|
||||
tft_blue4, tft_blue5, tft_blue6, tft_blue7,
|
||||
tft_vdden_gd, tft_panelclk, tft_blank_ls,
|
||||
tft_vsync_ns, tft_hsync_nr, tft_vd12acb,
|
||||
tft_pwrsave.
|
||||
function: tft, ext_dac, not_iqadc_stb, iqdac_stb, ts_out_1,
|
||||
lcd_trace, phy_ringosc.
|
||||
input-schmitt-enable: supported.
|
||||
input-schmitt-disable: supported.
|
||||
drive-strength: supported.
|
||||
|
||||
drive groups:
|
||||
|
||||
These all support input-schmitt-enable, input-schmitt-disable,
|
||||
and drive-strength.
|
||||
|
||||
jtag
|
||||
pins: tck, trst, tdi, tdo, tms.
|
||||
scb1
|
||||
pins: scb1_sdat, scb1_sclk.
|
||||
scb2
|
||||
pins: scb2_sdat, scb2_sclk.
|
||||
spi0
|
||||
pins: spi0_mclk, spi0_cs0, spi0_cs1, spi0_cs2, spi0_dout, spi0_din.
|
||||
spi1
|
||||
pins: spi1_mclk, spi1_cs0, spi1_cs1, spi1_cs2, spi1_dout, spi1_din.
|
||||
uart
|
||||
pins: uart0_txd, uart0_rxd, uart0_rts, uart0_cts,
|
||||
uart1_txd, uart1_rxd.
|
||||
drive_i2s
|
||||
pins: clk_out1, i2s_din, i2s_dout0, i2s_dout1, i2s_dout2,
|
||||
i2s_lrclk_out, i2s_bclk_out, i2s_mclk.
|
||||
drive_pdm
|
||||
pins: clk_out0, pdm_b, pdm_a.
|
||||
drive_scb0
|
||||
pins: scb0_sclk, scb0_sdat, pdm_d, pdm_c.
|
||||
drive_sdio
|
||||
pins: sdio_clk, sdio_cmd, sdio_d0, sdio_d1, sdio_d2, sdio_d3,
|
||||
sdh_wp, sdh_cd, sdh_clk_in.
|
||||
|
||||
convenience groups:
|
||||
|
||||
These are just convenient groupings of pins and don't support any drive
|
||||
configs.
|
||||
|
||||
uart0
|
||||
pins: uart0_cts, uart0_rts, uart0_rxd, uart0_txd.
|
||||
uart1
|
||||
pins: uart1_rxd, uart1_txd.
|
||||
scb0
|
||||
pins: scb0_sclk, scb0_sdat.
|
||||
i2s
|
||||
pins: i2s_bclk_out, i2s_din, i2s_dout0, i2s_dout1, i2s_dout2,
|
||||
i2s_lrclk_out, i2s_mclk.
|
||||
|
||||
Example:
|
||||
|
||||
pinctrl: pinctrl@02005800 {
|
||||
#gpio-range-cells = <3>;
|
||||
compatible = "img,tz1090-pinctrl";
|
||||
reg = <0x02005800 0xe4>;
|
||||
};
|
||||
|
||||
Example board file extract:
|
||||
|
||||
&pinctrl {
|
||||
uart0_default: uart0 {
|
||||
uart0_cfg {
|
||||
tz1090,pins = "uart0_rxd",
|
||||
"uart0_txd";
|
||||
tz1090,function = "perip";
|
||||
};
|
||||
};
|
||||
tft_default: tft {
|
||||
tft_cfg {
|
||||
tz1090,pins = "tft";
|
||||
tz1090,function = "tft";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
uart@02004b00 {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&uart0_default>;
|
||||
};
|
|
@ -10,29 +10,31 @@ Required properties:
|
|||
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.
|
||||
Note: pmu* also allows for Power Management functions listed below
|
||||
|
||||
name pins functions
|
||||
================================================================================
|
||||
mpp0 0 gpio, pmu, uart2(rts), sdio0(cd), lcd0(pwm)
|
||||
mpp1 1 gpio, pmu, uart2(cts), sdio0(wp), lcd1(pwm)
|
||||
mpp0 0 gpio, pmu, uart2(rts), sdio0(cd), lcd0(pwm), pmu*
|
||||
mpp1 1 gpio, pmu, uart2(cts), sdio0(wp), lcd1(pwm), pmu*
|
||||
mpp2 2 gpio, pmu, uart2(txd), sdio0(buspwr), sata(prsnt),
|
||||
uart1(rts)
|
||||
uart1(rts), pmu*
|
||||
mpp3 3 gpio, pmu, uart2(rxd), sdio0(ledctrl), sata(act),
|
||||
uart1(cts), lcd-spi(cs1)
|
||||
mpp4 4 gpio, pmu, uart3(rts), sdio1(cd), spi1(miso)
|
||||
mpp5 5 gpio, pmu, uart3(cts), sdio1(wp), spi1(cs)
|
||||
mpp6 6 gpio, pmu, uart3(txd), sdio1(buspwr), spi1(mosi)
|
||||
mpp7 7 gpio, pmu, uart3(rxd), sdio1(ledctrl), spi1(sck)
|
||||
mpp8 8 gpio, pmu, watchdog(rstout)
|
||||
mpp9 9 gpio, pmu, pex1(clkreq)
|
||||
mpp10 10 gpio, pmu, ssp(sclk)
|
||||
uart1(cts), lcd-spi(cs1), pmu*
|
||||
mpp4 4 gpio, pmu, uart3(rts), sdio1(cd), spi1(miso), pmu*
|
||||
mpp5 5 gpio, pmu, uart3(cts), sdio1(wp), spi1(cs), pmu*
|
||||
mpp6 6 gpio, pmu, uart3(txd), sdio1(buspwr), spi1(mosi), pmu*
|
||||
mpp7 7 gpio, pmu, uart3(rxd), sdio1(ledctrl), spi1(sck), pmu*
|
||||
mpp8 8 gpio, pmu, watchdog(rstout), pmu*
|
||||
mpp9 9 gpio, pmu, pex1(clkreq), pmu*
|
||||
mpp10 10 gpio, pmu, ssp(sclk), pmu*
|
||||
mpp11 11 gpio, pmu, sata(prsnt), sata-1(act), sdio0(ledctrl),
|
||||
sdio1(ledctrl), pex0(clkreq)
|
||||
mpp12 12 gpio, pmu, uart2(rts), audio0(extclk), sdio1(cd), sata(act)
|
||||
sdio1(ledctrl), pex0(clkreq), pmu*
|
||||
mpp12 12 gpio, pmu, uart2(rts), audio0(extclk), sdio1(cd),
|
||||
sata(act), pmu*
|
||||
mpp13 13 gpio, pmu, uart2(cts), audio1(extclk), sdio1(wp),
|
||||
ssp(extclk)
|
||||
mpp14 14 gpio, pmu, uart2(txd), sdio1(buspwr), ssp(rxd)
|
||||
mpp15 15 gpio, pmu, uart2(rxd), sdio1(ledctrl), ssp(sfrm)
|
||||
ssp(extclk), pmu*
|
||||
mpp14 14 gpio, pmu, uart2(txd), sdio1(buspwr), ssp(rxd), pmu*
|
||||
mpp15 15 gpio, pmu, uart2(rxd), sdio1(ledctrl), ssp(sfrm), pmu*
|
||||
mpp16 16 gpio, uart3(rts), sdio0(cd), ac97(sdi1), lcd-spi(cs1)
|
||||
mpp17 17 gpio, uart3(cts), sdio0(wp), ac97(sdi2), twsi(sda),
|
||||
ac97-1(sysclko)
|
||||
|
@ -57,6 +59,21 @@ mpp_nand 64-71 gpo, nand
|
|||
audio0 - i2s, ac97
|
||||
twsi - none, opt1, opt2, opt3
|
||||
|
||||
Power Management functions (pmu*):
|
||||
pmu-nc Pin not driven by any PM function
|
||||
pmu-low Pin driven low (0)
|
||||
pmu-high Pin driven high (1)
|
||||
pmic(sdi) Pin is used for PMIC SDI
|
||||
cpu-pwr-down Pin is used for CPU_PWRDWN
|
||||
standby-pwr-down Pin is used for STBY_PWRDWN
|
||||
core-pwr-good Pin is used for CORE_PWR_GOOD (Pins 0-7 only)
|
||||
cpu-pwr-good Pin is used for CPU_PWR_GOOD (Pins 8-15 only)
|
||||
bat-fault Pin is used for BATTERY_FAULT
|
||||
ext0-wakeup Pin is used for EXT0_WU
|
||||
ext1-wakeup Pin is used for EXT0_WU
|
||||
ext2-wakeup Pin is used for EXT0_WU
|
||||
pmu-blink Pin is used for blink function
|
||||
|
||||
Notes:
|
||||
* group "mpp_audio1" allows the following functions and gpio pins:
|
||||
- gpio : gpio on pins 52-57
|
||||
|
|
|
@ -126,3 +126,51 @@ device; they may be grandchildren, for example. Whether this is legal, and
|
|||
whether there is any interaction between the child and intermediate parent
|
||||
nodes, is again defined entirely by the binding for the individual pin
|
||||
controller device.
|
||||
|
||||
== Using generic pinconfig options ==
|
||||
|
||||
Generic pinconfig parameters can be used by defining a separate node containing
|
||||
the applicable parameters (and optional values), like:
|
||||
|
||||
pcfg_pull_up: pcfg_pull_up {
|
||||
bias-pull-up;
|
||||
drive-strength = <20>;
|
||||
};
|
||||
|
||||
This node should then be referenced in the appropriate pinctrl node as a phandle
|
||||
and parsed in the driver using the pinconf_generic_parse_dt_config function.
|
||||
|
||||
Supported configuration parameters are:
|
||||
|
||||
bias-disable - disable any pin bias
|
||||
bias-high-impedance - high impedance mode ("third-state", "floating")
|
||||
bias-bus-hold - latch weakly
|
||||
bias-pull-up - pull up the pin
|
||||
bias-pull-down - pull down the pin
|
||||
bias-pull-pin-default - use pin-default pull state
|
||||
drive-push-pull - drive actively high and low
|
||||
drive-open-drain - drive with open drain
|
||||
drive-open-source - drive with open source
|
||||
drive-strength - sink or source at most X mA
|
||||
input-schmitt-enable - enable schmitt-trigger mode
|
||||
input-schmitt-disable - disable schmitt-trigger mode
|
||||
input-debounce - debounce mode with debound time X
|
||||
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
|
||||
output-high - set the pin to output mode with high level
|
||||
|
||||
Arguments for parameters:
|
||||
|
||||
- bias-pull-up, -down and -pin-default take as optional argument on hardware
|
||||
supporting it the pull strength in Ohm. bias-disable will disable the pull.
|
||||
|
||||
- drive-strength takes as argument the target strength in mA.
|
||||
|
||||
- input-debounce takes the debounce time in usec as argument
|
||||
or 0 to disable debouncing
|
||||
|
||||
All parameters not listed here, do not take an argument.
|
||||
|
||||
More in-depth documentation on these parameters can be found in
|
||||
<include/linux/pinctrl/pinconfig-generic.h>
|
||||
|
|
|
@ -18,7 +18,8 @@ Optional properties:
|
|||
pin functions is ignored
|
||||
|
||||
- pinctrl-single,bit-per-mux : boolean to indicate that one register controls
|
||||
more than one pin
|
||||
more than one pin, for which "pinctrl-single,function-mask" property specifies
|
||||
position mask of pin.
|
||||
|
||||
- pinctrl-single,drive-strength : array of value that are used to configure
|
||||
drive strength in the pinmux register. They're value of drive strength
|
||||
|
|
|
@ -0,0 +1,153 @@
|
|||
* Renesas Pin Function Controller (GPIO and Pin Mux/Config)
|
||||
|
||||
The Pin Function Controller (PFC) is a Pin Mux/Config controller. On SH7372,
|
||||
SH73A0, R8A73A4 and R8A7740 it also acts as a GPIO controller.
|
||||
|
||||
|
||||
Pin Control
|
||||
-----------
|
||||
|
||||
Required Properties:
|
||||
|
||||
- compatible: should be one of the following.
|
||||
- "renesas,pfc-r8a73a4": for R8A73A4 (R-Mobile APE6) compatible pin-controller.
|
||||
- "renesas,pfc-r8a7740": for R8A7740 (R-Mobile A1) compatible pin-controller.
|
||||
- "renesas,pfc-r8a7778": for R8A7778 (R-Mobile M1) compatible pin-controller.
|
||||
- "renesas,pfc-r8a7779": for R8A7779 (R-Car H1) compatible pin-controller.
|
||||
- "renesas,pfc-r8a7790": for R8A7790 (R-Car H2) compatible pin-controller.
|
||||
- "renesas,pfc-sh7372": for SH7372 (SH-Mobile AP4) compatible pin-controller.
|
||||
- "renesas,pfc-sh73a0": for SH73A0 (SH-Mobile AG5) compatible pin-controller.
|
||||
|
||||
- reg: Base address and length of each memory resource used by the pin
|
||||
controller hardware module.
|
||||
|
||||
Optional properties:
|
||||
|
||||
- #gpio-range-cells: Mandatory when the PFC doesn't handle GPIO, forbidden
|
||||
otherwise. Should be 3.
|
||||
|
||||
The PFC node also acts as a container for pin configuration nodes. Please refer
|
||||
to pinctrl-bindings.txt in this directory for the definition of the term "pin
|
||||
configuration node" and for the common pinctrl bindings used by client devices.
|
||||
|
||||
Each pin configuration node represents a desired configuration for a pin, a
|
||||
pin group, or a list of pins or pin groups. The configuration can include the
|
||||
function to select on those pin(s) and pin configuration parameters (such as
|
||||
pull-up and pull-down).
|
||||
|
||||
Pin configuration nodes contain pin configuration properties, either directly
|
||||
or grouped in child subnodes. Both pin muxing and configuration parameters can
|
||||
be grouped in that way and referenced as a single pin configuration node by
|
||||
client devices.
|
||||
|
||||
A configuration node or subnode must reference at least one pin (through the
|
||||
pins or pin groups properties) and contain at least a function or one
|
||||
configuration parameter. When the function is present only pin groups can be
|
||||
used to reference pins.
|
||||
|
||||
All pin configuration nodes and subnodes names are ignored. All of those nodes
|
||||
are parsed through phandles and processed purely based on their content.
|
||||
|
||||
Pin Configuration Node Properties:
|
||||
|
||||
- renesas,pins : An array of strings, each string containing the name of a pin.
|
||||
- renesas,groups : An array of strings, each string containing the name of a pin
|
||||
group.
|
||||
|
||||
- renesas,function: A string containing the name of the function to mux to the
|
||||
pin group(s) specified by the renesas,groups property
|
||||
|
||||
Valid values for pin, group and function names can be found in the group and
|
||||
function arrays of the PFC data file corresponding to the SoC
|
||||
(drivers/pinctrl/sh-pfc/pfc-*.c)
|
||||
|
||||
The pin configuration parameters use the generic pinconf bindings defined in
|
||||
pinctrl-bindings.txt in this directory. The supported parameters are
|
||||
bias-disable, bias-pull-up and bias-pull-down.
|
||||
|
||||
|
||||
GPIO
|
||||
----
|
||||
|
||||
On SH7372, SH73A0, R8A73A4 and R8A7740 the PFC node is also a GPIO controller
|
||||
node.
|
||||
|
||||
Required Properties:
|
||||
|
||||
- gpio-controller: Marks the device node as a gpio controller.
|
||||
|
||||
- #gpio-cells: Should be 2. The first cell is the GPIO number and the second
|
||||
cell specifies GPIO flags, as defined in <dt-bindings/gpio/gpio.h>. Only the
|
||||
GPIO_ACTIVE_HIGH and GPIO_ACTIVE_LOW flags are supported.
|
||||
|
||||
The syntax of the gpio specifier used by client nodes should be the following
|
||||
with values derived from the SoC user manual.
|
||||
|
||||
<[phandle of the gpio controller node]
|
||||
[pin number within the gpio controller]
|
||||
[flags]>
|
||||
|
||||
On other mach-shmobile platforms GPIO is handled by the gpio-rcar driver.
|
||||
Please refer to Documentation/devicetree/bindings/gpio/renesas,gpio-rcar.txt
|
||||
for documentation of the GPIO device tree bindings on those platforms.
|
||||
|
||||
|
||||
Examples
|
||||
--------
|
||||
|
||||
Example 1: SH73A0 (SH-Mobile AG5) pin controller node
|
||||
|
||||
pfc: pfc@e6050000 {
|
||||
compatible = "renesas,pfc-sh73a0";
|
||||
reg = <0xe6050000 0x8000>,
|
||||
<0xe605801c 0x1c>;
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
Example 2: A GPIO LED node that references a GPIO
|
||||
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
|
||||
leds {
|
||||
compatible = "gpio-leds";
|
||||
led1 {
|
||||
gpios = <&pfc 20 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
};
|
||||
|
||||
Example 3: KZM-A9-GT (SH-Mobile AG5) default pin state hog and pin control maps
|
||||
for the MMCIF and SCIFA4 devices
|
||||
|
||||
&pfc {
|
||||
pinctrl-0 = <&scifa4_pins>;
|
||||
pinctrl-names = "default";
|
||||
|
||||
mmcif_pins: mmcif {
|
||||
mux {
|
||||
renesas,groups = "mmc0_data8_0", "mmc0_ctrl_0";
|
||||
renesas,function = "mmc0";
|
||||
};
|
||||
cfg {
|
||||
renesas,groups = "mmc0_data8_0";
|
||||
renesas,pins = "PORT279";
|
||||
bias-pull-up;
|
||||
};
|
||||
};
|
||||
|
||||
scifa4_pins: scifa4 {
|
||||
renesas,groups = "scifa4_data", "scifa4_ctrl";
|
||||
renesas,function = "scifa4";
|
||||
};
|
||||
};
|
||||
|
||||
Example 4: KZM-A9-GT (SH-Mobile AG5) default pin state for the MMCIF device
|
||||
|
||||
&mmcif {
|
||||
pinctrl-0 = <&mmcif_pins>;
|
||||
pinctrl-names = "default";
|
||||
|
||||
bus-width = <8>;
|
||||
vmmc-supply = <®_1p8v>;
|
||||
status = "okay";
|
||||
};
|
|
@ -0,0 +1,97 @@
|
|||
* Rockchip Pinmux Controller
|
||||
|
||||
The Rockchip Pinmux Controller, enables the IC
|
||||
to share one PAD to several functional blocks. The sharing is done by
|
||||
multiplexing the PAD input/output signals. For each PAD there are up to
|
||||
4 muxing options with option 0 being the use as a GPIO.
|
||||
|
||||
Please refer to pinctrl-bindings.txt in this directory for details of the
|
||||
common pinctrl bindings used by client devices, including the meaning of the
|
||||
phrase "pin configuration node".
|
||||
|
||||
The Rockchip pin configuration node is a node of a group of pins which can be
|
||||
used for a specific device or function. This node represents both mux and
|
||||
config of the pins in that group. The 'pins' selects the function mode(also
|
||||
named pin mode) this pin can work on and the 'config' configures various pad
|
||||
settings such as pull-up, etc.
|
||||
|
||||
The pins are grouped into up to 5 individual pin banks which need to be
|
||||
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"
|
||||
|
||||
Required properties for gpio sub nodes:
|
||||
- compatible: "rockchip,gpio-bank"
|
||||
- reg: register of the gpio bank (different than the iomux registerset)
|
||||
- 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.
|
||||
- #gpio-cells: number of cells in GPIO specifier. Since the generic GPIO
|
||||
binding is used, the amount of cells must be specified as 2. See generic
|
||||
GPIO binding documentation for description of particular cells.
|
||||
- interrupt-controller: identifies the controller node as interrupt-parent.
|
||||
- #interrupt-cells: the value of this property should be 2 and the interrupt
|
||||
cells should use the standard two-cell scheme described in
|
||||
bindings/interrupt-controller/interrupts.txt
|
||||
|
||||
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>.
|
||||
The MUX 0 means gpio and MUX 1 to 3 mean the specific device function.
|
||||
The phandle of a node containing the generic pinconfig options
|
||||
to use, as described in pinctrl-bindings.txt in this directory.
|
||||
|
||||
Examples:
|
||||
|
||||
#include <dt-bindings/pinctrl/rockchip.h>
|
||||
|
||||
...
|
||||
|
||||
pinctrl@20008000 {
|
||||
compatible = "rockchip,rk3066a-pinctrl";
|
||||
reg = <0x20008000 0x150>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
ranges;
|
||||
|
||||
gpio0: gpio0@20034000 {
|
||||
compatible = "rockchip,gpio-bank";
|
||||
reg = <0x20034000 0x100>;
|
||||
interrupts = <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&clk_gates8 9>;
|
||||
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
...
|
||||
|
||||
pcfg_pull_default: pcfg_pull_default {
|
||||
bias-pull-pin-default
|
||||
};
|
||||
|
||||
uart2 {
|
||||
uart2_xfer: uart2-xfer {
|
||||
rockchip,pins = <RK_GPIO1 8 1 &pcfg_pull_default>,
|
||||
<RK_GPIO1 9 1 &pcfg_pull_default>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
uart2: serial@20064000 {
|
||||
compatible = "snps,dw-apb-uart";
|
||||
reg = <0x20064000 0x400>;
|
||||
interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
|
||||
reg-shift = <2>;
|
||||
reg-io-width = <1>;
|
||||
clocks = <&mux_uart2>;
|
||||
status = "okay";
|
||||
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&uart2_xfer>;
|
||||
};
|
352
Documentation/devicetree/bindings/pinctrl/ste,abx500.txt
Normal file
352
Documentation/devicetree/bindings/pinctrl/ste,abx500.txt
Normal file
|
@ -0,0 +1,352 @@
|
|||
ST Ericsson abx500 pinmux controller
|
||||
|
||||
Required properties:
|
||||
- compatible: "stericsson,ab8500-gpio", "stericsson,ab8540-gpio",
|
||||
"stericsson,ab8505-gpio", "stericsson,ab9540-gpio",
|
||||
|
||||
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".
|
||||
|
||||
ST Ericsson's pin configuration nodes act as a container for an arbitrary number of
|
||||
subnodes. Each of these subnodes represents some desired configuration for a
|
||||
pin, a group, or a list of pins or groups. This configuration can include the
|
||||
mux function to select on those pin(s)/group(s), and various pin configuration
|
||||
parameters, such as input, output, pull up, pull down...
|
||||
|
||||
The name of each subnode is not important; all subnodes should be enumerated
|
||||
and processed purely based on their content.
|
||||
|
||||
Required subnode-properties:
|
||||
- ste,pins : An array of strings. Each string contains the name of a pin or
|
||||
group.
|
||||
|
||||
Optional subnode-properties:
|
||||
- ste,function: A string containing the name of the function to mux to the
|
||||
pin or group.
|
||||
|
||||
- generic pin configuration option to use. Example :
|
||||
|
||||
default_cfg {
|
||||
ste,pins = "GPIO1";
|
||||
bias-disable;
|
||||
};
|
||||
|
||||
- ste,config: Handle of pin configuration node containing the generic
|
||||
pinconfig options to use, as described in pinctrl-bindings.txt in
|
||||
this directory. Example :
|
||||
|
||||
pcfg_bias_disable: pcfg_bias_disable {
|
||||
bias-disable;
|
||||
};
|
||||
|
||||
default_cfg {
|
||||
ste,pins = "GPIO1";
|
||||
ste.config = <&pcfg_bias_disable>;
|
||||
};
|
||||
|
||||
Example board file extract:
|
||||
|
||||
&pinctrl_abx500 {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&sysclkreq2_default_mode>, <&sysclkreq3_default_mode>, <&gpio3_default_mode>, <&sysclkreq6_default_mode>, <&pwmout1_default_mode>, <&pwmout2_default_mode>, <&pwmout3_default_mode>, <&adi1_default_mode>, <&dmic12_default_mode>, <&dmic34_default_mode>, <&dmic56_default_mode>, <&sysclkreq5_default_mode>, <&batremn_default_mode>, <&service_default_mode>, <&pwrctrl0_default_mode>, <&pwrctrl1_default_mode>, <&pwmextvibra1_default_mode>, <&pwmextvibra2_default_mode>, <&gpio51_default_mode>, <&gpio52_default_mode>, <&gpio53_default_mode>, <&gpio54_default_mode>, <&pdmclkdat_default_mode>;
|
||||
|
||||
sysclkreq2 {
|
||||
sysclkreq2_default_mode: sysclkreq2_default {
|
||||
default_mux {
|
||||
ste,function = "sysclkreq";
|
||||
ste,pins = "sysclkreq2_d_1";
|
||||
};
|
||||
default_cfg {
|
||||
ste,pins = "GPIO1";
|
||||
bias-disable;
|
||||
};
|
||||
};
|
||||
};
|
||||
sysclkreq3 {
|
||||
sysclkreq3_default_mode: sysclkreq3_default {
|
||||
default_mux {
|
||||
ste,function = "sysclkreq";
|
||||
ste,pins = "sysclkreq3_d_1";
|
||||
};
|
||||
default_cfg {
|
||||
ste,pins = "GPIO2";
|
||||
output-low;
|
||||
};
|
||||
};
|
||||
};
|
||||
gpio3 {
|
||||
gpio3_default_mode: gpio3_default {
|
||||
default_mux {
|
||||
ste,function = "gpio";
|
||||
ste,pins = "gpio3_a_1";
|
||||
};
|
||||
default_cfg {
|
||||
ste,pins = "GPIO3";
|
||||
output-low;
|
||||
};
|
||||
};
|
||||
};
|
||||
sysclkreq6 {
|
||||
sysclkreq6_default_mode: sysclkreq6_default {
|
||||
default_mux {
|
||||
ste,function = "sysclkreq";
|
||||
ste,pins = "sysclkreq6_d_1";
|
||||
};
|
||||
default_cfg {
|
||||
ste,pins = "GPIO4";
|
||||
bias-disable;
|
||||
};
|
||||
};
|
||||
};
|
||||
pwmout1 {
|
||||
pwmout1_default_mode: pwmout1_default {
|
||||
default_mux {
|
||||
ste,function = "pwmout";
|
||||
ste,pins = "pwmout1_d_1";
|
||||
};
|
||||
default_cfg {
|
||||
ste,pins = "GPIO14";
|
||||
output-low;
|
||||
};
|
||||
};
|
||||
};
|
||||
pwmout2 {
|
||||
pwmout2_default_mode: pwmout2_default {
|
||||
pwmout2_default_mux {
|
||||
ste,function = "pwmout";
|
||||
ste,pins = "pwmout2_d_1";
|
||||
};
|
||||
pwmout2_default_cfg {
|
||||
ste,pins = "GPIO15";
|
||||
output-low;
|
||||
};
|
||||
};
|
||||
};
|
||||
pwmout3 {
|
||||
pwmout3_default_mode: pwmout3_default {
|
||||
pwmout3_default_mux {
|
||||
ste,function = "pwmout";
|
||||
ste,pins = "pwmout3_d_1";
|
||||
};
|
||||
pwmout3_default_cfg {
|
||||
ste,pins = "GPIO16";
|
||||
output-low;
|
||||
};
|
||||
};
|
||||
};
|
||||
adi1 {
|
||||
|
||||
adi1_default_mode: adi1_default {
|
||||
adi1_default_mux {
|
||||
ste,function = "adi1";
|
||||
ste,pins = "adi1_d_1";
|
||||
};
|
||||
adi1_default_cfg1 {
|
||||
ste,pins = "GPIO17","GPIO19","GPIO20";
|
||||
bias-disable;
|
||||
};
|
||||
adi1_default_cfg2 {
|
||||
ste,pins = "GPIO18";
|
||||
output-low;
|
||||
};
|
||||
};
|
||||
};
|
||||
dmic12 {
|
||||
dmic12_default_mode: dmic12_default {
|
||||
dmic12_default_mux {
|
||||
ste,function = "dmic";
|
||||
ste,pins = "dmic12_d_1";
|
||||
};
|
||||
dmic12_default_cfg1 {
|
||||
ste,pins = "GPIO27";
|
||||
output-low;
|
||||
};
|
||||
dmic12_default_cfg2 {
|
||||
ste,pins = "GPIO28";
|
||||
bias-disable;
|
||||
};
|
||||
};
|
||||
};
|
||||
dmic34 {
|
||||
dmic34_default_mode: dmic34_default {
|
||||
dmic34_default_mux {
|
||||
ste,function = "dmic";
|
||||
ste,pins = "dmic34_d_1";
|
||||
};
|
||||
dmic34_default_cfg1 {
|
||||
ste,pins = "GPIO29";
|
||||
output-low;
|
||||
};
|
||||
dmic34_default_cfg2 {
|
||||
ste,pins = "GPIO30";
|
||||
bias-disable;{
|
||||
|
||||
};
|
||||
};
|
||||
};
|
||||
dmic56 {
|
||||
dmic56_default_mode: dmic56_default {
|
||||
dmic56_default_mux {
|
||||
ste,function = "dmic";
|
||||
ste,pins = "dmic56_d_1";
|
||||
};
|
||||
dmic56_default_cfg1 {
|
||||
ste,pins = "GPIO31";
|
||||
output-low;
|
||||
};
|
||||
dmic56_default_cfg2 {
|
||||
ste,pins = "GPIO32";
|
||||
bias-disable;
|
||||
};
|
||||
};
|
||||
};
|
||||
sysclkreq5 {
|
||||
sysclkreq5_default_mode: sysclkreq5_default {
|
||||
sysclkreq5_default_mux {
|
||||
ste,function = "sysclkreq";
|
||||
ste,pins = "sysclkreq5_d_1";
|
||||
};
|
||||
sysclkreq5_default_cfg {
|
||||
ste,pins = "GPIO42";
|
||||
output-low;
|
||||
};
|
||||
};
|
||||
};
|
||||
batremn {
|
||||
batremn_default_mode: batremn_default {
|
||||
batremn_default_mux {
|
||||
ste,function = "batremn";
|
||||
ste,pins = "batremn_d_1";
|
||||
};
|
||||
batremn_default_cfg {
|
||||
ste,pins = "GPIO43";
|
||||
bias-disable;
|
||||
};
|
||||
};
|
||||
};
|
||||
service {
|
||||
service_default_mode: service_default {
|
||||
service_default_mux {
|
||||
ste,function = "service";
|
||||
ste,pins = "service_d_1";
|
||||
};
|
||||
service_default_cfg {
|
||||
ste,pins = "GPIO44";
|
||||
bias-disable;
|
||||
};
|
||||
};
|
||||
};
|
||||
pwrctrl0 {
|
||||
pwrctrl0_default_mux: pwrctrl0_mux {
|
||||
pwrctrl0_default_mux {
|
||||
ste,function = "pwrctrl";
|
||||
ste,pins = "pwrctrl0_d_1";
|
||||
};
|
||||
};
|
||||
pwrctrl0_default_mode: pwrctrl0_default {
|
||||
pwrctrl0_default_cfg {
|
||||
ste,pins = "GPIO45";
|
||||
bias-disable;
|
||||
};
|
||||
};
|
||||
};
|
||||
pwrctrl1 {
|
||||
pwrctrl1_default_mux: pwrctrl1_mux {
|
||||
pwrctrl1_default_mux {
|
||||
ste,function = "pwrctrl";
|
||||
ste,pins = "pwrctrl1_d_1";
|
||||
};
|
||||
};
|
||||
pwrctrl1_default_mode: pwrctrl1_default {
|
||||
pwrctrl1_default_cfg {
|
||||
ste,pins = "GPIO46";
|
||||
bias-disable;
|
||||
};
|
||||
};
|
||||
};
|
||||
pwmextvibra1 {
|
||||
pwmextvibra1_default_mode: pwmextvibra1_default {
|
||||
pwmextvibra1_default_mux {
|
||||
ste,function = "pwmextvibra";
|
||||
ste,pins = "pwmextvibra1_d_1";
|
||||
};
|
||||
pwmextvibra1_default_cfg {
|
||||
ste,pins = "GPIO47";
|
||||
bias-disable;
|
||||
};
|
||||
};
|
||||
};
|
||||
pwmextvibra2 {
|
||||
pwmextvibra2_default_mode: pwmextvibra2_default {
|
||||
pwmextvibra2_default_mux {
|
||||
ste,function = "pwmextvibra";
|
||||
ste,pins = "pwmextvibra2_d_1";
|
||||
};
|
||||
pwmextvibra1_default_cfg {
|
||||
ste,pins = "GPIO48";
|
||||
bias-disable;
|
||||
};
|
||||
};
|
||||
};
|
||||
gpio51 {
|
||||
gpio51_default_mode: gpio51_default {
|
||||
gpio51_default_mux {
|
||||
ste,function = "gpio";
|
||||
ste,pins = "gpio51_a_1";
|
||||
};
|
||||
gpio51_default_cfg {
|
||||
ste,pins = "GPIO51";
|
||||
output-low;
|
||||
};
|
||||
};
|
||||
};
|
||||
gpio52 {
|
||||
gpio52_default_mode: gpio52_default {
|
||||
gpio52_default_mux {
|
||||
ste,function = "gpio";
|
||||
ste,pins = "gpio52_a_1";
|
||||
};
|
||||
gpio52_default_cfg {
|
||||
ste,pins = "GPIO52";
|
||||
bias-pull-down;
|
||||
};
|
||||
};
|
||||
};
|
||||
gpio53 {
|
||||
gpio53_default_mode: gpio53_default {
|
||||
gpio53_default_mux {
|
||||
ste,function = "gpio";
|
||||
ste,pins = "gpio53_a_1";
|
||||
};
|
||||
gpio53_default_cfg {
|
||||
ste,pins = "GPIO53";
|
||||
bias-pull-down;
|
||||
};
|
||||
};
|
||||
};
|
||||
gpio54 {
|
||||
gpio54_default_mode: gpio54_default {
|
||||
gpio54_default_mux {
|
||||
ste,function = "gpio";
|
||||
ste,pins = "gpio54_a_1";
|
||||
};
|
||||
gpio54_default_cfg {
|
||||
ste,pins = "GPIO54";
|
||||
output-low;
|
||||
};
|
||||
};
|
||||
};
|
||||
pdmclkdat {
|
||||
pdmclkdat_default_mode: pdmclkdat_default {
|
||||
pdmclkdat_default_mux {
|
||||
ste,function = "pdm";
|
||||
ste,pins = "pdmclkdat_d_1";
|
||||
};
|
||||
pdmclkdat_default_cfg {
|
||||
ste,pins = "GPIO55", "GPIO56";
|
||||
bias-disable;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
|
@ -203,15 +203,8 @@ using a certain resistor value - pull up and pull down - so that the pin has a
|
|||
stable value when nothing is driving the rail it is connected to, or when it's
|
||||
unconnected.
|
||||
|
||||
Pin configuration can be programmed either using the explicit APIs described
|
||||
immediately below, or by adding configuration entries into the mapping table;
|
||||
see section "Board/machine configuration" below.
|
||||
|
||||
For example, a platform may do the following to pull up a pin to VDD:
|
||||
|
||||
#include <linux/pinctrl/consumer.h>
|
||||
|
||||
ret = pin_config_set("foo-dev", "FOO_GPIO_PIN", PLATFORM_X_PULL_UP);
|
||||
Pin configuration can be programmed by adding configuration entries into the
|
||||
mapping table; see section "Board/machine configuration" below.
|
||||
|
||||
The format and meaning of the configuration parameter, PLATFORM_X_PULL_UP
|
||||
above, is entirely defined by the pin controller driver.
|
||||
|
@ -350,6 +343,23 @@ chip b:
|
|||
- GPIO range : [48 .. 55]
|
||||
- pin range : [64 .. 71]
|
||||
|
||||
The above examples assume the mapping between the GPIOs and pins is
|
||||
linear. If the mapping is sparse or haphazard, an array of arbitrary pin
|
||||
numbers can be encoded in the range like this:
|
||||
|
||||
static const unsigned range_pins[] = { 14, 1, 22, 17, 10, 8, 6, 2 };
|
||||
|
||||
static struct pinctrl_gpio_range gpio_range = {
|
||||
.name = "chip",
|
||||
.id = 0,
|
||||
.base = 32,
|
||||
.pins = &range_pins,
|
||||
.npins = ARRAY_SIZE(range_pins),
|
||||
.gc = &chip;
|
||||
};
|
||||
|
||||
In this case the pin_base property will be ignored.
|
||||
|
||||
When GPIO-specific functions in the pin control subsystem are called, these
|
||||
ranges will be used to look up the appropriate pin controller by inspecting
|
||||
and matching the pin to the pin ranges across all controllers. When a
|
||||
|
@ -357,9 +367,9 @@ pin controller handling the matching range is found, GPIO-specific functions
|
|||
will be called on that specific pin controller.
|
||||
|
||||
For all functionalities dealing with pin biasing, pin muxing etc, the pin
|
||||
controller subsystem will subtract the range's .base offset from the passed
|
||||
in gpio number, and add the ranges's .pin_base offset to retrive a pin number.
|
||||
After that, the subsystem passes it on to the pin control driver, so the driver
|
||||
controller subsystem will look up the corresponding pin number from the passed
|
||||
in gpio number, and use the range's internals to retrive a pin number. After
|
||||
that, the subsystem passes it on to the pin control driver, so the driver
|
||||
will get an pin number into its handled number range. Further it is also passed
|
||||
the range ID value, so that the pin controller knows which range it should
|
||||
deal with.
|
||||
|
@ -368,6 +378,7 @@ Calling pinctrl_add_gpio_range from pinctrl driver is DEPRECATED. Please see
|
|||
section 2.1 of Documentation/devicetree/bindings/gpio/gpio.txt on how to bind
|
||||
pinctrl and gpio drivers.
|
||||
|
||||
|
||||
PINMUX interfaces
|
||||
=================
|
||||
|
||||
|
@ -1226,8 +1237,8 @@ setting up the config and muxing for the pins right before the device is
|
|||
probing, nevertheless orthogonal to the GPIO subsystem.
|
||||
|
||||
But there are also situations where it makes sense for the GPIO subsystem
|
||||
to communicate directly with with the pinctrl subsystem, using the latter
|
||||
as a back-end. This is when the GPIO driver may call out to the functions
|
||||
to communicate directly with the pinctrl subsystem, using the latter as a
|
||||
back-end. This is when the GPIO driver may call out to the functions
|
||||
described in the section "Pin control interaction with the GPIO subsystem"
|
||||
above. This only involves per-pin multiplexing, and will be completely
|
||||
hidden behind the gpio_*() function namespace. In this case, the driver
|
||||
|
|
10
MAINTAINERS
10
MAINTAINERS
|
@ -6295,6 +6295,16 @@ L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
|
|||
S: Maintained
|
||||
F: drivers/pinctrl/pinctrl-at91.c
|
||||
|
||||
PIN CONTROLLER - SAMSUNG
|
||||
M: Tomasz Figa <t.figa@samsung.com>
|
||||
M: Thomas Abraham <thomas.abraham@linaro.org>
|
||||
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
|
||||
L: linux-samsung-soc@vger.kernel.org (moderated for non-subscribers)
|
||||
S: Maintained
|
||||
F: drivers/pinctrl/pinctrl-exynos.*
|
||||
F: drivers/pinctrl/pinctrl-s3c*
|
||||
F: drivers/pinctrl/pinctrl-samsung.*
|
||||
|
||||
PIN CONTROLLER - ST SPEAR
|
||||
M: Viresh Kumar <viresh.linux@gmail.com>
|
||||
L: spear-devel@list.st.com
|
||||
|
|
|
@ -48,6 +48,25 @@ int pinctrl_bind_pins(struct device *dev)
|
|||
goto cleanup_get;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
/*
|
||||
* If power management is enabled, we also look for the optional
|
||||
* sleep and idle pin states, with semantics as defined in
|
||||
* <linux/pinctrl/pinctrl-state.h>
|
||||
*/
|
||||
dev->pins->sleep_state = pinctrl_lookup_state(dev->pins->p,
|
||||
PINCTRL_STATE_SLEEP);
|
||||
if (IS_ERR(dev->pins->sleep_state))
|
||||
/* Not supplying this state is perfectly legal */
|
||||
dev_dbg(dev, "no sleep pinctrl state\n");
|
||||
|
||||
dev->pins->idle_state = pinctrl_lookup_state(dev->pins->p,
|
||||
PINCTRL_STATE_IDLE);
|
||||
if (IS_ERR(dev->pins->idle_state))
|
||||
/* Not supplying this state is perfectly legal */
|
||||
dev_dbg(dev, "no idle pinctrl state\n");
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
||||
/*
|
||||
|
|
|
@ -148,10 +148,6 @@ struct i2c_nmk_client {
|
|||
* @stop: stop condition.
|
||||
* @xfer_complete: acknowledge completion for a I2C message.
|
||||
* @result: controller propogated result.
|
||||
* @pinctrl: pinctrl handle.
|
||||
* @pins_default: default state for the pins.
|
||||
* @pins_idle: idle state for the pins.
|
||||
* @pins_sleep: sleep state for the pins.
|
||||
* @busy: Busy doing transfer.
|
||||
*/
|
||||
struct nmk_i2c_dev {
|
||||
|
@ -165,11 +161,6 @@ struct nmk_i2c_dev {
|
|||
int stop;
|
||||
struct completion xfer_complete;
|
||||
int result;
|
||||
/* Three pin states - default, idle & sleep */
|
||||
struct pinctrl *pinctrl;
|
||||
struct pinctrl_state *pins_default;
|
||||
struct pinctrl_state *pins_idle;
|
||||
struct pinctrl_state *pins_sleep;
|
||||
bool busy;
|
||||
};
|
||||
|
||||
|
@ -645,13 +636,7 @@ static int nmk_i2c_xfer(struct i2c_adapter *i2c_adap,
|
|||
}
|
||||
|
||||
/* Optionaly enable pins to be muxed in and configured */
|
||||
if (!IS_ERR(dev->pins_default)) {
|
||||
status = pinctrl_select_state(dev->pinctrl,
|
||||
dev->pins_default);
|
||||
if (status)
|
||||
dev_err(&dev->adev->dev,
|
||||
"could not set default pins\n");
|
||||
}
|
||||
pinctrl_pm_select_default_state(&dev->adev->dev);
|
||||
|
||||
status = init_hw(dev);
|
||||
if (status)
|
||||
|
@ -681,13 +666,7 @@ static int nmk_i2c_xfer(struct i2c_adapter *i2c_adap,
|
|||
clk_disable_unprepare(dev->clk);
|
||||
out_clk:
|
||||
/* Optionally let pins go into idle state */
|
||||
if (!IS_ERR(dev->pins_idle)) {
|
||||
status = pinctrl_select_state(dev->pinctrl,
|
||||
dev->pins_idle);
|
||||
if (status)
|
||||
dev_err(&dev->adev->dev,
|
||||
"could not set pins to idle state\n");
|
||||
}
|
||||
pinctrl_pm_select_idle_state(&dev->adev->dev);
|
||||
|
||||
pm_runtime_put_sync(&dev->adev->dev);
|
||||
|
||||
|
@ -882,41 +861,22 @@ static int nmk_i2c_suspend(struct device *dev)
|
|||
{
|
||||
struct amba_device *adev = to_amba_device(dev);
|
||||
struct nmk_i2c_dev *nmk_i2c = amba_get_drvdata(adev);
|
||||
int ret;
|
||||
|
||||
if (nmk_i2c->busy)
|
||||
return -EBUSY;
|
||||
|
||||
if (!IS_ERR(nmk_i2c->pins_sleep)) {
|
||||
ret = pinctrl_select_state(nmk_i2c->pinctrl,
|
||||
nmk_i2c->pins_sleep);
|
||||
if (ret)
|
||||
dev_err(dev, "could not set pins to sleep state\n");
|
||||
}
|
||||
pinctrl_pm_select_sleep_state(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nmk_i2c_resume(struct device *dev)
|
||||
{
|
||||
struct amba_device *adev = to_amba_device(dev);
|
||||
struct nmk_i2c_dev *nmk_i2c = amba_get_drvdata(adev);
|
||||
int ret;
|
||||
|
||||
/* First go to the default state */
|
||||
if (!IS_ERR(nmk_i2c->pins_default)) {
|
||||
ret = pinctrl_select_state(nmk_i2c->pinctrl,
|
||||
nmk_i2c->pins_default);
|
||||
if (ret)
|
||||
dev_err(dev, "could not set pins to default state\n");
|
||||
}
|
||||
pinctrl_pm_select_default_state(dev);
|
||||
/* Then let's idle the pins until the next transfer happens */
|
||||
if (!IS_ERR(nmk_i2c->pins_idle)) {
|
||||
ret = pinctrl_select_state(nmk_i2c->pinctrl,
|
||||
nmk_i2c->pins_idle);
|
||||
if (ret)
|
||||
dev_err(dev, "could not set pins to idle state\n");
|
||||
}
|
||||
pinctrl_pm_select_idle_state(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
|
@ -1004,39 +964,10 @@ static int nmk_i2c_probe(struct amba_device *adev, const struct amba_id *id)
|
|||
dev->adev = adev;
|
||||
amba_set_drvdata(adev, dev);
|
||||
|
||||
dev->pinctrl = devm_pinctrl_get(&adev->dev);
|
||||
if (IS_ERR(dev->pinctrl)) {
|
||||
ret = PTR_ERR(dev->pinctrl);
|
||||
goto err_pinctrl;
|
||||
}
|
||||
|
||||
dev->pins_default = pinctrl_lookup_state(dev->pinctrl,
|
||||
PINCTRL_STATE_DEFAULT);
|
||||
if (IS_ERR(dev->pins_default)) {
|
||||
dev_err(&adev->dev, "could not get default pinstate\n");
|
||||
} else {
|
||||
ret = pinctrl_select_state(dev->pinctrl,
|
||||
dev->pins_default);
|
||||
if (ret)
|
||||
dev_dbg(&adev->dev, "could not set default pinstate\n");
|
||||
}
|
||||
|
||||
dev->pins_idle = pinctrl_lookup_state(dev->pinctrl,
|
||||
PINCTRL_STATE_IDLE);
|
||||
if (IS_ERR(dev->pins_idle)) {
|
||||
dev_dbg(&adev->dev, "could not get idle pinstate\n");
|
||||
} else {
|
||||
/* If possible, let's go to idle until the first transfer */
|
||||
ret = pinctrl_select_state(dev->pinctrl,
|
||||
dev->pins_idle);
|
||||
if (ret)
|
||||
dev_dbg(&adev->dev, "could not set idle pinstate\n");
|
||||
}
|
||||
|
||||
dev->pins_sleep = pinctrl_lookup_state(dev->pinctrl,
|
||||
PINCTRL_STATE_SLEEP);
|
||||
if (IS_ERR(dev->pins_sleep))
|
||||
dev_dbg(&adev->dev, "could not get sleep pinstate\n");
|
||||
/* Select default pin state */
|
||||
pinctrl_pm_select_default_state(&adev->dev);
|
||||
/* If possible, let's go to idle until the first transfer */
|
||||
pinctrl_pm_select_idle_state(&adev->dev);
|
||||
|
||||
dev->virtbase = ioremap(adev->res.start, resource_size(&adev->res));
|
||||
if (!dev->virtbase) {
|
||||
|
@ -1106,7 +1037,6 @@ static int nmk_i2c_probe(struct amba_device *adev, const struct amba_id *id)
|
|||
iounmap(dev->virtbase);
|
||||
err_no_ioremap:
|
||||
kfree(dev);
|
||||
err_pinctrl:
|
||||
err_no_mem:
|
||||
|
||||
return ret;
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include <linux/if_vlan.h>
|
||||
|
||||
#include <linux/platform_data/cpsw.h>
|
||||
#include <linux/pinctrl/consumer.h>
|
||||
|
||||
#include "cpsw_ale.h"
|
||||
#include "cpts.h"
|
||||
|
@ -1689,6 +1690,9 @@ static int cpsw_probe(struct platform_device *pdev)
|
|||
*/
|
||||
pm_runtime_enable(&pdev->dev);
|
||||
|
||||
/* Select default pin state */
|
||||
pinctrl_pm_select_default_state(&pdev->dev);
|
||||
|
||||
if (cpsw_probe_dt(&priv->data, pdev)) {
|
||||
pr_err("cpsw: platform data missing\n");
|
||||
ret = -ENODEV;
|
||||
|
@ -1981,6 +1985,9 @@ static int cpsw_suspend(struct device *dev)
|
|||
soft_reset("sliver 1", &priv->slaves[1].sliver->soft_reset);
|
||||
pm_runtime_put_sync(&pdev->dev);
|
||||
|
||||
/* Select sleep pin state */
|
||||
pinctrl_pm_select_sleep_state(&pdev->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1990,6 +1997,10 @@ static int cpsw_resume(struct device *dev)
|
|||
struct net_device *ndev = platform_get_drvdata(pdev);
|
||||
|
||||
pm_runtime_get_sync(&pdev->dev);
|
||||
|
||||
/* Select default pin state */
|
||||
pinctrl_pm_select_default_state(&pdev->dev);
|
||||
|
||||
if (netif_running(ndev))
|
||||
cpsw_ndo_open(ndev);
|
||||
return 0;
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include <linux/davinci_emac.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/pinctrl/consumer.h>
|
||||
|
||||
/*
|
||||
* This timeout definition is a worst-case ultra defensive measure against
|
||||
|
@ -347,6 +348,9 @@ static int davinci_mdio_probe(struct platform_device *pdev)
|
|||
data->bus->parent = dev;
|
||||
data->bus->priv = data;
|
||||
|
||||
/* Select default pin state */
|
||||
pinctrl_pm_select_default_state(&pdev->dev);
|
||||
|
||||
pm_runtime_enable(&pdev->dev);
|
||||
pm_runtime_get_sync(&pdev->dev);
|
||||
data->clk = clk_get(&pdev->dev, "fck");
|
||||
|
@ -453,6 +457,9 @@ static int davinci_mdio_suspend(struct device *dev)
|
|||
spin_unlock(&data->lock);
|
||||
pm_runtime_put_sync(data->dev);
|
||||
|
||||
/* Select sleep pin state */
|
||||
pinctrl_pm_select_sleep_state(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -460,6 +467,9 @@ static int davinci_mdio_resume(struct device *dev)
|
|||
{
|
||||
struct davinci_mdio_data *data = dev_get_drvdata(dev);
|
||||
|
||||
/* Select default pin state */
|
||||
pinctrl_pm_select_default_state(dev);
|
||||
|
||||
pm_runtime_get_sync(data->dev);
|
||||
|
||||
spin_lock(&data->lock);
|
||||
|
|
|
@ -58,6 +58,18 @@ config PINCTRL_AT91
|
|||
help
|
||||
Say Y here to enable the at91 pinctrl driver
|
||||
|
||||
config PINCTRL_BAYTRAIL
|
||||
bool "Intel Baytrail GPIO pin control"
|
||||
depends on GPIOLIB && ACPI && X86
|
||||
select IRQ_DOMAIN
|
||||
help
|
||||
driver for memory mapped GPIO functionality on Intel Baytrail
|
||||
platforms. Supports 3 banks with 102, 28 and 44 gpios.
|
||||
Most pins are usually muxed to some other functionality by firmware,
|
||||
so only a small amount is available for gpio use.
|
||||
|
||||
Requires ACPI device enumeration code to set up a platform device.
|
||||
|
||||
config PINCTRL_BCM2835
|
||||
bool
|
||||
select PINMUX
|
||||
|
@ -108,6 +120,14 @@ config PINCTRL_IMX6SL
|
|||
help
|
||||
Say Y here to enable the imx6sl pinctrl driver
|
||||
|
||||
config PINCTRL_VF610
|
||||
bool "Freescale Vybrid VF610 pinctrl driver"
|
||||
depends on OF
|
||||
depends on SOC_VF610
|
||||
select PINCTRL_IMX
|
||||
help
|
||||
Say Y here to enable the Freescale Vybrid VF610 pinctrl driver
|
||||
|
||||
config PINCTRL_LANTIQ
|
||||
bool
|
||||
depends on LANTIQ
|
||||
|
@ -150,6 +170,12 @@ config PINCTRL_DB8540
|
|||
bool "DB8540 pin controller driver"
|
||||
depends on PINCTRL_NOMADIK && ARCH_U8500
|
||||
|
||||
config PINCTRL_ROCKCHIP
|
||||
bool
|
||||
select PINMUX
|
||||
select GENERIC_PINCONF
|
||||
select GENERIC_IRQ_CHIP
|
||||
|
||||
config PINCTRL_SINGLE
|
||||
tristate "One-register-per-pin type device tree based pinctrl driver"
|
||||
depends on OF
|
||||
|
@ -192,6 +218,18 @@ config PINCTRL_TEGRA114
|
|||
bool
|
||||
select PINCTRL_TEGRA
|
||||
|
||||
config PINCTRL_TZ1090
|
||||
bool "Toumaz Xenif TZ1090 pin control driver"
|
||||
depends on SOC_TZ1090
|
||||
select PINMUX
|
||||
select GENERIC_PINCONF
|
||||
|
||||
config PINCTRL_TZ1090_PDC
|
||||
bool "Toumaz Xenif TZ1090 PDC pin control driver"
|
||||
depends on SOC_TZ1090
|
||||
select PINMUX
|
||||
select PINCONF
|
||||
|
||||
config PINCTRL_U300
|
||||
bool "U300 pin controller driver"
|
||||
depends on ARCH_U300
|
||||
|
|
|
@ -16,12 +16,14 @@ obj-$(CONFIG_PINCTRL_AB9540) += pinctrl-ab9540.o
|
|||
obj-$(CONFIG_PINCTRL_AB8505) += pinctrl-ab8505.o
|
||||
obj-$(CONFIG_PINCTRL_AT91) += pinctrl-at91.o
|
||||
obj-$(CONFIG_PINCTRL_BCM2835) += pinctrl-bcm2835.o
|
||||
obj-$(CONFIG_PINCTRL_BAYTRAIL) += pinctrl-baytrail.o
|
||||
obj-$(CONFIG_PINCTRL_IMX) += pinctrl-imx.o
|
||||
obj-$(CONFIG_PINCTRL_IMX35) += pinctrl-imx35.o
|
||||
obj-$(CONFIG_PINCTRL_IMX51) += pinctrl-imx51.o
|
||||
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_FALCON) += pinctrl-falcon.o
|
||||
obj-$(CONFIG_PINCTRL_MXS) += pinctrl-mxs.o
|
||||
obj-$(CONFIG_PINCTRL_IMX23) += pinctrl-imx23.o
|
||||
|
@ -30,13 +32,16 @@ obj-$(CONFIG_PINCTRL_NOMADIK) += pinctrl-nomadik.o
|
|||
obj-$(CONFIG_PINCTRL_STN8815) += pinctrl-nomadik-stn8815.o
|
||||
obj-$(CONFIG_PINCTRL_DB8500) += pinctrl-nomadik-db8500.o
|
||||
obj-$(CONFIG_PINCTRL_DB8540) += pinctrl-nomadik-db8540.o
|
||||
obj-$(CONFIG_PINCTRL_ROCKCHIP) += pinctrl-rockchip.o
|
||||
obj-$(CONFIG_PINCTRL_SINGLE) += pinctrl-single.o
|
||||
obj-$(CONFIG_PINCTRL_SIRF) += pinctrl-sirf.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
|
||||
obj-$(CONFIG_PINCTRL_TEGRA114) += pinctrl-tegra114.o
|
||||
obj-$(CONFIG_PINCTRL_TZ1090) += pinctrl-tz1090.o
|
||||
obj-$(CONFIG_PINCTRL_TZ1090_PDC) += pinctrl-tz1090-pdc.o
|
||||
obj-$(CONFIG_PINCTRL_U300) += pinctrl-u300.o
|
||||
obj-$(CONFIG_PINCTRL_COH901) += pinctrl-coh901.o
|
||||
obj-$(CONFIG_PINCTRL_SAMSUNG) += pinctrl-samsung.o
|
||||
|
@ -47,6 +52,7 @@ obj-$(CONFIG_PINCTRL_S3C64XX) += pinctrl-s3c64xx.o
|
|||
obj-$(CONFIG_PINCTRL_XWAY) += pinctrl-xway.o
|
||||
obj-$(CONFIG_PINCTRL_LANTIQ) += pinctrl-lantiq.o
|
||||
obj-$(CONFIG_PINCTRL_ST) += pinctrl-st.o
|
||||
obj-$(CONFIG_PINCTRL_VF610) += pinctrl-vf610.o
|
||||
|
||||
obj-$(CONFIG_PLAT_ORION) += mvebu/
|
||||
obj-$(CONFIG_ARCH_SHMOBILE) += sh-pfc/
|
||||
|
|
|
@ -41,13 +41,13 @@
|
|||
static bool pinctrl_dummy_state;
|
||||
|
||||
/* Mutex taken to protect pinctrl_list */
|
||||
DEFINE_MUTEX(pinctrl_list_mutex);
|
||||
static DEFINE_MUTEX(pinctrl_list_mutex);
|
||||
|
||||
/* Mutex taken to protect pinctrl_maps */
|
||||
DEFINE_MUTEX(pinctrl_maps_mutex);
|
||||
|
||||
/* Mutex taken to protect pinctrldev_list */
|
||||
DEFINE_MUTEX(pinctrldev_list_mutex);
|
||||
static DEFINE_MUTEX(pinctrldev_list_mutex);
|
||||
|
||||
/* Global list of pin control devices (struct pinctrl_dev) */
|
||||
static LIST_HEAD(pinctrldev_list);
|
||||
|
@ -101,20 +101,23 @@ EXPORT_SYMBOL_GPL(pinctrl_dev_get_drvdata);
|
|||
struct pinctrl_dev *get_pinctrl_dev_from_devname(const char *devname)
|
||||
{
|
||||
struct pinctrl_dev *pctldev = NULL;
|
||||
bool found = false;
|
||||
|
||||
if (!devname)
|
||||
return NULL;
|
||||
|
||||
mutex_lock(&pinctrldev_list_mutex);
|
||||
|
||||
list_for_each_entry(pctldev, &pinctrldev_list, node) {
|
||||
if (!strcmp(dev_name(pctldev->dev), devname)) {
|
||||
/* Matched on device name */
|
||||
found = true;
|
||||
break;
|
||||
mutex_unlock(&pinctrldev_list_mutex);
|
||||
return pctldev;
|
||||
}
|
||||
}
|
||||
|
||||
return found ? pctldev : NULL;
|
||||
mutex_unlock(&pinctrldev_list_mutex);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct pinctrl_dev *get_pinctrl_dev_from_of_node(struct device_node *np)
|
||||
|
@ -279,6 +282,29 @@ static int pinctrl_register_pins(struct pinctrl_dev *pctldev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* gpio_to_pin() - GPIO range GPIO number to pin number translation
|
||||
* @range: GPIO range used for the translation
|
||||
* @gpio: gpio pin to translate to a pin number
|
||||
*
|
||||
* Finds the pin number for a given GPIO using the specified GPIO range
|
||||
* as a base for translation. The distinction between linear GPIO ranges
|
||||
* and pin list based GPIO ranges is managed correctly by this function.
|
||||
*
|
||||
* This function assumes the gpio is part of the specified GPIO range, use
|
||||
* only after making sure this is the case (e.g. by calling it on the
|
||||
* result of successful pinctrl_get_device_gpio_range calls)!
|
||||
*/
|
||||
static inline int gpio_to_pin(struct pinctrl_gpio_range *range,
|
||||
unsigned int gpio)
|
||||
{
|
||||
unsigned int offset = gpio - range->base;
|
||||
if (range->pins)
|
||||
return range->pins[offset];
|
||||
else
|
||||
return range->pin_base + offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* pinctrl_match_gpio_range() - check if a certain GPIO pin is in range
|
||||
* @pctldev: pin controller device to check
|
||||
|
@ -326,6 +352,8 @@ static bool pinctrl_ready_for_gpio_range(unsigned gpio)
|
|||
struct pinctrl_gpio_range *range = NULL;
|
||||
struct gpio_chip *chip = gpio_to_chip(gpio);
|
||||
|
||||
mutex_lock(&pinctrldev_list_mutex);
|
||||
|
||||
/* Loop over the pin controllers */
|
||||
list_for_each_entry(pctldev, &pinctrldev_list, node) {
|
||||
/* Loop over the ranges */
|
||||
|
@ -334,9 +362,13 @@ static bool pinctrl_ready_for_gpio_range(unsigned gpio)
|
|||
if (range->base + range->npins - 1 < chip->base ||
|
||||
range->base > chip->base + chip->ngpio - 1)
|
||||
continue;
|
||||
mutex_unlock(&pinctrldev_list_mutex);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
mutex_unlock(&pinctrldev_list_mutex);
|
||||
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
|
@ -408,8 +440,6 @@ struct pinctrl_dev *pinctrl_find_and_add_gpio_range(const char *devname,
|
|||
{
|
||||
struct pinctrl_dev *pctldev;
|
||||
|
||||
mutex_lock(&pinctrldev_list_mutex);
|
||||
|
||||
pctldev = get_pinctrl_dev_from_devname(devname);
|
||||
|
||||
/*
|
||||
|
@ -418,13 +448,10 @@ struct pinctrl_dev *pinctrl_find_and_add_gpio_range(const char *devname,
|
|||
* range need to defer probing.
|
||||
*/
|
||||
if (!pctldev) {
|
||||
mutex_unlock(&pinctrldev_list_mutex);
|
||||
return ERR_PTR(-EPROBE_DEFER);
|
||||
}
|
||||
pinctrl_add_gpio_range(pctldev, range);
|
||||
|
||||
mutex_unlock(&pinctrldev_list_mutex);
|
||||
|
||||
return pctldev;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pinctrl_find_and_add_gpio_range);
|
||||
|
@ -438,21 +465,26 @@ struct pinctrl_gpio_range *
|
|||
pinctrl_find_gpio_range_from_pin(struct pinctrl_dev *pctldev,
|
||||
unsigned int pin)
|
||||
{
|
||||
struct pinctrl_gpio_range *range = NULL;
|
||||
struct pinctrl_gpio_range *range;
|
||||
|
||||
mutex_lock(&pctldev->mutex);
|
||||
/* Loop over the ranges */
|
||||
list_for_each_entry(range, &pctldev->gpio_ranges, node) {
|
||||
/* Check if we're in the valid range */
|
||||
if (pin >= range->pin_base &&
|
||||
pin < range->pin_base + range->npins) {
|
||||
mutex_unlock(&pctldev->mutex);
|
||||
return range;
|
||||
}
|
||||
if (range->pins) {
|
||||
int a;
|
||||
for (a = 0; a < range->npins; a++) {
|
||||
if (range->pins[a] == pin)
|
||||
goto out;
|
||||
}
|
||||
} else if (pin >= range->pin_base &&
|
||||
pin < range->pin_base + range->npins)
|
||||
goto out;
|
||||
}
|
||||
range = NULL;
|
||||
out:
|
||||
mutex_unlock(&pctldev->mutex);
|
||||
|
||||
return NULL;
|
||||
return range;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pinctrl_find_gpio_range_from_pin);
|
||||
|
||||
|
@ -517,22 +549,18 @@ int pinctrl_request_gpio(unsigned gpio)
|
|||
int ret;
|
||||
int pin;
|
||||
|
||||
mutex_lock(&pinctrldev_list_mutex);
|
||||
|
||||
ret = pinctrl_get_device_gpio_range(gpio, &pctldev, &range);
|
||||
if (ret) {
|
||||
if (pinctrl_ready_for_gpio_range(gpio))
|
||||
ret = 0;
|
||||
mutex_unlock(&pinctrldev_list_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Convert to the pin controllers number space */
|
||||
pin = gpio - range->base + range->pin_base;
|
||||
pin = gpio_to_pin(range, gpio);
|
||||
|
||||
ret = pinmux_request_gpio(pctldev, range, pin, gpio);
|
||||
|
||||
mutex_unlock(&pinctrldev_list_mutex);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pinctrl_request_gpio);
|
||||
|
@ -552,22 +580,18 @@ void pinctrl_free_gpio(unsigned gpio)
|
|||
int ret;
|
||||
int pin;
|
||||
|
||||
mutex_lock(&pinctrldev_list_mutex);
|
||||
|
||||
ret = pinctrl_get_device_gpio_range(gpio, &pctldev, &range);
|
||||
if (ret) {
|
||||
mutex_unlock(&pinctrldev_list_mutex);
|
||||
return;
|
||||
}
|
||||
mutex_lock(&pctldev->mutex);
|
||||
|
||||
/* Convert to the pin controllers number space */
|
||||
pin = gpio - range->base + range->pin_base;
|
||||
pin = gpio_to_pin(range, gpio);
|
||||
|
||||
pinmux_free_gpio(pctldev, pin, range);
|
||||
|
||||
mutex_unlock(&pctldev->mutex);
|
||||
mutex_unlock(&pinctrldev_list_mutex);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pinctrl_free_gpio);
|
||||
|
||||
|
@ -578,22 +602,18 @@ static int pinctrl_gpio_direction(unsigned gpio, bool input)
|
|||
int ret;
|
||||
int pin;
|
||||
|
||||
mutex_lock(&pinctrldev_list_mutex);
|
||||
|
||||
ret = pinctrl_get_device_gpio_range(gpio, &pctldev, &range);
|
||||
if (ret) {
|
||||
mutex_unlock(&pinctrldev_list_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
mutex_lock(&pctldev->mutex);
|
||||
|
||||
/* Convert to the pin controllers number space */
|
||||
pin = gpio - range->base + range->pin_base;
|
||||
pin = gpio_to_pin(range, gpio);
|
||||
ret = pinmux_gpio_direction(pctldev, range, pin, input);
|
||||
|
||||
mutex_unlock(&pctldev->mutex);
|
||||
mutex_unlock(&pinctrldev_list_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -1204,6 +1224,69 @@ int pinctrl_force_default(struct pinctrl_dev *pctldev)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(pinctrl_force_default);
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
||||
/**
|
||||
* pinctrl_pm_select_default_state() - select default pinctrl state for PM
|
||||
* @dev: device to select default state for
|
||||
*/
|
||||
int pinctrl_pm_select_default_state(struct device *dev)
|
||||
{
|
||||
struct dev_pin_info *pins = dev->pins;
|
||||
int ret;
|
||||
|
||||
if (!pins)
|
||||
return 0;
|
||||
if (IS_ERR(pins->default_state))
|
||||
return 0; /* No default state */
|
||||
ret = pinctrl_select_state(pins->p, pins->default_state);
|
||||
if (ret)
|
||||
dev_err(dev, "failed to activate default pinctrl state\n");
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pinctrl_pm_select_default_state);
|
||||
|
||||
/**
|
||||
* pinctrl_pm_select_sleep_state() - select sleep pinctrl state for PM
|
||||
* @dev: device to select sleep state for
|
||||
*/
|
||||
int pinctrl_pm_select_sleep_state(struct device *dev)
|
||||
{
|
||||
struct dev_pin_info *pins = dev->pins;
|
||||
int ret;
|
||||
|
||||
if (!pins)
|
||||
return 0;
|
||||
if (IS_ERR(pins->sleep_state))
|
||||
return 0; /* No sleep state */
|
||||
ret = pinctrl_select_state(pins->p, pins->sleep_state);
|
||||
if (ret)
|
||||
dev_err(dev, "failed to activate pinctrl sleep state\n");
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pinctrl_pm_select_sleep_state);
|
||||
|
||||
/**
|
||||
* pinctrl_pm_select_idle_state() - select idle pinctrl state for PM
|
||||
* @dev: device to select idle state for
|
||||
*/
|
||||
int pinctrl_pm_select_idle_state(struct device *dev)
|
||||
{
|
||||
struct dev_pin_info *pins = dev->pins;
|
||||
int ret;
|
||||
|
||||
if (!pins)
|
||||
return 0;
|
||||
if (IS_ERR(pins->idle_state))
|
||||
return 0; /* No idle state */
|
||||
ret = pinctrl_select_state(pins->p, pins->idle_state);
|
||||
if (ret)
|
||||
dev_err(dev, "failed to activate pinctrl idle state\n");
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pinctrl_pm_select_idle_state);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
|
||||
static int pinctrl_pins_show(struct seq_file *s, void *what)
|
||||
|
@ -1296,11 +1379,21 @@ static int pinctrl_gpioranges_show(struct seq_file *s, void *what)
|
|||
|
||||
/* Loop over the ranges */
|
||||
list_for_each_entry(range, &pctldev->gpio_ranges, node) {
|
||||
seq_printf(s, "%u: %s GPIOS [%u - %u] PINS [%u - %u]\n",
|
||||
range->id, range->name,
|
||||
range->base, (range->base + range->npins - 1),
|
||||
range->pin_base,
|
||||
(range->pin_base + range->npins - 1));
|
||||
if (range->pins) {
|
||||
int a;
|
||||
seq_printf(s, "%u: %s GPIOS [%u - %u] PINS {",
|
||||
range->id, range->name,
|
||||
range->base, (range->base + range->npins - 1));
|
||||
for (a = 0; a < range->npins - 1; a++)
|
||||
seq_printf(s, "%u, ", range->pins[a]);
|
||||
seq_printf(s, "%u}\n", range->pins[a]);
|
||||
}
|
||||
else
|
||||
seq_printf(s, "%u: %s GPIOS [%u - %u] PINS [%u - %u]\n",
|
||||
range->id, range->name,
|
||||
range->base, (range->base + range->npins - 1),
|
||||
range->pin_base,
|
||||
(range->pin_base + range->npins - 1));
|
||||
}
|
||||
|
||||
mutex_unlock(&pctldev->mutex);
|
||||
|
|
|
@ -26,6 +26,9 @@
|
|||
#define DOVE_MPP_VIRT_BASE (DOVE_SB_REGS_VIRT_BASE + 0xd0200)
|
||||
#define DOVE_PMU_MPP_GENERAL_CTRL (DOVE_MPP_VIRT_BASE + 0x10)
|
||||
#define DOVE_AU0_AC97_SEL BIT(16)
|
||||
#define DOVE_PMU_SIGNAL_SELECT_0 (DOVE_SB_REGS_VIRT_BASE + 0xd802C)
|
||||
#define DOVE_PMU_SIGNAL_SELECT_1 (DOVE_SB_REGS_VIRT_BASE + 0xd8030)
|
||||
#define DOVE_GLOBAL_CONFIG_1 (DOVE_SB_REGS_VIRT_BASE + 0xe802C)
|
||||
#define DOVE_GLOBAL_CONFIG_1 (DOVE_SB_REGS_VIRT_BASE + 0xe802C)
|
||||
#define DOVE_TWSI_ENABLE_OPTION1 BIT(7)
|
||||
#define DOVE_GLOBAL_CONFIG_2 (DOVE_SB_REGS_VIRT_BASE + 0xe8030)
|
||||
|
@ -58,12 +61,16 @@ static int dove_pmu_mpp_ctrl_get(struct mvebu_mpp_ctrl *ctrl,
|
|||
unsigned off = (ctrl->pid / MPPS_PER_REG) * MPP_BITS;
|
||||
unsigned shift = (ctrl->pid % MPPS_PER_REG) * MPP_BITS;
|
||||
unsigned long pmu = readl(DOVE_PMU_MPP_GENERAL_CTRL);
|
||||
unsigned long mpp = readl(DOVE_MPP_VIRT_BASE + off);
|
||||
unsigned long func;
|
||||
|
||||
if (pmu & (1 << ctrl->pid))
|
||||
*config = CONFIG_PMU;
|
||||
else
|
||||
*config = (mpp >> shift) & MPP_MASK;
|
||||
if (pmu & (1 << ctrl->pid)) {
|
||||
func = readl(DOVE_PMU_SIGNAL_SELECT_0 + off);
|
||||
*config = (func >> shift) & MPP_MASK;
|
||||
*config |= CONFIG_PMU;
|
||||
} else {
|
||||
func = readl(DOVE_MPP_VIRT_BASE + off);
|
||||
*config = (func >> shift) & MPP_MASK;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -73,15 +80,20 @@ static int dove_pmu_mpp_ctrl_set(struct mvebu_mpp_ctrl *ctrl,
|
|||
unsigned off = (ctrl->pid / MPPS_PER_REG) * MPP_BITS;
|
||||
unsigned shift = (ctrl->pid % MPPS_PER_REG) * MPP_BITS;
|
||||
unsigned long pmu = readl(DOVE_PMU_MPP_GENERAL_CTRL);
|
||||
unsigned long mpp = readl(DOVE_MPP_VIRT_BASE + off);
|
||||
unsigned long func;
|
||||
|
||||
if (config == CONFIG_PMU)
|
||||
if (config & CONFIG_PMU) {
|
||||
writel(pmu | (1 << ctrl->pid), DOVE_PMU_MPP_GENERAL_CTRL);
|
||||
else {
|
||||
func = readl(DOVE_PMU_SIGNAL_SELECT_0 + off);
|
||||
func &= ~(MPP_MASK << shift);
|
||||
func |= (config & MPP_MASK) << shift;
|
||||
writel(func, DOVE_PMU_SIGNAL_SELECT_0 + off);
|
||||
} else {
|
||||
writel(pmu & ~(1 << ctrl->pid), DOVE_PMU_MPP_GENERAL_CTRL);
|
||||
mpp &= ~(MPP_MASK << shift);
|
||||
mpp |= config << shift;
|
||||
writel(mpp, DOVE_MPP_VIRT_BASE + off);
|
||||
func = readl(DOVE_MPP_VIRT_BASE + off);
|
||||
func &= ~(MPP_MASK << shift);
|
||||
func |= (config & MPP_MASK) << shift;
|
||||
writel(func, DOVE_MPP_VIRT_BASE + off);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -378,20 +390,53 @@ static struct mvebu_mpp_mode dove_mpp_modes[] = {
|
|||
MPP_FUNCTION(0x02, "uart2", "rts"),
|
||||
MPP_FUNCTION(0x03, "sdio0", "cd"),
|
||||
MPP_FUNCTION(0x0f, "lcd0", "pwm"),
|
||||
MPP_FUNCTION(0x10, "pmu", NULL)),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x0, "pmu-nc", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x1, "pmu-low", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x2, "pmu-high", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x3, "pmic", "sdi"),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x4, "cpu-pwr-down", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x5, "standby-pwr-down", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x8, "core-pwr-good", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xa, "bat-fault", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xb, "ext0-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xc, "ext1-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xd, "ext2-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xe, "pmu-blink", NULL)),
|
||||
MPP_MODE(1,
|
||||
MPP_FUNCTION(0x00, "gpio", NULL),
|
||||
MPP_FUNCTION(0x02, "uart2", "cts"),
|
||||
MPP_FUNCTION(0x03, "sdio0", "wp"),
|
||||
MPP_FUNCTION(0x0f, "lcd1", "pwm"),
|
||||
MPP_FUNCTION(0x10, "pmu", NULL)),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x0, "pmu-nc", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x1, "pmu-low", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x2, "pmu-high", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x3, "pmic", "sdi"),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x4, "cpu-pwr-down", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x5, "standby-pwr-down", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x8, "core-pwr-good", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xa, "bat-fault", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xb, "ext0-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xc, "ext1-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xd, "ext2-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xe, "pmu-blink", NULL)),
|
||||
MPP_MODE(2,
|
||||
MPP_FUNCTION(0x00, "gpio", NULL),
|
||||
MPP_FUNCTION(0x01, "sata", "prsnt"),
|
||||
MPP_FUNCTION(0x02, "uart2", "txd"),
|
||||
MPP_FUNCTION(0x03, "sdio0", "buspwr"),
|
||||
MPP_FUNCTION(0x04, "uart1", "rts"),
|
||||
MPP_FUNCTION(0x10, "pmu", NULL)),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x0, "pmu-nc", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x1, "pmu-low", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x2, "pmu-high", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x3, "pmic", "sdi"),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x4, "cpu-pwr-down", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x5, "standby-pwr-down", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x8, "core-pwr-good", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xa, "bat-fault", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xb, "ext0-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xc, "ext1-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xd, "ext2-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xe, "pmu-blink", NULL)),
|
||||
MPP_MODE(3,
|
||||
MPP_FUNCTION(0x00, "gpio", NULL),
|
||||
MPP_FUNCTION(0x01, "sata", "act"),
|
||||
|
@ -399,43 +444,131 @@ static struct mvebu_mpp_mode dove_mpp_modes[] = {
|
|||
MPP_FUNCTION(0x03, "sdio0", "ledctrl"),
|
||||
MPP_FUNCTION(0x04, "uart1", "cts"),
|
||||
MPP_FUNCTION(0x0f, "lcd-spi", "cs1"),
|
||||
MPP_FUNCTION(0x10, "pmu", NULL)),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x0, "pmu-nc", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x1, "pmu-low", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x2, "pmu-high", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x3, "pmic", "sdi"),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x4, "cpu-pwr-down", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x5, "standby-pwr-down", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x8, "core-pwr-good", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xa, "bat-fault", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xb, "ext0-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xc, "ext1-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xd, "ext2-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xe, "pmu-blink", NULL)),
|
||||
MPP_MODE(4,
|
||||
MPP_FUNCTION(0x00, "gpio", NULL),
|
||||
MPP_FUNCTION(0x02, "uart3", "rts"),
|
||||
MPP_FUNCTION(0x03, "sdio1", "cd"),
|
||||
MPP_FUNCTION(0x04, "spi1", "miso"),
|
||||
MPP_FUNCTION(0x10, "pmu", NULL)),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x0, "pmu-nc", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x1, "pmu-low", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x2, "pmu-high", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x3, "pmic", "sdi"),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x4, "cpu-pwr-down", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x5, "standby-pwr-down", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x8, "core-pwr-good", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xa, "bat-fault", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xb, "ext0-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xc, "ext1-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xd, "ext2-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xe, "pmu-blink", NULL)),
|
||||
MPP_MODE(5,
|
||||
MPP_FUNCTION(0x00, "gpio", NULL),
|
||||
MPP_FUNCTION(0x02, "uart3", "cts"),
|
||||
MPP_FUNCTION(0x03, "sdio1", "wp"),
|
||||
MPP_FUNCTION(0x04, "spi1", "cs"),
|
||||
MPP_FUNCTION(0x10, "pmu", NULL)),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x0, "pmu-nc", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x1, "pmu-low", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x2, "pmu-high", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x3, "pmic", "sdi"),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x4, "cpu-pwr-down", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x5, "standby-pwr-down", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x8, "core-pwr-good", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xa, "bat-fault", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xb, "ext0-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xc, "ext1-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xd, "ext2-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xe, "pmu-blink", NULL)),
|
||||
MPP_MODE(6,
|
||||
MPP_FUNCTION(0x00, "gpio", NULL),
|
||||
MPP_FUNCTION(0x02, "uart3", "txd"),
|
||||
MPP_FUNCTION(0x03, "sdio1", "buspwr"),
|
||||
MPP_FUNCTION(0x04, "spi1", "mosi"),
|
||||
MPP_FUNCTION(0x10, "pmu", NULL)),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x0, "pmu-nc", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x1, "pmu-low", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x2, "pmu-high", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x3, "pmic", "sdi"),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x4, "cpu-pwr-down", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x5, "standby-pwr-down", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x8, "core-pwr-good", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xa, "bat-fault", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xb, "ext0-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xc, "ext1-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xd, "ext2-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xe, "pmu-blink", NULL)),
|
||||
MPP_MODE(7,
|
||||
MPP_FUNCTION(0x00, "gpio", NULL),
|
||||
MPP_FUNCTION(0x02, "uart3", "rxd"),
|
||||
MPP_FUNCTION(0x03, "sdio1", "ledctrl"),
|
||||
MPP_FUNCTION(0x04, "spi1", "sck"),
|
||||
MPP_FUNCTION(0x10, "pmu", NULL)),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x0, "pmu-nc", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x1, "pmu-low", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x2, "pmu-high", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x3, "pmic", "sdi"),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x4, "cpu-pwr-down", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x5, "standby-pwr-down", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x8, "core-pwr-good", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xa, "bat-fault", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xb, "ext0-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xc, "ext1-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xd, "ext2-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xe, "pmu-blink", NULL)),
|
||||
MPP_MODE(8,
|
||||
MPP_FUNCTION(0x00, "gpio", NULL),
|
||||
MPP_FUNCTION(0x01, "watchdog", "rstout"),
|
||||
MPP_FUNCTION(0x10, "pmu", NULL)),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x0, "pmu-nc", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x1, "pmu-low", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x2, "pmu-high", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x3, "pmic", "sdi"),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x4, "cpu-pwr-down", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x5, "standby-pwr-down", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x8, "cpu-pwr-good", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xa, "bat-fault", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xb, "ext0-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xc, "ext1-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xd, "ext2-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xe, "pmu-blink", NULL)),
|
||||
MPP_MODE(9,
|
||||
MPP_FUNCTION(0x00, "gpio", NULL),
|
||||
MPP_FUNCTION(0x05, "pex1", "clkreq"),
|
||||
MPP_FUNCTION(0x10, "pmu", NULL)),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x0, "pmu-nc", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x1, "pmu-low", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x2, "pmu-high", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x3, "pmic", "sdi"),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x4, "cpu-pwr-down", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x5, "standby-pwr-down", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x8, "cpu-pwr-good", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xa, "bat-fault", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xb, "ext0-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xc, "ext1-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xd, "ext2-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xe, "pmu-blink", NULL)),
|
||||
MPP_MODE(10,
|
||||
MPP_FUNCTION(0x00, "gpio", NULL),
|
||||
MPP_FUNCTION(0x05, "ssp", "sclk"),
|
||||
MPP_FUNCTION(0x10, "pmu", NULL)),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x0, "pmu-nc", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x1, "pmu-low", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x2, "pmu-high", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x3, "pmic", "sdi"),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x4, "cpu-pwr-down", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x5, "standby-pwr-down", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x8, "cpu-pwr-good", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xa, "bat-fault", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xb, "ext0-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xc, "ext1-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xd, "ext2-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xe, "pmu-blink", NULL)),
|
||||
MPP_MODE(11,
|
||||
MPP_FUNCTION(0x00, "gpio", NULL),
|
||||
MPP_FUNCTION(0x01, "sata", "prsnt"),
|
||||
|
@ -443,33 +576,88 @@ static struct mvebu_mpp_mode dove_mpp_modes[] = {
|
|||
MPP_FUNCTION(0x03, "sdio0", "ledctrl"),
|
||||
MPP_FUNCTION(0x04, "sdio1", "ledctrl"),
|
||||
MPP_FUNCTION(0x05, "pex0", "clkreq"),
|
||||
MPP_FUNCTION(0x10, "pmu", NULL)),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x0, "pmu-nc", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x1, "pmu-low", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x2, "pmu-high", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x3, "pmic", "sdi"),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x4, "cpu-pwr-down", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x5, "standby-pwr-down", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x8, "cpu-pwr-good", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xa, "bat-fault", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xb, "ext0-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xc, "ext1-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xd, "ext2-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xe, "pmu-blink", NULL)),
|
||||
MPP_MODE(12,
|
||||
MPP_FUNCTION(0x00, "gpio", NULL),
|
||||
MPP_FUNCTION(0x01, "sata", "act"),
|
||||
MPP_FUNCTION(0x02, "uart2", "rts"),
|
||||
MPP_FUNCTION(0x03, "audio0", "extclk"),
|
||||
MPP_FUNCTION(0x04, "sdio1", "cd"),
|
||||
MPP_FUNCTION(0x10, "pmu", NULL)),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x0, "pmu-nc", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x1, "pmu-low", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x2, "pmu-high", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x3, "pmic", "sdi"),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x4, "cpu-pwr-down", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x5, "standby-pwr-down", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x8, "cpu-pwr-good", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xa, "bat-fault", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xb, "ext0-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xc, "ext1-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xd, "ext2-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xe, "pmu-blink", NULL)),
|
||||
MPP_MODE(13,
|
||||
MPP_FUNCTION(0x00, "gpio", NULL),
|
||||
MPP_FUNCTION(0x02, "uart2", "cts"),
|
||||
MPP_FUNCTION(0x03, "audio1", "extclk"),
|
||||
MPP_FUNCTION(0x04, "sdio1", "wp"),
|
||||
MPP_FUNCTION(0x05, "ssp", "extclk"),
|
||||
MPP_FUNCTION(0x10, "pmu", NULL)),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x0, "pmu-nc", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x1, "pmu-low", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x2, "pmu-high", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x3, "pmic", "sdi"),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x4, "cpu-pwr-down", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x5, "standby-pwr-down", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x8, "cpu-pwr-good", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xa, "bat-fault", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xb, "ext0-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xc, "ext1-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xd, "ext2-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xe, "pmu-blink", NULL)),
|
||||
MPP_MODE(14,
|
||||
MPP_FUNCTION(0x00, "gpio", NULL),
|
||||
MPP_FUNCTION(0x02, "uart2", "txd"),
|
||||
MPP_FUNCTION(0x04, "sdio1", "buspwr"),
|
||||
MPP_FUNCTION(0x05, "ssp", "rxd"),
|
||||
MPP_FUNCTION(0x10, "pmu", NULL)),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x0, "pmu-nc", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x1, "pmu-low", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x2, "pmu-high", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x3, "pmic", "sdi"),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x4, "cpu-pwr-down", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x5, "standby-pwr-down", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x8, "cpu-pwr-good", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xa, "bat-fault", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xb, "ext0-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xc, "ext1-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xd, "ext2-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xe, "pmu-blink", NULL)),
|
||||
MPP_MODE(15,
|
||||
MPP_FUNCTION(0x00, "gpio", NULL),
|
||||
MPP_FUNCTION(0x02, "uart2", "rxd"),
|
||||
MPP_FUNCTION(0x04, "sdio1", "ledctrl"),
|
||||
MPP_FUNCTION(0x05, "ssp", "sfrm"),
|
||||
MPP_FUNCTION(0x10, "pmu", NULL)),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x0, "pmu-nc", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x1, "pmu-low", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x2, "pmu-high", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x3, "pmic", "sdi"),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x4, "cpu-pwr-down", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x5, "standby-pwr-down", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x8, "cpu-pwr-good", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xa, "bat-fault", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xb, "ext0-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xc, "ext1-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xd, "ext2-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xe, "pmu-blink", NULL)),
|
||||
MPP_MODE(16,
|
||||
MPP_FUNCTION(0x00, "gpio", NULL),
|
||||
MPP_FUNCTION(0x02, "uart3", "rts"),
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include <linux/pinctrl/pinctrl.h>
|
||||
#include <linux/pinctrl/pinconf.h>
|
||||
#include <linux/pinctrl/pinconf-generic.h>
|
||||
#include <linux/of.h>
|
||||
#include "core.h"
|
||||
#include "pinconf.h"
|
||||
|
||||
|
@ -37,14 +38,18 @@ struct pin_config_item {
|
|||
static struct pin_config_item conf_items[] = {
|
||||
PCONFDUMP(PIN_CONFIG_BIAS_DISABLE, "input bias disabled", NULL),
|
||||
PCONFDUMP(PIN_CONFIG_BIAS_HIGH_IMPEDANCE, "input bias high impedance", NULL),
|
||||
PCONFDUMP(PIN_CONFIG_BIAS_BUS_HOLD, "input bias bus hold", NULL),
|
||||
PCONFDUMP(PIN_CONFIG_BIAS_PULL_UP, "input bias pull up", NULL),
|
||||
PCONFDUMP(PIN_CONFIG_BIAS_PULL_DOWN, "input bias pull down", NULL),
|
||||
PCONFDUMP(PIN_CONFIG_BIAS_PULL_PIN_DEFAULT,
|
||||
"input bias pull to pin specific state", NULL),
|
||||
PCONFDUMP(PIN_CONFIG_DRIVE_PUSH_PULL, "output drive push pull", NULL),
|
||||
PCONFDUMP(PIN_CONFIG_DRIVE_OPEN_DRAIN, "output drive open drain", NULL),
|
||||
PCONFDUMP(PIN_CONFIG_DRIVE_OPEN_SOURCE, "output drive open source", NULL),
|
||||
PCONFDUMP(PIN_CONFIG_DRIVE_STRENGTH, "output drive strength", "mA"),
|
||||
PCONFDUMP(PIN_CONFIG_INPUT_SCHMITT_ENABLE, "input schmitt enabled", NULL),
|
||||
PCONFDUMP(PIN_CONFIG_INPUT_SCHMITT, "input schmitt trigger", NULL),
|
||||
PCONFDUMP(PIN_CONFIG_INPUT_DEBOUNCE, "input debounce", "time units"),
|
||||
PCONFDUMP(PIN_CONFIG_INPUT_DEBOUNCE, "input debounce", "usec"),
|
||||
PCONFDUMP(PIN_CONFIG_POWER_SOURCE, "pin power source", "selector"),
|
||||
PCONFDUMP(PIN_CONFIG_SLEW_RATE, "slew rate", NULL),
|
||||
PCONFDUMP(PIN_CONFIG_LOW_POWER_MODE, "pin low power", "mode"),
|
||||
|
@ -135,3 +140,100 @@ void pinconf_generic_dump_config(struct pinctrl_dev *pctldev,
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(pinconf_generic_dump_config);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
struct pinconf_generic_dt_params {
|
||||
const char * const property;
|
||||
enum pin_config_param param;
|
||||
u32 default_value;
|
||||
};
|
||||
|
||||
static struct pinconf_generic_dt_params dt_params[] = {
|
||||
{ "bias-disable", PIN_CONFIG_BIAS_DISABLE, 0 },
|
||||
{ "bias-high-impedance", PIN_CONFIG_BIAS_HIGH_IMPEDANCE, 0 },
|
||||
{ "bias-bus-hold", PIN_CONFIG_BIAS_BUS_HOLD, 0 },
|
||||
{ "bias-pull-up", PIN_CONFIG_BIAS_PULL_UP, 1 },
|
||||
{ "bias-pull-down", PIN_CONFIG_BIAS_PULL_DOWN, 1 },
|
||||
{ "bias-pull-pin-default", PIN_CONFIG_BIAS_PULL_PIN_DEFAULT, 1 },
|
||||
{ "drive-push-pull", PIN_CONFIG_DRIVE_PUSH_PULL, 0 },
|
||||
{ "drive-open-drain", PIN_CONFIG_DRIVE_OPEN_DRAIN, 0 },
|
||||
{ "drive-open-source", PIN_CONFIG_DRIVE_OPEN_SOURCE, 0 },
|
||||
{ "drive-strength", PIN_CONFIG_DRIVE_STRENGTH, 0 },
|
||||
{ "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 },
|
||||
{ "low-power-enable", PIN_CONFIG_LOW_POWER_MODE, 1 },
|
||||
{ "low-power-disable", PIN_CONFIG_LOW_POWER_MODE, 0 },
|
||||
{ "output-low", PIN_CONFIG_OUTPUT, 0, },
|
||||
{ "output-high", PIN_CONFIG_OUTPUT, 1, },
|
||||
};
|
||||
|
||||
/**
|
||||
* pinconf_generic_parse_dt_config()
|
||||
* parse the config properties into generic pinconfig values.
|
||||
* @np: node containing the pinconfig properties
|
||||
* @configs: array with nconfigs entries containing the generic pinconf values
|
||||
* @nconfigs: umber of configurations
|
||||
*/
|
||||
int pinconf_generic_parse_dt_config(struct device_node *np,
|
||||
unsigned long **configs,
|
||||
unsigned int *nconfigs)
|
||||
{
|
||||
unsigned long *cfg;
|
||||
unsigned int ncfg = 0;
|
||||
int ret;
|
||||
int i;
|
||||
u32 val;
|
||||
|
||||
if (!np)
|
||||
return -EINVAL;
|
||||
|
||||
/* allocate a temporary array big enough to hold one of each option */
|
||||
cfg = kzalloc(sizeof(*cfg) * ARRAY_SIZE(dt_params), GFP_KERNEL);
|
||||
if (!cfg)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(dt_params); i++) {
|
||||
struct pinconf_generic_dt_params *par = &dt_params[i];
|
||||
ret = of_property_read_u32(np, par->property, &val);
|
||||
|
||||
/* property not found */
|
||||
if (ret == -EINVAL)
|
||||
continue;
|
||||
|
||||
/* use default value, when no value is specified */
|
||||
if (ret)
|
||||
val = par->default_value;
|
||||
|
||||
pr_debug("found %s with value %u\n", par->property, val);
|
||||
cfg[ncfg] = pinconf_to_config_packed(par->param, val);
|
||||
ncfg++;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
/* no configs found at all */
|
||||
if (ncfg == 0) {
|
||||
*configs = NULL;
|
||||
*nconfigs = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Now limit the number of configs to the real number of
|
||||
* found properties.
|
||||
*/
|
||||
*configs = kzalloc(ncfg * sizeof(unsigned long), GFP_KERNEL);
|
||||
if (!*configs) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
memcpy(*configs, cfg, ncfg * sizeof(unsigned long));
|
||||
*nconfigs = ncfg;
|
||||
|
||||
out:
|
||||
kfree(cfg);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -75,98 +75,6 @@ int pin_config_get_for_pin(struct pinctrl_dev *pctldev, unsigned pin,
|
|||
return ops->pin_config_get(pctldev, pin, config);
|
||||
}
|
||||
|
||||
/**
|
||||
* pin_config_get() - get the configuration of a single pin parameter
|
||||
* @dev_name: name of the pin controller device for this pin
|
||||
* @name: name of the pin to get the config for
|
||||
* @config: the config pointed to by this argument will be filled in with the
|
||||
* current pin state, it can be used directly by drivers as a numeral, or
|
||||
* it can be dereferenced to any struct.
|
||||
*/
|
||||
int pin_config_get(const char *dev_name, const char *name,
|
||||
unsigned long *config)
|
||||
{
|
||||
struct pinctrl_dev *pctldev;
|
||||
int pin;
|
||||
|
||||
pctldev = get_pinctrl_dev_from_devname(dev_name);
|
||||
if (!pctldev) {
|
||||
pin = -EINVAL;
|
||||
return pin;
|
||||
}
|
||||
|
||||
mutex_lock(&pctldev->mutex);
|
||||
|
||||
pin = pin_get_from_name(pctldev, name);
|
||||
if (pin < 0)
|
||||
goto unlock;
|
||||
|
||||
pin = pin_config_get_for_pin(pctldev, pin, config);
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&pctldev->mutex);
|
||||
return pin;
|
||||
}
|
||||
EXPORT_SYMBOL(pin_config_get);
|
||||
|
||||
static int pin_config_set_for_pin(struct pinctrl_dev *pctldev, unsigned pin,
|
||||
unsigned long config)
|
||||
{
|
||||
const struct pinconf_ops *ops = pctldev->desc->confops;
|
||||
int ret;
|
||||
|
||||
if (!ops || !ops->pin_config_set) {
|
||||
dev_err(pctldev->dev, "cannot configure pin, missing "
|
||||
"config function in driver\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = ops->pin_config_set(pctldev, pin, config);
|
||||
if (ret) {
|
||||
dev_err(pctldev->dev,
|
||||
"unable to set pin configuration on pin %d\n", pin);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* pin_config_set() - set the configuration of a single pin parameter
|
||||
* @dev_name: name of pin controller device for this pin
|
||||
* @name: name of the pin to set the config for
|
||||
* @config: the config in this argument will contain the desired pin state, it
|
||||
* can be used directly by drivers as a numeral, or it can be dereferenced
|
||||
* to any struct.
|
||||
*/
|
||||
int pin_config_set(const char *dev_name, const char *name,
|
||||
unsigned long config)
|
||||
{
|
||||
struct pinctrl_dev *pctldev;
|
||||
int pin, ret;
|
||||
|
||||
pctldev = get_pinctrl_dev_from_devname(dev_name);
|
||||
if (!pctldev) {
|
||||
ret = -EINVAL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
mutex_lock(&pctldev->mutex);
|
||||
|
||||
pin = pin_get_from_name(pctldev, name);
|
||||
if (pin < 0) {
|
||||
ret = pin;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
ret = pin_config_set_for_pin(pctldev, pin, config);
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&pctldev->mutex);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(pin_config_set);
|
||||
|
||||
int pin_config_group_get(const char *dev_name, const char *pin_group,
|
||||
unsigned long *config)
|
||||
{
|
||||
|
@ -204,88 +112,6 @@ int pin_config_group_get(const char *dev_name, const char *pin_group,
|
|||
mutex_unlock(&pctldev->mutex);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(pin_config_group_get);
|
||||
|
||||
int pin_config_group_set(const char *dev_name, const char *pin_group,
|
||||
unsigned long config)
|
||||
{
|
||||
struct pinctrl_dev *pctldev;
|
||||
const struct pinconf_ops *ops;
|
||||
const struct pinctrl_ops *pctlops;
|
||||
int selector;
|
||||
const unsigned *pins;
|
||||
unsigned num_pins;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
pctldev = get_pinctrl_dev_from_devname(dev_name);
|
||||
if (!pctldev) {
|
||||
ret = -EINVAL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
mutex_lock(&pctldev->mutex);
|
||||
|
||||
ops = pctldev->desc->confops;
|
||||
pctlops = pctldev->desc->pctlops;
|
||||
|
||||
if (!ops || (!ops->pin_config_group_set && !ops->pin_config_set)) {
|
||||
dev_err(pctldev->dev, "cannot configure pin group, missing "
|
||||
"config function in driver\n");
|
||||
ret = -EINVAL;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
selector = pinctrl_get_group_selector(pctldev, pin_group);
|
||||
if (selector < 0) {
|
||||
ret = selector;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
ret = pctlops->get_group_pins(pctldev, selector, &pins, &num_pins);
|
||||
if (ret) {
|
||||
dev_err(pctldev->dev, "cannot configure pin group, error "
|
||||
"getting pins\n");
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the pin controller supports handling entire groups we use that
|
||||
* capability.
|
||||
*/
|
||||
if (ops->pin_config_group_set) {
|
||||
ret = ops->pin_config_group_set(pctldev, selector, config);
|
||||
/*
|
||||
* If the pin controller prefer that a certain group be handled
|
||||
* pin-by-pin as well, it returns -EAGAIN.
|
||||
*/
|
||||
if (ret != -EAGAIN)
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the controller cannot handle entire groups, we configure each pin
|
||||
* individually.
|
||||
*/
|
||||
if (!ops->pin_config_set) {
|
||||
ret = 0;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
for (i = 0; i < num_pins; i++) {
|
||||
ret = ops->pin_config_set(pctldev, pins[i], config);
|
||||
if (ret < 0)
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&pctldev->mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(pin_config_group_set);
|
||||
|
||||
int pinconf_map_to_setting(struct pinctrl_map const *map,
|
||||
struct pinctrl_setting *setting)
|
||||
|
|
|
@ -123,3 +123,9 @@ static inline void pinconf_generic_dump_config(struct pinctrl_dev *pctldev,
|
|||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_GENERIC_PINCONF) && defined(CONFIG_OF)
|
||||
int pinconf_generic_parse_dt_config(struct device_node *np,
|
||||
unsigned long **configs,
|
||||
unsigned int *nconfigs);
|
||||
#endif
|
||||
|
|
|
@ -30,8 +30,11 @@
|
|||
#include <linux/pinctrl/pinmux.h>
|
||||
#include <linux/pinctrl/pinconf.h>
|
||||
#include <linux/pinctrl/pinconf-generic.h>
|
||||
#include <linux/pinctrl/machine.h>
|
||||
|
||||
#include "pinctrl-abx500.h"
|
||||
#include "core.h"
|
||||
#include "pinconf.h"
|
||||
|
||||
/*
|
||||
* The AB9540 and AB8540 GPIO support are extended versions
|
||||
|
@ -93,13 +96,15 @@
|
|||
#define AB8540_GPIOX_VBAT_START 51
|
||||
#define AB8540_GPIOX_VBAT_END 54
|
||||
|
||||
#define ABX500_GPIO_INPUT 0
|
||||
#define ABX500_GPIO_OUTPUT 1
|
||||
|
||||
struct abx500_pinctrl {
|
||||
struct device *dev;
|
||||
struct pinctrl_dev *pctldev;
|
||||
struct abx500_pinctrl_soc_data *soc;
|
||||
struct gpio_chip chip;
|
||||
struct ab8500 *parent;
|
||||
struct mutex lock;
|
||||
struct abx500_gpio_irq_cluster *irq_cluster;
|
||||
int irq_cluster_size;
|
||||
};
|
||||
|
@ -129,8 +134,8 @@ static int abx500_gpio_get_bit(struct gpio_chip *chip, u8 reg,
|
|||
|
||||
if (ret < 0)
|
||||
dev_err(pct->dev,
|
||||
"%s read reg =%x, offset=%x failed\n",
|
||||
__func__, reg, offset);
|
||||
"%s read reg =%x, offset=%x failed (%d)\n",
|
||||
__func__, reg, offset, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -146,7 +151,8 @@ static int abx500_gpio_set_bits(struct gpio_chip *chip, u8 reg,
|
|||
ret = abx500_mask_and_set_register_interruptible(pct->dev,
|
||||
AB8500_MISC, reg, BIT(pos), val << pos);
|
||||
if (ret < 0)
|
||||
dev_err(pct->dev, "%s write failed\n", __func__);
|
||||
dev_err(pct->dev, "%s write reg, %x offset %x failed (%d)\n",
|
||||
__func__, reg, offset, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -160,12 +166,24 @@ static int abx500_gpio_get(struct gpio_chip *chip, unsigned offset)
|
|||
{
|
||||
struct abx500_pinctrl *pct = to_abx500_pinctrl(chip);
|
||||
bool bit;
|
||||
bool is_out;
|
||||
u8 gpio_offset = offset - 1;
|
||||
int ret;
|
||||
|
||||
ret = abx500_gpio_get_bit(chip, AB8500_GPIO_IN1_REG,
|
||||
offset, &bit);
|
||||
ret = abx500_gpio_get_bit(chip, AB8500_GPIO_DIR1_REG,
|
||||
gpio_offset, &is_out);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
if (is_out)
|
||||
ret = abx500_gpio_get_bit(chip, AB8500_GPIO_OUT1_REG,
|
||||
gpio_offset, &bit);
|
||||
else
|
||||
ret = abx500_gpio_get_bit(chip, AB8500_GPIO_IN1_REG,
|
||||
gpio_offset, &bit);
|
||||
out:
|
||||
if (ret < 0) {
|
||||
dev_err(pct->dev, "%s failed\n", __func__);
|
||||
dev_err(pct->dev, "%s failed (%d)\n", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -179,11 +197,47 @@ static void abx500_gpio_set(struct gpio_chip *chip, unsigned offset, int val)
|
|||
|
||||
ret = abx500_gpio_set_bits(chip, AB8500_GPIO_OUT1_REG, offset, val);
|
||||
if (ret < 0)
|
||||
dev_err(pct->dev, "%s write failed\n", __func__);
|
||||
dev_err(pct->dev, "%s write failed (%d)\n", __func__, ret);
|
||||
}
|
||||
|
||||
static int abx500_config_pull_updown(struct abx500_pinctrl *pct,
|
||||
int offset, enum abx500_gpio_pull_updown val)
|
||||
static int abx500_get_pull_updown(struct abx500_pinctrl *pct, int offset,
|
||||
enum abx500_gpio_pull_updown *pull_updown)
|
||||
{
|
||||
u8 pos;
|
||||
u8 val;
|
||||
int ret;
|
||||
struct pullud *pullud;
|
||||
|
||||
if (!pct->soc->pullud) {
|
||||
dev_err(pct->dev, "%s AB chip doesn't support pull up/down feature",
|
||||
__func__);
|
||||
ret = -EPERM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
pullud = pct->soc->pullud;
|
||||
|
||||
if ((offset < pullud->first_pin)
|
||||
|| (offset > pullud->last_pin)) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = abx500_get_register_interruptible(pct->dev,
|
||||
AB8500_MISC, AB8540_GPIO_PULL_UPDOWN_REG, &val);
|
||||
|
||||
pos = (offset - pullud->first_pin) << 1;
|
||||
*pull_updown = (val >> pos) & AB8540_GPIO_PULL_UPDOWN_MASK;
|
||||
|
||||
out:
|
||||
if (ret < 0)
|
||||
dev_err(pct->dev, "%s failed (%d)\n", __func__, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int abx500_set_pull_updown(struct abx500_pinctrl *pct,
|
||||
int offset, enum abx500_gpio_pull_updown val)
|
||||
{
|
||||
u8 pos;
|
||||
int ret;
|
||||
|
@ -203,8 +257,7 @@ static int abx500_config_pull_updown(struct abx500_pinctrl *pct,
|
|||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
pos = offset << 1;
|
||||
pos = (offset - pullud->first_pin) << 1;
|
||||
|
||||
ret = abx500_mask_and_set_register_interruptible(pct->dev,
|
||||
AB8500_MISC, AB8540_GPIO_PULL_UPDOWN_REG,
|
||||
|
@ -217,33 +270,51 @@ static int abx500_config_pull_updown(struct abx500_pinctrl *pct,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static bool abx500_pullud_supported(struct gpio_chip *chip, unsigned gpio)
|
||||
{
|
||||
struct abx500_pinctrl *pct = to_abx500_pinctrl(chip);
|
||||
struct pullud *pullud = pct->soc->pullud;
|
||||
|
||||
return (pullud &&
|
||||
gpio >= pullud->first_pin &&
|
||||
gpio <= pullud->last_pin);
|
||||
}
|
||||
|
||||
static int abx500_gpio_direction_output(struct gpio_chip *chip,
|
||||
unsigned offset,
|
||||
int val)
|
||||
{
|
||||
struct abx500_pinctrl *pct = to_abx500_pinctrl(chip);
|
||||
struct pullud *pullud = pct->soc->pullud;
|
||||
unsigned gpio;
|
||||
int ret;
|
||||
|
||||
/* set direction as output */
|
||||
ret = abx500_gpio_set_bits(chip, AB8500_GPIO_DIR1_REG, offset, 1);
|
||||
ret = abx500_gpio_set_bits(chip,
|
||||
AB8500_GPIO_DIR1_REG,
|
||||
offset,
|
||||
ABX500_GPIO_OUTPUT);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
goto out;
|
||||
|
||||
/* disable pull down */
|
||||
ret = abx500_gpio_set_bits(chip, AB8500_GPIO_PUD1_REG, offset, 1);
|
||||
ret = abx500_gpio_set_bits(chip,
|
||||
AB8500_GPIO_PUD1_REG,
|
||||
offset,
|
||||
ABX500_GPIO_PULL_NONE);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
goto out;
|
||||
|
||||
/* if supported, disable both pull down and pull up */
|
||||
gpio = offset + 1;
|
||||
if (pullud && gpio >= pullud->first_pin && gpio <= pullud->last_pin) {
|
||||
ret = abx500_config_pull_updown(pct,
|
||||
if (abx500_pullud_supported(chip, gpio)) {
|
||||
ret = abx500_set_pull_updown(pct,
|
||||
gpio,
|
||||
ABX500_GPIO_PULL_NONE);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
out:
|
||||
if (ret < 0) {
|
||||
dev_err(pct->dev, "%s failed (%d)\n", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* set the output as 1 or 0 */
|
||||
|
@ -253,7 +324,10 @@ static int abx500_gpio_direction_output(struct gpio_chip *chip,
|
|||
static int abx500_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
/* set the register as input */
|
||||
return abx500_gpio_set_bits(chip, AB8500_GPIO_DIR1_REG, offset, 0);
|
||||
return abx500_gpio_set_bits(chip,
|
||||
AB8500_GPIO_DIR1_REG,
|
||||
offset,
|
||||
ABX500_GPIO_INPUT);
|
||||
}
|
||||
|
||||
static int abx500_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
|
||||
|
@ -338,10 +412,16 @@ static int abx500_set_mode(struct pinctrl_dev *pctldev, struct gpio_chip *chip,
|
|||
if (af.alt_bit1 != UNUSED) {
|
||||
ret = abx500_gpio_set_bits(chip, AB8500_GPIO_SEL1_REG,
|
||||
offset, 0);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
ret = abx500_gpio_set_bits(chip,
|
||||
AB8500_GPIO_ALTFUN_REG,
|
||||
af.alt_bit1,
|
||||
!!(af.alta_val && BIT(0)));
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
if (af.alt_bit2 != UNUSED)
|
||||
ret = abx500_gpio_set_bits(chip,
|
||||
AB8500_GPIO_ALTFUN_REG,
|
||||
|
@ -355,8 +435,14 @@ static int abx500_set_mode(struct pinctrl_dev *pctldev, struct gpio_chip *chip,
|
|||
case ABX500_ALT_B:
|
||||
ret = abx500_gpio_set_bits(chip, AB8500_GPIO_SEL1_REG,
|
||||
offset, 0);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
ret = abx500_gpio_set_bits(chip, AB8500_GPIO_ALTFUN_REG,
|
||||
af.alt_bit1, !!(af.altb_val && BIT(0)));
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
if (af.alt_bit2 != UNUSED)
|
||||
ret = abx500_gpio_set_bits(chip,
|
||||
AB8500_GPIO_ALTFUN_REG,
|
||||
|
@ -367,8 +453,14 @@ static int abx500_set_mode(struct pinctrl_dev *pctldev, struct gpio_chip *chip,
|
|||
case ABX500_ALT_C:
|
||||
ret = abx500_gpio_set_bits(chip, AB8500_GPIO_SEL1_REG,
|
||||
offset, 0);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
ret = abx500_gpio_set_bits(chip, AB8500_GPIO_ALTFUN_REG,
|
||||
af.alt_bit2, !!(af.altc_val && BIT(0)));
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
ret = abx500_gpio_set_bits(chip, AB8500_GPIO_ALTFUN_REG,
|
||||
af.alt_bit2, !!(af.altc_val && BIT(1)));
|
||||
break;
|
||||
|
@ -378,11 +470,14 @@ static int abx500_set_mode(struct pinctrl_dev *pctldev, struct gpio_chip *chip,
|
|||
|
||||
return -EINVAL;
|
||||
}
|
||||
out:
|
||||
if (ret < 0)
|
||||
dev_err(pct->dev, "%s failed (%d)\n", __func__, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static u8 abx500_get_mode(struct pinctrl_dev *pctldev, struct gpio_chip *chip,
|
||||
static int abx500_get_mode(struct pinctrl_dev *pctldev, struct gpio_chip *chip,
|
||||
unsigned gpio)
|
||||
{
|
||||
u8 mode;
|
||||
|
@ -393,6 +488,7 @@ static u8 abx500_get_mode(struct pinctrl_dev *pctldev, struct gpio_chip *chip,
|
|||
struct alternate_functions af = pct->soc->alternate_functions[gpio];
|
||||
/* on ABx5xx, there is no GPIO0, so adjust the offset */
|
||||
unsigned offset = gpio - 1;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* if gpiosel_bit is set to unused,
|
||||
|
@ -402,8 +498,11 @@ static u8 abx500_get_mode(struct pinctrl_dev *pctldev, struct gpio_chip *chip,
|
|||
return ABX500_DEFAULT;
|
||||
|
||||
/* read GpioSelx register */
|
||||
abx500_gpio_get_bit(chip, AB8500_GPIO_SEL1_REG + (offset / 8),
|
||||
ret = abx500_gpio_get_bit(chip, AB8500_GPIO_SEL1_REG + (offset / 8),
|
||||
af.gpiosel_bit, &bit_mode);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
mode = bit_mode;
|
||||
|
||||
/* sanity check */
|
||||
|
@ -435,14 +534,19 @@ static u8 abx500_get_mode(struct pinctrl_dev *pctldev, struct gpio_chip *chip,
|
|||
* pin use the AlternatFunction register
|
||||
* read alt_bit1 value
|
||||
*/
|
||||
abx500_gpio_get_bit(chip, AB8500_GPIO_ALTFUN_REG,
|
||||
ret = abx500_gpio_get_bit(chip, AB8500_GPIO_ALTFUN_REG,
|
||||
af.alt_bit1, &alt_bit1);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
if (af.alt_bit2 != UNUSED)
|
||||
if (af.alt_bit2 != UNUSED) {
|
||||
/* read alt_bit2 value */
|
||||
abx500_gpio_get_bit(chip, AB8500_GPIO_ALTFUN_REG, af.alt_bit2,
|
||||
ret = abx500_gpio_get_bit(chip, AB8500_GPIO_ALTFUN_REG,
|
||||
af.alt_bit2,
|
||||
&alt_bit2);
|
||||
else
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
} else
|
||||
alt_bit2 = 0;
|
||||
|
||||
mode = (alt_bit2 << 1) + alt_bit1;
|
||||
|
@ -452,6 +556,10 @@ static u8 abx500_get_mode(struct pinctrl_dev *pctldev, struct gpio_chip *chip,
|
|||
return ABX500_ALT_B;
|
||||
else
|
||||
return ABX500_ALT_C;
|
||||
|
||||
out:
|
||||
dev_err(pct->dev, "%s failed (%d)\n", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
|
@ -463,11 +571,14 @@ static void abx500_gpio_dbg_show_one(struct seq_file *s,
|
|||
struct gpio_chip *chip,
|
||||
unsigned offset, unsigned gpio)
|
||||
{
|
||||
struct abx500_pinctrl *pct = pinctrl_dev_get_drvdata(pctldev);
|
||||
const char *label = gpiochip_is_requested(chip, offset - 1);
|
||||
u8 gpio_offset = offset - 1;
|
||||
int mode = -1;
|
||||
bool is_out;
|
||||
bool pull;
|
||||
bool pd;
|
||||
enum abx500_gpio_pull_updown pud = 0;
|
||||
int ret;
|
||||
|
||||
const char *modes[] = {
|
||||
[ABX500_DEFAULT] = "default",
|
||||
|
@ -476,21 +587,48 @@ static void abx500_gpio_dbg_show_one(struct seq_file *s,
|
|||
[ABX500_ALT_C] = "altC",
|
||||
};
|
||||
|
||||
abx500_gpio_get_bit(chip, AB8500_GPIO_DIR1_REG, gpio_offset, &is_out);
|
||||
abx500_gpio_get_bit(chip, AB8500_GPIO_PUD1_REG, gpio_offset, &pull);
|
||||
const char *pull_up_down[] = {
|
||||
[ABX500_GPIO_PULL_DOWN] = "pull down",
|
||||
[ABX500_GPIO_PULL_NONE] = "pull none",
|
||||
[ABX500_GPIO_PULL_NONE + 1] = "pull none",
|
||||
[ABX500_GPIO_PULL_UP] = "pull up",
|
||||
};
|
||||
|
||||
ret = abx500_gpio_get_bit(chip, AB8500_GPIO_DIR1_REG,
|
||||
gpio_offset, &is_out);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
seq_printf(s, " gpio-%-3d (%-20.20s) %-3s",
|
||||
gpio, label ?: "(none)",
|
||||
is_out ? "out" : "in ");
|
||||
|
||||
if (!is_out) {
|
||||
if (abx500_pullud_supported(chip, offset)) {
|
||||
ret = abx500_get_pull_updown(pct, offset, &pud);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
seq_printf(s, " %-9s", pull_up_down[pud]);
|
||||
} else {
|
||||
ret = abx500_gpio_get_bit(chip, AB8500_GPIO_PUD1_REG,
|
||||
gpio_offset, &pd);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
seq_printf(s, " %-9s", pull_up_down[pd]);
|
||||
}
|
||||
} else
|
||||
seq_printf(s, " %-9s", chip->get(chip, offset) ? "hi" : "lo");
|
||||
|
||||
if (pctldev)
|
||||
mode = abx500_get_mode(pctldev, chip, offset);
|
||||
|
||||
seq_printf(s, " gpio-%-3d (%-20.20s) %-3s %-9s %s",
|
||||
gpio, label ?: "(none)",
|
||||
is_out ? "out" : "in ",
|
||||
is_out ?
|
||||
(chip->get
|
||||
? (chip->get(chip, offset) ? "hi" : "lo")
|
||||
: "? ")
|
||||
: (pull ? "pull up" : "pull down"),
|
||||
(mode < 0) ? "unknown" : modes[mode]);
|
||||
seq_printf(s, " %s", (mode < 0) ? "unknown" : modes[mode]);
|
||||
|
||||
out:
|
||||
if (ret < 0)
|
||||
dev_err(pct->dev, "%s failed (%d)\n", __func__, ret);
|
||||
}
|
||||
|
||||
static void abx500_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
|
||||
|
@ -594,6 +732,9 @@ static int abx500_pmx_enable(struct pinctrl_dev *pctldev, unsigned function,
|
|||
ret = abx500_set_mode(pctldev, chip, g->pins[i], g->altsetting);
|
||||
}
|
||||
|
||||
if (ret < 0)
|
||||
dev_err(pct->dev, "%s failed (%d)\n", __func__, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -642,10 +783,8 @@ static int abx500_gpio_request_enable(struct pinctrl_dev *pctldev,
|
|||
|
||||
ret = abx500_set_mode(pct->pctldev, &pct->chip,
|
||||
offset, p->altfunc);
|
||||
if (ret < 0) {
|
||||
if (ret < 0)
|
||||
dev_err(pct->dev, "%s setting altfunc failed\n", __func__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -704,11 +843,193 @@ static void abx500_pin_dbg_show(struct pinctrl_dev *pctldev,
|
|||
chip->base + offset - 1);
|
||||
}
|
||||
|
||||
static void abx500_dt_free_map(struct pinctrl_dev *pctldev,
|
||||
struct pinctrl_map *map, unsigned num_maps)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num_maps; i++)
|
||||
if (map[i].type == PIN_MAP_TYPE_CONFIGS_PIN)
|
||||
kfree(map[i].data.configs.configs);
|
||||
kfree(map);
|
||||
}
|
||||
|
||||
static int abx500_dt_reserve_map(struct pinctrl_map **map,
|
||||
unsigned *reserved_maps,
|
||||
unsigned *num_maps,
|
||||
unsigned reserve)
|
||||
{
|
||||
unsigned old_num = *reserved_maps;
|
||||
unsigned new_num = *num_maps + reserve;
|
||||
struct pinctrl_map *new_map;
|
||||
|
||||
if (old_num >= new_num)
|
||||
return 0;
|
||||
|
||||
new_map = krealloc(*map, sizeof(*new_map) * new_num, GFP_KERNEL);
|
||||
if (!new_map)
|
||||
return -ENOMEM;
|
||||
|
||||
memset(new_map + old_num, 0, (new_num - old_num) * sizeof(*new_map));
|
||||
|
||||
*map = new_map;
|
||||
*reserved_maps = new_num;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int abx500_dt_add_map_mux(struct pinctrl_map **map,
|
||||
unsigned *reserved_maps,
|
||||
unsigned *num_maps, const char *group,
|
||||
const char *function)
|
||||
{
|
||||
if (*num_maps == *reserved_maps)
|
||||
return -ENOSPC;
|
||||
|
||||
(*map)[*num_maps].type = PIN_MAP_TYPE_MUX_GROUP;
|
||||
(*map)[*num_maps].data.mux.group = group;
|
||||
(*map)[*num_maps].data.mux.function = function;
|
||||
(*num_maps)++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int abx500_dt_add_map_configs(struct pinctrl_map **map,
|
||||
unsigned *reserved_maps,
|
||||
unsigned *num_maps, const char *group,
|
||||
unsigned long *configs, unsigned num_configs)
|
||||
{
|
||||
unsigned long *dup_configs;
|
||||
|
||||
if (*num_maps == *reserved_maps)
|
||||
return -ENOSPC;
|
||||
|
||||
dup_configs = kmemdup(configs, num_configs * sizeof(*dup_configs),
|
||||
GFP_KERNEL);
|
||||
if (!dup_configs)
|
||||
return -ENOMEM;
|
||||
|
||||
(*map)[*num_maps].type = PIN_MAP_TYPE_CONFIGS_PIN;
|
||||
|
||||
(*map)[*num_maps].data.configs.group_or_pin = group;
|
||||
(*map)[*num_maps].data.configs.configs = dup_configs;
|
||||
(*map)[*num_maps].data.configs.num_configs = num_configs;
|
||||
(*num_maps)++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char *abx500_find_pin_name(struct pinctrl_dev *pctldev,
|
||||
const char *pin_name)
|
||||
{
|
||||
int i, pin_number;
|
||||
struct abx500_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev);
|
||||
|
||||
if (sscanf((char *)pin_name, "GPIO%d", &pin_number) == 1)
|
||||
for (i = 0; i < npct->soc->npins; i++)
|
||||
if (npct->soc->pins[i].number == pin_number)
|
||||
return npct->soc->pins[i].name;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int abx500_dt_subnode_to_map(struct pinctrl_dev *pctldev,
|
||||
struct device_node *np,
|
||||
struct pinctrl_map **map,
|
||||
unsigned *reserved_maps,
|
||||
unsigned *num_maps)
|
||||
{
|
||||
int ret;
|
||||
const char *function = NULL;
|
||||
unsigned long *configs;
|
||||
unsigned int nconfigs = 0;
|
||||
bool has_config = 0;
|
||||
unsigned reserve = 0;
|
||||
struct property *prop;
|
||||
const char *group, *gpio_name;
|
||||
struct device_node *np_config;
|
||||
|
||||
ret = of_property_read_string(np, "ste,function", &function);
|
||||
if (ret >= 0)
|
||||
reserve = 1;
|
||||
|
||||
ret = pinconf_generic_parse_dt_config(np, &configs, &nconfigs);
|
||||
if (nconfigs)
|
||||
has_config = 1;
|
||||
|
||||
np_config = of_parse_phandle(np, "ste,config", 0);
|
||||
if (np_config) {
|
||||
ret = pinconf_generic_parse_dt_config(np_config, &configs,
|
||||
&nconfigs);
|
||||
if (ret)
|
||||
goto exit;
|
||||
has_config |= nconfigs;
|
||||
}
|
||||
|
||||
ret = of_property_count_strings(np, "ste,pins");
|
||||
if (ret < 0)
|
||||
goto exit;
|
||||
|
||||
if (has_config)
|
||||
reserve++;
|
||||
|
||||
reserve *= ret;
|
||||
|
||||
ret = abx500_dt_reserve_map(map, reserved_maps, num_maps, reserve);
|
||||
if (ret < 0)
|
||||
goto exit;
|
||||
|
||||
of_property_for_each_string(np, "ste,pins", prop, group) {
|
||||
if (function) {
|
||||
ret = abx500_dt_add_map_mux(map, reserved_maps,
|
||||
num_maps, group, function);
|
||||
if (ret < 0)
|
||||
goto exit;
|
||||
}
|
||||
if (has_config) {
|
||||
gpio_name = abx500_find_pin_name(pctldev, group);
|
||||
|
||||
ret = abx500_dt_add_map_configs(map, reserved_maps,
|
||||
num_maps, gpio_name, configs, 1);
|
||||
if (ret < 0)
|
||||
goto exit;
|
||||
}
|
||||
|
||||
}
|
||||
exit:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int abx500_dt_node_to_map(struct pinctrl_dev *pctldev,
|
||||
struct device_node *np_config,
|
||||
struct pinctrl_map **map, unsigned *num_maps)
|
||||
{
|
||||
unsigned reserved_maps;
|
||||
struct device_node *np;
|
||||
int ret;
|
||||
|
||||
reserved_maps = 0;
|
||||
*map = NULL;
|
||||
*num_maps = 0;
|
||||
|
||||
for_each_child_of_node(np_config, np) {
|
||||
ret = abx500_dt_subnode_to_map(pctldev, np, map,
|
||||
&reserved_maps, num_maps);
|
||||
if (ret < 0) {
|
||||
abx500_dt_free_map(pctldev, *map, *num_maps);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct pinctrl_ops abx500_pinctrl_ops = {
|
||||
.get_groups_count = abx500_get_groups_cnt,
|
||||
.get_group_name = abx500_get_group_name,
|
||||
.get_group_pins = abx500_get_group_pins,
|
||||
.pin_dbg_show = abx500_pin_dbg_show,
|
||||
.dt_node_to_map = abx500_dt_node_to_map,
|
||||
.dt_free_map = abx500_dt_free_map,
|
||||
};
|
||||
|
||||
static int abx500_pin_config_get(struct pinctrl_dev *pctldev,
|
||||
|
@ -723,10 +1044,9 @@ static int abx500_pin_config_set(struct pinctrl_dev *pctldev,
|
|||
unsigned long config)
|
||||
{
|
||||
struct abx500_pinctrl *pct = pinctrl_dev_get_drvdata(pctldev);
|
||||
struct pullud *pullud = pct->soc->pullud;
|
||||
struct gpio_chip *chip = &pct->chip;
|
||||
unsigned offset;
|
||||
int ret;
|
||||
int ret = -EINVAL;
|
||||
enum pin_config_param param = pinconf_to_config_param(config);
|
||||
enum pin_config_param argument = pinconf_to_config_argument(config);
|
||||
|
||||
|
@ -739,12 +1059,10 @@ static int abx500_pin_config_set(struct pinctrl_dev *pctldev,
|
|||
offset = pin - 1;
|
||||
|
||||
switch (param) {
|
||||
case PIN_CONFIG_BIAS_PULL_DOWN:
|
||||
/*
|
||||
* if argument = 1 set the pull down
|
||||
* else clear the pull down
|
||||
*/
|
||||
case PIN_CONFIG_BIAS_DISABLE:
|
||||
ret = abx500_gpio_direction_input(chip, offset);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
/*
|
||||
* Some chips only support pull down, while some actually
|
||||
* support both pull up and pull down. Such chips have
|
||||
|
@ -752,28 +1070,72 @@ static int abx500_pin_config_set(struct pinctrl_dev *pctldev,
|
|||
* both features. If the pin is not within that range, we
|
||||
* fall back to the old bit set that only support pull down.
|
||||
*/
|
||||
if (pullud &&
|
||||
pin >= pullud->first_pin &&
|
||||
pin <= pullud->last_pin)
|
||||
ret = abx500_config_pull_updown(pct,
|
||||
if (abx500_pullud_supported(chip, pin))
|
||||
ret = abx500_set_pull_updown(pct,
|
||||
pin,
|
||||
ABX500_GPIO_PULL_NONE);
|
||||
else
|
||||
/* Chip only supports pull down */
|
||||
ret = abx500_gpio_set_bits(chip, AB8500_GPIO_PUD1_REG,
|
||||
offset, ABX500_GPIO_PULL_NONE);
|
||||
break;
|
||||
|
||||
case PIN_CONFIG_BIAS_PULL_DOWN:
|
||||
ret = abx500_gpio_direction_input(chip, offset);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
/*
|
||||
* if argument = 1 set the pull down
|
||||
* else clear the pull down
|
||||
* Some chips only support pull down, while some actually
|
||||
* support both pull up and pull down. Such chips have
|
||||
* a "pullud" range specified for the pins that support
|
||||
* both features. If the pin is not within that range, we
|
||||
* fall back to the old bit set that only support pull down.
|
||||
*/
|
||||
if (abx500_pullud_supported(chip, pin))
|
||||
ret = abx500_set_pull_updown(pct,
|
||||
pin,
|
||||
argument ? ABX500_GPIO_PULL_DOWN : ABX500_GPIO_PULL_NONE);
|
||||
else
|
||||
/* Chip only supports pull down */
|
||||
ret = abx500_gpio_set_bits(chip, AB8500_GPIO_PUD1_REG,
|
||||
offset, argument ? 0 : 1);
|
||||
offset,
|
||||
argument ? ABX500_GPIO_PULL_DOWN : ABX500_GPIO_PULL_NONE);
|
||||
break;
|
||||
|
||||
case PIN_CONFIG_BIAS_PULL_UP:
|
||||
ret = abx500_gpio_direction_input(chip, offset);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
/*
|
||||
* if argument = 1 set the pull up
|
||||
* else clear the pull up
|
||||
*/
|
||||
ret = abx500_gpio_direction_input(chip, offset);
|
||||
/*
|
||||
* Some chips only support pull down, while some actually
|
||||
* support both pull up and pull down. Such chips have
|
||||
* a "pullud" range specified for the pins that support
|
||||
* both features. If the pin is not within that range, do
|
||||
* nothing
|
||||
*/
|
||||
if (abx500_pullud_supported(chip, pin))
|
||||
ret = abx500_set_pull_updown(pct,
|
||||
pin,
|
||||
argument ? ABX500_GPIO_PULL_UP : ABX500_GPIO_PULL_NONE);
|
||||
break;
|
||||
|
||||
case PIN_CONFIG_OUTPUT:
|
||||
ret = abx500_gpio_direction_output(chip, offset, argument);
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
dev_err(chip->dev, "illegal configuration requested\n");
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
out:
|
||||
if (ret < 0)
|
||||
dev_err(pct->dev, "%s failed (%d)\n", __func__, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -881,9 +1243,6 @@ static int abx500_gpio_probe(struct platform_device *pdev)
|
|||
id = (unsigned long)match->data;
|
||||
}
|
||||
|
||||
/* initialize the lock */
|
||||
mutex_init(&pct->lock);
|
||||
|
||||
/* Poke in other ASIC variants here */
|
||||
switch (id) {
|
||||
case PINCTRL_AB8500:
|
||||
|
@ -900,13 +1259,11 @@ static int abx500_gpio_probe(struct platform_device *pdev)
|
|||
break;
|
||||
default:
|
||||
dev_err(&pdev->dev, "Unsupported pinctrl sub driver (%d)\n", id);
|
||||
mutex_destroy(&pct->lock);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!pct->soc) {
|
||||
dev_err(&pdev->dev, "Invalid SOC data\n");
|
||||
mutex_destroy(&pct->lock);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -917,7 +1274,6 @@ static int abx500_gpio_probe(struct platform_device *pdev)
|
|||
ret = gpiochip_add(&pct->chip);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "unable to add gpiochip: %d\n", ret);
|
||||
mutex_destroy(&pct->lock);
|
||||
return ret;
|
||||
}
|
||||
dev_info(&pdev->dev, "added gpiochip\n");
|
||||
|
@ -954,7 +1310,6 @@ static int abx500_gpio_probe(struct platform_device *pdev)
|
|||
if (err)
|
||||
dev_info(&pdev->dev, "failed to remove gpiochip\n");
|
||||
|
||||
mutex_destroy(&pct->lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -974,8 +1329,6 @@ static int abx500_gpio_remove(struct platform_device *pdev)
|
|||
return ret;
|
||||
}
|
||||
|
||||
mutex_destroy(&pct->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -1543,12 +1543,6 @@ static int at91_gpio_probe(struct platform_device *pdev)
|
|||
goto err;
|
||||
}
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!res) {
|
||||
ret = -ENOENT;
|
||||
goto err;
|
||||
}
|
||||
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq < 0) {
|
||||
ret = irq;
|
||||
|
@ -1561,6 +1555,7 @@ static int at91_gpio_probe(struct platform_device *pdev)
|
|||
goto err;
|
||||
}
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
at91_chip->regbase = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(at91_chip->regbase)) {
|
||||
ret = PTR_ERR(at91_chip->regbase);
|
||||
|
|
543
drivers/pinctrl/pinctrl-baytrail.c
Normal file
543
drivers/pinctrl/pinctrl-baytrail.c
Normal file
|
@ -0,0 +1,543 @@
|
|||
/*
|
||||
* Pinctrl GPIO driver for Intel Baytrail
|
||||
* Copyright (c) 2012-2013, Intel Corporation.
|
||||
*
|
||||
* Author: Mathias Nyman <mathias.nyman@linux.intel.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/irqdomain.h>
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/acpi_gpio.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/pinctrl/pinctrl.h>
|
||||
|
||||
/* memory mapped register offsets */
|
||||
#define BYT_CONF0_REG 0x000
|
||||
#define BYT_CONF1_REG 0x004
|
||||
#define BYT_VAL_REG 0x008
|
||||
#define BYT_DFT_REG 0x00c
|
||||
#define BYT_INT_STAT_REG 0x800
|
||||
|
||||
/* BYT_CONF0_REG register bits */
|
||||
#define BYT_TRIG_NEG BIT(26)
|
||||
#define BYT_TRIG_POS BIT(25)
|
||||
#define BYT_TRIG_LVL BIT(24)
|
||||
#define BYT_PIN_MUX 0x07
|
||||
|
||||
/* BYT_VAL_REG register bits */
|
||||
#define BYT_INPUT_EN BIT(2) /* 0: input enabled (active low)*/
|
||||
#define BYT_OUTPUT_EN BIT(1) /* 0: output enabled (active low)*/
|
||||
#define BYT_LEVEL BIT(0)
|
||||
|
||||
#define BYT_DIR_MASK (BIT(1) | BIT(2))
|
||||
#define BYT_TRIG_MASK (BIT(26) | BIT(25) | BIT(24))
|
||||
|
||||
#define BYT_NGPIO_SCORE 102
|
||||
#define BYT_NGPIO_NCORE 28
|
||||
#define BYT_NGPIO_SUS 44
|
||||
|
||||
/*
|
||||
* Baytrail gpio controller consist of three separate sub-controllers called
|
||||
* SCORE, NCORE and SUS. The sub-controllers are identified by their acpi UID.
|
||||
*
|
||||
* GPIO numbering is _not_ ordered meaning that gpio # 0 in ACPI namespace does
|
||||
* _not_ correspond to the first gpio register at controller's gpio base.
|
||||
* There is no logic or pattern in mapping gpio numbers to registers (pads) so
|
||||
* each sub-controller needs to have its own mapping table
|
||||
*/
|
||||
|
||||
/* score_pins[gpio_nr] = pad_nr */
|
||||
|
||||
static unsigned const score_pins[BYT_NGPIO_SCORE] = {
|
||||
85, 89, 93, 96, 99, 102, 98, 101, 34, 37,
|
||||
36, 38, 39, 35, 40, 84, 62, 61, 64, 59,
|
||||
54, 56, 60, 55, 63, 57, 51, 50, 53, 47,
|
||||
52, 49, 48, 43, 46, 41, 45, 42, 58, 44,
|
||||
95, 105, 70, 68, 67, 66, 69, 71, 65, 72,
|
||||
86, 90, 88, 92, 103, 77, 79, 83, 78, 81,
|
||||
80, 82, 13, 12, 15, 14, 17, 18, 19, 16,
|
||||
2, 1, 0, 4, 6, 7, 9, 8, 33, 32,
|
||||
31, 30, 29, 27, 25, 28, 26, 23, 21, 20,
|
||||
24, 22, 5, 3, 10, 11, 106, 87, 91, 104,
|
||||
97, 100,
|
||||
};
|
||||
|
||||
static unsigned const ncore_pins[BYT_NGPIO_NCORE] = {
|
||||
19, 18, 17, 20, 21, 22, 24, 25, 23, 16,
|
||||
14, 15, 12, 26, 27, 1, 4, 8, 11, 0,
|
||||
3, 6, 10, 13, 2, 5, 9, 7,
|
||||
};
|
||||
|
||||
static unsigned const sus_pins[BYT_NGPIO_SUS] = {
|
||||
29, 33, 30, 31, 32, 34, 36, 35, 38, 37,
|
||||
18, 7, 11, 20, 17, 1, 8, 10, 19, 12,
|
||||
0, 2, 23, 39, 28, 27, 22, 21, 24, 25,
|
||||
26, 51, 56, 54, 49, 55, 48, 57, 50, 58,
|
||||
52, 53, 59, 40,
|
||||
};
|
||||
|
||||
static struct pinctrl_gpio_range byt_ranges[] = {
|
||||
{
|
||||
.name = "1", /* match with acpi _UID in probe */
|
||||
.npins = BYT_NGPIO_SCORE,
|
||||
.pins = score_pins,
|
||||
},
|
||||
{
|
||||
.name = "2",
|
||||
.npins = BYT_NGPIO_NCORE,
|
||||
.pins = ncore_pins,
|
||||
},
|
||||
{
|
||||
.name = "3",
|
||||
.npins = BYT_NGPIO_SUS,
|
||||
.pins = sus_pins,
|
||||
},
|
||||
{
|
||||
},
|
||||
};
|
||||
|
||||
struct byt_gpio {
|
||||
struct gpio_chip chip;
|
||||
struct irq_domain *domain;
|
||||
struct platform_device *pdev;
|
||||
spinlock_t lock;
|
||||
void __iomem *reg_base;
|
||||
struct pinctrl_gpio_range *range;
|
||||
};
|
||||
|
||||
static void __iomem *byt_gpio_reg(struct gpio_chip *chip, unsigned offset,
|
||||
int reg)
|
||||
{
|
||||
struct byt_gpio *vg = container_of(chip, struct byt_gpio, chip);
|
||||
u32 reg_offset;
|
||||
void __iomem *ptr;
|
||||
|
||||
if (reg == BYT_INT_STAT_REG)
|
||||
reg_offset = (offset / 32) * 4;
|
||||
else
|
||||
reg_offset = vg->range->pins[offset] * 16;
|
||||
|
||||
ptr = (void __iomem *) (vg->reg_base + reg_offset + reg);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static int byt_gpio_request(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
struct byt_gpio *vg = container_of(chip, struct byt_gpio, chip);
|
||||
|
||||
pm_runtime_get(&vg->pdev->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void byt_gpio_free(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
struct byt_gpio *vg = container_of(chip, struct byt_gpio, chip);
|
||||
void __iomem *reg = byt_gpio_reg(&vg->chip, offset, BYT_CONF0_REG);
|
||||
u32 value;
|
||||
|
||||
/* clear interrupt triggering */
|
||||
value = readl(reg);
|
||||
value &= ~(BYT_TRIG_POS | BYT_TRIG_NEG | BYT_TRIG_LVL);
|
||||
writel(value, reg);
|
||||
|
||||
pm_runtime_put(&vg->pdev->dev);
|
||||
}
|
||||
|
||||
static int byt_irq_type(struct irq_data *d, unsigned type)
|
||||
{
|
||||
struct byt_gpio *vg = irq_data_get_irq_chip_data(d);
|
||||
u32 offset = irqd_to_hwirq(d);
|
||||
u32 value;
|
||||
unsigned long flags;
|
||||
void __iomem *reg = byt_gpio_reg(&vg->chip, offset, BYT_CONF0_REG);
|
||||
|
||||
if (offset >= vg->chip.ngpio)
|
||||
return -EINVAL;
|
||||
|
||||
spin_lock_irqsave(&vg->lock, flags);
|
||||
value = readl(reg);
|
||||
|
||||
/* For level trigges the BYT_TRIG_POS and BYT_TRIG_NEG bits
|
||||
* are used to indicate high and low level triggering
|
||||
*/
|
||||
value &= ~(BYT_TRIG_POS | BYT_TRIG_NEG | BYT_TRIG_LVL);
|
||||
|
||||
switch (type) {
|
||||
case IRQ_TYPE_LEVEL_HIGH:
|
||||
value |= BYT_TRIG_LVL;
|
||||
case IRQ_TYPE_EDGE_RISING:
|
||||
value |= BYT_TRIG_POS;
|
||||
break;
|
||||
case IRQ_TYPE_LEVEL_LOW:
|
||||
value |= BYT_TRIG_LVL;
|
||||
case IRQ_TYPE_EDGE_FALLING:
|
||||
value |= BYT_TRIG_NEG;
|
||||
break;
|
||||
case IRQ_TYPE_EDGE_BOTH:
|
||||
value |= (BYT_TRIG_NEG | BYT_TRIG_POS);
|
||||
break;
|
||||
}
|
||||
writel(value, reg);
|
||||
|
||||
spin_unlock_irqrestore(&vg->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int byt_gpio_get(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
void __iomem *reg = byt_gpio_reg(chip, offset, BYT_VAL_REG);
|
||||
return readl(reg) & BYT_LEVEL;
|
||||
}
|
||||
|
||||
static void byt_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
|
||||
{
|
||||
struct byt_gpio *vg = container_of(chip, struct byt_gpio, chip);
|
||||
void __iomem *reg = byt_gpio_reg(chip, offset, BYT_VAL_REG);
|
||||
unsigned long flags;
|
||||
u32 old_val;
|
||||
|
||||
spin_lock_irqsave(&vg->lock, flags);
|
||||
|
||||
old_val = readl(reg);
|
||||
|
||||
if (value)
|
||||
writel(old_val | BYT_LEVEL, reg);
|
||||
else
|
||||
writel(old_val & ~BYT_LEVEL, reg);
|
||||
|
||||
spin_unlock_irqrestore(&vg->lock, flags);
|
||||
}
|
||||
|
||||
static int byt_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
struct byt_gpio *vg = container_of(chip, struct byt_gpio, chip);
|
||||
void __iomem *reg = byt_gpio_reg(chip, offset, BYT_VAL_REG);
|
||||
unsigned long flags;
|
||||
u32 value;
|
||||
|
||||
spin_lock_irqsave(&vg->lock, flags);
|
||||
|
||||
value = readl(reg) | BYT_DIR_MASK;
|
||||
value = value & (~BYT_INPUT_EN); /* active low */
|
||||
writel(value, reg);
|
||||
|
||||
spin_unlock_irqrestore(&vg->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int byt_gpio_direction_output(struct gpio_chip *chip,
|
||||
unsigned gpio, int value)
|
||||
{
|
||||
struct byt_gpio *vg = container_of(chip, struct byt_gpio, chip);
|
||||
void __iomem *reg = byt_gpio_reg(chip, gpio, BYT_VAL_REG);
|
||||
unsigned long flags;
|
||||
u32 reg_val;
|
||||
|
||||
spin_lock_irqsave(&vg->lock, flags);
|
||||
|
||||
reg_val = readl(reg) | (BYT_DIR_MASK | !!value);
|
||||
reg_val &= ~(BYT_OUTPUT_EN | !value);
|
||||
writel(reg_val, reg);
|
||||
|
||||
spin_unlock_irqrestore(&vg->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void byt_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
|
||||
{
|
||||
struct byt_gpio *vg = container_of(chip, struct byt_gpio, chip);
|
||||
int i;
|
||||
unsigned long flags;
|
||||
u32 conf0, val, offs;
|
||||
|
||||
spin_lock_irqsave(&vg->lock, flags);
|
||||
|
||||
for (i = 0; i < vg->chip.ngpio; i++) {
|
||||
offs = vg->range->pins[i] * 16;
|
||||
conf0 = readl(vg->reg_base + offs + BYT_CONF0_REG);
|
||||
val = readl(vg->reg_base + offs + BYT_VAL_REG);
|
||||
|
||||
seq_printf(s,
|
||||
" gpio-%-3d %s %s %s pad-%-3d offset:0x%03x mux:%d %s%s%s\n",
|
||||
i,
|
||||
val & BYT_INPUT_EN ? " " : "in",
|
||||
val & BYT_OUTPUT_EN ? " " : "out",
|
||||
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 ? "lvl " : "");
|
||||
}
|
||||
spin_unlock_irqrestore(&vg->lock, flags);
|
||||
}
|
||||
|
||||
static int byt_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
struct byt_gpio *vg = container_of(chip, struct byt_gpio, chip);
|
||||
return irq_create_mapping(vg->domain, offset);
|
||||
}
|
||||
|
||||
static void byt_gpio_irq_handler(unsigned irq, struct irq_desc *desc)
|
||||
{
|
||||
struct irq_data *data = irq_desc_get_irq_data(desc);
|
||||
struct byt_gpio *vg = irq_data_get_irq_handler_data(data);
|
||||
struct irq_chip *chip = irq_data_get_irq_chip(data);
|
||||
u32 base, pin, mask;
|
||||
void __iomem *reg;
|
||||
u32 pending;
|
||||
unsigned virq;
|
||||
int looplimit = 0;
|
||||
|
||||
/* check from GPIO controller which pin triggered the interrupt */
|
||||
for (base = 0; base < vg->chip.ngpio; base += 32) {
|
||||
|
||||
reg = byt_gpio_reg(&vg->chip, base, BYT_INT_STAT_REG);
|
||||
|
||||
while ((pending = readl(reg))) {
|
||||
pin = __ffs(pending);
|
||||
mask = BIT(pin);
|
||||
/* Clear before handling so we can't lose an edge */
|
||||
writel(mask, reg);
|
||||
|
||||
virq = irq_find_mapping(vg->domain, base + pin);
|
||||
generic_handle_irq(virq);
|
||||
|
||||
/* In case bios or user sets triggering incorretly a pin
|
||||
* might remain in "interrupt triggered" state.
|
||||
*/
|
||||
if (looplimit++ > 32) {
|
||||
dev_err(&vg->pdev->dev,
|
||||
"Gpio %d interrupt flood, disabling\n",
|
||||
base + pin);
|
||||
|
||||
reg = byt_gpio_reg(&vg->chip, base + pin,
|
||||
BYT_CONF0_REG);
|
||||
mask = readl(reg);
|
||||
mask &= ~(BYT_TRIG_NEG | BYT_TRIG_POS |
|
||||
BYT_TRIG_LVL);
|
||||
writel(mask, reg);
|
||||
mask = readl(reg); /* flush */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
chip->irq_eoi(data);
|
||||
}
|
||||
|
||||
static void byt_irq_unmask(struct irq_data *d)
|
||||
{
|
||||
}
|
||||
|
||||
static void byt_irq_mask(struct irq_data *d)
|
||||
{
|
||||
}
|
||||
|
||||
static struct irq_chip byt_irqchip = {
|
||||
.name = "BYT-GPIO",
|
||||
.irq_mask = byt_irq_mask,
|
||||
.irq_unmask = byt_irq_unmask,
|
||||
.irq_set_type = byt_irq_type,
|
||||
};
|
||||
|
||||
static void byt_gpio_irq_init_hw(struct byt_gpio *vg)
|
||||
{
|
||||
void __iomem *reg;
|
||||
u32 base, value;
|
||||
|
||||
/* clear interrupt status trigger registers */
|
||||
for (base = 0; base < vg->chip.ngpio; base += 32) {
|
||||
reg = byt_gpio_reg(&vg->chip, base, BYT_INT_STAT_REG);
|
||||
writel(0xffffffff, reg);
|
||||
/* make sure trigger bits are cleared, if not then a pin
|
||||
might be misconfigured in bios */
|
||||
value = readl(reg);
|
||||
if (value)
|
||||
dev_err(&vg->pdev->dev,
|
||||
"GPIO interrupt error, pins misconfigured\n");
|
||||
}
|
||||
}
|
||||
|
||||
static int byt_gpio_irq_map(struct irq_domain *d, unsigned int virq,
|
||||
irq_hw_number_t hw)
|
||||
{
|
||||
struct byt_gpio *vg = d->host_data;
|
||||
|
||||
irq_set_chip_and_handler_name(virq, &byt_irqchip, handle_simple_irq,
|
||||
"demux");
|
||||
irq_set_chip_data(virq, vg);
|
||||
irq_set_irq_type(virq, IRQ_TYPE_NONE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct irq_domain_ops byt_gpio_irq_ops = {
|
||||
.map = byt_gpio_irq_map,
|
||||
};
|
||||
|
||||
static int byt_gpio_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct byt_gpio *vg;
|
||||
struct gpio_chip *gc;
|
||||
struct resource *mem_rc, *irq_rc;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct acpi_device *acpi_dev;
|
||||
struct pinctrl_gpio_range *range;
|
||||
acpi_handle handle = ACPI_HANDLE(dev);
|
||||
unsigned hwirq;
|
||||
int ret;
|
||||
|
||||
if (acpi_bus_get_device(handle, &acpi_dev))
|
||||
return -ENODEV;
|
||||
|
||||
vg = devm_kzalloc(dev, sizeof(struct byt_gpio), GFP_KERNEL);
|
||||
if (!vg) {
|
||||
dev_err(&pdev->dev, "can't allocate byt_gpio chip data\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
for (range = byt_ranges; range->name; range++) {
|
||||
if (!strcmp(acpi_dev->pnp.unique_id, range->name)) {
|
||||
vg->chip.ngpio = range->npins;
|
||||
vg->range = range;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!vg->chip.ngpio || !vg->range)
|
||||
return -ENODEV;
|
||||
|
||||
vg->pdev = pdev;
|
||||
platform_set_drvdata(pdev, vg);
|
||||
|
||||
mem_rc = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
vg->reg_base = devm_ioremap_resource(dev, mem_rc);
|
||||
if (IS_ERR(vg->reg_base))
|
||||
return PTR_ERR(vg->reg_base);
|
||||
|
||||
spin_lock_init(&vg->lock);
|
||||
|
||||
gc = &vg->chip;
|
||||
gc->label = dev_name(&pdev->dev);
|
||||
gc->owner = THIS_MODULE;
|
||||
gc->request = byt_gpio_request;
|
||||
gc->free = byt_gpio_free;
|
||||
gc->direction_input = byt_gpio_direction_input;
|
||||
gc->direction_output = byt_gpio_direction_output;
|
||||
gc->get = byt_gpio_get;
|
||||
gc->set = byt_gpio_set;
|
||||
gc->dbg_show = byt_gpio_dbg_show;
|
||||
gc->base = -1;
|
||||
gc->can_sleep = 0;
|
||||
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) {
|
||||
hwirq = irq_rc->start;
|
||||
gc->to_irq = byt_gpio_to_irq;
|
||||
|
||||
vg->domain = irq_domain_add_linear(NULL, gc->ngpio,
|
||||
&byt_gpio_irq_ops, vg);
|
||||
if (!vg->domain)
|
||||
return -ENXIO;
|
||||
|
||||
byt_gpio_irq_init_hw(vg);
|
||||
|
||||
irq_set_handler_data(hwirq, vg);
|
||||
irq_set_chained_handler(hwirq, byt_gpio_irq_handler);
|
||||
|
||||
/* Register interrupt handlers for gpio signaled acpi events */
|
||||
acpi_gpiochip_request_interrupts(gc);
|
||||
}
|
||||
|
||||
pm_runtime_enable(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int byt_gpio_runtime_suspend(struct device *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int byt_gpio_runtime_resume(struct device *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops byt_gpio_pm_ops = {
|
||||
.runtime_suspend = byt_gpio_runtime_suspend,
|
||||
.runtime_resume = byt_gpio_runtime_resume,
|
||||
};
|
||||
|
||||
static const struct acpi_device_id byt_gpio_acpi_match[] = {
|
||||
{ "INT33B2", 0 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(acpi, byt_gpio_acpi_match);
|
||||
|
||||
static int byt_gpio_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct byt_gpio *vg = platform_get_drvdata(pdev);
|
||||
int err;
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
err = gpiochip_remove(&vg->chip);
|
||||
if (err)
|
||||
dev_warn(&pdev->dev, "failed to remove gpio_chip.\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver byt_gpio_driver = {
|
||||
.probe = byt_gpio_probe,
|
||||
.remove = byt_gpio_remove,
|
||||
.driver = {
|
||||
.name = "byt_gpio",
|
||||
.owner = THIS_MODULE,
|
||||
.pm = &byt_gpio_pm_ops,
|
||||
.acpi_match_table = ACPI_PTR(byt_gpio_acpi_match),
|
||||
},
|
||||
};
|
||||
|
||||
static int __init byt_gpio_init(void)
|
||||
{
|
||||
return platform_driver_register(&byt_gpio_driver);
|
||||
}
|
||||
|
||||
subsys_initcall(byt_gpio_init);
|
|
@ -113,7 +113,7 @@ static struct lock_class_key gpio_lock_class;
|
|||
|
||||
/* pins are just named GPIO0..GPIO53 */
|
||||
#define BCM2835_GPIO_PIN(a) PINCTRL_PIN(a, "gpio" #a)
|
||||
struct pinctrl_pin_desc bcm2835_gpio_pins[] = {
|
||||
static struct pinctrl_pin_desc bcm2835_gpio_pins[] = {
|
||||
BCM2835_GPIO_PIN(0),
|
||||
BCM2835_GPIO_PIN(1),
|
||||
BCM2835_GPIO_PIN(2),
|
||||
|
|
|
@ -853,7 +853,6 @@ static int __exit u300_gpio_remove(struct platform_device *pdev)
|
|||
}
|
||||
u300_gpio_free_ports(gpio);
|
||||
clk_disable_unprepare(gpio->clk);
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -50,28 +50,21 @@ static const struct of_device_id exynos_wkup_irq_ids[] = {
|
|||
{ }
|
||||
};
|
||||
|
||||
static void exynos_gpio_irq_unmask(struct irq_data *irqd)
|
||||
{
|
||||
struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
|
||||
struct samsung_pinctrl_drv_data *d = bank->drvdata;
|
||||
unsigned long reg_mask = d->ctrl->geint_mask + bank->eint_offset;
|
||||
unsigned long mask;
|
||||
|
||||
mask = readl(d->virt_base + reg_mask);
|
||||
mask &= ~(1 << irqd->hwirq);
|
||||
writel(mask, d->virt_base + reg_mask);
|
||||
}
|
||||
|
||||
static void exynos_gpio_irq_mask(struct irq_data *irqd)
|
||||
{
|
||||
struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
|
||||
struct samsung_pinctrl_drv_data *d = bank->drvdata;
|
||||
unsigned long reg_mask = d->ctrl->geint_mask + bank->eint_offset;
|
||||
unsigned long mask;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&bank->slock, flags);
|
||||
|
||||
mask = readl(d->virt_base + reg_mask);
|
||||
mask |= 1 << irqd->hwirq;
|
||||
writel(mask, d->virt_base + reg_mask);
|
||||
|
||||
spin_unlock_irqrestore(&bank->slock, flags);
|
||||
}
|
||||
|
||||
static void exynos_gpio_irq_ack(struct irq_data *irqd)
|
||||
|
@ -83,6 +76,34 @@ static void exynos_gpio_irq_ack(struct irq_data *irqd)
|
|||
writel(1 << irqd->hwirq, d->virt_base + reg_pend);
|
||||
}
|
||||
|
||||
static void exynos_gpio_irq_unmask(struct irq_data *irqd)
|
||||
{
|
||||
struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
|
||||
struct samsung_pinctrl_drv_data *d = bank->drvdata;
|
||||
unsigned long reg_mask = d->ctrl->geint_mask + bank->eint_offset;
|
||||
unsigned long mask;
|
||||
unsigned long flags;
|
||||
|
||||
/*
|
||||
* Ack level interrupts right before unmask
|
||||
*
|
||||
* If we don't do this we'll get a double-interrupt. Level triggered
|
||||
* interrupts must not fire an interrupt if the level is not
|
||||
* _currently_ active, even if it was active while the interrupt was
|
||||
* masked.
|
||||
*/
|
||||
if (irqd_get_trigger_type(irqd) & IRQ_TYPE_LEVEL_MASK)
|
||||
exynos_gpio_irq_ack(irqd);
|
||||
|
||||
spin_lock_irqsave(&bank->slock, flags);
|
||||
|
||||
mask = readl(d->virt_base + reg_mask);
|
||||
mask &= ~(1 << irqd->hwirq);
|
||||
writel(mask, d->virt_base + reg_mask);
|
||||
|
||||
spin_unlock_irqrestore(&bank->slock, flags);
|
||||
}
|
||||
|
||||
static int exynos_gpio_irq_set_type(struct irq_data *irqd, unsigned int type)
|
||||
{
|
||||
struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
|
||||
|
@ -258,28 +279,21 @@ static int exynos_eint_gpio_init(struct samsung_pinctrl_drv_data *d)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void exynos_wkup_irq_unmask(struct irq_data *irqd)
|
||||
{
|
||||
struct samsung_pin_bank *b = irq_data_get_irq_chip_data(irqd);
|
||||
struct samsung_pinctrl_drv_data *d = b->drvdata;
|
||||
unsigned long reg_mask = d->ctrl->weint_mask + b->eint_offset;
|
||||
unsigned long mask;
|
||||
|
||||
mask = readl(d->virt_base + reg_mask);
|
||||
mask &= ~(1 << irqd->hwirq);
|
||||
writel(mask, d->virt_base + reg_mask);
|
||||
}
|
||||
|
||||
static void exynos_wkup_irq_mask(struct irq_data *irqd)
|
||||
{
|
||||
struct samsung_pin_bank *b = irq_data_get_irq_chip_data(irqd);
|
||||
struct samsung_pinctrl_drv_data *d = b->drvdata;
|
||||
unsigned long reg_mask = d->ctrl->weint_mask + b->eint_offset;
|
||||
unsigned long mask;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&b->slock, flags);
|
||||
|
||||
mask = readl(d->virt_base + reg_mask);
|
||||
mask |= 1 << irqd->hwirq;
|
||||
writel(mask, d->virt_base + reg_mask);
|
||||
|
||||
spin_unlock_irqrestore(&b->slock, flags);
|
||||
}
|
||||
|
||||
static void exynos_wkup_irq_ack(struct irq_data *irqd)
|
||||
|
@ -291,6 +305,34 @@ static void exynos_wkup_irq_ack(struct irq_data *irqd)
|
|||
writel(1 << irqd->hwirq, d->virt_base + pend);
|
||||
}
|
||||
|
||||
static void exynos_wkup_irq_unmask(struct irq_data *irqd)
|
||||
{
|
||||
struct samsung_pin_bank *b = irq_data_get_irq_chip_data(irqd);
|
||||
struct samsung_pinctrl_drv_data *d = b->drvdata;
|
||||
unsigned long reg_mask = d->ctrl->weint_mask + b->eint_offset;
|
||||
unsigned long mask;
|
||||
unsigned long flags;
|
||||
|
||||
/*
|
||||
* Ack level interrupts right before unmask
|
||||
*
|
||||
* If we don't do this we'll get a double-interrupt. Level triggered
|
||||
* interrupts must not fire an interrupt if the level is not
|
||||
* _currently_ active, even if it was active while the interrupt was
|
||||
* masked.
|
||||
*/
|
||||
if (irqd_get_trigger_type(irqd) & IRQ_TYPE_LEVEL_MASK)
|
||||
exynos_wkup_irq_ack(irqd);
|
||||
|
||||
spin_lock_irqsave(&b->slock, flags);
|
||||
|
||||
mask = readl(d->virt_base + reg_mask);
|
||||
mask &= ~(1 << irqd->hwirq);
|
||||
writel(mask, d->virt_base + reg_mask);
|
||||
|
||||
spin_unlock_irqrestore(&b->slock, flags);
|
||||
}
|
||||
|
||||
static int exynos_wkup_irq_set_type(struct irq_data *irqd, unsigned int type)
|
||||
{
|
||||
struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
|
||||
|
|
|
@ -220,7 +220,7 @@ static int exynos5440_dt_node_to_map(struct pinctrl_dev *pctldev,
|
|||
dev_err(dev, "failed to alloc memory for group name\n");
|
||||
goto free_map;
|
||||
}
|
||||
sprintf(gname, "%s%s", np->name, GROUP_SUFFIX);
|
||||
snprintf(gname, strlen(np->name) + 4, "%s%s", np->name, GROUP_SUFFIX);
|
||||
|
||||
/*
|
||||
* don't have config options? then skip over to creating function
|
||||
|
@ -259,7 +259,8 @@ static int exynos5440_dt_node_to_map(struct pinctrl_dev *pctldev,
|
|||
dev_err(dev, "failed to alloc memory for func name\n");
|
||||
goto free_cfg;
|
||||
}
|
||||
sprintf(fname, "%s%s", np->name, FUNCTION_SUFFIX);
|
||||
snprintf(fname, strlen(np->name) + 4, "%s%s", np->name,
|
||||
FUNCTION_SUFFIX);
|
||||
|
||||
map[*nmaps].data.mux.group = gname;
|
||||
map[*nmaps].data.mux.function = fname;
|
||||
|
@ -713,7 +714,8 @@ static int exynos5440_pinctrl_parse_dt(struct platform_device *pdev,
|
|||
dev_err(dev, "failed to alloc memory for group name\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
sprintf(gname, "%s%s", cfg_np->name, GROUP_SUFFIX);
|
||||
snprintf(gname, strlen(cfg_np->name) + 4, "%s%s", cfg_np->name,
|
||||
GROUP_SUFFIX);
|
||||
|
||||
grp->name = gname;
|
||||
grp->pins = pin_list;
|
||||
|
@ -733,7 +735,8 @@ static int exynos5440_pinctrl_parse_dt(struct platform_device *pdev,
|
|||
dev_err(dev, "failed to alloc memory for func name\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
sprintf(fname, "%s%s", cfg_np->name, FUNCTION_SUFFIX);
|
||||
snprintf(fname, strlen(cfg_np->name) + 4, "%s%s", cfg_np->name,
|
||||
FUNCTION_SUFFIX);
|
||||
|
||||
func->name = fname;
|
||||
func->groups = devm_kzalloc(dev, sizeof(char *), GFP_KERNEL);
|
||||
|
@ -806,7 +809,7 @@ static int exynos5440_pinctrl_register(struct platform_device *pdev,
|
|||
|
||||
/* for each pin, set the name of the pin */
|
||||
for (pin = 0; pin < ctrldesc->npins; pin++) {
|
||||
sprintf(pin_names, "gpio%02d", pin);
|
||||
snprintf(pin_names, 6, "gpio%02d", pin);
|
||||
pdesc = pindesc + pin;
|
||||
pdesc->name = pin_names;
|
||||
pin_names += PIN_NAME_LENGTH;
|
||||
|
|
|
@ -221,13 +221,21 @@ static int imx_pmx_enable(struct pinctrl_dev *pctldev, unsigned selector,
|
|||
pin_id = pins[i];
|
||||
pin_reg = &info->pin_regs[pin_id];
|
||||
|
||||
if (!pin_reg->mux_reg) {
|
||||
if (!(info->flags & ZERO_OFFSET_VALID) && !pin_reg->mux_reg) {
|
||||
dev_err(ipctl->dev, "Pin(%s) does not support mux function\n",
|
||||
info->pins[pin_id].name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
writel(mux[i], ipctl->base + pin_reg->mux_reg);
|
||||
if (info->flags & SHARE_MUX_CONF_REG) {
|
||||
u32 reg;
|
||||
reg = readl(ipctl->base + pin_reg->mux_reg);
|
||||
reg &= ~(0x7 << 20);
|
||||
reg |= (mux[i] << 20);
|
||||
writel(reg, ipctl->base + pin_reg->mux_reg);
|
||||
} else {
|
||||
writel(mux[i], ipctl->base + pin_reg->mux_reg);
|
||||
}
|
||||
dev_dbg(ipctl->dev, "write: offset 0x%x val 0x%x\n",
|
||||
pin_reg->mux_reg, mux[i]);
|
||||
|
||||
|
@ -287,7 +295,7 @@ static int imx_pinconf_get(struct pinctrl_dev *pctldev,
|
|||
const 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) {
|
||||
if (!(info->flags & ZERO_OFFSET_VALID) && !pin_reg->conf_reg) {
|
||||
dev_err(info->dev, "Pin(%s) does not support config function\n",
|
||||
info->pins[pin_id].name);
|
||||
return -EINVAL;
|
||||
|
@ -295,6 +303,9 @@ static int imx_pinconf_get(struct pinctrl_dev *pctldev,
|
|||
|
||||
*config = readl(ipctl->base + pin_reg->conf_reg);
|
||||
|
||||
if (info->flags & SHARE_MUX_CONF_REG)
|
||||
*config &= 0xffff;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -305,7 +316,7 @@ static int imx_pinconf_set(struct pinctrl_dev *pctldev,
|
|||
const 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) {
|
||||
if (!(info->flags & ZERO_OFFSET_VALID) && !pin_reg->conf_reg) {
|
||||
dev_err(info->dev, "Pin(%s) does not support config function\n",
|
||||
info->pins[pin_id].name);
|
||||
return -EINVAL;
|
||||
|
@ -314,7 +325,15 @@ static int imx_pinconf_set(struct pinctrl_dev *pctldev,
|
|||
dev_dbg(ipctl->dev, "pinconf set pin %s\n",
|
||||
info->pins[pin_id].name);
|
||||
|
||||
writel(config, ipctl->base + pin_reg->conf_reg);
|
||||
if (info->flags & SHARE_MUX_CONF_REG) {
|
||||
u32 reg;
|
||||
reg = readl(ipctl->base + pin_reg->conf_reg);
|
||||
reg &= ~0xffff;
|
||||
reg |= config;
|
||||
writel(reg, ipctl->base + pin_reg->conf_reg);
|
||||
} else {
|
||||
writel(config, ipctl->base + pin_reg->conf_reg);
|
||||
}
|
||||
dev_dbg(ipctl->dev, "write: offset 0x%x val 0x%lx\n",
|
||||
pin_reg->conf_reg, config);
|
||||
|
||||
|
@ -381,19 +400,24 @@ static struct pinctrl_desc imx_pinctrl_desc = {
|
|||
* 1 u32 CONFIG, so 24 types in total for each pin.
|
||||
*/
|
||||
#define FSL_PIN_SIZE 24
|
||||
#define SHARE_FSL_PIN_SIZE 20
|
||||
|
||||
static int imx_pinctrl_parse_groups(struct device_node *np,
|
||||
struct imx_pin_group *grp,
|
||||
struct imx_pinctrl_soc_info *info,
|
||||
u32 index)
|
||||
{
|
||||
int size;
|
||||
int size, pin_size;
|
||||
const __be32 *list;
|
||||
int i;
|
||||
u32 config;
|
||||
|
||||
dev_dbg(info->dev, "group(%d): %s\n", index, np->name);
|
||||
|
||||
if (info->flags & SHARE_MUX_CONF_REG)
|
||||
pin_size = SHARE_FSL_PIN_SIZE;
|
||||
else
|
||||
pin_size = FSL_PIN_SIZE;
|
||||
/* Initialise group */
|
||||
grp->name = np->name;
|
||||
|
||||
|
@ -403,12 +427,12 @@ static int imx_pinctrl_parse_groups(struct device_node *np,
|
|||
*/
|
||||
list = of_get_property(np, "fsl,pins", &size);
|
||||
/* we do not check return since it's safe node passed down */
|
||||
if (!size || size % FSL_PIN_SIZE) {
|
||||
if (!size || size % pin_size) {
|
||||
dev_err(info->dev, "Invalid fsl,pins property\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
grp->npins = size / FSL_PIN_SIZE;
|
||||
grp->npins = size / pin_size;
|
||||
grp->pins = devm_kzalloc(info->dev, grp->npins * sizeof(unsigned int),
|
||||
GFP_KERNEL);
|
||||
grp->mux_mode = devm_kzalloc(info->dev, grp->npins * sizeof(unsigned int),
|
||||
|
@ -421,10 +445,17 @@ static int imx_pinctrl_parse_groups(struct device_node *np,
|
|||
GFP_KERNEL);
|
||||
for (i = 0; i < grp->npins; i++) {
|
||||
u32 mux_reg = be32_to_cpu(*list++);
|
||||
u32 conf_reg = be32_to_cpu(*list++);
|
||||
unsigned int pin_id = mux_reg ? mux_reg / 4 : conf_reg / 4;
|
||||
struct imx_pin_reg *pin_reg = &info->pin_regs[pin_id];
|
||||
u32 conf_reg;
|
||||
unsigned int pin_id;
|
||||
struct imx_pin_reg *pin_reg;
|
||||
|
||||
if (info->flags & SHARE_MUX_CONF_REG)
|
||||
conf_reg = mux_reg;
|
||||
else
|
||||
conf_reg = be32_to_cpu(*list++);
|
||||
|
||||
pin_id = mux_reg ? mux_reg / 4 : conf_reg / 4;
|
||||
pin_reg = &info->pin_regs[pin_id];
|
||||
grp->pins[i] = pin_id;
|
||||
pin_reg->mux_reg = mux_reg;
|
||||
pin_reg->conf_reg = conf_reg;
|
||||
|
|
|
@ -74,8 +74,12 @@ struct imx_pinctrl_soc_info {
|
|||
unsigned int ngroups;
|
||||
struct imx_pmx_func *functions;
|
||||
unsigned int nfunctions;
|
||||
unsigned int flags;
|
||||
};
|
||||
|
||||
#define ZERO_OFFSET_VALID 0x1
|
||||
#define SHARE_MUX_CONF_REG 0x2
|
||||
|
||||
#define NO_MUX 0x0
|
||||
#define NO_PAD 0x0
|
||||
|
||||
|
|
|
@ -515,7 +515,6 @@ int mxs_pinctrl_probe(struct platform_device *pdev,
|
|||
return 0;
|
||||
|
||||
err:
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
iounmap(d->base);
|
||||
return ret;
|
||||
}
|
||||
|
@ -525,7 +524,6 @@ int mxs_pinctrl_remove(struct platform_device *pdev)
|
|||
{
|
||||
struct mxs_pinctrl_data *d = platform_get_drvdata(pdev);
|
||||
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
pinctrl_unregister(d->pctl);
|
||||
iounmap(d->base);
|
||||
|
||||
|
|
|
@ -1309,7 +1309,7 @@ static int nmk_gpio_irq_map(struct irq_domain *d, unsigned int irq,
|
|||
return 0;
|
||||
}
|
||||
|
||||
const struct irq_domain_ops nmk_gpio_irq_simple_ops = {
|
||||
static const struct irq_domain_ops nmk_gpio_irq_simple_ops = {
|
||||
.map = nmk_gpio_irq_map,
|
||||
.xlate = irq_domain_xlate_twocell,
|
||||
};
|
||||
|
@ -1681,7 +1681,7 @@ static bool nmk_pinctrl_dt_get_config(struct device_node *np,
|
|||
return has_config;
|
||||
}
|
||||
|
||||
int nmk_pinctrl_dt_subnode_to_map(struct pinctrl_dev *pctldev,
|
||||
static int nmk_pinctrl_dt_subnode_to_map(struct pinctrl_dev *pctldev,
|
||||
struct device_node *np,
|
||||
struct pinctrl_map **map,
|
||||
unsigned *reserved_maps,
|
||||
|
@ -1740,7 +1740,7 @@ int nmk_pinctrl_dt_subnode_to_map(struct pinctrl_dev *pctldev,
|
|||
return ret;
|
||||
}
|
||||
|
||||
int nmk_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
|
||||
static int nmk_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
|
||||
struct device_node *np_config,
|
||||
struct pinctrl_map **map, unsigned *num_maps)
|
||||
{
|
||||
|
|
1394
drivers/pinctrl/pinctrl-rockchip.c
Normal file
1394
drivers/pinctrl/pinctrl-rockchip.c
Normal file
File diff suppressed because it is too large
Load Diff
|
@ -50,7 +50,7 @@ static struct pin_config {
|
|||
};
|
||||
|
||||
/* Global list of devices (struct samsung_pinctrl_drv_data) */
|
||||
LIST_HEAD(drvdata_list);
|
||||
static LIST_HEAD(drvdata_list);
|
||||
|
||||
static unsigned int pin_base;
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
#define DRIVER_NAME "pinctrl-single"
|
||||
#define PCS_MUX_PINS_NAME "pinctrl-single,pins"
|
||||
#define PCS_MUX_BITS_NAME "pinctrl-single,bits"
|
||||
#define PCS_REG_NAME_LEN ((sizeof(unsigned long) * 2) + 1)
|
||||
#define PCS_REG_NAME_LEN ((sizeof(unsigned long) * 2) + 3)
|
||||
#define PCS_OFF_DISABLED ~0U
|
||||
|
||||
/**
|
||||
|
@ -163,6 +163,7 @@ struct pcs_name {
|
|||
* @foff: value to turn mux off
|
||||
* @fmax: max number of functions in fmask
|
||||
* @is_pinconf: whether supports pinconf
|
||||
* @bits_per_pin:number of bits per pin
|
||||
* @names: array of register names for pins
|
||||
* @pins: physical pins on the SoC
|
||||
* @pgtree: pingroup index radix tree
|
||||
|
@ -190,6 +191,7 @@ struct pcs_device {
|
|||
unsigned fmax;
|
||||
bool bits_per_mux;
|
||||
bool is_pinconf;
|
||||
unsigned bits_per_pin;
|
||||
struct pcs_name *names;
|
||||
struct pcs_data pins;
|
||||
struct radix_tree_root pgtree;
|
||||
|
@ -431,10 +433,11 @@ static int pcs_enable(struct pinctrl_dev *pctldev, unsigned fselector,
|
|||
|
||||
vals = &func->vals[i];
|
||||
val = pcs->read(vals->reg);
|
||||
if (!vals->mask)
|
||||
mask = pcs->fmask;
|
||||
|
||||
if (pcs->bits_per_mux)
|
||||
mask = vals->mask;
|
||||
else
|
||||
mask = pcs->fmask & vals->mask;
|
||||
mask = pcs->fmask;
|
||||
|
||||
val &= ~mask;
|
||||
val |= (vals->val & mask);
|
||||
|
@ -741,7 +744,8 @@ static const struct pinconf_ops pcs_pinconf_ops = {
|
|||
* @pcs: pcs driver instance
|
||||
* @offset: register offset from base
|
||||
*/
|
||||
static int pcs_add_pin(struct pcs_device *pcs, unsigned offset)
|
||||
static int pcs_add_pin(struct pcs_device *pcs, unsigned offset,
|
||||
unsigned pin_pos)
|
||||
{
|
||||
struct pinctrl_pin_desc *pin;
|
||||
struct pcs_name *pn;
|
||||
|
@ -756,8 +760,8 @@ static int pcs_add_pin(struct pcs_device *pcs, unsigned offset)
|
|||
|
||||
pin = &pcs->pins.pa[i];
|
||||
pn = &pcs->names[i];
|
||||
sprintf(pn->name, "%lx",
|
||||
(unsigned long)pcs->res->start + offset);
|
||||
sprintf(pn->name, "%lx.%d",
|
||||
(unsigned long)pcs->res->start + offset, pin_pos);
|
||||
pin->name = pn->name;
|
||||
pin->number = i;
|
||||
pcs->pins.cur++;
|
||||
|
@ -777,9 +781,17 @@ static int pcs_add_pin(struct pcs_device *pcs, unsigned offset)
|
|||
static int pcs_allocate_pin_table(struct pcs_device *pcs)
|
||||
{
|
||||
int mux_bytes, nr_pins, i;
|
||||
int num_pins_in_register = 0;
|
||||
|
||||
mux_bytes = pcs->width / BITS_PER_BYTE;
|
||||
nr_pins = pcs->size / mux_bytes;
|
||||
|
||||
if (pcs->bits_per_mux) {
|
||||
pcs->bits_per_pin = fls(pcs->fmask);
|
||||
nr_pins = (pcs->size * BITS_PER_BYTE) / pcs->bits_per_pin;
|
||||
num_pins_in_register = pcs->width / pcs->bits_per_pin;
|
||||
} else {
|
||||
nr_pins = pcs->size / mux_bytes;
|
||||
}
|
||||
|
||||
dev_dbg(pcs->dev, "allocating %i pins\n", nr_pins);
|
||||
pcs->pins.pa = devm_kzalloc(pcs->dev,
|
||||
|
@ -800,9 +812,17 @@ static int pcs_allocate_pin_table(struct pcs_device *pcs)
|
|||
for (i = 0; i < pcs->desc.npins; i++) {
|
||||
unsigned offset;
|
||||
int res;
|
||||
int byte_num;
|
||||
int pin_pos = 0;
|
||||
|
||||
offset = i * mux_bytes;
|
||||
res = pcs_add_pin(pcs, offset);
|
||||
if (pcs->bits_per_mux) {
|
||||
byte_num = (pcs->bits_per_pin * i) / BITS_PER_BYTE;
|
||||
offset = (byte_num / mux_bytes) * mux_bytes;
|
||||
pin_pos = i % num_pins_in_register;
|
||||
} else {
|
||||
offset = i * mux_bytes;
|
||||
}
|
||||
res = pcs_add_pin(pcs, offset, pin_pos);
|
||||
if (res < 0) {
|
||||
dev_err(pcs->dev, "error adding pins: %i\n", res);
|
||||
return res;
|
||||
|
@ -919,7 +939,10 @@ static int pcs_get_pin_by_offset(struct pcs_device *pcs, unsigned offset)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
index = offset / (pcs->width / BITS_PER_BYTE);
|
||||
if (pcs->bits_per_mux)
|
||||
index = (offset * BITS_PER_BYTE) / pcs->bits_per_pin;
|
||||
else
|
||||
index = offset / (pcs->width / BITS_PER_BYTE);
|
||||
|
||||
return index;
|
||||
}
|
||||
|
@ -1097,29 +1120,18 @@ static int pcs_parse_one_pinctrl_entry(struct pcs_device *pcs,
|
|||
{
|
||||
struct pcs_func_vals *vals;
|
||||
const __be32 *mux;
|
||||
int size, params, rows, *pins, index = 0, found = 0, res = -ENOMEM;
|
||||
int size, rows, *pins, index = 0, found = 0, res = -ENOMEM;
|
||||
struct pcs_function *function;
|
||||
|
||||
if (pcs->bits_per_mux) {
|
||||
params = 3;
|
||||
mux = of_get_property(np, PCS_MUX_BITS_NAME, &size);
|
||||
} else {
|
||||
params = 2;
|
||||
mux = of_get_property(np, PCS_MUX_PINS_NAME, &size);
|
||||
}
|
||||
|
||||
if (!mux) {
|
||||
dev_err(pcs->dev, "no valid property for %s\n", np->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (size < (sizeof(*mux) * params)) {
|
||||
dev_err(pcs->dev, "bad data for %s\n", np->name);
|
||||
mux = of_get_property(np, PCS_MUX_PINS_NAME, &size);
|
||||
if ((!mux) || (size < sizeof(*mux) * 2)) {
|
||||
dev_err(pcs->dev, "bad data for mux %s\n",
|
||||
np->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
size /= sizeof(*mux); /* Number of elements in array */
|
||||
rows = size / params;
|
||||
rows = size / 2;
|
||||
|
||||
vals = devm_kzalloc(pcs->dev, sizeof(*vals) * rows, GFP_KERNEL);
|
||||
if (!vals)
|
||||
|
@ -1137,10 +1149,6 @@ static int pcs_parse_one_pinctrl_entry(struct pcs_device *pcs,
|
|||
val = be32_to_cpup(mux + index++);
|
||||
vals[found].reg = pcs->base + offset;
|
||||
vals[found].val = val;
|
||||
if (params == 3) {
|
||||
val = be32_to_cpup(mux + index++);
|
||||
vals[found].mask = val;
|
||||
}
|
||||
|
||||
pin = pcs_get_pin_by_offset(pcs, offset);
|
||||
if (pin < 0) {
|
||||
|
@ -1184,6 +1192,125 @@ static int pcs_parse_one_pinctrl_entry(struct pcs_device *pcs,
|
|||
free_pins:
|
||||
devm_kfree(pcs->dev, pins);
|
||||
|
||||
free_vals:
|
||||
devm_kfree(pcs->dev, vals);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
#define PARAMS_FOR_BITS_PER_MUX 3
|
||||
|
||||
static int pcs_parse_bits_in_pinctrl_entry(struct pcs_device *pcs,
|
||||
struct device_node *np,
|
||||
struct pinctrl_map **map,
|
||||
unsigned *num_maps,
|
||||
const char **pgnames)
|
||||
{
|
||||
struct pcs_func_vals *vals;
|
||||
const __be32 *mux;
|
||||
int size, rows, *pins, index = 0, found = 0, res = -ENOMEM;
|
||||
int npins_in_row;
|
||||
struct pcs_function *function;
|
||||
|
||||
mux = of_get_property(np, PCS_MUX_BITS_NAME, &size);
|
||||
|
||||
if (!mux) {
|
||||
dev_err(pcs->dev, "no valid property for %s\n", np->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (size < (sizeof(*mux) * PARAMS_FOR_BITS_PER_MUX)) {
|
||||
dev_err(pcs->dev, "bad data for %s\n", np->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Number of elements in array */
|
||||
size /= sizeof(*mux);
|
||||
|
||||
rows = size / PARAMS_FOR_BITS_PER_MUX;
|
||||
npins_in_row = pcs->width / pcs->bits_per_pin;
|
||||
|
||||
vals = devm_kzalloc(pcs->dev, sizeof(*vals) * rows * npins_in_row,
|
||||
GFP_KERNEL);
|
||||
if (!vals)
|
||||
return -ENOMEM;
|
||||
|
||||
pins = devm_kzalloc(pcs->dev, sizeof(*pins) * rows * npins_in_row,
|
||||
GFP_KERNEL);
|
||||
if (!pins)
|
||||
goto free_vals;
|
||||
|
||||
while (index < size) {
|
||||
unsigned offset, val;
|
||||
unsigned mask, bit_pos, val_pos, mask_pos, submask;
|
||||
unsigned pin_num_from_lsb;
|
||||
int pin;
|
||||
|
||||
offset = be32_to_cpup(mux + index++);
|
||||
val = be32_to_cpup(mux + index++);
|
||||
mask = be32_to_cpup(mux + index++);
|
||||
|
||||
/* Parse pins in each row from LSB */
|
||||
while (mask) {
|
||||
bit_pos = ffs(mask);
|
||||
pin_num_from_lsb = bit_pos / pcs->bits_per_pin;
|
||||
mask_pos = ((pcs->fmask) << (bit_pos - 1));
|
||||
val_pos = val & mask_pos;
|
||||
submask = mask & mask_pos;
|
||||
mask &= ~mask_pos;
|
||||
|
||||
if (submask != mask_pos) {
|
||||
dev_warn(pcs->dev,
|
||||
"Invalid submask 0x%x for %s at 0x%x\n",
|
||||
submask, np->name, offset);
|
||||
continue;
|
||||
}
|
||||
|
||||
vals[found].mask = submask;
|
||||
vals[found].reg = pcs->base + offset;
|
||||
vals[found].val = val_pos;
|
||||
|
||||
pin = pcs_get_pin_by_offset(pcs, offset);
|
||||
if (pin < 0) {
|
||||
dev_err(pcs->dev,
|
||||
"could not add functions for %s %ux\n",
|
||||
np->name, offset);
|
||||
break;
|
||||
}
|
||||
pins[found++] = pin + pin_num_from_lsb;
|
||||
}
|
||||
}
|
||||
|
||||
pgnames[0] = np->name;
|
||||
function = pcs_add_function(pcs, np, np->name, vals, found, pgnames, 1);
|
||||
if (!function)
|
||||
goto free_pins;
|
||||
|
||||
res = pcs_add_pingroup(pcs, np, np->name, pins, found);
|
||||
if (res < 0)
|
||||
goto free_function;
|
||||
|
||||
(*map)->type = PIN_MAP_TYPE_MUX_GROUP;
|
||||
(*map)->data.mux.group = np->name;
|
||||
(*map)->data.mux.function = np->name;
|
||||
|
||||
if (pcs->is_pinconf) {
|
||||
dev_err(pcs->dev, "pinconf not supported\n");
|
||||
goto free_pingroups;
|
||||
}
|
||||
|
||||
*num_maps = 1;
|
||||
return 0;
|
||||
|
||||
free_pingroups:
|
||||
pcs_free_pingroups(pcs);
|
||||
*num_maps = 1;
|
||||
free_function:
|
||||
pcs_remove_function(pcs, function);
|
||||
|
||||
free_pins:
|
||||
devm_kfree(pcs->dev, pins);
|
||||
|
||||
free_vals:
|
||||
devm_kfree(pcs->dev, vals);
|
||||
|
||||
|
@ -1219,12 +1346,22 @@ static int pcs_dt_node_to_map(struct pinctrl_dev *pctldev,
|
|||
goto free_map;
|
||||
}
|
||||
|
||||
ret = pcs_parse_one_pinctrl_entry(pcs, np_config, map, num_maps,
|
||||
pgnames);
|
||||
if (ret < 0) {
|
||||
dev_err(pcs->dev, "no pins entries for %s\n",
|
||||
np_config->name);
|
||||
goto free_pgnames;
|
||||
if (pcs->bits_per_mux) {
|
||||
ret = pcs_parse_bits_in_pinctrl_entry(pcs, np_config, map,
|
||||
num_maps, pgnames);
|
||||
if (ret < 0) {
|
||||
dev_err(pcs->dev, "no pins entries for %s\n",
|
||||
np_config->name);
|
||||
goto free_pgnames;
|
||||
}
|
||||
} else {
|
||||
ret = pcs_parse_one_pinctrl_entry(pcs, np_config, map,
|
||||
num_maps, pgnames);
|
||||
if (ret < 0) {
|
||||
dev_err(pcs->dev, "no pins entries for %s\n",
|
||||
np_config->name);
|
||||
goto free_pgnames;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -1346,6 +1483,29 @@ static int pcs_add_gpio_func(struct device_node *node, struct pcs_device *pcs)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int pinctrl_single_suspend(struct platform_device *pdev,
|
||||
pm_message_t state)
|
||||
{
|
||||
struct pcs_device *pcs;
|
||||
|
||||
pcs = platform_get_drvdata(pdev);
|
||||
if (!pcs)
|
||||
return -EINVAL;
|
||||
|
||||
return pinctrl_force_sleep(pcs->pctl);
|
||||
}
|
||||
|
||||
static int pinctrl_single_resume(struct platform_device *pdev)
|
||||
{
|
||||
struct pcs_device *pcs;
|
||||
|
||||
pcs = platform_get_drvdata(pdev);
|
||||
if (!pcs)
|
||||
return -EINVAL;
|
||||
|
||||
return pinctrl_force_default(pcs->pctl);
|
||||
}
|
||||
|
||||
static int pcs_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
|
@ -1494,6 +1654,10 @@ static struct platform_driver pcs_driver = {
|
|||
.name = DRIVER_NAME,
|
||||
.of_match_table = pcs_of_match,
|
||||
},
|
||||
#ifdef CONFIG_PM
|
||||
.suspend = pinctrl_single_suspend,
|
||||
.resume = pinctrl_single_resume,
|
||||
#endif
|
||||
};
|
||||
|
||||
module_platform_driver(pcs_driver);
|
||||
|
|
2023
drivers/pinctrl/pinctrl-sunxi-pins.h
Normal file
2023
drivers/pinctrl/pinctrl-sunxi-pins.h
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -344,9 +344,31 @@
|
|||
#define PULL_PINS_BITS 2
|
||||
#define PULL_PINS_MASK 0x03
|
||||
|
||||
#define SUNXI_IRQ_NUMBER 32
|
||||
|
||||
#define IRQ_CFG_REG 0x200
|
||||
#define IRQ_CFG_IRQ_PER_REG 8
|
||||
#define IRQ_CFG_IRQ_BITS 4
|
||||
#define IRQ_CFG_IRQ_MASK ((1 << IRQ_CFG_IRQ_BITS) - 1)
|
||||
#define IRQ_CTRL_REG 0x210
|
||||
#define IRQ_CTRL_IRQ_PER_REG 32
|
||||
#define IRQ_CTRL_IRQ_BITS 1
|
||||
#define IRQ_CTRL_IRQ_MASK ((1 << IRQ_CTRL_IRQ_BITS) - 1)
|
||||
#define IRQ_STATUS_REG 0x214
|
||||
#define IRQ_STATUS_IRQ_PER_REG 32
|
||||
#define IRQ_STATUS_IRQ_BITS 1
|
||||
#define IRQ_STATUS_IRQ_MASK ((1 << IRQ_STATUS_IRQ_BITS) - 1)
|
||||
|
||||
#define IRQ_EDGE_RISING 0x00
|
||||
#define IRQ_EDGE_FALLING 0x01
|
||||
#define IRQ_LEVEL_HIGH 0x02
|
||||
#define IRQ_LEVEL_LOW 0x03
|
||||
#define IRQ_EDGE_BOTH 0x04
|
||||
|
||||
struct sunxi_desc_function {
|
||||
const char *name;
|
||||
u8 muxval;
|
||||
u8 irqnum;
|
||||
};
|
||||
|
||||
struct sunxi_desc_pin {
|
||||
|
@ -378,10 +400,13 @@ struct sunxi_pinctrl {
|
|||
struct gpio_chip *chip;
|
||||
struct sunxi_pinctrl_desc *desc;
|
||||
struct device *dev;
|
||||
struct irq_domain *domain;
|
||||
struct sunxi_pinctrl_function *functions;
|
||||
unsigned nfunctions;
|
||||
struct sunxi_pinctrl_group *groups;
|
||||
unsigned ngroups;
|
||||
int irq;
|
||||
int irq_array[SUNXI_IRQ_NUMBER];
|
||||
struct pinctrl_dev *pctl_dev;
|
||||
};
|
||||
|
||||
|
@ -398,6 +423,13 @@ struct sunxi_pinctrl {
|
|||
.muxval = _val, \
|
||||
}
|
||||
|
||||
#define SUNXI_FUNCTION_IRQ(_val, _irq) \
|
||||
{ \
|
||||
.name = "irq", \
|
||||
.muxval = _val, \
|
||||
.irqnum = _irq, \
|
||||
}
|
||||
|
||||
/*
|
||||
* The sunXi PIO registers are organized as is:
|
||||
* 0x00 - 0x0c Muxing values.
|
||||
|
@ -475,4 +507,40 @@ static inline u32 sunxi_pull_offset(u16 pin)
|
|||
return pin_num * PULL_PINS_BITS;
|
||||
}
|
||||
|
||||
static inline u32 sunxi_irq_cfg_reg(u16 irq)
|
||||
{
|
||||
u8 reg = irq / IRQ_CFG_IRQ_PER_REG;
|
||||
return reg + IRQ_CFG_REG;
|
||||
}
|
||||
|
||||
static inline u32 sunxi_irq_cfg_offset(u16 irq)
|
||||
{
|
||||
u32 irq_num = irq % IRQ_CFG_IRQ_PER_REG;
|
||||
return irq_num * IRQ_CFG_IRQ_BITS;
|
||||
}
|
||||
|
||||
static inline u32 sunxi_irq_ctrl_reg(u16 irq)
|
||||
{
|
||||
u8 reg = irq / IRQ_CTRL_IRQ_PER_REG;
|
||||
return reg + IRQ_CTRL_REG;
|
||||
}
|
||||
|
||||
static inline u32 sunxi_irq_ctrl_offset(u16 irq)
|
||||
{
|
||||
u32 irq_num = irq % IRQ_CTRL_IRQ_PER_REG;
|
||||
return irq_num * IRQ_CTRL_IRQ_BITS;
|
||||
}
|
||||
|
||||
static inline u32 sunxi_irq_status_reg(u16 irq)
|
||||
{
|
||||
u8 reg = irq / IRQ_STATUS_IRQ_PER_REG;
|
||||
return reg + IRQ_STATUS_REG;
|
||||
}
|
||||
|
||||
static inline u32 sunxi_irq_status_offset(u16 irq)
|
||||
{
|
||||
u32 irq_num = irq % IRQ_STATUS_IRQ_PER_REG;
|
||||
return irq_num * IRQ_STATUS_IRQ_BITS;
|
||||
}
|
||||
|
||||
#endif /* __PINCTRL_SUNXI_H */
|
||||
|
|
1024
drivers/pinctrl/pinctrl-tz1090-pdc.c
Normal file
1024
drivers/pinctrl/pinctrl-tz1090-pdc.c
Normal file
File diff suppressed because it is too large
Load Diff
2072
drivers/pinctrl/pinctrl-tz1090.c
Normal file
2072
drivers/pinctrl/pinctrl-tz1090.c
Normal file
File diff suppressed because it is too large
Load Diff
|
@ -1100,7 +1100,6 @@ static int u300_pmx_remove(struct platform_device *pdev)
|
|||
struct u300_pmx *upmx = platform_get_drvdata(pdev);
|
||||
|
||||
pinctrl_unregister(upmx->pctl);
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
338
drivers/pinctrl/pinctrl-vf610.c
Normal file
338
drivers/pinctrl/pinctrl-vf610.c
Normal file
|
@ -0,0 +1,338 @@
|
|||
/*
|
||||
* VF610 pinctrl driver based on imx pinmux and pinconf core
|
||||
*
|
||||
* Copyright 2013 Freescale Semiconductor, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include <linux/err.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/pinctrl/pinctrl.h>
|
||||
|
||||
#include "pinctrl-imx.h"
|
||||
|
||||
enum vf610_pads {
|
||||
VF610_PAD_PTA6 = 0,
|
||||
VF610_PAD_PTA8 = 1,
|
||||
VF610_PAD_PTA9 = 2,
|
||||
VF610_PAD_PTA10 = 3,
|
||||
VF610_PAD_PTA11 = 4,
|
||||
VF610_PAD_PTA12 = 5,
|
||||
VF610_PAD_PTA16 = 6,
|
||||
VF610_PAD_PTA17 = 7,
|
||||
VF610_PAD_PTA18 = 8,
|
||||
VF610_PAD_PTA19 = 9,
|
||||
VF610_PAD_PTA20 = 10,
|
||||
VF610_PAD_PTA21 = 11,
|
||||
VF610_PAD_PTA22 = 12,
|
||||
VF610_PAD_PTA23 = 13,
|
||||
VF610_PAD_PTA24 = 14,
|
||||
VF610_PAD_PTA25 = 15,
|
||||
VF610_PAD_PTA26 = 16,
|
||||
VF610_PAD_PTA27 = 17,
|
||||
VF610_PAD_PTA28 = 18,
|
||||
VF610_PAD_PTA29 = 19,
|
||||
VF610_PAD_PTA30 = 20,
|
||||
VF610_PAD_PTA31 = 21,
|
||||
VF610_PAD_PTB0 = 22,
|
||||
VF610_PAD_PTB1 = 23,
|
||||
VF610_PAD_PTB2 = 24,
|
||||
VF610_PAD_PTB3 = 25,
|
||||
VF610_PAD_PTB4 = 26,
|
||||
VF610_PAD_PTB5 = 27,
|
||||
VF610_PAD_PTB6 = 28,
|
||||
VF610_PAD_PTB7 = 29,
|
||||
VF610_PAD_PTB8 = 30,
|
||||
VF610_PAD_PTB9 = 31,
|
||||
VF610_PAD_PTB10 = 32,
|
||||
VF610_PAD_PTB11 = 33,
|
||||
VF610_PAD_PTB12 = 34,
|
||||
VF610_PAD_PTB13 = 35,
|
||||
VF610_PAD_PTB14 = 36,
|
||||
VF610_PAD_PTB15 = 37,
|
||||
VF610_PAD_PTB16 = 38,
|
||||
VF610_PAD_PTB17 = 39,
|
||||
VF610_PAD_PTB18 = 40,
|
||||
VF610_PAD_PTB19 = 41,
|
||||
VF610_PAD_PTB20 = 42,
|
||||
VF610_PAD_PTB21 = 43,
|
||||
VF610_PAD_PTB22 = 44,
|
||||
VF610_PAD_PTC0 = 45,
|
||||
VF610_PAD_PTC1 = 46,
|
||||
VF610_PAD_PTC2 = 47,
|
||||
VF610_PAD_PTC3 = 48,
|
||||
VF610_PAD_PTC4 = 49,
|
||||
VF610_PAD_PTC5 = 50,
|
||||
VF610_PAD_PTC6 = 51,
|
||||
VF610_PAD_PTC7 = 52,
|
||||
VF610_PAD_PTC8 = 53,
|
||||
VF610_PAD_PTC9 = 54,
|
||||
VF610_PAD_PTC10 = 55,
|
||||
VF610_PAD_PTC11 = 56,
|
||||
VF610_PAD_PTC12 = 57,
|
||||
VF610_PAD_PTC13 = 58,
|
||||
VF610_PAD_PTC14 = 59,
|
||||
VF610_PAD_PTC15 = 60,
|
||||
VF610_PAD_PTC16 = 61,
|
||||
VF610_PAD_PTC17 = 62,
|
||||
VF610_PAD_PTD31 = 63,
|
||||
VF610_PAD_PTD30 = 64,
|
||||
VF610_PAD_PTD29 = 65,
|
||||
VF610_PAD_PTD28 = 66,
|
||||
VF610_PAD_PTD27 = 67,
|
||||
VF610_PAD_PTD26 = 68,
|
||||
VF610_PAD_PTD25 = 69,
|
||||
VF610_PAD_PTD24 = 70,
|
||||
VF610_PAD_PTD23 = 71,
|
||||
VF610_PAD_PTD22 = 72,
|
||||
VF610_PAD_PTD21 = 73,
|
||||
VF610_PAD_PTD20 = 74,
|
||||
VF610_PAD_PTD19 = 75,
|
||||
VF610_PAD_PTD18 = 76,
|
||||
VF610_PAD_PTD17 = 77,
|
||||
VF610_PAD_PTD16 = 78,
|
||||
VF610_PAD_PTD0 = 79,
|
||||
VF610_PAD_PTD1 = 80,
|
||||
VF610_PAD_PTD2 = 81,
|
||||
VF610_PAD_PTD3 = 82,
|
||||
VF610_PAD_PTD4 = 83,
|
||||
VF610_PAD_PTD5 = 84,
|
||||
VF610_PAD_PTD6 = 85,
|
||||
VF610_PAD_PTD7 = 86,
|
||||
VF610_PAD_PTD8 = 87,
|
||||
VF610_PAD_PTD9 = 88,
|
||||
VF610_PAD_PTD10 = 89,
|
||||
VF610_PAD_PTD11 = 90,
|
||||
VF610_PAD_PTD12 = 91,
|
||||
VF610_PAD_PTD13 = 92,
|
||||
VF610_PAD_PTB23 = 93,
|
||||
VF610_PAD_PTB24 = 94,
|
||||
VF610_PAD_PTB25 = 95,
|
||||
VF610_PAD_PTB26 = 96,
|
||||
VF610_PAD_PTB27 = 97,
|
||||
VF610_PAD_PTB28 = 98,
|
||||
VF610_PAD_PTC26 = 99,
|
||||
VF610_PAD_PTC27 = 100,
|
||||
VF610_PAD_PTC28 = 101,
|
||||
VF610_PAD_PTC29 = 102,
|
||||
VF610_PAD_PTC30 = 103,
|
||||
VF610_PAD_PTC31 = 104,
|
||||
VF610_PAD_PTE0 = 105,
|
||||
VF610_PAD_PTE1 = 106,
|
||||
VF610_PAD_PTE2 = 107,
|
||||
VF610_PAD_PTE3 = 108,
|
||||
VF610_PAD_PTE4 = 109,
|
||||
VF610_PAD_PTE5 = 110,
|
||||
VF610_PAD_PTE6 = 111,
|
||||
VF610_PAD_PTE7 = 112,
|
||||
VF610_PAD_PTE8 = 113,
|
||||
VF610_PAD_PTE9 = 114,
|
||||
VF610_PAD_PTE10 = 115,
|
||||
VF610_PAD_PTE11 = 116,
|
||||
VF610_PAD_PTE12 = 117,
|
||||
VF610_PAD_PTE13 = 118,
|
||||
VF610_PAD_PTE14 = 119,
|
||||
VF610_PAD_PTE15 = 120,
|
||||
VF610_PAD_PTE16 = 121,
|
||||
VF610_PAD_PTE17 = 122,
|
||||
VF610_PAD_PTE18 = 123,
|
||||
VF610_PAD_PTE19 = 124,
|
||||
VF610_PAD_PTE20 = 125,
|
||||
VF610_PAD_PTE21 = 126,
|
||||
VF610_PAD_PTE22 = 127,
|
||||
VF610_PAD_PTE23 = 128,
|
||||
VF610_PAD_PTE24 = 129,
|
||||
VF610_PAD_PTE25 = 130,
|
||||
VF610_PAD_PTE26 = 131,
|
||||
VF610_PAD_PTE27 = 132,
|
||||
VF610_PAD_PTE28 = 133,
|
||||
VF610_PAD_PTA7 = 134,
|
||||
};
|
||||
|
||||
/* Pad names for the pinmux subsystem */
|
||||
static const struct pinctrl_pin_desc vf610_pinctrl_pads[] = {
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTA6),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTA8),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTA9),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTA10),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTA11),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTA12),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTA16),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTA17),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTA18),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTA19),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTA20),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTA21),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTA22),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTA23),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTA24),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTA25),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTA26),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTA27),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTA28),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTA29),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTA30),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTA31),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTB0),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTB1),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTB2),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTB3),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTB4),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTB5),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTB6),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTB7),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTB8),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTB9),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTB10),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTB11),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTB12),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTB13),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTB14),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTB15),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTB16),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTB17),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTB18),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTB19),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTB20),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTB21),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTB22),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTC0),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTC1),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTC2),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTC3),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTC4),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTC5),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTC6),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTC7),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTC8),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTC9),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTC10),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTC11),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTC12),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTC13),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTC14),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTC15),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTC16),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTC17),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTD31),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTD30),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTD29),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTD28),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTD27),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTD26),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTD25),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTD24),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTD23),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTD22),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTD21),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTD20),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTD19),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTD18),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTD17),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTD16),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTD0),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTD1),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTD2),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTD3),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTD4),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTD5),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTD6),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTD7),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTD8),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTD9),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTD10),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTD11),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTD12),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTD13),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTB23),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTB24),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTB25),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTB26),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTB27),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTB28),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTC26),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTC27),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTC28),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTC29),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTC30),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTC31),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTE0),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTE1),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTE2),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTE3),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTE4),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTE5),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTE6),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTE7),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTE8),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTE9),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTE10),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTE11),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTE12),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTE13),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTE14),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTE15),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTE16),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTE17),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTE18),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTE19),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTE20),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTE21),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTE22),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTE23),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTE24),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTE25),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTE26),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTE27),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTE28),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTA7),
|
||||
};
|
||||
|
||||
static struct imx_pinctrl_soc_info vf610_pinctrl_info = {
|
||||
.pins = vf610_pinctrl_pads,
|
||||
.npins = ARRAY_SIZE(vf610_pinctrl_pads),
|
||||
.flags = ZERO_OFFSET_VALID | SHARE_MUX_CONF_REG,
|
||||
};
|
||||
|
||||
static struct of_device_id vf610_pinctrl_of_match[] = {
|
||||
{ .compatible = "fsl,vf610-iomuxc", },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
|
||||
static int vf610_pinctrl_probe(struct platform_device *pdev)
|
||||
{
|
||||
return imx_pinctrl_probe(pdev, &vf610_pinctrl_info);
|
||||
}
|
||||
|
||||
static struct platform_driver vf610_pinctrl_driver = {
|
||||
.driver = {
|
||||
.name = "vf610-pinctrl",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = of_match_ptr(vf610_pinctrl_of_match),
|
||||
},
|
||||
.probe = vf610_pinctrl_probe,
|
||||
.remove = imx_pinctrl_remove,
|
||||
};
|
||||
|
||||
static int __init vf610_pinctrl_init(void)
|
||||
{
|
||||
return platform_driver_register(&vf610_pinctrl_driver);
|
||||
}
|
||||
arch_initcall(vf610_pinctrl_init);
|
||||
|
||||
static void __exit vf610_pinctrl_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&vf610_pinctrl_driver);
|
||||
}
|
||||
module_exit(vf610_pinctrl_exit);
|
||||
|
||||
MODULE_DESCRIPTION("Freescale VF610 pinctrl driver");
|
||||
MODULE_LICENSE("GPL v2");
|
|
@ -18,6 +18,8 @@
|
|||
#include <linux/ioport.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/pinctrl/machine.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
|
@ -348,14 +350,72 @@ int sh_pfc_config_mux(struct sh_pfc *pfc, unsigned mark, int pinmux_type)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static const struct of_device_id sh_pfc_of_table[] = {
|
||||
#ifdef CONFIG_PINCTRL_PFC_R8A73A4
|
||||
{
|
||||
.compatible = "renesas,pfc-r8a73a4",
|
||||
.data = &r8a73a4_pinmux_info,
|
||||
},
|
||||
#endif
|
||||
#ifdef CONFIG_PINCTRL_PFC_R8A7740
|
||||
{
|
||||
.compatible = "renesas,pfc-r8a7740",
|
||||
.data = &r8a7740_pinmux_info,
|
||||
},
|
||||
#endif
|
||||
#ifdef CONFIG_PINCTRL_PFC_R8A7778
|
||||
{
|
||||
.compatible = "renesas,pfc-r8a7778",
|
||||
.data = &r8a7778_pinmux_info,
|
||||
},
|
||||
#endif
|
||||
#ifdef CONFIG_PINCTRL_PFC_R8A7779
|
||||
{
|
||||
.compatible = "renesas,pfc-r8a7779",
|
||||
.data = &r8a7779_pinmux_info,
|
||||
},
|
||||
#endif
|
||||
#ifdef CONFIG_PINCTRL_PFC_R8A7790
|
||||
{
|
||||
.compatible = "renesas,pfc-r8a7790",
|
||||
.data = &r8a7790_pinmux_info,
|
||||
},
|
||||
#endif
|
||||
#ifdef CONFIG_PINCTRL_PFC_SH7372
|
||||
{
|
||||
.compatible = "renesas,pfc-sh7372",
|
||||
.data = &sh7372_pinmux_info,
|
||||
},
|
||||
#endif
|
||||
#ifdef CONFIG_PINCTRL_PFC_SH73A0
|
||||
{
|
||||
.compatible = "renesas,pfc-sh73a0",
|
||||
.data = &sh73a0_pinmux_info,
|
||||
},
|
||||
#endif
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, sh_pfc_of_table);
|
||||
#endif
|
||||
|
||||
static int sh_pfc_probe(struct platform_device *pdev)
|
||||
{
|
||||
const struct platform_device_id *platid = platform_get_device_id(pdev);
|
||||
#ifdef CONFIG_OF
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
#endif
|
||||
const struct sh_pfc_soc_info *info;
|
||||
struct sh_pfc *pfc;
|
||||
int ret;
|
||||
|
||||
info = pdev->id_entry->driver_data
|
||||
? (void *)pdev->id_entry->driver_data : pdev->dev.platform_data;
|
||||
#ifdef CONFIG_OF
|
||||
if (np)
|
||||
info = of_match_device(sh_pfc_of_table, &pdev->dev)->data;
|
||||
else
|
||||
#endif
|
||||
info = platid ? (const void *)platid->driver_data : NULL;
|
||||
|
||||
if (info == NULL)
|
||||
return -ENODEV;
|
||||
|
||||
|
@ -501,6 +561,7 @@ static struct platform_driver sh_pfc_driver = {
|
|||
.driver = {
|
||||
.name = DRV_NAME,
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = of_match_ptr(sh_pfc_of_table),
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -14,7 +14,9 @@
|
|||
#include <linux/err.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/pinctrl/consumer.h>
|
||||
#include <linux/pinctrl/machine.h>
|
||||
#include <linux/pinctrl/pinconf.h>
|
||||
#include <linux/pinctrl/pinconf-generic.h>
|
||||
#include <linux/pinctrl/pinctrl.h>
|
||||
|
@ -72,11 +74,214 @@ static void sh_pfc_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
|
|||
seq_printf(s, "%s", DRV_NAME);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static int sh_pfc_map_add_config(struct pinctrl_map *map,
|
||||
const char *group_or_pin,
|
||||
enum pinctrl_map_type type,
|
||||
unsigned long *configs,
|
||||
unsigned int num_configs)
|
||||
{
|
||||
unsigned long *cfgs;
|
||||
|
||||
cfgs = kmemdup(configs, num_configs * sizeof(*cfgs),
|
||||
GFP_KERNEL);
|
||||
if (cfgs == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
map->type = type;
|
||||
map->data.configs.group_or_pin = group_or_pin;
|
||||
map->data.configs.configs = cfgs;
|
||||
map->data.configs.num_configs = num_configs;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sh_pfc_dt_subnode_to_map(struct device *dev, struct device_node *np,
|
||||
struct pinctrl_map **map,
|
||||
unsigned int *num_maps, unsigned int *index)
|
||||
{
|
||||
struct pinctrl_map *maps = *map;
|
||||
unsigned int nmaps = *num_maps;
|
||||
unsigned int idx = *index;
|
||||
unsigned int num_configs;
|
||||
const char *function = NULL;
|
||||
unsigned long *configs;
|
||||
struct property *prop;
|
||||
unsigned int num_groups;
|
||||
unsigned int num_pins;
|
||||
const char *group;
|
||||
const char *pin;
|
||||
int ret;
|
||||
|
||||
/* Parse the function and configuration properties. At least a function
|
||||
* or one configuration must be specified.
|
||||
*/
|
||||
ret = of_property_read_string(np, "renesas,function", &function);
|
||||
if (ret < 0 && ret != -EINVAL) {
|
||||
dev_err(dev, "Invalid function in DT\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = pinconf_generic_parse_dt_config(np, &configs, &num_configs);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (!function && num_configs == 0) {
|
||||
dev_err(dev,
|
||||
"DT node must contain at least a function or config\n");
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Count the number of pins and groups and reallocate mappings. */
|
||||
ret = of_property_count_strings(np, "renesas,pins");
|
||||
if (ret == -EINVAL) {
|
||||
num_pins = 0;
|
||||
} else if (ret < 0) {
|
||||
dev_err(dev, "Invalid pins list in DT\n");
|
||||
goto done;
|
||||
} else {
|
||||
num_pins = ret;
|
||||
}
|
||||
|
||||
ret = of_property_count_strings(np, "renesas,groups");
|
||||
if (ret == -EINVAL) {
|
||||
num_groups = 0;
|
||||
} else if (ret < 0) {
|
||||
dev_err(dev, "Invalid pin groups list in DT\n");
|
||||
goto done;
|
||||
} else {
|
||||
num_groups = ret;
|
||||
}
|
||||
|
||||
if (!num_pins && !num_groups) {
|
||||
dev_err(dev, "No pin or group provided in DT node\n");
|
||||
ret = -ENODEV;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (function)
|
||||
nmaps += num_groups;
|
||||
if (configs)
|
||||
nmaps += num_pins + num_groups;
|
||||
|
||||
maps = krealloc(maps, sizeof(*maps) * nmaps, GFP_KERNEL);
|
||||
if (maps == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto done;
|
||||
}
|
||||
|
||||
*map = maps;
|
||||
*num_maps = nmaps;
|
||||
|
||||
/* Iterate over pins and groups and create the mappings. */
|
||||
of_property_for_each_string(np, "renesas,groups", prop, group) {
|
||||
if (function) {
|
||||
maps[idx].type = PIN_MAP_TYPE_MUX_GROUP;
|
||||
maps[idx].data.mux.group = group;
|
||||
maps[idx].data.mux.function = function;
|
||||
idx++;
|
||||
}
|
||||
|
||||
if (configs) {
|
||||
ret = sh_pfc_map_add_config(&maps[idx], group,
|
||||
PIN_MAP_TYPE_CONFIGS_GROUP,
|
||||
configs, num_configs);
|
||||
if (ret < 0)
|
||||
goto done;
|
||||
|
||||
idx++;
|
||||
}
|
||||
}
|
||||
|
||||
if (!configs) {
|
||||
ret = 0;
|
||||
goto done;
|
||||
}
|
||||
|
||||
of_property_for_each_string(np, "renesas,pins", prop, pin) {
|
||||
ret = sh_pfc_map_add_config(&maps[idx], pin,
|
||||
PIN_MAP_TYPE_CONFIGS_PIN,
|
||||
configs, num_configs);
|
||||
if (ret < 0)
|
||||
goto done;
|
||||
|
||||
idx++;
|
||||
}
|
||||
|
||||
done:
|
||||
*index = idx;
|
||||
kfree(configs);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void sh_pfc_dt_free_map(struct pinctrl_dev *pctldev,
|
||||
struct pinctrl_map *map, unsigned num_maps)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
if (map == NULL)
|
||||
return;
|
||||
|
||||
for (i = 0; i < num_maps; ++i) {
|
||||
if (map[i].type == PIN_MAP_TYPE_CONFIGS_GROUP ||
|
||||
map[i].type == PIN_MAP_TYPE_CONFIGS_PIN)
|
||||
kfree(map[i].data.configs.configs);
|
||||
}
|
||||
|
||||
kfree(map);
|
||||
}
|
||||
|
||||
static int sh_pfc_dt_node_to_map(struct pinctrl_dev *pctldev,
|
||||
struct device_node *np,
|
||||
struct pinctrl_map **map, unsigned *num_maps)
|
||||
{
|
||||
struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
|
||||
struct device *dev = pmx->pfc->dev;
|
||||
struct device_node *child;
|
||||
unsigned int index;
|
||||
int ret;
|
||||
|
||||
*map = NULL;
|
||||
*num_maps = 0;
|
||||
index = 0;
|
||||
|
||||
for_each_child_of_node(np, child) {
|
||||
ret = sh_pfc_dt_subnode_to_map(dev, child, map, num_maps,
|
||||
&index);
|
||||
if (ret < 0)
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* If no mapping has been found in child nodes try the config node. */
|
||||
if (*num_maps == 0) {
|
||||
ret = sh_pfc_dt_subnode_to_map(dev, np, map, num_maps, &index);
|
||||
if (ret < 0)
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (*num_maps)
|
||||
return 0;
|
||||
|
||||
dev_err(dev, "no mapping found in node %s\n", np->full_name);
|
||||
ret = -EINVAL;
|
||||
|
||||
done:
|
||||
if (ret < 0)
|
||||
sh_pfc_dt_free_map(pctldev, *map, *num_maps);
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif /* CONFIG_OF */
|
||||
|
||||
static const struct pinctrl_ops sh_pfc_pinctrl_ops = {
|
||||
.get_groups_count = sh_pfc_get_groups_count,
|
||||
.get_group_name = sh_pfc_get_group_name,
|
||||
.get_group_pins = sh_pfc_get_group_pins,
|
||||
.pin_dbg_show = sh_pfc_pin_dbg_show,
|
||||
#ifdef CONFIG_OF
|
||||
.dt_node_to_map = sh_pfc_dt_node_to_map,
|
||||
.dt_free_map = sh_pfc_dt_free_map,
|
||||
#endif
|
||||
};
|
||||
|
||||
static int sh_pfc_get_functions_count(struct pinctrl_dev *pctldev)
|
||||
|
|
5
drivers/pinctrl/sirf/Makefile
Normal file
5
drivers/pinctrl/sirf/Makefile
Normal file
|
@ -0,0 +1,5 @@
|
|||
# CSR SiRFsoc pinmux support
|
||||
|
||||
obj-y += pinctrl-sirf.o
|
||||
obj-y += pinctrl-prima2.o
|
||||
obj-y += pinctrl-atlas6.o
|
947
drivers/pinctrl/sirf/pinctrl-atlas6.c
Normal file
947
drivers/pinctrl/sirf/pinctrl-atlas6.c
Normal file
|
@ -0,0 +1,947 @@
|
|||
/*
|
||||
* pinctrl pads, groups, functions for CSR SiRFatlasVI
|
||||
*
|
||||
* Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
|
||||
*
|
||||
* Licensed under GPLv2 or later.
|
||||
*/
|
||||
|
||||
#include <linux/pinctrl/pinctrl.h>
|
||||
#include <linux/bitops.h>
|
||||
|
||||
#include "pinctrl-sirf.h"
|
||||
|
||||
/*
|
||||
* pad list for the pinmux subsystem
|
||||
* refer to atlasVI_io_table_v0.93.xls
|
||||
*/
|
||||
static const struct pinctrl_pin_desc sirfsoc_pads[] = {
|
||||
PINCTRL_PIN(0, "gpio0-0"),
|
||||
PINCTRL_PIN(1, "gpio0-1"),
|
||||
PINCTRL_PIN(2, "gpio0-2"),
|
||||
PINCTRL_PIN(3, "gpio0-3"),
|
||||
PINCTRL_PIN(4, "pwm0"),
|
||||
PINCTRL_PIN(5, "pwm1"),
|
||||
PINCTRL_PIN(6, "pwm2"),
|
||||
PINCTRL_PIN(7, "pwm3"),
|
||||
PINCTRL_PIN(8, "warm_rst_b"),
|
||||
PINCTRL_PIN(9, "odo_0"),
|
||||
PINCTRL_PIN(10, "odo_1"),
|
||||
PINCTRL_PIN(11, "dr_dir"),
|
||||
PINCTRL_PIN(12, "rts_0"),
|
||||
PINCTRL_PIN(13, "scl_1"),
|
||||
PINCTRL_PIN(14, "ntrst"),
|
||||
PINCTRL_PIN(15, "sda_1"),
|
||||
PINCTRL_PIN(16, "x_ldd[16]"),
|
||||
PINCTRL_PIN(17, "x_ldd[17]"),
|
||||
PINCTRL_PIN(18, "x_ldd[18]"),
|
||||
PINCTRL_PIN(19, "x_ldd[19]"),
|
||||
PINCTRL_PIN(20, "x_ldd[20]"),
|
||||
PINCTRL_PIN(21, "x_ldd[21]"),
|
||||
PINCTRL_PIN(22, "x_ldd[22]"),
|
||||
PINCTRL_PIN(23, "x_ldd[23]"),
|
||||
PINCTRL_PIN(24, "gps_sgn"),
|
||||
PINCTRL_PIN(25, "gps_mag"),
|
||||
PINCTRL_PIN(26, "gps_clk"),
|
||||
PINCTRL_PIN(27, "sd_cd_b_2"),
|
||||
PINCTRL_PIN(28, "sd_vcc_on_2"),
|
||||
PINCTRL_PIN(29, "sd_wp_b_2"),
|
||||
PINCTRL_PIN(30, "sd_clk_3"),
|
||||
PINCTRL_PIN(31, "sd_cmd_3"),
|
||||
|
||||
PINCTRL_PIN(32, "x_sd_dat_3[0]"),
|
||||
PINCTRL_PIN(33, "x_sd_dat_3[1]"),
|
||||
PINCTRL_PIN(34, "x_sd_dat_3[2]"),
|
||||
PINCTRL_PIN(35, "x_sd_dat_3[3]"),
|
||||
PINCTRL_PIN(36, "usb_clk"),
|
||||
PINCTRL_PIN(37, "usb_dir"),
|
||||
PINCTRL_PIN(38, "usb_nxt"),
|
||||
PINCTRL_PIN(39, "usb_stp"),
|
||||
PINCTRL_PIN(40, "usb_dat[7]"),
|
||||
PINCTRL_PIN(41, "usb_dat[6]"),
|
||||
PINCTRL_PIN(42, "x_cko_1"),
|
||||
PINCTRL_PIN(43, "spi_clk_1"),
|
||||
PINCTRL_PIN(44, "spi_dout_1"),
|
||||
PINCTRL_PIN(45, "spi_din_1"),
|
||||
PINCTRL_PIN(46, "spi_en_1"),
|
||||
PINCTRL_PIN(47, "x_txd_1"),
|
||||
PINCTRL_PIN(48, "x_txd_2"),
|
||||
PINCTRL_PIN(49, "x_rxd_1"),
|
||||
PINCTRL_PIN(50, "x_rxd_2"),
|
||||
PINCTRL_PIN(51, "x_usclk_0"),
|
||||
PINCTRL_PIN(52, "x_utxd_0"),
|
||||
PINCTRL_PIN(53, "x_urxd_0"),
|
||||
PINCTRL_PIN(54, "x_utfs_0"),
|
||||
PINCTRL_PIN(55, "x_urfs_0"),
|
||||
PINCTRL_PIN(56, "usb_dat5"),
|
||||
PINCTRL_PIN(57, "usb_dat4"),
|
||||
PINCTRL_PIN(58, "usb_dat3"),
|
||||
PINCTRL_PIN(59, "usb_dat2"),
|
||||
PINCTRL_PIN(60, "usb_dat1"),
|
||||
PINCTRL_PIN(61, "usb_dat0"),
|
||||
PINCTRL_PIN(62, "x_ldd[14]"),
|
||||
PINCTRL_PIN(63, "x_ldd[15]"),
|
||||
|
||||
PINCTRL_PIN(64, "x_gps_gpio"),
|
||||
PINCTRL_PIN(65, "x_ldd[13]"),
|
||||
PINCTRL_PIN(66, "x_df_we_b"),
|
||||
PINCTRL_PIN(67, "x_df_re_b"),
|
||||
PINCTRL_PIN(68, "x_txd_0"),
|
||||
PINCTRL_PIN(69, "x_rxd_0"),
|
||||
PINCTRL_PIN(70, "x_l_lck"),
|
||||
PINCTRL_PIN(71, "x_l_fck"),
|
||||
PINCTRL_PIN(72, "x_l_de"),
|
||||
PINCTRL_PIN(73, "x_ldd[0]"),
|
||||
PINCTRL_PIN(74, "x_ldd[1]"),
|
||||
PINCTRL_PIN(75, "x_ldd[2]"),
|
||||
PINCTRL_PIN(76, "x_ldd[3]"),
|
||||
PINCTRL_PIN(77, "x_ldd[4]"),
|
||||
PINCTRL_PIN(78, "x_cko_0"),
|
||||
PINCTRL_PIN(79, "x_ldd[5]"),
|
||||
PINCTRL_PIN(80, "x_ldd[6]"),
|
||||
PINCTRL_PIN(81, "x_ldd[7]"),
|
||||
PINCTRL_PIN(82, "x_ldd[8]"),
|
||||
PINCTRL_PIN(83, "x_ldd[9]"),
|
||||
PINCTRL_PIN(84, "x_ldd[10]"),
|
||||
PINCTRL_PIN(85, "x_ldd[11]"),
|
||||
PINCTRL_PIN(86, "x_ldd[12]"),
|
||||
PINCTRL_PIN(87, "x_vip_vsync"),
|
||||
PINCTRL_PIN(88, "x_vip_hsync"),
|
||||
PINCTRL_PIN(89, "x_vip_pxclk"),
|
||||
PINCTRL_PIN(90, "x_sda_0"),
|
||||
PINCTRL_PIN(91, "x_scl_0"),
|
||||
PINCTRL_PIN(92, "x_df_ry_by"),
|
||||
PINCTRL_PIN(93, "x_df_cs_b[1]"),
|
||||
PINCTRL_PIN(94, "x_df_cs_b[0]"),
|
||||
PINCTRL_PIN(95, "x_l_pclk"),
|
||||
|
||||
PINCTRL_PIN(96, "x_df_dqs"),
|
||||
PINCTRL_PIN(97, "x_df_wp_b"),
|
||||
PINCTRL_PIN(98, "ac97_sync"),
|
||||
PINCTRL_PIN(99, "ac97_bit_clk "),
|
||||
PINCTRL_PIN(100, "ac97_dout"),
|
||||
PINCTRL_PIN(101, "ac97_din"),
|
||||
PINCTRL_PIN(102, "x_rtc_io"),
|
||||
};
|
||||
|
||||
static const struct sirfsoc_muxmask lcd_16bits_sirfsoc_muxmask[] = {
|
||||
{
|
||||
.group = 1,
|
||||
.mask = BIT(30) | BIT(31),
|
||||
}, {
|
||||
.group = 2,
|
||||
.mask = BIT(1) | BIT(6) | BIT(7) | BIT(8) | BIT(9) | BIT(10) | BIT(11) |
|
||||
BIT(12) | BIT(13) | BIT(15) | BIT(16) | BIT(17) | BIT(18) | BIT(19) |
|
||||
BIT(20) | BIT(21) | BIT(22) | BIT(31),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct sirfsoc_padmux lcd_16bits_padmux = {
|
||||
.muxmask_counts = ARRAY_SIZE(lcd_16bits_sirfsoc_muxmask),
|
||||
.muxmask = lcd_16bits_sirfsoc_muxmask,
|
||||
.funcmask = BIT(4),
|
||||
.funcval = 0,
|
||||
};
|
||||
|
||||
static const unsigned lcd_16bits_pins[] = { 62, 63, 65, 70, 71, 72, 73, 74, 75, 76, 77, 79, 80, 81, 82, 83,
|
||||
84, 85, 86, 95 };
|
||||
|
||||
static const struct sirfsoc_muxmask lcd_18bits_muxmask[] = {
|
||||
{
|
||||
.group = 2,
|
||||
.mask = BIT(1) | BIT(6) | BIT(7) | BIT(8) | BIT(9) | BIT(10) | BIT(11) |
|
||||
BIT(12) | BIT(13) | BIT(15) | BIT(16) | BIT(17) | BIT(18) | BIT(19) |
|
||||
BIT(20) | BIT(21) | BIT(22) | BIT(31),
|
||||
}, {
|
||||
.group = 1,
|
||||
.mask = BIT(30) | BIT(31),
|
||||
}, {
|
||||
.group = 0,
|
||||
.mask = BIT(16) | BIT(17),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct sirfsoc_padmux lcd_18bits_padmux = {
|
||||
.muxmask_counts = ARRAY_SIZE(lcd_18bits_muxmask),
|
||||
.muxmask = lcd_18bits_muxmask,
|
||||
.funcmask = BIT(4) | BIT(15),
|
||||
.funcval = 0,
|
||||
};
|
||||
|
||||
static const unsigned lcd_18bits_pins[] = { 16, 17, 62, 63, 65, 70, 71, 72, 73, 74, 75, 76, 77, 79, 80, 81, 82, 83,
|
||||
84, 85, 86, 95 };
|
||||
|
||||
static const struct sirfsoc_muxmask lcd_24bits_muxmask[] = {
|
||||
{
|
||||
.group = 2,
|
||||
.mask = BIT(1) | BIT(6) | BIT(7) | BIT(8) | BIT(9) | BIT(10) | BIT(11) |
|
||||
BIT(12) | BIT(13) | BIT(15) | BIT(16) | BIT(17) | BIT(18) | BIT(19) |
|
||||
BIT(20) | BIT(21) | BIT(22) | BIT(31),
|
||||
}, {
|
||||
.group = 1,
|
||||
.mask = BIT(30) | BIT(31),
|
||||
}, {
|
||||
.group = 0,
|
||||
.mask = BIT(16) | BIT(17) | BIT(18) | BIT(19) | BIT(20) | BIT(21) | BIT(22) | BIT(23),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct sirfsoc_padmux lcd_24bits_padmux = {
|
||||
.muxmask_counts = ARRAY_SIZE(lcd_24bits_muxmask),
|
||||
.muxmask = lcd_24bits_muxmask,
|
||||
.funcmask = BIT(4) | BIT(15),
|
||||
.funcval = 0,
|
||||
};
|
||||
|
||||
static const unsigned lcd_24bits_pins[] = { 16, 17, 18, 19, 20, 21, 22, 23, 62, 63, 65, 70, 71, 72, 73, 74, 75, 76, 77, 79,
|
||||
80, 81, 82, 83, 84, 85, 86, 95};
|
||||
|
||||
static const struct sirfsoc_muxmask lcdrom_muxmask[] = {
|
||||
{
|
||||
.group = 2,
|
||||
.mask = BIT(1) | BIT(6) | BIT(7) | BIT(8) | BIT(9) | BIT(10) | BIT(11) |
|
||||
BIT(12) | BIT(13) | BIT(15) | BIT(16) | BIT(17) | BIT(18) | BIT(19) |
|
||||
BIT(20) | BIT(21) | BIT(22) | BIT(31),
|
||||
}, {
|
||||
.group = 1,
|
||||
.mask = BIT(30) | BIT(31),
|
||||
}, {
|
||||
.group = 0,
|
||||
.mask = BIT(8),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct sirfsoc_padmux lcdrom_padmux = {
|
||||
.muxmask_counts = ARRAY_SIZE(lcdrom_muxmask),
|
||||
.muxmask = lcdrom_muxmask,
|
||||
.funcmask = BIT(4),
|
||||
.funcval = BIT(4),
|
||||
};
|
||||
|
||||
static const unsigned lcdrom_pins[] = { 8, 62, 63, 65, 70, 71, 72, 73, 74, 75, 76, 77, 79, 80, 81, 82, 83,
|
||||
84, 85, 86, 95};
|
||||
|
||||
static const struct sirfsoc_muxmask uart0_muxmask[] = {
|
||||
{
|
||||
.group = 0,
|
||||
.mask = BIT(12),
|
||||
}, {
|
||||
.group = 1,
|
||||
.mask = BIT(23),
|
||||
}, {
|
||||
.group = 2,
|
||||
.mask = BIT(4) | BIT(5),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct sirfsoc_padmux uart0_padmux = {
|
||||
.muxmask_counts = ARRAY_SIZE(uart0_muxmask),
|
||||
.muxmask = uart0_muxmask,
|
||||
.funcmask = BIT(9),
|
||||
.funcval = BIT(9),
|
||||
};
|
||||
|
||||
static const unsigned uart0_pins[] = { 12, 55, 68, 69 };
|
||||
|
||||
static const struct sirfsoc_muxmask uart0_nostreamctrl_muxmask[] = {
|
||||
{
|
||||
.group = 2,
|
||||
.mask = BIT(4) | BIT(5),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct sirfsoc_padmux uart0_nostreamctrl_padmux = {
|
||||
.muxmask_counts = ARRAY_SIZE(uart0_nostreamctrl_muxmask),
|
||||
.muxmask = uart0_nostreamctrl_muxmask,
|
||||
};
|
||||
|
||||
static const unsigned uart0_nostreamctrl_pins[] = { 68, 69 };
|
||||
|
||||
static const struct sirfsoc_muxmask uart1_muxmask[] = {
|
||||
{
|
||||
.group = 1,
|
||||
.mask = BIT(15) | BIT(17),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct sirfsoc_padmux uart1_padmux = {
|
||||
.muxmask_counts = ARRAY_SIZE(uart1_muxmask),
|
||||
.muxmask = uart1_muxmask,
|
||||
};
|
||||
|
||||
static const unsigned uart1_pins[] = { 47, 49 };
|
||||
|
||||
static const struct sirfsoc_muxmask uart2_muxmask[] = {
|
||||
{
|
||||
.group = 0,
|
||||
.mask = BIT(10) | BIT(14),
|
||||
}, {
|
||||
.group = 1,
|
||||
.mask = BIT(16) | BIT(18),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct sirfsoc_padmux uart2_padmux = {
|
||||
.muxmask_counts = ARRAY_SIZE(uart2_muxmask),
|
||||
.muxmask = uart2_muxmask,
|
||||
.funcmask = BIT(10),
|
||||
.funcval = BIT(10),
|
||||
};
|
||||
|
||||
static const unsigned uart2_pins[] = { 10, 14, 48, 50 };
|
||||
|
||||
static const struct sirfsoc_muxmask uart2_nostreamctrl_muxmask[] = {
|
||||
{
|
||||
.group = 1,
|
||||
.mask = BIT(16) | BIT(18),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct sirfsoc_padmux uart2_nostreamctrl_padmux = {
|
||||
.muxmask_counts = ARRAY_SIZE(uart2_nostreamctrl_muxmask),
|
||||
.muxmask = uart2_nostreamctrl_muxmask,
|
||||
};
|
||||
|
||||
static const unsigned uart2_nostreamctrl_pins[] = { 48, 50 };
|
||||
|
||||
static const struct sirfsoc_muxmask sdmmc3_muxmask[] = {
|
||||
{
|
||||
.group = 0,
|
||||
.mask = BIT(30) | BIT(31),
|
||||
}, {
|
||||
.group = 1,
|
||||
.mask = BIT(0) | BIT(1) | BIT(2) | BIT(3),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct sirfsoc_padmux sdmmc3_padmux = {
|
||||
.muxmask_counts = ARRAY_SIZE(sdmmc3_muxmask),
|
||||
.muxmask = sdmmc3_muxmask,
|
||||
.funcmask = BIT(7),
|
||||
.funcval = 0,
|
||||
};
|
||||
|
||||
static const unsigned sdmmc3_pins[] = { 30, 31, 32, 33, 34, 35 };
|
||||
|
||||
static const struct sirfsoc_muxmask spi0_muxmask[] = {
|
||||
{
|
||||
.group = 0,
|
||||
.mask = BIT(30),
|
||||
}, {
|
||||
.group = 1,
|
||||
.mask = BIT(0) | BIT(2) | BIT(3),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct sirfsoc_padmux spi0_padmux = {
|
||||
.muxmask_counts = ARRAY_SIZE(spi0_muxmask),
|
||||
.muxmask = spi0_muxmask,
|
||||
.funcmask = BIT(7),
|
||||
.funcval = BIT(7),
|
||||
};
|
||||
|
||||
static const unsigned spi0_pins[] = { 30, 32, 34, 35 };
|
||||
|
||||
static const struct sirfsoc_muxmask cko1_muxmask[] = {
|
||||
{
|
||||
.group = 1,
|
||||
.mask = BIT(10),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct sirfsoc_padmux cko1_padmux = {
|
||||
.muxmask_counts = ARRAY_SIZE(cko1_muxmask),
|
||||
.muxmask = cko1_muxmask,
|
||||
.funcmask = BIT(3),
|
||||
.funcval = 0,
|
||||
};
|
||||
|
||||
static const unsigned cko1_pins[] = { 42 };
|
||||
|
||||
static const struct sirfsoc_muxmask i2s_muxmask[] = {
|
||||
{
|
||||
.group = 1,
|
||||
.mask = BIT(10),
|
||||
}, {
|
||||
.group = 3,
|
||||
.mask = BIT(2) | BIT(3) | BIT(4) | BIT(5),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct sirfsoc_padmux i2s_padmux = {
|
||||
.muxmask_counts = ARRAY_SIZE(i2s_muxmask),
|
||||
.muxmask = i2s_muxmask,
|
||||
.funcmask = BIT(3),
|
||||
.funcval = BIT(3),
|
||||
};
|
||||
|
||||
static const unsigned i2s_pins[] = { 42, 98, 99, 100, 101 };
|
||||
|
||||
static const struct sirfsoc_muxmask i2s_no_din_muxmask[] = {
|
||||
{
|
||||
.group = 1,
|
||||
.mask = BIT(10),
|
||||
}, {
|
||||
.group = 3,
|
||||
.mask = BIT(2) | BIT(3) | BIT(4),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct sirfsoc_padmux i2s_no_din_padmux = {
|
||||
.muxmask_counts = ARRAY_SIZE(i2s_no_din_muxmask),
|
||||
.muxmask = i2s_no_din_muxmask,
|
||||
.funcmask = BIT(3),
|
||||
.funcval = BIT(3),
|
||||
};
|
||||
|
||||
static const unsigned i2s_no_din_pins[] = { 42, 98, 99, 100 };
|
||||
|
||||
static const struct sirfsoc_muxmask i2s_6chn_muxmask[] = {
|
||||
{
|
||||
.group = 1,
|
||||
.mask = BIT(10) | BIT(20) | BIT(23),
|
||||
}, {
|
||||
.group = 3,
|
||||
.mask = BIT(2) | BIT(3) | BIT(4) | BIT(5),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct sirfsoc_padmux i2s_6chn_padmux = {
|
||||
.muxmask_counts = ARRAY_SIZE(i2s_6chn_muxmask),
|
||||
.muxmask = i2s_6chn_muxmask,
|
||||
.funcmask = BIT(1) | BIT(3) | BIT(9),
|
||||
.funcval = BIT(1) | BIT(3) | BIT(9),
|
||||
};
|
||||
|
||||
static const unsigned i2s_6chn_pins[] = { 42, 52, 55, 98, 99, 100, 101 };
|
||||
|
||||
static const struct sirfsoc_muxmask ac97_muxmask[] = {
|
||||
{
|
||||
.group = 3,
|
||||
.mask = BIT(2) | BIT(3) | BIT(4) | BIT(5),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct sirfsoc_padmux ac97_padmux = {
|
||||
.muxmask_counts = ARRAY_SIZE(ac97_muxmask),
|
||||
.muxmask = ac97_muxmask,
|
||||
};
|
||||
|
||||
static const unsigned ac97_pins[] = { 98, 99, 100, 101 };
|
||||
|
||||
static const struct sirfsoc_muxmask spi1_muxmask[] = {
|
||||
{
|
||||
.group = 1,
|
||||
.mask = BIT(11) | BIT(12) | BIT(13) | BIT(14),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct sirfsoc_padmux spi1_padmux = {
|
||||
.muxmask_counts = ARRAY_SIZE(spi1_muxmask),
|
||||
.muxmask = spi1_muxmask,
|
||||
.funcmask = BIT(16),
|
||||
.funcval = 0,
|
||||
};
|
||||
|
||||
static const unsigned spi1_pins[] = { 43, 44, 45, 46 };
|
||||
|
||||
static const struct sirfsoc_muxmask sdmmc1_muxmask[] = {
|
||||
{
|
||||
.group = 2,
|
||||
.mask = BIT(2) | BIT(3),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct sirfsoc_padmux sdmmc1_padmux = {
|
||||
.muxmask_counts = ARRAY_SIZE(sdmmc1_muxmask),
|
||||
.muxmask = sdmmc1_muxmask,
|
||||
.funcmask = BIT(5),
|
||||
.funcval = BIT(5),
|
||||
};
|
||||
|
||||
static const unsigned sdmmc1_pins[] = { 66, 67 };
|
||||
|
||||
static const struct sirfsoc_muxmask gps_muxmask[] = {
|
||||
{
|
||||
.group = 0,
|
||||
.mask = BIT(24) | BIT(25) | BIT(26),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct sirfsoc_padmux gps_padmux = {
|
||||
.muxmask_counts = ARRAY_SIZE(gps_muxmask),
|
||||
.muxmask = gps_muxmask,
|
||||
.funcmask = BIT(13),
|
||||
.funcval = 0,
|
||||
};
|
||||
|
||||
static const unsigned gps_pins[] = { 24, 25, 26 };
|
||||
|
||||
static const struct sirfsoc_muxmask sdmmc5_muxmask[] = {
|
||||
{
|
||||
.group = 0,
|
||||
.mask = BIT(24) | BIT(25) | BIT(26),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct sirfsoc_padmux sdmmc5_padmux = {
|
||||
.muxmask_counts = ARRAY_SIZE(sdmmc5_muxmask),
|
||||
.muxmask = sdmmc5_muxmask,
|
||||
.funcmask = BIT(13),
|
||||
.funcval = BIT(13),
|
||||
};
|
||||
|
||||
static const unsigned sdmmc5_pins[] = { 24, 25, 26 };
|
||||
|
||||
static const struct sirfsoc_muxmask usp0_muxmask[] = {
|
||||
{
|
||||
.group = 1,
|
||||
.mask = BIT(19) | BIT(20) | BIT(21) | BIT(22),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct sirfsoc_padmux usp0_padmux = {
|
||||
.muxmask_counts = ARRAY_SIZE(usp0_muxmask),
|
||||
.muxmask = usp0_muxmask,
|
||||
.funcmask = BIT(1) | BIT(2) | BIT(9),
|
||||
.funcval = 0,
|
||||
};
|
||||
|
||||
static const unsigned usp0_pins[] = { 51, 52, 53, 54 };
|
||||
|
||||
static const struct sirfsoc_muxmask usp1_muxmask[] = {
|
||||
{
|
||||
.group = 0,
|
||||
.mask = BIT(15),
|
||||
}, {
|
||||
.group = 1,
|
||||
.mask = BIT(11) | BIT(12) | BIT(13) | BIT(14),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct sirfsoc_padmux usp1_padmux = {
|
||||
.muxmask_counts = ARRAY_SIZE(usp1_muxmask),
|
||||
.muxmask = usp1_muxmask,
|
||||
.funcmask = BIT(16),
|
||||
.funcval = BIT(16),
|
||||
};
|
||||
|
||||
static const unsigned usp1_pins[] = { 15, 43, 44, 45, 46 };
|
||||
|
||||
static const struct sirfsoc_muxmask nand_muxmask[] = {
|
||||
{
|
||||
.group = 2,
|
||||
.mask = BIT(2) | BIT(3) | BIT(28) | BIT(29) | BIT(30),
|
||||
}, {
|
||||
.group = 3,
|
||||
.mask = BIT(0) | BIT(1),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct sirfsoc_padmux nand_padmux = {
|
||||
.muxmask_counts = ARRAY_SIZE(nand_muxmask),
|
||||
.muxmask = nand_muxmask,
|
||||
.funcmask = BIT(5) | BIT(19),
|
||||
.funcval = 0,
|
||||
};
|
||||
|
||||
static const unsigned nand_pins[] = { 66, 67, 92, 93, 94, 96, 97 };
|
||||
|
||||
static const struct sirfsoc_muxmask sdmmc0_muxmask[] = {
|
||||
{
|
||||
.group = 3,
|
||||
.mask = BIT(1),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct sirfsoc_padmux sdmmc0_padmux = {
|
||||
.muxmask_counts = ARRAY_SIZE(sdmmc0_muxmask),
|
||||
.muxmask = sdmmc0_muxmask,
|
||||
.funcmask = BIT(5) | BIT(19),
|
||||
.funcval = BIT(19),
|
||||
};
|
||||
|
||||
static const unsigned sdmmc0_pins[] = { 97 };
|
||||
|
||||
static const struct sirfsoc_muxmask sdmmc2_muxmask[] = {
|
||||
{
|
||||
.group = 0,
|
||||
.mask = BIT(27) | BIT(28) | BIT(29),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct sirfsoc_padmux sdmmc2_padmux = {
|
||||
.muxmask_counts = ARRAY_SIZE(sdmmc2_muxmask),
|
||||
.muxmask = sdmmc2_muxmask,
|
||||
.funcmask = BIT(11),
|
||||
.funcval = 0,
|
||||
};
|
||||
|
||||
static const unsigned sdmmc2_pins[] = { 27, 28, 29 };
|
||||
|
||||
static const struct sirfsoc_muxmask sdmmc2_nowp_muxmask[] = {
|
||||
{
|
||||
.group = 0,
|
||||
.mask = BIT(27) | BIT(28),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct sirfsoc_padmux sdmmc2_nowp_padmux = {
|
||||
.muxmask_counts = ARRAY_SIZE(sdmmc2_nowp_muxmask),
|
||||
.muxmask = sdmmc2_nowp_muxmask,
|
||||
.funcmask = BIT(11),
|
||||
.funcval = 0,
|
||||
};
|
||||
|
||||
static const unsigned sdmmc2_nowp_pins[] = { 27, 28 };
|
||||
|
||||
static const struct sirfsoc_muxmask cko0_muxmask[] = {
|
||||
{
|
||||
.group = 2,
|
||||
.mask = BIT(14),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct sirfsoc_padmux cko0_padmux = {
|
||||
.muxmask_counts = ARRAY_SIZE(cko0_muxmask),
|
||||
.muxmask = cko0_muxmask,
|
||||
};
|
||||
|
||||
static const unsigned cko0_pins[] = { 78 };
|
||||
|
||||
static const struct sirfsoc_muxmask vip_muxmask[] = {
|
||||
{
|
||||
.group = 1,
|
||||
.mask = BIT(4) | BIT(5) | BIT(6) | BIT(8) | BIT(9)
|
||||
| BIT(24) | BIT(25) | BIT(26) | BIT(27) | BIT(28) |
|
||||
BIT(29),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct sirfsoc_padmux vip_padmux = {
|
||||
.muxmask_counts = ARRAY_SIZE(vip_muxmask),
|
||||
.muxmask = vip_muxmask,
|
||||
.funcmask = BIT(18),
|
||||
.funcval = BIT(18),
|
||||
};
|
||||
|
||||
static const unsigned vip_pins[] = { 36, 37, 38, 40, 41, 56, 57, 58, 59, 60, 61 };
|
||||
|
||||
static const struct sirfsoc_muxmask vip_noupli_muxmask[] = {
|
||||
{
|
||||
.group = 0,
|
||||
.mask = BIT(16) | BIT(17) | BIT(18) | BIT(19) | BIT(20)
|
||||
| BIT(21) | BIT(22) | BIT(23),
|
||||
}, {
|
||||
.group = 2,
|
||||
.mask = BIT(23) | BIT(24) | BIT(25),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct sirfsoc_padmux vip_noupli_padmux = {
|
||||
.muxmask_counts = ARRAY_SIZE(vip_noupli_muxmask),
|
||||
.muxmask = vip_noupli_muxmask,
|
||||
.funcmask = BIT(15),
|
||||
.funcval = BIT(15),
|
||||
};
|
||||
|
||||
static const unsigned vip_noupli_pins[] = { 16, 17, 18, 19, 20, 21, 22, 23, 87, 88, 89 };
|
||||
|
||||
static const struct sirfsoc_muxmask i2c0_muxmask[] = {
|
||||
{
|
||||
.group = 2,
|
||||
.mask = BIT(26) | BIT(27),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct sirfsoc_padmux i2c0_padmux = {
|
||||
.muxmask_counts = ARRAY_SIZE(i2c0_muxmask),
|
||||
.muxmask = i2c0_muxmask,
|
||||
};
|
||||
|
||||
static const unsigned i2c0_pins[] = { 90, 91 };
|
||||
|
||||
static const struct sirfsoc_muxmask i2c1_muxmask[] = {
|
||||
{
|
||||
.group = 0,
|
||||
.mask = BIT(13) | BIT(15),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct sirfsoc_padmux i2c1_padmux = {
|
||||
.muxmask_counts = ARRAY_SIZE(i2c1_muxmask),
|
||||
.muxmask = i2c1_muxmask,
|
||||
.funcmask = BIT(16),
|
||||
.funcval = 0,
|
||||
};
|
||||
|
||||
static const unsigned i2c1_pins[] = { 13, 15 };
|
||||
|
||||
static const struct sirfsoc_muxmask pwm0_muxmask[] = {
|
||||
{
|
||||
.group = 0,
|
||||
.mask = BIT(4),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct sirfsoc_padmux pwm0_padmux = {
|
||||
.muxmask_counts = ARRAY_SIZE(pwm0_muxmask),
|
||||
.muxmask = pwm0_muxmask,
|
||||
.funcmask = BIT(12),
|
||||
.funcval = 0,
|
||||
};
|
||||
|
||||
static const unsigned pwm0_pins[] = { 4 };
|
||||
|
||||
static const struct sirfsoc_muxmask pwm1_muxmask[] = {
|
||||
{
|
||||
.group = 0,
|
||||
.mask = BIT(5),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct sirfsoc_padmux pwm1_padmux = {
|
||||
.muxmask_counts = ARRAY_SIZE(pwm1_muxmask),
|
||||
.muxmask = pwm1_muxmask,
|
||||
};
|
||||
|
||||
static const unsigned pwm1_pins[] = { 5 };
|
||||
|
||||
static const struct sirfsoc_muxmask pwm2_muxmask[] = {
|
||||
{
|
||||
.group = 0,
|
||||
.mask = BIT(6),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct sirfsoc_padmux pwm2_padmux = {
|
||||
.muxmask_counts = ARRAY_SIZE(pwm2_muxmask),
|
||||
.muxmask = pwm2_muxmask,
|
||||
};
|
||||
|
||||
static const unsigned pwm2_pins[] = { 6 };
|
||||
|
||||
static const struct sirfsoc_muxmask pwm3_muxmask[] = {
|
||||
{
|
||||
.group = 0,
|
||||
.mask = BIT(7),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct sirfsoc_padmux pwm3_padmux = {
|
||||
.muxmask_counts = ARRAY_SIZE(pwm3_muxmask),
|
||||
.muxmask = pwm3_muxmask,
|
||||
};
|
||||
|
||||
static const unsigned pwm3_pins[] = { 7 };
|
||||
|
||||
static const struct sirfsoc_muxmask pwm4_muxmask[] = {
|
||||
{
|
||||
.group = 2,
|
||||
.mask = BIT(14),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct sirfsoc_padmux pwm4_padmux = {
|
||||
.muxmask_counts = ARRAY_SIZE(pwm4_muxmask),
|
||||
.muxmask = pwm4_muxmask,
|
||||
};
|
||||
|
||||
static const unsigned pwm4_pins[] = { 78 };
|
||||
|
||||
static const struct sirfsoc_muxmask warm_rst_muxmask[] = {
|
||||
{
|
||||
.group = 0,
|
||||
.mask = BIT(8),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct sirfsoc_padmux warm_rst_padmux = {
|
||||
.muxmask_counts = ARRAY_SIZE(warm_rst_muxmask),
|
||||
.muxmask = warm_rst_muxmask,
|
||||
.funcmask = BIT(4),
|
||||
.funcval = 0,
|
||||
};
|
||||
|
||||
static const unsigned warm_rst_pins[] = { 8 };
|
||||
|
||||
static const struct sirfsoc_muxmask usb0_upli_drvbus_muxmask[] = {
|
||||
{
|
||||
.group = 1,
|
||||
.mask = BIT(4) | BIT(5) | BIT(6) | BIT(7) | BIT(8)
|
||||
| BIT(9) | BIT(24) | BIT(25) | BIT(26) |
|
||||
BIT(27) | BIT(28) | BIT(29),
|
||||
},
|
||||
};
|
||||
static const struct sirfsoc_padmux usb0_upli_drvbus_padmux = {
|
||||
.muxmask_counts = ARRAY_SIZE(usb0_upli_drvbus_muxmask),
|
||||
.muxmask = usb0_upli_drvbus_muxmask,
|
||||
.funcmask = BIT(18),
|
||||
.funcval = 0,
|
||||
};
|
||||
|
||||
static const unsigned usb0_upli_drvbus_pins[] = { 36, 37, 38, 39, 40, 41, 56, 57, 58, 59, 60, 61 };
|
||||
|
||||
static const struct sirfsoc_muxmask usb1_utmi_drvbus_muxmask[] = {
|
||||
{
|
||||
.group = 0,
|
||||
.mask = BIT(28),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct sirfsoc_padmux usb1_utmi_drvbus_padmux = {
|
||||
.muxmask_counts = ARRAY_SIZE(usb1_utmi_drvbus_muxmask),
|
||||
.muxmask = usb1_utmi_drvbus_muxmask,
|
||||
.funcmask = BIT(11),
|
||||
.funcval = BIT(11), /* refer to PAD_UTMI_DRVVBUS1_ENABLE */
|
||||
};
|
||||
|
||||
static const unsigned usb1_utmi_drvbus_pins[] = { 28 };
|
||||
|
||||
static const struct sirfsoc_muxmask pulse_count_muxmask[] = {
|
||||
{
|
||||
.group = 0,
|
||||
.mask = BIT(9) | BIT(10) | BIT(11),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct sirfsoc_padmux pulse_count_padmux = {
|
||||
.muxmask_counts = ARRAY_SIZE(pulse_count_muxmask),
|
||||
.muxmask = pulse_count_muxmask,
|
||||
};
|
||||
|
||||
static const unsigned pulse_count_pins[] = { 9, 10, 11 };
|
||||
|
||||
static const struct sirfsoc_pin_group sirfsoc_pin_groups[] = {
|
||||
SIRFSOC_PIN_GROUP("lcd_16bitsgrp", lcd_16bits_pins),
|
||||
SIRFSOC_PIN_GROUP("lcd_18bitsgrp", lcd_18bits_pins),
|
||||
SIRFSOC_PIN_GROUP("lcd_24bitsgrp", lcd_24bits_pins),
|
||||
SIRFSOC_PIN_GROUP("lcdrom_grp", lcdrom_pins),
|
||||
SIRFSOC_PIN_GROUP("uart0grp", uart0_pins),
|
||||
SIRFSOC_PIN_GROUP("uart1grp", uart1_pins),
|
||||
SIRFSOC_PIN_GROUP("uart2grp", uart2_pins),
|
||||
SIRFSOC_PIN_GROUP("uart2_nostreamctrlgrp", uart2_nostreamctrl_pins),
|
||||
SIRFSOC_PIN_GROUP("usp0grp", usp0_pins),
|
||||
SIRFSOC_PIN_GROUP("usp1grp", usp1_pins),
|
||||
SIRFSOC_PIN_GROUP("i2c0grp", i2c0_pins),
|
||||
SIRFSOC_PIN_GROUP("i2c1grp", i2c1_pins),
|
||||
SIRFSOC_PIN_GROUP("pwm0grp", pwm0_pins),
|
||||
SIRFSOC_PIN_GROUP("pwm1grp", pwm1_pins),
|
||||
SIRFSOC_PIN_GROUP("pwm2grp", pwm2_pins),
|
||||
SIRFSOC_PIN_GROUP("pwm3grp", pwm3_pins),
|
||||
SIRFSOC_PIN_GROUP("pwm4grp", pwm4_pins),
|
||||
SIRFSOC_PIN_GROUP("vipgrp", vip_pins),
|
||||
SIRFSOC_PIN_GROUP("vip_noupligrp", vip_noupli_pins),
|
||||
SIRFSOC_PIN_GROUP("warm_rstgrp", warm_rst_pins),
|
||||
SIRFSOC_PIN_GROUP("cko0grp", cko0_pins),
|
||||
SIRFSOC_PIN_GROUP("cko1grp", cko1_pins),
|
||||
SIRFSOC_PIN_GROUP("sdmmc0grp", sdmmc0_pins),
|
||||
SIRFSOC_PIN_GROUP("sdmmc1grp", sdmmc1_pins),
|
||||
SIRFSOC_PIN_GROUP("sdmmc2grp", sdmmc2_pins),
|
||||
SIRFSOC_PIN_GROUP("sdmmc2_nowpgrp", sdmmc2_nowp_pins),
|
||||
SIRFSOC_PIN_GROUP("sdmmc3grp", sdmmc3_pins),
|
||||
SIRFSOC_PIN_GROUP("sdmmc5grp", sdmmc5_pins),
|
||||
SIRFSOC_PIN_GROUP("usb0_upli_drvbusgrp", usb0_upli_drvbus_pins),
|
||||
SIRFSOC_PIN_GROUP("usb1_utmi_drvbusgrp", usb1_utmi_drvbus_pins),
|
||||
SIRFSOC_PIN_GROUP("pulse_countgrp", pulse_count_pins),
|
||||
SIRFSOC_PIN_GROUP("i2sgrp", i2s_pins),
|
||||
SIRFSOC_PIN_GROUP("i2s_no_dingrp", i2s_no_din_pins),
|
||||
SIRFSOC_PIN_GROUP("i2s_6chngrp", i2s_6chn_pins),
|
||||
SIRFSOC_PIN_GROUP("ac97grp", ac97_pins),
|
||||
SIRFSOC_PIN_GROUP("nandgrp", nand_pins),
|
||||
SIRFSOC_PIN_GROUP("spi0grp", spi0_pins),
|
||||
SIRFSOC_PIN_GROUP("spi1grp", spi1_pins),
|
||||
SIRFSOC_PIN_GROUP("gpsgrp", gps_pins),
|
||||
};
|
||||
|
||||
static const char * const lcd_16bitsgrp[] = { "lcd_16bitsgrp" };
|
||||
static const char * const lcd_18bitsgrp[] = { "lcd_18bitsgrp" };
|
||||
static const char * const lcd_24bitsgrp[] = { "lcd_24bitsgrp" };
|
||||
static const char * const lcdromgrp[] = { "lcdromgrp" };
|
||||
static const char * const uart0grp[] = { "uart0grp" };
|
||||
static const char * const uart1grp[] = { "uart1grp" };
|
||||
static const char * const uart2grp[] = { "uart2grp" };
|
||||
static const char * const uart2_nostreamctrlgrp[] = { "uart2_nostreamctrlgrp" };
|
||||
static const char * const usp0grp[] = { "usp0grp" };
|
||||
static const char * const usp1grp[] = { "usp1grp" };
|
||||
static const char * const i2c0grp[] = { "i2c0grp" };
|
||||
static const char * const i2c1grp[] = { "i2c1grp" };
|
||||
static const char * const pwm0grp[] = { "pwm0grp" };
|
||||
static const char * const pwm1grp[] = { "pwm1grp" };
|
||||
static const char * const pwm2grp[] = { "pwm2grp" };
|
||||
static const char * const pwm3grp[] = { "pwm3grp" };
|
||||
static const char * const pwm4grp[] = { "pwm4grp" };
|
||||
static const char * const vipgrp[] = { "vipgrp" };
|
||||
static const char * const vip_noupligrp[] = { "vip_noupligrp" };
|
||||
static const char * const warm_rstgrp[] = { "warm_rstgrp" };
|
||||
static const char * const cko0grp[] = { "cko0grp" };
|
||||
static const char * const cko1grp[] = { "cko1grp" };
|
||||
static const char * const sdmmc0grp[] = { "sdmmc0grp" };
|
||||
static const char * const sdmmc1grp[] = { "sdmmc1grp" };
|
||||
static const char * const sdmmc2grp[] = { "sdmmc2grp" };
|
||||
static const char * const sdmmc3grp[] = { "sdmmc3grp" };
|
||||
static const char * const sdmmc5grp[] = { "sdmmc5grp" };
|
||||
static const char * const sdmmc2_nowpgrp[] = { "sdmmc2_nowpgrp" };
|
||||
static const char * const usb0_upli_drvbusgrp[] = { "usb0_upli_drvbusgrp" };
|
||||
static const char * const usb1_utmi_drvbusgrp[] = { "usb1_utmi_drvbusgrp" };
|
||||
static const char * const pulse_countgrp[] = { "pulse_countgrp" };
|
||||
static const char * const i2sgrp[] = { "i2sgrp" };
|
||||
static const char * const i2s_no_dingrp[] = { "i2s_no_dingrp" };
|
||||
static const char * const i2s_6chngrp[] = { "i2s_6chngrp" };
|
||||
static const char * const ac97grp[] = { "ac97grp" };
|
||||
static const char * const nandgrp[] = { "nandgrp" };
|
||||
static const char * const spi0grp[] = { "spi0grp" };
|
||||
static const char * const spi1grp[] = { "spi1grp" };
|
||||
static const char * const gpsgrp[] = { "gpsgrp" };
|
||||
|
||||
static const struct sirfsoc_pmx_func sirfsoc_pmx_functions[] = {
|
||||
SIRFSOC_PMX_FUNCTION("lcd_16bits", lcd_16bitsgrp, lcd_16bits_padmux),
|
||||
SIRFSOC_PMX_FUNCTION("lcd_18bits", lcd_18bitsgrp, lcd_18bits_padmux),
|
||||
SIRFSOC_PMX_FUNCTION("lcd_24bits", lcd_24bitsgrp, lcd_24bits_padmux),
|
||||
SIRFSOC_PMX_FUNCTION("lcdrom", lcdromgrp, lcdrom_padmux),
|
||||
SIRFSOC_PMX_FUNCTION("uart0", uart0grp, uart0_padmux),
|
||||
SIRFSOC_PMX_FUNCTION("uart1", uart1grp, uart1_padmux),
|
||||
SIRFSOC_PMX_FUNCTION("uart2", uart2grp, uart2_padmux),
|
||||
SIRFSOC_PMX_FUNCTION("uart2_nostreamctrl", uart2_nostreamctrlgrp, uart2_nostreamctrl_padmux),
|
||||
SIRFSOC_PMX_FUNCTION("usp0", usp0grp, usp0_padmux),
|
||||
SIRFSOC_PMX_FUNCTION("usp1", usp1grp, usp1_padmux),
|
||||
SIRFSOC_PMX_FUNCTION("i2c0", i2c0grp, i2c0_padmux),
|
||||
SIRFSOC_PMX_FUNCTION("i2c1", i2c1grp, i2c1_padmux),
|
||||
SIRFSOC_PMX_FUNCTION("pwm0", pwm0grp, pwm0_padmux),
|
||||
SIRFSOC_PMX_FUNCTION("pwm1", pwm1grp, pwm1_padmux),
|
||||
SIRFSOC_PMX_FUNCTION("pwm2", pwm2grp, pwm2_padmux),
|
||||
SIRFSOC_PMX_FUNCTION("pwm3", pwm3grp, pwm3_padmux),
|
||||
SIRFSOC_PMX_FUNCTION("pwm4", pwm4grp, pwm4_padmux),
|
||||
SIRFSOC_PMX_FUNCTION("vip", vipgrp, vip_padmux),
|
||||
SIRFSOC_PMX_FUNCTION("vip_noupli", vip_noupligrp, vip_noupli_padmux),
|
||||
SIRFSOC_PMX_FUNCTION("warm_rst", warm_rstgrp, warm_rst_padmux),
|
||||
SIRFSOC_PMX_FUNCTION("cko0", cko0grp, cko0_padmux),
|
||||
SIRFSOC_PMX_FUNCTION("cko1", cko1grp, cko1_padmux),
|
||||
SIRFSOC_PMX_FUNCTION("sdmmc0", sdmmc0grp, sdmmc0_padmux),
|
||||
SIRFSOC_PMX_FUNCTION("sdmmc1", sdmmc1grp, sdmmc1_padmux),
|
||||
SIRFSOC_PMX_FUNCTION("sdmmc2", sdmmc2grp, sdmmc2_padmux),
|
||||
SIRFSOC_PMX_FUNCTION("sdmmc3", sdmmc3grp, sdmmc3_padmux),
|
||||
SIRFSOC_PMX_FUNCTION("sdmmc5", sdmmc5grp, sdmmc5_padmux),
|
||||
SIRFSOC_PMX_FUNCTION("sdmmc2_nowp", sdmmc2_nowpgrp, sdmmc2_nowp_padmux),
|
||||
SIRFSOC_PMX_FUNCTION("usb0_upli_drvbus", usb0_upli_drvbusgrp, usb0_upli_drvbus_padmux),
|
||||
SIRFSOC_PMX_FUNCTION("usb1_utmi_drvbus", usb1_utmi_drvbusgrp, usb1_utmi_drvbus_padmux),
|
||||
SIRFSOC_PMX_FUNCTION("pulse_count", pulse_countgrp, pulse_count_padmux),
|
||||
SIRFSOC_PMX_FUNCTION("i2s", i2sgrp, i2s_padmux),
|
||||
SIRFSOC_PMX_FUNCTION("i2s_no_din", i2s_no_dingrp, i2s_no_din_padmux),
|
||||
SIRFSOC_PMX_FUNCTION("i2s_6chn", i2s_6chngrp, i2s_6chn_padmux),
|
||||
SIRFSOC_PMX_FUNCTION("ac97", ac97grp, ac97_padmux),
|
||||
SIRFSOC_PMX_FUNCTION("nand", nandgrp, nand_padmux),
|
||||
SIRFSOC_PMX_FUNCTION("spi0", spi0grp, spi0_padmux),
|
||||
SIRFSOC_PMX_FUNCTION("spi1", spi1grp, spi1_padmux),
|
||||
SIRFSOC_PMX_FUNCTION("gps", gpsgrp, gps_padmux),
|
||||
};
|
||||
|
||||
struct sirfsoc_pinctrl_data atlas6_pinctrl_data = {
|
||||
(struct pinctrl_pin_desc *)sirfsoc_pads,
|
||||
ARRAY_SIZE(sirfsoc_pads),
|
||||
(struct sirfsoc_pin_group *)sirfsoc_pin_groups,
|
||||
ARRAY_SIZE(sirfsoc_pin_groups),
|
||||
(struct sirfsoc_pmx_func *)sirfsoc_pmx_functions,
|
||||
ARRAY_SIZE(sirfsoc_pmx_functions),
|
||||
};
|
||||
|
File diff suppressed because it is too large
Load Diff
929
drivers/pinctrl/sirf/pinctrl-sirf.c
Normal file
929
drivers/pinctrl/sirf/pinctrl-sirf.c
Normal file
|
@ -0,0 +1,929 @@
|
|||
/*
|
||||
* pinmux driver for CSR SiRFprimaII
|
||||
*
|
||||
* Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
|
||||
*
|
||||
* Licensed under GPLv2 or later.
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/irqdomain.h>
|
||||
#include <linux/irqchip/chained_irq.h>
|
||||
#include <linux/pinctrl/pinctrl.h>
|
||||
#include <linux/pinctrl/pinmux.h>
|
||||
#include <linux/pinctrl/consumer.h>
|
||||
#include <linux/pinctrl/machine.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <asm/mach/irq.h>
|
||||
|
||||
#include "pinctrl-sirf.h"
|
||||
|
||||
#define DRIVER_NAME "pinmux-sirf"
|
||||
|
||||
struct sirfsoc_gpio_bank {
|
||||
struct of_mm_gpio_chip chip;
|
||||
struct irq_domain *domain;
|
||||
int id;
|
||||
int parent_irq;
|
||||
spinlock_t lock;
|
||||
bool is_marco; /* for marco, some registers are different with prima2 */
|
||||
};
|
||||
|
||||
static struct sirfsoc_gpio_bank sgpio_bank[SIRFSOC_GPIO_NO_OF_BANKS];
|
||||
static DEFINE_SPINLOCK(sgpio_lock);
|
||||
|
||||
static struct sirfsoc_pin_group *sirfsoc_pin_groups;
|
||||
static int sirfsoc_pingrp_cnt;
|
||||
|
||||
static int sirfsoc_get_groups_count(struct pinctrl_dev *pctldev)
|
||||
{
|
||||
return sirfsoc_pingrp_cnt;
|
||||
}
|
||||
|
||||
static const char *sirfsoc_get_group_name(struct pinctrl_dev *pctldev,
|
||||
unsigned selector)
|
||||
{
|
||||
return sirfsoc_pin_groups[selector].name;
|
||||
}
|
||||
|
||||
static int sirfsoc_get_group_pins(struct pinctrl_dev *pctldev, unsigned selector,
|
||||
const unsigned **pins,
|
||||
unsigned *num_pins)
|
||||
{
|
||||
*pins = sirfsoc_pin_groups[selector].pins;
|
||||
*num_pins = sirfsoc_pin_groups[selector].num_pins;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void sirfsoc_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
|
||||
unsigned offset)
|
||||
{
|
||||
seq_printf(s, " " DRIVER_NAME);
|
||||
}
|
||||
|
||||
static int sirfsoc_dt_node_to_map(struct pinctrl_dev *pctldev,
|
||||
struct device_node *np_config,
|
||||
struct pinctrl_map **map, unsigned *num_maps)
|
||||
{
|
||||
struct sirfsoc_pmx *spmx = pinctrl_dev_get_drvdata(pctldev);
|
||||
struct device_node *np;
|
||||
struct property *prop;
|
||||
const char *function, *group;
|
||||
int ret, index = 0, count = 0;
|
||||
|
||||
/* calculate number of maps required */
|
||||
for_each_child_of_node(np_config, np) {
|
||||
ret = of_property_read_string(np, "sirf,function", &function);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = of_property_count_strings(np, "sirf,pins");
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
count += ret;
|
||||
}
|
||||
|
||||
if (!count) {
|
||||
dev_err(spmx->dev, "No child nodes passed via DT\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
*map = kzalloc(sizeof(**map) * count, GFP_KERNEL);
|
||||
if (!*map)
|
||||
return -ENOMEM;
|
||||
|
||||
for_each_child_of_node(np_config, np) {
|
||||
of_property_read_string(np, "sirf,function", &function);
|
||||
of_property_for_each_string(np, "sirf,pins", prop, group) {
|
||||
(*map)[index].type = PIN_MAP_TYPE_MUX_GROUP;
|
||||
(*map)[index].data.mux.group = group;
|
||||
(*map)[index].data.mux.function = function;
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
*num_maps = count;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void sirfsoc_dt_free_map(struct pinctrl_dev *pctldev,
|
||||
struct pinctrl_map *map, unsigned num_maps)
|
||||
{
|
||||
kfree(map);
|
||||
}
|
||||
|
||||
static struct pinctrl_ops sirfsoc_pctrl_ops = {
|
||||
.get_groups_count = sirfsoc_get_groups_count,
|
||||
.get_group_name = sirfsoc_get_group_name,
|
||||
.get_group_pins = sirfsoc_get_group_pins,
|
||||
.pin_dbg_show = sirfsoc_pin_dbg_show,
|
||||
.dt_node_to_map = sirfsoc_dt_node_to_map,
|
||||
.dt_free_map = sirfsoc_dt_free_map,
|
||||
};
|
||||
|
||||
static struct sirfsoc_pmx_func *sirfsoc_pmx_functions;
|
||||
static int sirfsoc_pmxfunc_cnt;
|
||||
|
||||
static void sirfsoc_pinmux_endisable(struct sirfsoc_pmx *spmx, unsigned selector,
|
||||
bool enable)
|
||||
{
|
||||
int i;
|
||||
const struct sirfsoc_padmux *mux = sirfsoc_pmx_functions[selector].padmux;
|
||||
const struct sirfsoc_muxmask *mask = mux->muxmask;
|
||||
|
||||
for (i = 0; i < mux->muxmask_counts; i++) {
|
||||
u32 muxval;
|
||||
if (!spmx->is_marco) {
|
||||
muxval = readl(spmx->gpio_virtbase + SIRFSOC_GPIO_PAD_EN(mask[i].group));
|
||||
if (enable)
|
||||
muxval = muxval & ~mask[i].mask;
|
||||
else
|
||||
muxval = muxval | mask[i].mask;
|
||||
writel(muxval, spmx->gpio_virtbase + SIRFSOC_GPIO_PAD_EN(mask[i].group));
|
||||
} else {
|
||||
if (enable)
|
||||
writel(mask[i].mask, spmx->gpio_virtbase +
|
||||
SIRFSOC_GPIO_PAD_EN_CLR(mask[i].group));
|
||||
else
|
||||
writel(mask[i].mask, spmx->gpio_virtbase +
|
||||
SIRFSOC_GPIO_PAD_EN(mask[i].group));
|
||||
}
|
||||
}
|
||||
|
||||
if (mux->funcmask && enable) {
|
||||
u32 func_en_val;
|
||||
func_en_val =
|
||||
readl(spmx->rsc_virtbase + SIRFSOC_RSC_PIN_MUX);
|
||||
func_en_val =
|
||||
(func_en_val & ~mux->funcmask) | (mux->
|
||||
funcval);
|
||||
writel(func_en_val, spmx->rsc_virtbase + SIRFSOC_RSC_PIN_MUX);
|
||||
}
|
||||
}
|
||||
|
||||
static int sirfsoc_pinmux_enable(struct pinctrl_dev *pmxdev, unsigned selector,
|
||||
unsigned group)
|
||||
{
|
||||
struct sirfsoc_pmx *spmx;
|
||||
|
||||
spmx = pinctrl_dev_get_drvdata(pmxdev);
|
||||
sirfsoc_pinmux_endisable(spmx, selector, true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void sirfsoc_pinmux_disable(struct pinctrl_dev *pmxdev, unsigned selector,
|
||||
unsigned group)
|
||||
{
|
||||
struct sirfsoc_pmx *spmx;
|
||||
|
||||
spmx = pinctrl_dev_get_drvdata(pmxdev);
|
||||
sirfsoc_pinmux_endisable(spmx, selector, false);
|
||||
}
|
||||
|
||||
static int sirfsoc_pinmux_get_funcs_count(struct pinctrl_dev *pmxdev)
|
||||
{
|
||||
return sirfsoc_pmxfunc_cnt;
|
||||
}
|
||||
|
||||
static const char *sirfsoc_pinmux_get_func_name(struct pinctrl_dev *pctldev,
|
||||
unsigned selector)
|
||||
{
|
||||
return sirfsoc_pmx_functions[selector].name;
|
||||
}
|
||||
|
||||
static int sirfsoc_pinmux_get_groups(struct pinctrl_dev *pctldev, unsigned selector,
|
||||
const char * const **groups,
|
||||
unsigned * const num_groups)
|
||||
{
|
||||
*groups = sirfsoc_pmx_functions[selector].groups;
|
||||
*num_groups = sirfsoc_pmx_functions[selector].num_groups;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sirfsoc_pinmux_request_gpio(struct pinctrl_dev *pmxdev,
|
||||
struct pinctrl_gpio_range *range, unsigned offset)
|
||||
{
|
||||
struct sirfsoc_pmx *spmx;
|
||||
|
||||
int group = range->id;
|
||||
|
||||
u32 muxval;
|
||||
|
||||
spmx = pinctrl_dev_get_drvdata(pmxdev);
|
||||
|
||||
if (!spmx->is_marco) {
|
||||
muxval = readl(spmx->gpio_virtbase + SIRFSOC_GPIO_PAD_EN(group));
|
||||
muxval = muxval | (1 << (offset - range->pin_base));
|
||||
writel(muxval, spmx->gpio_virtbase + SIRFSOC_GPIO_PAD_EN(group));
|
||||
} else {
|
||||
writel(1 << (offset - range->pin_base), spmx->gpio_virtbase +
|
||||
SIRFSOC_GPIO_PAD_EN(group));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct pinmux_ops sirfsoc_pinmux_ops = {
|
||||
.enable = sirfsoc_pinmux_enable,
|
||||
.disable = sirfsoc_pinmux_disable,
|
||||
.get_functions_count = sirfsoc_pinmux_get_funcs_count,
|
||||
.get_function_name = sirfsoc_pinmux_get_func_name,
|
||||
.get_function_groups = sirfsoc_pinmux_get_groups,
|
||||
.gpio_request_enable = sirfsoc_pinmux_request_gpio,
|
||||
};
|
||||
|
||||
static struct pinctrl_desc sirfsoc_pinmux_desc = {
|
||||
.name = DRIVER_NAME,
|
||||
.pctlops = &sirfsoc_pctrl_ops,
|
||||
.pmxops = &sirfsoc_pinmux_ops,
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
/*
|
||||
* Todo: bind irq_chip to every pinctrl_gpio_range
|
||||
*/
|
||||
static struct pinctrl_gpio_range sirfsoc_gpio_ranges[] = {
|
||||
{
|
||||
.name = "sirfsoc-gpio*",
|
||||
.id = 0,
|
||||
.base = 0,
|
||||
.pin_base = 0,
|
||||
.npins = 32,
|
||||
}, {
|
||||
.name = "sirfsoc-gpio*",
|
||||
.id = 1,
|
||||
.base = 32,
|
||||
.pin_base = 32,
|
||||
.npins = 32,
|
||||
}, {
|
||||
.name = "sirfsoc-gpio*",
|
||||
.id = 2,
|
||||
.base = 64,
|
||||
.pin_base = 64,
|
||||
.npins = 32,
|
||||
}, {
|
||||
.name = "sirfsoc-gpio*",
|
||||
.id = 3,
|
||||
.base = 96,
|
||||
.pin_base = 96,
|
||||
.npins = 19,
|
||||
},
|
||||
};
|
||||
|
||||
static void __iomem *sirfsoc_rsc_of_iomap(void)
|
||||
{
|
||||
const struct of_device_id rsc_ids[] = {
|
||||
{ .compatible = "sirf,prima2-rsc" },
|
||||
{ .compatible = "sirf,marco-rsc" },
|
||||
{}
|
||||
};
|
||||
struct device_node *np;
|
||||
|
||||
np = of_find_matching_node(NULL, rsc_ids);
|
||||
if (!np)
|
||||
panic("unable to find compatible rsc node in dtb\n");
|
||||
|
||||
return of_iomap(np, 0);
|
||||
}
|
||||
|
||||
static int sirfsoc_gpio_of_xlate(struct gpio_chip *gc,
|
||||
const struct of_phandle_args *gpiospec,
|
||||
u32 *flags)
|
||||
{
|
||||
if (gpiospec->args[0] > SIRFSOC_GPIO_NO_OF_BANKS * SIRFSOC_GPIO_BANK_SIZE)
|
||||
return -EINVAL;
|
||||
|
||||
if (gc != &sgpio_bank[gpiospec->args[0] / SIRFSOC_GPIO_BANK_SIZE].chip.gc)
|
||||
return -EINVAL;
|
||||
|
||||
if (flags)
|
||||
*flags = gpiospec->args[1];
|
||||
|
||||
return gpiospec->args[0] % SIRFSOC_GPIO_BANK_SIZE;
|
||||
}
|
||||
|
||||
static const struct of_device_id pinmux_ids[] = {
|
||||
{ .compatible = "sirf,prima2-pinctrl", .data = &prima2_pinctrl_data, },
|
||||
{ .compatible = "sirf,atlas6-pinctrl", .data = &atlas6_pinctrl_data, },
|
||||
{ .compatible = "sirf,marco-pinctrl", .data = &prima2_pinctrl_data, },
|
||||
{}
|
||||
};
|
||||
|
||||
static int sirfsoc_pinmux_probe(struct platform_device *pdev)
|
||||
{
|
||||
int ret;
|
||||
struct sirfsoc_pmx *spmx;
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
const struct sirfsoc_pinctrl_data *pdata;
|
||||
int i;
|
||||
|
||||
/* Create state holders etc for this driver */
|
||||
spmx = devm_kzalloc(&pdev->dev, sizeof(*spmx), GFP_KERNEL);
|
||||
if (!spmx)
|
||||
return -ENOMEM;
|
||||
|
||||
spmx->dev = &pdev->dev;
|
||||
|
||||
platform_set_drvdata(pdev, spmx);
|
||||
|
||||
spmx->gpio_virtbase = of_iomap(np, 0);
|
||||
if (!spmx->gpio_virtbase) {
|
||||
dev_err(&pdev->dev, "can't map gpio registers\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
spmx->rsc_virtbase = sirfsoc_rsc_of_iomap();
|
||||
if (!spmx->rsc_virtbase) {
|
||||
ret = -ENOMEM;
|
||||
dev_err(&pdev->dev, "can't map rsc registers\n");
|
||||
goto out_no_rsc_remap;
|
||||
}
|
||||
|
||||
if (of_device_is_compatible(np, "sirf,marco-pinctrl"))
|
||||
spmx->is_marco = 1;
|
||||
|
||||
pdata = of_match_node(pinmux_ids, np)->data;
|
||||
sirfsoc_pin_groups = pdata->grps;
|
||||
sirfsoc_pingrp_cnt = pdata->grps_cnt;
|
||||
sirfsoc_pmx_functions = pdata->funcs;
|
||||
sirfsoc_pmxfunc_cnt = pdata->funcs_cnt;
|
||||
sirfsoc_pinmux_desc.pins = pdata->pads;
|
||||
sirfsoc_pinmux_desc.npins = pdata->pads_cnt;
|
||||
|
||||
|
||||
/* Now register the pin controller and all pins it handles */
|
||||
spmx->pmx = pinctrl_register(&sirfsoc_pinmux_desc, &pdev->dev, spmx);
|
||||
if (!spmx->pmx) {
|
||||
dev_err(&pdev->dev, "could not register SIRFSOC pinmux driver\n");
|
||||
ret = -EINVAL;
|
||||
goto out_no_pmx;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(sirfsoc_gpio_ranges); i++) {
|
||||
sirfsoc_gpio_ranges[i].gc = &sgpio_bank[i].chip.gc;
|
||||
pinctrl_add_gpio_range(spmx->pmx, &sirfsoc_gpio_ranges[i]);
|
||||
}
|
||||
|
||||
dev_info(&pdev->dev, "initialized SIRFSOC pinmux driver\n");
|
||||
|
||||
return 0;
|
||||
|
||||
out_no_pmx:
|
||||
iounmap(spmx->rsc_virtbase);
|
||||
out_no_rsc_remap:
|
||||
iounmap(spmx->gpio_virtbase);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int sirfsoc_pinmux_suspend_noirq(struct device *dev)
|
||||
{
|
||||
int i, j;
|
||||
struct sirfsoc_pmx *spmx = dev_get_drvdata(dev);
|
||||
|
||||
for (i = 0; i < SIRFSOC_GPIO_NO_OF_BANKS; i++) {
|
||||
for (j = 0; j < SIRFSOC_GPIO_BANK_SIZE; j++) {
|
||||
spmx->gpio_regs[i][j] = readl(spmx->gpio_virtbase +
|
||||
SIRFSOC_GPIO_CTRL(i, j));
|
||||
}
|
||||
spmx->ints_regs[i] = readl(spmx->gpio_virtbase +
|
||||
SIRFSOC_GPIO_INT_STATUS(i));
|
||||
spmx->paden_regs[i] = readl(spmx->gpio_virtbase +
|
||||
SIRFSOC_GPIO_PAD_EN(i));
|
||||
}
|
||||
spmx->dspen_regs = readl(spmx->gpio_virtbase + SIRFSOC_GPIO_DSP_EN0);
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
spmx->rsc_regs[i] = readl(spmx->rsc_virtbase + 4 * i);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sirfsoc_pinmux_resume_noirq(struct device *dev)
|
||||
{
|
||||
int i, j;
|
||||
struct sirfsoc_pmx *spmx = dev_get_drvdata(dev);
|
||||
|
||||
for (i = 0; i < SIRFSOC_GPIO_NO_OF_BANKS; i++) {
|
||||
for (j = 0; j < SIRFSOC_GPIO_BANK_SIZE; j++) {
|
||||
writel(spmx->gpio_regs[i][j], spmx->gpio_virtbase +
|
||||
SIRFSOC_GPIO_CTRL(i, j));
|
||||
}
|
||||
writel(spmx->ints_regs[i], spmx->gpio_virtbase +
|
||||
SIRFSOC_GPIO_INT_STATUS(i));
|
||||
writel(spmx->paden_regs[i], spmx->gpio_virtbase +
|
||||
SIRFSOC_GPIO_PAD_EN(i));
|
||||
}
|
||||
writel(spmx->dspen_regs, spmx->gpio_virtbase + SIRFSOC_GPIO_DSP_EN0);
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
writel(spmx->rsc_regs[i], spmx->rsc_virtbase + 4 * i);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops sirfsoc_pinmux_pm_ops = {
|
||||
.suspend_noirq = sirfsoc_pinmux_suspend_noirq,
|
||||
.resume_noirq = sirfsoc_pinmux_resume_noirq,
|
||||
};
|
||||
#endif
|
||||
|
||||
static struct platform_driver sirfsoc_pinmux_driver = {
|
||||
.driver = {
|
||||
.name = DRIVER_NAME,
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = pinmux_ids,
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
.pm = &sirfsoc_pinmux_pm_ops,
|
||||
#endif
|
||||
},
|
||||
.probe = sirfsoc_pinmux_probe,
|
||||
};
|
||||
|
||||
static int __init sirfsoc_pinmux_init(void)
|
||||
{
|
||||
return platform_driver_register(&sirfsoc_pinmux_driver);
|
||||
}
|
||||
arch_initcall(sirfsoc_pinmux_init);
|
||||
|
||||
static inline int sirfsoc_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
struct sirfsoc_gpio_bank *bank = container_of(to_of_mm_gpio_chip(chip),
|
||||
struct sirfsoc_gpio_bank, chip);
|
||||
|
||||
return irq_create_mapping(bank->domain, offset);
|
||||
}
|
||||
|
||||
static inline int sirfsoc_gpio_to_offset(unsigned int gpio)
|
||||
{
|
||||
return gpio % SIRFSOC_GPIO_BANK_SIZE;
|
||||
}
|
||||
|
||||
static inline struct sirfsoc_gpio_bank *sirfsoc_gpio_to_bank(unsigned int gpio)
|
||||
{
|
||||
return &sgpio_bank[gpio / SIRFSOC_GPIO_BANK_SIZE];
|
||||
}
|
||||
|
||||
static inline struct sirfsoc_gpio_bank *sirfsoc_irqchip_to_bank(struct gpio_chip *chip)
|
||||
{
|
||||
return container_of(to_of_mm_gpio_chip(chip), struct sirfsoc_gpio_bank, chip);
|
||||
}
|
||||
|
||||
static void sirfsoc_gpio_irq_ack(struct irq_data *d)
|
||||
{
|
||||
struct sirfsoc_gpio_bank *bank = irq_data_get_irq_chip_data(d);
|
||||
int idx = d->hwirq % SIRFSOC_GPIO_BANK_SIZE;
|
||||
u32 val, offset;
|
||||
unsigned long flags;
|
||||
|
||||
offset = SIRFSOC_GPIO_CTRL(bank->id, idx);
|
||||
|
||||
spin_lock_irqsave(&sgpio_lock, flags);
|
||||
|
||||
val = readl(bank->chip.regs + offset);
|
||||
|
||||
writel(val, bank->chip.regs + offset);
|
||||
|
||||
spin_unlock_irqrestore(&sgpio_lock, flags);
|
||||
}
|
||||
|
||||
static void __sirfsoc_gpio_irq_mask(struct sirfsoc_gpio_bank *bank, int idx)
|
||||
{
|
||||
u32 val, offset;
|
||||
unsigned long flags;
|
||||
|
||||
offset = SIRFSOC_GPIO_CTRL(bank->id, idx);
|
||||
|
||||
spin_lock_irqsave(&sgpio_lock, flags);
|
||||
|
||||
val = readl(bank->chip.regs + offset);
|
||||
val &= ~SIRFSOC_GPIO_CTL_INTR_EN_MASK;
|
||||
val &= ~SIRFSOC_GPIO_CTL_INTR_STS_MASK;
|
||||
writel(val, bank->chip.regs + offset);
|
||||
|
||||
spin_unlock_irqrestore(&sgpio_lock, flags);
|
||||
}
|
||||
|
||||
static void sirfsoc_gpio_irq_mask(struct irq_data *d)
|
||||
{
|
||||
struct sirfsoc_gpio_bank *bank = irq_data_get_irq_chip_data(d);
|
||||
|
||||
__sirfsoc_gpio_irq_mask(bank, d->hwirq % SIRFSOC_GPIO_BANK_SIZE);
|
||||
}
|
||||
|
||||
static void sirfsoc_gpio_irq_unmask(struct irq_data *d)
|
||||
{
|
||||
struct sirfsoc_gpio_bank *bank = irq_data_get_irq_chip_data(d);
|
||||
int idx = d->hwirq % SIRFSOC_GPIO_BANK_SIZE;
|
||||
u32 val, offset;
|
||||
unsigned long flags;
|
||||
|
||||
offset = SIRFSOC_GPIO_CTRL(bank->id, idx);
|
||||
|
||||
spin_lock_irqsave(&sgpio_lock, flags);
|
||||
|
||||
val = readl(bank->chip.regs + offset);
|
||||
val &= ~SIRFSOC_GPIO_CTL_INTR_STS_MASK;
|
||||
val |= SIRFSOC_GPIO_CTL_INTR_EN_MASK;
|
||||
writel(val, bank->chip.regs + offset);
|
||||
|
||||
spin_unlock_irqrestore(&sgpio_lock, flags);
|
||||
}
|
||||
|
||||
static int sirfsoc_gpio_irq_type(struct irq_data *d, unsigned type)
|
||||
{
|
||||
struct sirfsoc_gpio_bank *bank = irq_data_get_irq_chip_data(d);
|
||||
int idx = d->hwirq % SIRFSOC_GPIO_BANK_SIZE;
|
||||
u32 val, offset;
|
||||
unsigned long flags;
|
||||
|
||||
offset = SIRFSOC_GPIO_CTRL(bank->id, idx);
|
||||
|
||||
spin_lock_irqsave(&sgpio_lock, flags);
|
||||
|
||||
val = readl(bank->chip.regs + offset);
|
||||
val &= ~SIRFSOC_GPIO_CTL_INTR_STS_MASK;
|
||||
|
||||
switch (type) {
|
||||
case IRQ_TYPE_NONE:
|
||||
break;
|
||||
case IRQ_TYPE_EDGE_RISING:
|
||||
val |= SIRFSOC_GPIO_CTL_INTR_HIGH_MASK | SIRFSOC_GPIO_CTL_INTR_TYPE_MASK;
|
||||
val &= ~SIRFSOC_GPIO_CTL_INTR_LOW_MASK;
|
||||
break;
|
||||
case IRQ_TYPE_EDGE_FALLING:
|
||||
val &= ~SIRFSOC_GPIO_CTL_INTR_HIGH_MASK;
|
||||
val |= SIRFSOC_GPIO_CTL_INTR_LOW_MASK | SIRFSOC_GPIO_CTL_INTR_TYPE_MASK;
|
||||
break;
|
||||
case IRQ_TYPE_EDGE_BOTH:
|
||||
val |= SIRFSOC_GPIO_CTL_INTR_HIGH_MASK | SIRFSOC_GPIO_CTL_INTR_LOW_MASK |
|
||||
SIRFSOC_GPIO_CTL_INTR_TYPE_MASK;
|
||||
break;
|
||||
case IRQ_TYPE_LEVEL_LOW:
|
||||
val &= ~(SIRFSOC_GPIO_CTL_INTR_HIGH_MASK | SIRFSOC_GPIO_CTL_INTR_TYPE_MASK);
|
||||
val |= SIRFSOC_GPIO_CTL_INTR_LOW_MASK;
|
||||
break;
|
||||
case IRQ_TYPE_LEVEL_HIGH:
|
||||
val |= SIRFSOC_GPIO_CTL_INTR_HIGH_MASK;
|
||||
val &= ~(SIRFSOC_GPIO_CTL_INTR_LOW_MASK | SIRFSOC_GPIO_CTL_INTR_TYPE_MASK);
|
||||
break;
|
||||
}
|
||||
|
||||
writel(val, bank->chip.regs + offset);
|
||||
|
||||
spin_unlock_irqrestore(&sgpio_lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct irq_chip sirfsoc_irq_chip = {
|
||||
.name = "sirf-gpio-irq",
|
||||
.irq_ack = sirfsoc_gpio_irq_ack,
|
||||
.irq_mask = sirfsoc_gpio_irq_mask,
|
||||
.irq_unmask = sirfsoc_gpio_irq_unmask,
|
||||
.irq_set_type = sirfsoc_gpio_irq_type,
|
||||
};
|
||||
|
||||
static void sirfsoc_gpio_handle_irq(unsigned int irq, struct irq_desc *desc)
|
||||
{
|
||||
struct sirfsoc_gpio_bank *bank = irq_get_handler_data(irq);
|
||||
u32 status, ctrl;
|
||||
int idx = 0;
|
||||
struct irq_chip *chip = irq_get_chip(irq);
|
||||
|
||||
chained_irq_enter(chip, desc);
|
||||
|
||||
status = readl(bank->chip.regs + SIRFSOC_GPIO_INT_STATUS(bank->id));
|
||||
if (!status) {
|
||||
printk(KERN_WARNING
|
||||
"%s: gpio id %d status %#x no interrupt is flaged\n",
|
||||
__func__, bank->id, status);
|
||||
handle_bad_irq(irq, desc);
|
||||
return;
|
||||
}
|
||||
|
||||
while (status) {
|
||||
ctrl = readl(bank->chip.regs + SIRFSOC_GPIO_CTRL(bank->id, idx));
|
||||
|
||||
/*
|
||||
* Here we must check whether the corresponding GPIO's interrupt
|
||||
* has been enabled, otherwise just skip it
|
||||
*/
|
||||
if ((status & 0x1) && (ctrl & SIRFSOC_GPIO_CTL_INTR_EN_MASK)) {
|
||||
pr_debug("%s: gpio id %d idx %d happens\n",
|
||||
__func__, bank->id, idx);
|
||||
generic_handle_irq(irq_find_mapping(bank->domain, idx));
|
||||
}
|
||||
|
||||
idx++;
|
||||
status = status >> 1;
|
||||
}
|
||||
|
||||
chained_irq_exit(chip, desc);
|
||||
}
|
||||
|
||||
static inline void sirfsoc_gpio_set_input(struct sirfsoc_gpio_bank *bank, unsigned ctrl_offset)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
val = readl(bank->chip.regs + ctrl_offset);
|
||||
val &= ~SIRFSOC_GPIO_CTL_OUT_EN_MASK;
|
||||
writel(val, bank->chip.regs + ctrl_offset);
|
||||
}
|
||||
|
||||
static int sirfsoc_gpio_request(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
struct sirfsoc_gpio_bank *bank = sirfsoc_irqchip_to_bank(chip);
|
||||
unsigned long flags;
|
||||
|
||||
if (pinctrl_request_gpio(chip->base + offset))
|
||||
return -ENODEV;
|
||||
|
||||
spin_lock_irqsave(&bank->lock, flags);
|
||||
|
||||
/*
|
||||
* default status:
|
||||
* set direction as input and mask irq
|
||||
*/
|
||||
sirfsoc_gpio_set_input(bank, SIRFSOC_GPIO_CTRL(bank->id, offset));
|
||||
__sirfsoc_gpio_irq_mask(bank, offset);
|
||||
|
||||
spin_unlock_irqrestore(&bank->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void sirfsoc_gpio_free(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
struct sirfsoc_gpio_bank *bank = sirfsoc_irqchip_to_bank(chip);
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&bank->lock, flags);
|
||||
|
||||
__sirfsoc_gpio_irq_mask(bank, offset);
|
||||
sirfsoc_gpio_set_input(bank, SIRFSOC_GPIO_CTRL(bank->id, offset));
|
||||
|
||||
spin_unlock_irqrestore(&bank->lock, flags);
|
||||
|
||||
pinctrl_free_gpio(chip->base + offset);
|
||||
}
|
||||
|
||||
static int sirfsoc_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
|
||||
{
|
||||
struct sirfsoc_gpio_bank *bank = sirfsoc_irqchip_to_bank(chip);
|
||||
int idx = sirfsoc_gpio_to_offset(gpio);
|
||||
unsigned long flags;
|
||||
unsigned offset;
|
||||
|
||||
offset = SIRFSOC_GPIO_CTRL(bank->id, idx);
|
||||
|
||||
spin_lock_irqsave(&bank->lock, flags);
|
||||
|
||||
sirfsoc_gpio_set_input(bank, offset);
|
||||
|
||||
spin_unlock_irqrestore(&bank->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void sirfsoc_gpio_set_output(struct sirfsoc_gpio_bank *bank, unsigned offset,
|
||||
int value)
|
||||
{
|
||||
u32 out_ctrl;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&bank->lock, flags);
|
||||
|
||||
out_ctrl = readl(bank->chip.regs + offset);
|
||||
if (value)
|
||||
out_ctrl |= SIRFSOC_GPIO_CTL_DATAOUT_MASK;
|
||||
else
|
||||
out_ctrl &= ~SIRFSOC_GPIO_CTL_DATAOUT_MASK;
|
||||
|
||||
out_ctrl &= ~SIRFSOC_GPIO_CTL_INTR_EN_MASK;
|
||||
out_ctrl |= SIRFSOC_GPIO_CTL_OUT_EN_MASK;
|
||||
writel(out_ctrl, bank->chip.regs + offset);
|
||||
|
||||
spin_unlock_irqrestore(&bank->lock, flags);
|
||||
}
|
||||
|
||||
static int sirfsoc_gpio_direction_output(struct gpio_chip *chip, unsigned gpio, int value)
|
||||
{
|
||||
struct sirfsoc_gpio_bank *bank = sirfsoc_irqchip_to_bank(chip);
|
||||
int idx = sirfsoc_gpio_to_offset(gpio);
|
||||
u32 offset;
|
||||
unsigned long flags;
|
||||
|
||||
offset = SIRFSOC_GPIO_CTRL(bank->id, idx);
|
||||
|
||||
spin_lock_irqsave(&sgpio_lock, flags);
|
||||
|
||||
sirfsoc_gpio_set_output(bank, offset, value);
|
||||
|
||||
spin_unlock_irqrestore(&sgpio_lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sirfsoc_gpio_get_value(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
struct sirfsoc_gpio_bank *bank = sirfsoc_irqchip_to_bank(chip);
|
||||
u32 val;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&bank->lock, flags);
|
||||
|
||||
val = readl(bank->chip.regs + SIRFSOC_GPIO_CTRL(bank->id, offset));
|
||||
|
||||
spin_unlock_irqrestore(&bank->lock, flags);
|
||||
|
||||
return !!(val & SIRFSOC_GPIO_CTL_DATAIN_MASK);
|
||||
}
|
||||
|
||||
static void sirfsoc_gpio_set_value(struct gpio_chip *chip, unsigned offset,
|
||||
int value)
|
||||
{
|
||||
struct sirfsoc_gpio_bank *bank = sirfsoc_irqchip_to_bank(chip);
|
||||
u32 ctrl;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&bank->lock, flags);
|
||||
|
||||
ctrl = readl(bank->chip.regs + SIRFSOC_GPIO_CTRL(bank->id, offset));
|
||||
if (value)
|
||||
ctrl |= SIRFSOC_GPIO_CTL_DATAOUT_MASK;
|
||||
else
|
||||
ctrl &= ~SIRFSOC_GPIO_CTL_DATAOUT_MASK;
|
||||
writel(ctrl, bank->chip.regs + SIRFSOC_GPIO_CTRL(bank->id, offset));
|
||||
|
||||
spin_unlock_irqrestore(&bank->lock, flags);
|
||||
}
|
||||
|
||||
static int sirfsoc_gpio_irq_map(struct irq_domain *d, unsigned int irq,
|
||||
irq_hw_number_t hwirq)
|
||||
{
|
||||
struct sirfsoc_gpio_bank *bank = d->host_data;
|
||||
|
||||
if (!bank)
|
||||
return -EINVAL;
|
||||
|
||||
irq_set_chip(irq, &sirfsoc_irq_chip);
|
||||
irq_set_handler(irq, handle_level_irq);
|
||||
irq_set_chip_data(irq, bank);
|
||||
set_irq_flags(irq, IRQF_VALID);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct irq_domain_ops sirfsoc_gpio_irq_simple_ops = {
|
||||
.map = sirfsoc_gpio_irq_map,
|
||||
.xlate = irq_domain_xlate_twocell,
|
||||
};
|
||||
|
||||
static void sirfsoc_gpio_set_pullup(const u32 *pullups)
|
||||
{
|
||||
int i, n;
|
||||
const unsigned long *p = (const unsigned long *)pullups;
|
||||
|
||||
for (i = 0; i < SIRFSOC_GPIO_NO_OF_BANKS; i++) {
|
||||
for_each_set_bit(n, p + i, BITS_PER_LONG) {
|
||||
u32 offset = SIRFSOC_GPIO_CTRL(i, n);
|
||||
u32 val = readl(sgpio_bank[i].chip.regs + offset);
|
||||
val |= SIRFSOC_GPIO_CTL_PULL_MASK;
|
||||
val |= SIRFSOC_GPIO_CTL_PULL_HIGH;
|
||||
writel(val, sgpio_bank[i].chip.regs + offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void sirfsoc_gpio_set_pulldown(const u32 *pulldowns)
|
||||
{
|
||||
int i, n;
|
||||
const unsigned long *p = (const unsigned long *)pulldowns;
|
||||
|
||||
for (i = 0; i < SIRFSOC_GPIO_NO_OF_BANKS; i++) {
|
||||
for_each_set_bit(n, p + i, BITS_PER_LONG) {
|
||||
u32 offset = SIRFSOC_GPIO_CTRL(i, n);
|
||||
u32 val = readl(sgpio_bank[i].chip.regs + offset);
|
||||
val |= SIRFSOC_GPIO_CTL_PULL_MASK;
|
||||
val &= ~SIRFSOC_GPIO_CTL_PULL_HIGH;
|
||||
writel(val, sgpio_bank[i].chip.regs + offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int sirfsoc_gpio_probe(struct device_node *np)
|
||||
{
|
||||
int i, err = 0;
|
||||
struct sirfsoc_gpio_bank *bank;
|
||||
void *regs;
|
||||
struct platform_device *pdev;
|
||||
bool is_marco = false;
|
||||
|
||||
u32 pullups[SIRFSOC_GPIO_NO_OF_BANKS], pulldowns[SIRFSOC_GPIO_NO_OF_BANKS];
|
||||
|
||||
pdev = of_find_device_by_node(np);
|
||||
if (!pdev)
|
||||
return -ENODEV;
|
||||
|
||||
regs = of_iomap(np, 0);
|
||||
if (!regs)
|
||||
return -ENOMEM;
|
||||
|
||||
if (of_device_is_compatible(np, "sirf,marco-pinctrl"))
|
||||
is_marco = 1;
|
||||
|
||||
for (i = 0; i < SIRFSOC_GPIO_NO_OF_BANKS; i++) {
|
||||
bank = &sgpio_bank[i];
|
||||
spin_lock_init(&bank->lock);
|
||||
bank->chip.gc.request = sirfsoc_gpio_request;
|
||||
bank->chip.gc.free = sirfsoc_gpio_free;
|
||||
bank->chip.gc.direction_input = sirfsoc_gpio_direction_input;
|
||||
bank->chip.gc.get = sirfsoc_gpio_get_value;
|
||||
bank->chip.gc.direction_output = sirfsoc_gpio_direction_output;
|
||||
bank->chip.gc.set = sirfsoc_gpio_set_value;
|
||||
bank->chip.gc.to_irq = sirfsoc_gpio_to_irq;
|
||||
bank->chip.gc.base = i * SIRFSOC_GPIO_BANK_SIZE;
|
||||
bank->chip.gc.ngpio = SIRFSOC_GPIO_BANK_SIZE;
|
||||
bank->chip.gc.label = kstrdup(np->full_name, GFP_KERNEL);
|
||||
bank->chip.gc.of_node = np;
|
||||
bank->chip.gc.of_xlate = sirfsoc_gpio_of_xlate;
|
||||
bank->chip.gc.of_gpio_n_cells = 2;
|
||||
bank->chip.regs = regs;
|
||||
bank->id = i;
|
||||
bank->is_marco = is_marco;
|
||||
bank->parent_irq = platform_get_irq(pdev, i);
|
||||
if (bank->parent_irq < 0) {
|
||||
err = bank->parent_irq;
|
||||
goto out;
|
||||
}
|
||||
|
||||
err = gpiochip_add(&bank->chip.gc);
|
||||
if (err) {
|
||||
pr_err("%s: error in probe function with status %d\n",
|
||||
np->full_name, err);
|
||||
goto out;
|
||||
}
|
||||
|
||||
bank->domain = irq_domain_add_linear(np, SIRFSOC_GPIO_BANK_SIZE,
|
||||
&sirfsoc_gpio_irq_simple_ops, bank);
|
||||
|
||||
if (!bank->domain) {
|
||||
pr_err("%s: Failed to create irqdomain\n", np->full_name);
|
||||
err = -ENOSYS;
|
||||
goto out;
|
||||
}
|
||||
|
||||
irq_set_chained_handler(bank->parent_irq, sirfsoc_gpio_handle_irq);
|
||||
irq_set_handler_data(bank->parent_irq, bank);
|
||||
}
|
||||
|
||||
if (!of_property_read_u32_array(np, "sirf,pullups", pullups,
|
||||
SIRFSOC_GPIO_NO_OF_BANKS))
|
||||
sirfsoc_gpio_set_pullup(pullups);
|
||||
|
||||
if (!of_property_read_u32_array(np, "sirf,pulldowns", pulldowns,
|
||||
SIRFSOC_GPIO_NO_OF_BANKS))
|
||||
sirfsoc_gpio_set_pulldown(pulldowns);
|
||||
|
||||
return 0;
|
||||
|
||||
out:
|
||||
iounmap(regs);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int __init sirfsoc_gpio_init(void)
|
||||
{
|
||||
|
||||
struct device_node *np;
|
||||
|
||||
np = of_find_matching_node(NULL, pinmux_ids);
|
||||
|
||||
if (!np)
|
||||
return -ENODEV;
|
||||
|
||||
return sirfsoc_gpio_probe(np);
|
||||
}
|
||||
subsys_initcall(sirfsoc_gpio_init);
|
||||
|
||||
MODULE_AUTHOR("Rongjun Ying <rongjun.ying@csr.com>, "
|
||||
"Yuping Luo <yuping.luo@csr.com>, "
|
||||
"Barry Song <baohua.song@csr.com>");
|
||||
MODULE_DESCRIPTION("SIRFSOC pin control driver");
|
||||
MODULE_LICENSE("GPL");
|
116
drivers/pinctrl/sirf/pinctrl-sirf.h
Normal file
116
drivers/pinctrl/sirf/pinctrl-sirf.h
Normal file
|
@ -0,0 +1,116 @@
|
|||
/*
|
||||
* pinmux driver shared headfile for CSR SiRFsoc
|
||||
*
|
||||
* Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
|
||||
*
|
||||
* Licensed under GPLv2 or later.
|
||||
*/
|
||||
|
||||
#ifndef __PINMUX_SIRF_H__
|
||||
#define __PINMUX_SIRF_H__
|
||||
|
||||
#define SIRFSOC_NUM_PADS 622
|
||||
#define SIRFSOC_RSC_PIN_MUX 0x4
|
||||
|
||||
#define SIRFSOC_GPIO_PAD_EN(g) ((g)*0x100 + 0x84)
|
||||
#define SIRFSOC_GPIO_PAD_EN_CLR(g) ((g)*0x100 + 0x90)
|
||||
#define SIRFSOC_GPIO_CTRL(g, i) ((g)*0x100 + (i)*4)
|
||||
#define SIRFSOC_GPIO_DSP_EN0 (0x80)
|
||||
#define SIRFSOC_GPIO_INT_STATUS(g) ((g)*0x100 + 0x8C)
|
||||
|
||||
#define SIRFSOC_GPIO_CTL_INTR_LOW_MASK 0x1
|
||||
#define SIRFSOC_GPIO_CTL_INTR_HIGH_MASK 0x2
|
||||
#define SIRFSOC_GPIO_CTL_INTR_TYPE_MASK 0x4
|
||||
#define SIRFSOC_GPIO_CTL_INTR_EN_MASK 0x8
|
||||
#define SIRFSOC_GPIO_CTL_INTR_STS_MASK 0x10
|
||||
#define SIRFSOC_GPIO_CTL_OUT_EN_MASK 0x20
|
||||
#define SIRFSOC_GPIO_CTL_DATAOUT_MASK 0x40
|
||||
#define SIRFSOC_GPIO_CTL_DATAIN_MASK 0x80
|
||||
#define SIRFSOC_GPIO_CTL_PULL_MASK 0x100
|
||||
#define SIRFSOC_GPIO_CTL_PULL_HIGH 0x200
|
||||
#define SIRFSOC_GPIO_CTL_DSP_INT 0x400
|
||||
|
||||
#define SIRFSOC_GPIO_NO_OF_BANKS 5
|
||||
#define SIRFSOC_GPIO_BANK_SIZE 32
|
||||
#define SIRFSOC_GPIO_NUM(bank, index) (((bank)*(32)) + (index))
|
||||
|
||||
/**
|
||||
* @dev: a pointer back to containing device
|
||||
* @virtbase: the offset to the controller in virtual memory
|
||||
*/
|
||||
struct sirfsoc_pmx {
|
||||
struct device *dev;
|
||||
struct pinctrl_dev *pmx;
|
||||
void __iomem *gpio_virtbase;
|
||||
void __iomem *rsc_virtbase;
|
||||
u32 gpio_regs[SIRFSOC_GPIO_NO_OF_BANKS][SIRFSOC_GPIO_BANK_SIZE];
|
||||
u32 ints_regs[SIRFSOC_GPIO_NO_OF_BANKS];
|
||||
u32 paden_regs[SIRFSOC_GPIO_NO_OF_BANKS];
|
||||
u32 dspen_regs;
|
||||
u32 rsc_regs[3];
|
||||
bool is_marco;
|
||||
};
|
||||
|
||||
/* SIRFSOC_GPIO_PAD_EN set */
|
||||
struct sirfsoc_muxmask {
|
||||
unsigned long group;
|
||||
unsigned long mask;
|
||||
};
|
||||
|
||||
struct sirfsoc_padmux {
|
||||
unsigned long muxmask_counts;
|
||||
const struct sirfsoc_muxmask *muxmask;
|
||||
/* RSC_PIN_MUX set */
|
||||
unsigned long funcmask;
|
||||
unsigned long funcval;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct sirfsoc_pin_group - describes a SiRFprimaII pin group
|
||||
* @name: the name of this specific pin group
|
||||
* @pins: an array of discrete physical pins used in this group, taken
|
||||
* from the driver-local pin enumeration space
|
||||
* @num_pins: the number of pins in this group array, i.e. the number of
|
||||
* elements in .pins so we can iterate over that array
|
||||
*/
|
||||
struct sirfsoc_pin_group {
|
||||
const char *name;
|
||||
const unsigned int *pins;
|
||||
const unsigned num_pins;
|
||||
};
|
||||
|
||||
#define SIRFSOC_PIN_GROUP(n, p) \
|
||||
{ \
|
||||
.name = n, \
|
||||
.pins = p, \
|
||||
.num_pins = ARRAY_SIZE(p), \
|
||||
}
|
||||
|
||||
struct sirfsoc_pmx_func {
|
||||
const char *name;
|
||||
const char * const *groups;
|
||||
const unsigned num_groups;
|
||||
const struct sirfsoc_padmux *padmux;
|
||||
};
|
||||
|
||||
#define SIRFSOC_PMX_FUNCTION(n, g, m) \
|
||||
{ \
|
||||
.name = n, \
|
||||
.groups = g, \
|
||||
.num_groups = ARRAY_SIZE(g), \
|
||||
.padmux = &m, \
|
||||
}
|
||||
|
||||
struct sirfsoc_pinctrl_data {
|
||||
struct pinctrl_pin_desc *pads;
|
||||
int pads_cnt;
|
||||
struct sirfsoc_pin_group *grps;
|
||||
int grps_cnt;
|
||||
struct sirfsoc_pmx_func *funcs;
|
||||
int funcs_cnt;
|
||||
};
|
||||
|
||||
extern struct sirfsoc_pinctrl_data prima2_pinctrl_data;
|
||||
extern struct sirfsoc_pinctrl_data atlas6_pinctrl_data;
|
||||
|
||||
#endif
|
|
@ -441,7 +441,7 @@ static int spear310_p2o(int pin)
|
|||
return offset;
|
||||
}
|
||||
|
||||
int spear310_o2p(int offset)
|
||||
static int spear310_o2p(int offset)
|
||||
{
|
||||
if (offset <= 3)
|
||||
return 101 - offset;
|
||||
|
@ -528,18 +528,13 @@ static int plgpio_probe(struct platform_device *pdev)
|
|||
struct resource *res;
|
||||
int ret, irq, i;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!res) {
|
||||
dev_err(&pdev->dev, "invalid IORESOURCE_MEM\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
plgpio = devm_kzalloc(&pdev->dev, sizeof(*plgpio), GFP_KERNEL);
|
||||
if (!plgpio) {
|
||||
dev_err(&pdev->dev, "memory allocation fail\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
plgpio->base = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(plgpio->base))
|
||||
return PTR_ERR(plgpio->base);
|
||||
|
|
|
@ -569,11 +569,9 @@ int wmt_pinctrl_probe(struct platform_device *pdev,
|
|||
struct resource *res;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
data->base = devm_request_and_ioremap(&pdev->dev, res);
|
||||
if (!data->base) {
|
||||
dev_err(&pdev->dev, "failed to map memory resource\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
data->base = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(data->base))
|
||||
return PTR_ERR(data->base);
|
||||
|
||||
wmt_desc.pins = data->pins;
|
||||
wmt_desc.npins = data->npins;
|
||||
|
|
|
@ -368,11 +368,6 @@ struct pl022 {
|
|||
resource_size_t phybase;
|
||||
void __iomem *virtbase;
|
||||
struct clk *clk;
|
||||
/* Two optional pin states - default & sleep */
|
||||
struct pinctrl *pinctrl;
|
||||
struct pinctrl_state *pins_default;
|
||||
struct pinctrl_state *pins_idle;
|
||||
struct pinctrl_state *pins_sleep;
|
||||
struct spi_master *master;
|
||||
struct pl022_ssp_controller *master_info;
|
||||
/* Message per-transfer pump */
|
||||
|
@ -2134,32 +2129,7 @@ static int pl022_probe(struct amba_device *adev, const struct amba_id *id)
|
|||
pl022->chipselects = devm_kzalloc(dev, num_cs * sizeof(int),
|
||||
GFP_KERNEL);
|
||||
|
||||
pl022->pinctrl = devm_pinctrl_get(dev);
|
||||
if (IS_ERR(pl022->pinctrl)) {
|
||||
status = PTR_ERR(pl022->pinctrl);
|
||||
goto err_no_pinctrl;
|
||||
}
|
||||
|
||||
pl022->pins_default = pinctrl_lookup_state(pl022->pinctrl,
|
||||
PINCTRL_STATE_DEFAULT);
|
||||
/* enable pins to be muxed in and configured */
|
||||
if (!IS_ERR(pl022->pins_default)) {
|
||||
status = pinctrl_select_state(pl022->pinctrl,
|
||||
pl022->pins_default);
|
||||
if (status)
|
||||
dev_err(dev, "could not set default pins\n");
|
||||
} else
|
||||
dev_err(dev, "could not get default pinstate\n");
|
||||
|
||||
pl022->pins_idle = pinctrl_lookup_state(pl022->pinctrl,
|
||||
PINCTRL_STATE_IDLE);
|
||||
if (IS_ERR(pl022->pins_idle))
|
||||
dev_dbg(dev, "could not get idle pinstate\n");
|
||||
|
||||
pl022->pins_sleep = pinctrl_lookup_state(pl022->pinctrl,
|
||||
PINCTRL_STATE_SLEEP);
|
||||
if (IS_ERR(pl022->pins_sleep))
|
||||
dev_dbg(dev, "could not get sleep pinstate\n");
|
||||
pinctrl_pm_select_default_state(dev);
|
||||
|
||||
/*
|
||||
* Bus Number Which has been Assigned to this SSP controller
|
||||
|
@ -2309,7 +2279,6 @@ static int pl022_probe(struct amba_device *adev, const struct amba_id *id)
|
|||
amba_release_regions(adev);
|
||||
err_no_ioregion:
|
||||
err_no_gpio:
|
||||
err_no_pinctrl:
|
||||
spi_master_put(master);
|
||||
return status;
|
||||
}
|
||||
|
@ -2349,44 +2318,21 @@ pl022_remove(struct amba_device *adev)
|
|||
*/
|
||||
static void pl022_suspend_resources(struct pl022 *pl022, bool runtime)
|
||||
{
|
||||
int ret;
|
||||
struct pinctrl_state *pins_state;
|
||||
|
||||
clk_disable(pl022->clk);
|
||||
|
||||
pins_state = runtime ? pl022->pins_idle : pl022->pins_sleep;
|
||||
/* Optionally let pins go into sleep states */
|
||||
if (!IS_ERR(pins_state)) {
|
||||
ret = pinctrl_select_state(pl022->pinctrl, pins_state);
|
||||
if (ret)
|
||||
dev_err(&pl022->adev->dev, "could not set %s pins\n",
|
||||
runtime ? "idle" : "sleep");
|
||||
}
|
||||
if (runtime)
|
||||
pinctrl_pm_select_idle_state(&pl022->adev->dev);
|
||||
else
|
||||
pinctrl_pm_select_sleep_state(&pl022->adev->dev);
|
||||
}
|
||||
|
||||
static void pl022_resume_resources(struct pl022 *pl022, bool runtime)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Optionaly enable pins to be muxed in and configured */
|
||||
/* First go to the default state */
|
||||
if (!IS_ERR(pl022->pins_default)) {
|
||||
ret = pinctrl_select_state(pl022->pinctrl, pl022->pins_default);
|
||||
if (ret)
|
||||
dev_err(&pl022->adev->dev,
|
||||
"could not set default pins\n");
|
||||
}
|
||||
|
||||
if (!runtime) {
|
||||
pinctrl_pm_select_default_state(&pl022->adev->dev);
|
||||
if (!runtime)
|
||||
/* Then let's idle the pins until the next transfer happens */
|
||||
if (!IS_ERR(pl022->pins_idle)) {
|
||||
ret = pinctrl_select_state(pl022->pinctrl,
|
||||
pl022->pins_idle);
|
||||
if (ret)
|
||||
dev_err(&pl022->adev->dev,
|
||||
"could not set idle pins\n");
|
||||
}
|
||||
}
|
||||
pinctrl_pm_select_idle_state(&pl022->adev->dev);
|
||||
|
||||
clk_enable(pl022->clk);
|
||||
}
|
||||
|
|
|
@ -150,10 +150,6 @@ struct pl011_dmatx_data {
|
|||
struct uart_amba_port {
|
||||
struct uart_port port;
|
||||
struct clk *clk;
|
||||
/* Two optional pin states - default & sleep */
|
||||
struct pinctrl *pinctrl;
|
||||
struct pinctrl_state *pins_default;
|
||||
struct pinctrl_state *pins_sleep;
|
||||
const struct vendor_data *vendor;
|
||||
unsigned int dmacr; /* dma control reg */
|
||||
unsigned int im; /* interrupt mask */
|
||||
|
@ -1479,12 +1475,7 @@ static int pl011_hwinit(struct uart_port *port)
|
|||
int retval;
|
||||
|
||||
/* Optionaly enable pins to be muxed in and configured */
|
||||
if (!IS_ERR(uap->pins_default)) {
|
||||
retval = pinctrl_select_state(uap->pinctrl, uap->pins_default);
|
||||
if (retval)
|
||||
dev_err(port->dev,
|
||||
"could not set default pins\n");
|
||||
}
|
||||
pinctrl_pm_select_default_state(port->dev);
|
||||
|
||||
/*
|
||||
* Try to enable the clock producer.
|
||||
|
@ -1610,7 +1601,6 @@ static void pl011_shutdown(struct uart_port *port)
|
|||
{
|
||||
struct uart_amba_port *uap = (struct uart_amba_port *)port;
|
||||
unsigned int cr;
|
||||
int retval;
|
||||
|
||||
/*
|
||||
* disable all interrupts
|
||||
|
@ -1653,13 +1643,7 @@ static void pl011_shutdown(struct uart_port *port)
|
|||
*/
|
||||
clk_disable_unprepare(uap->clk);
|
||||
/* Optionally let pins go into sleep states */
|
||||
if (!IS_ERR(uap->pins_sleep)) {
|
||||
retval = pinctrl_select_state(uap->pinctrl, uap->pins_sleep);
|
||||
if (retval)
|
||||
dev_err(port->dev,
|
||||
"could not set pins to sleep state\n");
|
||||
}
|
||||
|
||||
pinctrl_pm_select_sleep_state(port->dev);
|
||||
|
||||
if (uap->port.dev->platform_data) {
|
||||
struct amba_pl011_data *plat;
|
||||
|
@ -2012,12 +1996,7 @@ static int __init pl011_console_setup(struct console *co, char *options)
|
|||
return -ENODEV;
|
||||
|
||||
/* Allow pins to be muxed in and configured */
|
||||
if (!IS_ERR(uap->pins_default)) {
|
||||
ret = pinctrl_select_state(uap->pinctrl, uap->pins_default);
|
||||
if (ret)
|
||||
dev_err(uap->port.dev,
|
||||
"could not set default pins\n");
|
||||
}
|
||||
pinctrl_pm_select_default_state(uap->port.dev);
|
||||
|
||||
ret = clk_prepare(uap->clk);
|
||||
if (ret)
|
||||
|
@ -2131,21 +2110,6 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
|
|||
goto out;
|
||||
}
|
||||
|
||||
uap->pinctrl = devm_pinctrl_get(&dev->dev);
|
||||
if (IS_ERR(uap->pinctrl)) {
|
||||
ret = PTR_ERR(uap->pinctrl);
|
||||
goto out;
|
||||
}
|
||||
uap->pins_default = pinctrl_lookup_state(uap->pinctrl,
|
||||
PINCTRL_STATE_DEFAULT);
|
||||
if (IS_ERR(uap->pins_default))
|
||||
dev_err(&dev->dev, "could not get default pinstate\n");
|
||||
|
||||
uap->pins_sleep = pinctrl_lookup_state(uap->pinctrl,
|
||||
PINCTRL_STATE_SLEEP);
|
||||
if (IS_ERR(uap->pins_sleep))
|
||||
dev_dbg(&dev->dev, "could not get sleep pinstate\n");
|
||||
|
||||
uap->clk = devm_clk_get(&dev->dev, NULL);
|
||||
if (IS_ERR(uap->clk)) {
|
||||
ret = PTR_ERR(uap->clk);
|
||||
|
|
32
include/dt-bindings/pinctrl/rockchip.h
Normal file
32
include/dt-bindings/pinctrl/rockchip.h
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Header providing constants for Rockchip pinctrl bindings.
|
||||
*
|
||||
* Copyright (c) 2013 MundoReader S.L.
|
||||
* Author: Heiko Stuebner <heiko@sntech.de>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef __DT_BINDINGS_ROCKCHIP_PINCTRL_H__
|
||||
#define __DT_BINDINGS_ROCKCHIP_PINCTRL_H__
|
||||
|
||||
#define RK_GPIO0 0
|
||||
#define RK_GPIO1 1
|
||||
#define RK_GPIO2 2
|
||||
#define RK_GPIO3 3
|
||||
#define RK_GPIO4 4
|
||||
#define RK_GPIO6 6
|
||||
|
||||
#define RK_FUNC_GPIO 0
|
||||
#define RK_FUNC_1 1
|
||||
#define RK_FUNC_2 2
|
||||
|
||||
#endif
|
|
@ -40,6 +40,25 @@ extern int pinctrl_select_state(struct pinctrl *p, struct pinctrl_state *s);
|
|||
extern struct pinctrl * __must_check devm_pinctrl_get(struct device *dev);
|
||||
extern void devm_pinctrl_put(struct pinctrl *p);
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
extern int pinctrl_pm_select_default_state(struct device *dev);
|
||||
extern int pinctrl_pm_select_sleep_state(struct device *dev);
|
||||
extern int pinctrl_pm_select_idle_state(struct device *dev);
|
||||
#else
|
||||
static inline int pinctrl_pm_select_default_state(struct device *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline int pinctrl_pm_select_sleep_state(struct device *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline int pinctrl_pm_select_idle_state(struct device *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#else /* !CONFIG_PINCTRL */
|
||||
|
||||
static inline int pinctrl_request_gpio(unsigned gpio)
|
||||
|
@ -92,6 +111,21 @@ static inline void devm_pinctrl_put(struct pinctrl *p)
|
|||
{
|
||||
}
|
||||
|
||||
static inline int pinctrl_pm_select_default_state(struct device *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int pinctrl_pm_select_sleep_state(struct device *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int pinctrl_pm_select_idle_state(struct device *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_PINCTRL */
|
||||
|
||||
static inline struct pinctrl * __must_check pinctrl_get_select(
|
||||
|
@ -158,47 +192,4 @@ static inline struct pinctrl * __must_check devm_pinctrl_get_select_default(
|
|||
return devm_pinctrl_get_select(dev, PINCTRL_STATE_DEFAULT);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PINCONF
|
||||
|
||||
extern int pin_config_get(const char *dev_name, const char *name,
|
||||
unsigned long *config);
|
||||
extern int pin_config_set(const char *dev_name, const char *name,
|
||||
unsigned long config);
|
||||
extern int pin_config_group_get(const char *dev_name,
|
||||
const char *pin_group,
|
||||
unsigned long *config);
|
||||
extern int pin_config_group_set(const char *dev_name,
|
||||
const char *pin_group,
|
||||
unsigned long config);
|
||||
|
||||
#else
|
||||
|
||||
static inline int pin_config_get(const char *dev_name, const char *name,
|
||||
unsigned long *config)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int pin_config_set(const char *dev_name, const char *name,
|
||||
unsigned long config)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int pin_config_group_get(const char *dev_name,
|
||||
const char *pin_group,
|
||||
unsigned long *config)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int pin_config_group_set(const char *dev_name,
|
||||
const char *pin_group,
|
||||
unsigned long config)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* __LINUX_PINCTRL_CONSUMER_H */
|
||||
|
|
|
@ -28,6 +28,10 @@
|
|||
struct dev_pin_info {
|
||||
struct pinctrl *p;
|
||||
struct pinctrl_state *default_state;
|
||||
#ifdef CONFIG_PM
|
||||
struct pinctrl_state *sleep_state;
|
||||
struct pinctrl_state *idle_state;
|
||||
#endif
|
||||
};
|
||||
|
||||
extern int pinctrl_bind_pins(struct device *dev);
|
||||
|
|
|
@ -29,12 +29,25 @@
|
|||
* if for example some other pin is going to drive the signal connected
|
||||
* to it for a while. Pins used for input are usually always high
|
||||
* impedance.
|
||||
* @PIN_CONFIG_BIAS_BUS_HOLD: the pin will be set to weakly latch so that it
|
||||
* weakly drives the last value on a tristate bus, also known as a "bus
|
||||
* holder", "bus keeper" or "repeater". This allows another device on the
|
||||
* bus to change the value by driving the bus high or low and switching to
|
||||
* tristate. The argument is ignored.
|
||||
* @PIN_CONFIG_BIAS_PULL_UP: the pin will be pulled up (usually with high
|
||||
* impedance to VDD). If the argument is != 0 pull-up is enabled,
|
||||
* if it is 0, pull-up is disabled.
|
||||
* if it is 0, pull-up is total, i.e. the pin is connected to VDD.
|
||||
* @PIN_CONFIG_BIAS_PULL_DOWN: the pin will be pulled down (usually with high
|
||||
* impedance to GROUND). If the argument is != 0 pull-down is enabled,
|
||||
* if it is 0, pull-down is disabled.
|
||||
* if it is 0, pull-down is total, i.e. the pin is connected to GROUND.
|
||||
* @PIN_CONFIG_BIAS_PULL_PIN_DEFAULT: the pin will be pulled up or down based
|
||||
* on embedded knowledge of the controller hardware, like current mux
|
||||
* function. The pull direction and possibly strength too will normally
|
||||
* be decided completely inside the hardware block and not be readable
|
||||
* from the kernel side.
|
||||
* If the argument is != 0 pull up/down is enabled, if it is 0, the
|
||||
* configuration is ignored. The proper way to disable it is to use
|
||||
* @PIN_CONFIG_BIAS_DISABLE.
|
||||
* @PIN_CONFIG_DRIVE_PUSH_PULL: the pin will be driven actively high and
|
||||
* low, this is the most typical case and is typically achieved with two
|
||||
* active transistors on the output. Setting this config will enable
|
||||
|
@ -57,14 +70,14 @@
|
|||
* setting pins to this mode.
|
||||
* @PIN_CONFIG_INPUT_DEBOUNCE: this will configure the pin to debounce mode,
|
||||
* which means it will wait for signals to settle when reading inputs. The
|
||||
* argument gives the debounce time on a custom format. Setting the
|
||||
* argument gives the debounce time in usecs. Setting the
|
||||
* argument to zero turns debouncing off.
|
||||
* @PIN_CONFIG_POWER_SOURCE: if the pin can select between different power
|
||||
* supplies, the argument to this parameter (on a custom format) tells
|
||||
* the driver which alternative power source to use.
|
||||
* @PIN_CONFIG_SLEW_RATE: if the pin can select slew rate, the argument to
|
||||
* this parameter (on a custom format) tells the driver which alternative
|
||||
* slew rate to use.
|
||||
* this parameter (on a custom format) tells the driver which alternative
|
||||
* slew rate to use.
|
||||
* @PIN_CONFIG_LOW_POWER_MODE: this will configure the pin for low power
|
||||
* operation, if several modes of operation are supported these can be
|
||||
* passed in the argument on a custom form, else just use argument 1
|
||||
|
@ -78,8 +91,10 @@
|
|||
enum pin_config_param {
|
||||
PIN_CONFIG_BIAS_DISABLE,
|
||||
PIN_CONFIG_BIAS_HIGH_IMPEDANCE,
|
||||
PIN_CONFIG_BIAS_BUS_HOLD,
|
||||
PIN_CONFIG_BIAS_PULL_UP,
|
||||
PIN_CONFIG_BIAS_PULL_DOWN,
|
||||
PIN_CONFIG_BIAS_PULL_PIN_DEFAULT,
|
||||
PIN_CONFIG_DRIVE_PUSH_PULL,
|
||||
PIN_CONFIG_DRIVE_OPEN_DRAIN,
|
||||
PIN_CONFIG_DRIVE_OPEN_SOURCE,
|
||||
|
|
|
@ -30,7 +30,7 @@ struct seq_file;
|
|||
* @pin_config_set: configure an individual pin
|
||||
* @pin_config_group_get: get configurations for an entire pin group
|
||||
* @pin_config_group_set: configure all pins in a group
|
||||
* @pin_config_group_dbg_set: optional debugfs to modify a pin configuration
|
||||
* @pin_config_dbg_parse_modify: optional debugfs to modify a pin configuration
|
||||
* @pin_config_dbg_show: optional debugfs display hook that will provide
|
||||
* per-device info for a certain pin in debugfs
|
||||
* @pin_config_group_dbg_show: optional debugfs display hook that will provide
|
||||
|
|
|
@ -49,7 +49,8 @@ struct pinctrl_pin_desc {
|
|||
* @name: a name for the chip in this range
|
||||
* @id: an ID number for the chip in this range
|
||||
* @base: base offset of the GPIO range
|
||||
* @pin_base: base pin number of the GPIO range
|
||||
* @pin_base: base pin number of the GPIO range if pins == NULL
|
||||
* @pins: enumeration of pins in GPIO range or NULL
|
||||
* @npins: number of pins in the GPIO range, including the base number
|
||||
* @gc: an optional pointer to a gpio_chip
|
||||
*/
|
||||
|
@ -59,6 +60,7 @@ struct pinctrl_gpio_range {
|
|||
unsigned int id;
|
||||
unsigned int base;
|
||||
unsigned int pin_base;
|
||||
unsigned const *pins;
|
||||
unsigned int npins;
|
||||
struct gpio_chip *gc;
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue
Block a user