mirror of
https://github.com/FEX-Emu/linux.git
synced 2024-12-16 22:10:24 +00:00
These are the pinctrl changes for v3.10:
- Patrice Chotard contributed a new configuration debugfs interface and reintroduced fine-grained locking into the core: instead of having a "big pinctrl lock" we have a per-controller lock and specialized locks for the global controller and pinctrl handle lists. - Haoijan Zhuang deleted all the PXA and MMP2 pinctrl drivers and replaced them with pinctrl-single (which is also used by other SoCs) so we are gaining consolidation. The platform particulars now come in through the device tree. - Haoijan also added support for generic pin config into the pinctrl-single driver which is another big consolidation win. - Finally also GPIO ranges are now supported by the pinctrl-single driver. - Tomasz Figa contributed a new Samsung S3C pinctrl driver, bringing more of the older Samsung platforms under the pinctrl umbrella and out of arch/arm. - Maxime Ripard contributed new Allwinner A10/A13 drivers. - Sachin Kamat, Wei Yongjun and Axel Lin did a lot of cleanups. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.10 (GNU/Linux) iQIcBAABAgAGBQJRfmmSAAoJEEEQszewGV1z2BEQAKZ5RhNu+Rc0AoDxYlVWg6bf GBepmdjHXvYSlFltIu7/ti0ttGGfU/F5j8eqGQDBZl9WnYu9WEglPp7EdBNn4/oo fVtqwWH0tAXbk3BNn7tpufWQh0HpFnmkMqtqtfM9HqvRLnw7HISLYzSjBO41rTiw +Cpx/FMogRK1ABKyWvoddXQnQ2ApJwLlgaJ95vkuaQe3i0PVz39e/GdKW4aM7Y6N ksim0GXGLuOObdp42b1Ib5/MdHJKCQfwmtOd+d017uREXxR5u5y49oyjYRTeHcjk qMqKUL3c+HNN1b39I9O2LoWuKAALN6WSOl+o+o+GXLHHe96i8nwp59f7Q7No2v3J x1bCCfbJ1yoRfmdpA/P9DYFj7taiEhCfVKf34NJcw5ZhRk3soJ9BpyYqhPAlEdgD pDjalTeMRJORo8ZuOpmR8f3sFNd6XnO84NWFoPOPiRQJYKYCUehY5bOVP8nfYTXJ A9VWS0ZCFFLS6wU2kSU++gVg0sFToCbYCEP6fSnl9n48U56jXUgNt36+HL69bGw/ Du7WdHilNuMfGM3HhAf2dM7NlzSyIbUwagBJHPVa4iF/pDF5BeCdsP983INfomuR SQv25JfOMGB1iIyC87j9+1Mzuc2ouFV/QXBsTtmiyYmIaWhf8SGeioyXGfqUiQmE 6sZKS27MYtAKQHmwvf5U =CyMU -----END PGP SIGNATURE----- Merge tag 'pinctrl-for-v3.10' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl Pull pinctrl update from Linus Walleij: "These are the pinctrl changes for v3.10: - Patrice Chotard contributed a new configuration debugfs interface and reintroduced fine-grained locking into the core: instead of having a "big pinctrl lock" we have a per-controller lock and specialized locks for the global controller and pinctrl handle lists. - Haoijan Zhuang deleted all the PXA and MMP2 pinctrl drivers and replaced them with pinctrl-single (which is also used by other SoCs) so we are gaining consolidation. The platform particulars now come in through the device tree. - Haoijan also added support for generic pin config into the pinctrl-single driver which is another big consolidation win. - Finally also GPIO ranges are now supported by the pinctrl-single driver. - Tomasz Figa contributed a new Samsung S3C pinctrl driver, bringing more of the older Samsung platforms under the pinctrl umbrella and out of arch/arm. - Maxime Ripard contributed new Allwinner A10/A13 drivers. - Sachin Kamat, Wei Yongjun and Axel Lin did a lot of cleanups." * tag 'pinctrl-for-v3.10' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl: (66 commits) pinctrl: move subsystem mutex to pinctrl_dev struct pinctrl/pinconfig: fix misplaced goto pinctrl: s3c64xx: Fix build error caused by undefined chained_irq_enter pinctrl/pinconfig: add debug interface pinctrl: abx500: fix issue when no pdata pinctrl: pinctrl-single: add missing double quote pinctrl: sunxi: Rename wemac functions to emac pinctrl: exynos5440: add gpio interrupt support pinctrl: exynos5440: fix probe failure due to missing pin-list in config nodes pinctrl: ab8505: Staticize some symbols pinctrl: ab8540: Staticize some symbols pinctrl: ab9540: Staticize some symbols pinctrl: ab8500: Staticize some symbols pinctrl: abx500: Staticize some symbols pinctrl: Add pinctrl-s3c64xx driver pinctrl: samsung: Handle banks with two configuration registers pinctrl: samsung: Remove hardcoded register offsets pinctrl: samsung: Split pin bank description into two structures pinctrl: samsung: Include pinctrl-exynos driver data conditionally pinctrl: samsung: Protect bank registers with a spinlock ...
This commit is contained in:
commit
000a74f41e
@ -98,7 +98,7 @@ announce the pinrange to the pin ctrl subsystem. For example,
|
||||
compatible = "fsl,qe-pario-bank-e", "fsl,qe-pario-bank";
|
||||
reg = <0x1460 0x18>;
|
||||
gpio-controller;
|
||||
gpio-ranges = <&pinctrl1 20 10>, <&pinctrl2 50 20>;
|
||||
gpio-ranges = <&pinctrl1 0 20 10>, <&pinctrl2 10 50 20>;
|
||||
|
||||
}
|
||||
|
||||
@ -107,8 +107,8 @@ where,
|
||||
|
||||
Next values specify the base pin and number of pins for the range
|
||||
handled by 'qe_pio_e' gpio. In the given example from base pin 20 to
|
||||
pin 29 under pinctrl1 and pin 50 to pin 69 under pinctrl2 is handled
|
||||
by this gpio controller.
|
||||
pin 29 under pinctrl1 with gpio offset 0 and pin 50 to pin 69 under
|
||||
pinctrl2 with gpio offset 10 is handled by this gpio controller.
|
||||
|
||||
The pinctrl node must have "#gpio-range-cells" property to show number of
|
||||
arguments to pass with phandle from gpio controllers node.
|
||||
|
@ -1,7 +1,9 @@
|
||||
One-register-per-pin type device tree based pinctrl driver
|
||||
|
||||
Required properties:
|
||||
- compatible : "pinctrl-single"
|
||||
- compatible : "pinctrl-single" or "pinconf-single".
|
||||
"pinctrl-single" means that pinconf isn't supported.
|
||||
"pinconf-single" means that generic pinconf is supported.
|
||||
|
||||
- reg : offset and length of the register set for the mux registers
|
||||
|
||||
@ -14,9 +16,61 @@ Optional properties:
|
||||
- pinctrl-single,function-off : function off mode for disabled state if
|
||||
available and same for all registers; if not specified, disabling of
|
||||
pin functions is ignored
|
||||
|
||||
- pinctrl-single,bit-per-mux : boolean to indicate that one register controls
|
||||
more than one 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
|
||||
current and drive strength mask.
|
||||
|
||||
/* drive strength current, mask */
|
||||
pinctrl-single,power-source = <0x30 0xf0>;
|
||||
|
||||
- pinctrl-single,bias-pullup : array of value that are used to configure the
|
||||
input bias pullup in the pinmux register.
|
||||
|
||||
/* input, enabled pullup bits, disabled pullup bits, mask */
|
||||
pinctrl-single,bias-pullup = <0 1 0 1>;
|
||||
|
||||
- pinctrl-single,bias-pulldown : array of value that are used to configure the
|
||||
input bias pulldown in the pinmux register.
|
||||
|
||||
/* input, enabled pulldown bits, disabled pulldown bits, mask */
|
||||
pinctrl-single,bias-pulldown = <2 2 0 2>;
|
||||
|
||||
* Two bits to control input bias pullup and pulldown: User should use
|
||||
pinctrl-single,bias-pullup & pinctrl-single,bias-pulldown. One bit means
|
||||
pullup, and the other one bit means pulldown.
|
||||
* Three bits to control input bias enable, pullup and pulldown. User should
|
||||
use pinctrl-single,bias-pullup & pinctrl-single,bias-pulldown. Input bias
|
||||
enable bit should be included in pullup or pulldown bits.
|
||||
* Although driver could set PIN_CONFIG_BIAS_DISABLE, there's no property as
|
||||
pinctrl-single,bias-disable. Because pinctrl single driver could implement
|
||||
it by calling pulldown, pullup disabled.
|
||||
|
||||
- pinctrl-single,input-schmitt : array of value that are used to configure
|
||||
input schmitt in the pinmux register. In some silicons, there're two input
|
||||
schmitt value (rising-edge & falling-edge) in the pinmux register.
|
||||
|
||||
/* input schmitt value, mask */
|
||||
pinctrl-single,input-schmitt = <0x30 0x70>;
|
||||
|
||||
- pinctrl-single,input-schmitt-enable : array of value that are used to
|
||||
configure input schmitt enable or disable in the pinmux register.
|
||||
|
||||
/* input, enable bits, disable bits, mask */
|
||||
pinctrl-single,input-schmitt-enable = <0x30 0x40 0 0x70>;
|
||||
|
||||
- pinctrl-single,gpio-range : list of value that are used to configure a GPIO
|
||||
range. They're value of subnode phandle, pin base in pinctrl device, pin
|
||||
number in this range, GPIO function value of this GPIO range.
|
||||
The number of parameters is depend on #pinctrl-single,gpio-range-cells
|
||||
property.
|
||||
|
||||
/* pin base, nr pins & gpio function */
|
||||
pinctrl-single,gpio-range = <&range 0 3 0 &range 3 9 1>;
|
||||
|
||||
This driver assumes that there is only one register for each pin (unless the
|
||||
pinctrl-single,bit-per-mux is set), and uses the common pinctrl bindings as
|
||||
specified in the pinctrl-bindings.txt document in this directory.
|
||||
@ -42,6 +96,20 @@ Where 0xdc is the offset from the pinctrl register base address for the
|
||||
device pinctrl register, 0x18 is the desired value, and 0xff is the sub mask to
|
||||
be used when applying this change to the register.
|
||||
|
||||
|
||||
Optional sub-node: In case some pins could be configured as GPIO in the pinmux
|
||||
register, those pins could be defined as a GPIO range. This sub-node is required
|
||||
by pinctrl-single,gpio-range property.
|
||||
|
||||
Required properties in sub-node:
|
||||
- #pinctrl-single,gpio-range-cells : the number of parameters after phandle in
|
||||
pinctrl-single,gpio-range property.
|
||||
|
||||
range: gpio-range {
|
||||
#pinctrl-single,gpio-range-cells = <3>;
|
||||
};
|
||||
|
||||
|
||||
Example:
|
||||
|
||||
/* SoC common file */
|
||||
@ -58,7 +126,7 @@ pmx_core: pinmux@4a100040 {
|
||||
|
||||
/* second controller instance for pins in wkup domain */
|
||||
pmx_wkup: pinmux@4a31e040 {
|
||||
compatible = "pinctrl-single;
|
||||
compatible = "pinctrl-single";
|
||||
reg = <0x4a31e040 0x0038>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
@ -76,6 +144,29 @@ control_devconf0: pinmux@48002274 {
|
||||
pinctrl-single,function-mask = <0x5F>;
|
||||
};
|
||||
|
||||
/* third controller instance for pins in gpio domain */
|
||||
pmx_gpio: pinmux@d401e000 {
|
||||
compatible = "pinconf-single";
|
||||
reg = <0xd401e000 0x0330>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
ranges;
|
||||
|
||||
pinctrl-single,register-width = <32>;
|
||||
pinctrl-single,function-mask = <7>;
|
||||
|
||||
/* sparse GPIO range could be supported */
|
||||
pinctrl-single,gpio-range = <&range 0 3 0 &range 3 9 1
|
||||
&range 12 1 0 &range 13 29 1
|
||||
&range 43 1 0 &range 44 49 1
|
||||
&range 94 1 1 &range 96 2 1>;
|
||||
|
||||
range: gpio-range {
|
||||
#pinctrl-single,gpio-range-cells = <3>;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/* board specific .dts file */
|
||||
|
||||
&pmx_core {
|
||||
@ -96,6 +187,15 @@ control_devconf0: pinmux@48002274 {
|
||||
>;
|
||||
};
|
||||
|
||||
uart0_pins: pinmux_uart0_pins {
|
||||
pinctrl-single,pins = <
|
||||
0x208 0 /* UART0_RXD (IOCFG138) */
|
||||
0x20c 0 /* UART0_TXD (IOCFG139) */
|
||||
>;
|
||||
pinctrl-single,bias-pulldown = <0 2 2>;
|
||||
pinctrl-single,bias-pullup = <0 1 1>;
|
||||
};
|
||||
|
||||
/* map uart2 pins */
|
||||
uart2_pins: pinmux_uart2_pins {
|
||||
pinctrl-single,pins = <
|
||||
@ -122,6 +222,11 @@ control_devconf0: pinmux@48002274 {
|
||||
|
||||
};
|
||||
|
||||
&uart1 {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&uart0_pins>;
|
||||
};
|
||||
|
||||
&uart2 {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&uart2_pins>;
|
||||
|
@ -7,6 +7,7 @@ on-chip controllers onto these pads.
|
||||
|
||||
Required Properties:
|
||||
- compatible: should be one of the following.
|
||||
- "samsung,s3c64xx-pinctrl": for S3C64xx-compatible pin-controller,
|
||||
- "samsung,exynos4210-pinctrl": for Exynos4210 compatible pin-controller.
|
||||
- "samsung,exynos4x12-pinctrl": for Exynos4x12 compatible pin-controller.
|
||||
- "samsung,exynos5250-pinctrl": for Exynos5250 compatible pin-controller.
|
||||
@ -105,6 +106,8 @@ B. External Wakeup Interrupts: For supporting external wakeup interrupts, a
|
||||
|
||||
- compatible: identifies the type of the external wakeup interrupt controller
|
||||
The possible values are:
|
||||
- samsung,s3c64xx-wakeup-eint: represents wakeup interrupt controller
|
||||
found on Samsung S3C64xx SoCs,
|
||||
- samsung,exynos4210-wakeup-eint: represents wakeup interrupt controller
|
||||
found on Samsung Exynos4210 SoC.
|
||||
- interrupt-parent: phandle of the interrupt parent to which the external
|
||||
|
@ -736,6 +736,13 @@ All the above functions are mandatory to implement for a pinmux driver.
|
||||
Pin control interaction with the GPIO subsystem
|
||||
===============================================
|
||||
|
||||
Note that the following implies that the use case is to use a certain pin
|
||||
from the Linux kernel using the API in <linux/gpio.h> with gpio_request()
|
||||
and similar functions. There are cases where you may be using something
|
||||
that your datasheet calls "GPIO mode" but actually is just an electrical
|
||||
configuration for a certain device. See the section below named
|
||||
"GPIO mode pitfalls" for more details on this scenario.
|
||||
|
||||
The public pinmux API contains two functions named pinctrl_request_gpio()
|
||||
and pinctrl_free_gpio(). These two functions shall *ONLY* be called from
|
||||
gpiolib-based drivers as part of their gpio_request() and
|
||||
@ -774,6 +781,111 @@ obtain the function "gpioN" where "N" is the global GPIO pin number if no
|
||||
special GPIO-handler is registered.
|
||||
|
||||
|
||||
GPIO mode pitfalls
|
||||
==================
|
||||
|
||||
Sometime the developer may be confused by a datasheet talking about a pin
|
||||
being possible to set into "GPIO mode". It appears that what hardware
|
||||
engineers mean with "GPIO mode" is not necessarily the use case that is
|
||||
implied in the kernel interface <linux/gpio.h>: a pin that you grab from
|
||||
kernel code and then either listen for input or drive high/low to
|
||||
assert/deassert some external line.
|
||||
|
||||
Rather hardware engineers think that "GPIO mode" means that you can
|
||||
software-control a few electrical properties of the pin that you would
|
||||
not be able to control if the pin was in some other mode, such as muxed in
|
||||
for a device.
|
||||
|
||||
Example: a pin is usually muxed in to be used as a UART TX line. But during
|
||||
system sleep, we need to put this pin into "GPIO mode" and ground it.
|
||||
|
||||
If you make a 1-to-1 map to the GPIO subsystem for this pin, you may start
|
||||
to think that you need to come up with something real complex, that the
|
||||
pin shall be used for UART TX and GPIO at the same time, that you will grab
|
||||
a pin control handle and set it to a certain state to enable UART TX to be
|
||||
muxed in, then twist it over to GPIO mode and use gpio_direction_output()
|
||||
to drive it low during sleep, then mux it over to UART TX again when you
|
||||
wake up and maybe even gpio_request/gpio_free as part of this cycle. This
|
||||
all gets very complicated.
|
||||
|
||||
The solution is to not think that what the datasheet calls "GPIO mode"
|
||||
has to be handled by the <linux/gpio.h> interface. Instead view this as
|
||||
a certain pin config setting. Look in e.g. <linux/pinctrl/pinconf-generic.h>
|
||||
and you find this in the documentation:
|
||||
|
||||
PIN_CONFIG_OUTPUT: this will configure the pin in output, use argument
|
||||
1 to indicate high level, argument 0 to indicate low level.
|
||||
|
||||
So it is perfectly possible to push a pin into "GPIO mode" and drive the
|
||||
line low as part of the usual pin control map. So for example your UART
|
||||
driver may look like this:
|
||||
|
||||
#include <linux/pinctrl/consumer.h>
|
||||
|
||||
struct pinctrl *pinctrl;
|
||||
struct pinctrl_state *pins_default;
|
||||
struct pinctrl_state *pins_sleep;
|
||||
|
||||
pins_default = pinctrl_lookup_state(uap->pinctrl, PINCTRL_STATE_DEFAULT);
|
||||
pins_sleep = pinctrl_lookup_state(uap->pinctrl, PINCTRL_STATE_SLEEP);
|
||||
|
||||
/* Normal mode */
|
||||
retval = pinctrl_select_state(pinctrl, pins_default);
|
||||
/* Sleep mode */
|
||||
retval = pinctrl_select_state(pinctrl, pins_sleep);
|
||||
|
||||
And your machine configuration may look like this:
|
||||
--------------------------------------------------
|
||||
|
||||
static unsigned long uart_default_mode[] = {
|
||||
PIN_CONF_PACKED(PIN_CONFIG_DRIVE_PUSH_PULL, 0),
|
||||
};
|
||||
|
||||
static unsigned long uart_sleep_mode[] = {
|
||||
PIN_CONF_PACKED(PIN_CONFIG_OUTPUT, 0),
|
||||
};
|
||||
|
||||
static struct pinctrl_map __initdata pinmap[] = {
|
||||
PIN_MAP_MUX_GROUP("uart", PINCTRL_STATE_DEFAULT, "pinctrl-foo",
|
||||
"u0_group", "u0"),
|
||||
PIN_MAP_CONFIGS_PIN("uart", PINCTRL_STATE_DEFAULT, "pinctrl-foo",
|
||||
"UART_TX_PIN", uart_default_mode),
|
||||
PIN_MAP_MUX_GROUP("uart", PINCTRL_STATE_SLEEP, "pinctrl-foo",
|
||||
"u0_group", "gpio-mode"),
|
||||
PIN_MAP_CONFIGS_PIN("uart", PINCTRL_STATE_SLEEP, "pinctrl-foo",
|
||||
"UART_TX_PIN", uart_sleep_mode),
|
||||
};
|
||||
|
||||
foo_init(void) {
|
||||
pinctrl_register_mappings(pinmap, ARRAY_SIZE(pinmap));
|
||||
}
|
||||
|
||||
Here the pins we want to control are in the "u0_group" and there is some
|
||||
function called "u0" that can be enabled on this group of pins, and then
|
||||
everything is UART business as usual. But there is also some function
|
||||
named "gpio-mode" that can be mapped onto the same pins to move them into
|
||||
GPIO mode.
|
||||
|
||||
This will give the desired effect without any bogus interaction with the
|
||||
GPIO subsystem. It is just an electrical configuration used by that device
|
||||
when going to sleep, it might imply that the pin is set into something the
|
||||
datasheet calls "GPIO mode" but that is not the point: it is still used
|
||||
by that UART device to control the pins that pertain to that very UART
|
||||
driver, putting them into modes needed by the UART. GPIO in the Linux
|
||||
kernel sense are just some 1-bit line, and is a different use case.
|
||||
|
||||
How the registers are poked to attain the push/pull and output low
|
||||
configuration and the muxing of the "u0" or "gpio-mode" group onto these
|
||||
pins is a question for the driver.
|
||||
|
||||
Some datasheets will be more helpful and refer to the "GPIO mode" as
|
||||
"low power mode" rather than anything to do with GPIO. This often means
|
||||
the same thing electrically speaking, but in this latter case the
|
||||
software engineers will usually quickly identify that this is some
|
||||
specific muxing/configuration rather than anything related to the GPIO
|
||||
API.
|
||||
|
||||
|
||||
Board/machine configuration
|
||||
==================================
|
||||
|
||||
|
@ -89,7 +89,7 @@
|
||||
pinmux: pinmux@e0700000 {
|
||||
compatible = "st,spear1310-pinmux";
|
||||
reg = <0xe0700000 0x1000>;
|
||||
#gpio-range-cells = <2>;
|
||||
#gpio-range-cells = <3>;
|
||||
};
|
||||
|
||||
apb {
|
||||
@ -212,7 +212,7 @@
|
||||
interrupt-controller;
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
gpio-ranges = <&pinmux 0 246>;
|
||||
gpio-ranges = <&pinmux 0 0 246>;
|
||||
status = "disabled";
|
||||
|
||||
st-plgpio,ngpio = <246>;
|
||||
|
@ -63,7 +63,7 @@
|
||||
pinmux: pinmux@e0700000 {
|
||||
compatible = "st,spear1340-pinmux";
|
||||
reg = <0xe0700000 0x1000>;
|
||||
#gpio-range-cells = <2>;
|
||||
#gpio-range-cells = <3>;
|
||||
};
|
||||
|
||||
pwm: pwm@e0180000 {
|
||||
@ -127,7 +127,7 @@
|
||||
interrupt-controller;
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
gpio-ranges = <&pinmux 0 252>;
|
||||
gpio-ranges = <&pinmux 0 0 252>;
|
||||
status = "disabled";
|
||||
|
||||
st-plgpio,ngpio = <250>;
|
||||
|
@ -25,7 +25,7 @@
|
||||
pinmux: pinmux@b4000000 {
|
||||
compatible = "st,spear310-pinmux";
|
||||
reg = <0xb4000000 0x1000>;
|
||||
#gpio-range-cells = <2>;
|
||||
#gpio-range-cells = <3>;
|
||||
};
|
||||
|
||||
fsmc: flash@44000000 {
|
||||
@ -102,7 +102,7 @@
|
||||
interrupt-controller;
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
gpio-ranges = <&pinmux 0 102>;
|
||||
gpio-ranges = <&pinmux 0 0 102>;
|
||||
status = "disabled";
|
||||
|
||||
st-plgpio,ngpio = <102>;
|
||||
|
@ -24,7 +24,7 @@
|
||||
pinmux: pinmux@b3000000 {
|
||||
compatible = "st,spear320-pinmux";
|
||||
reg = <0xb3000000 0x1000>;
|
||||
#gpio-range-cells = <2>;
|
||||
#gpio-range-cells = <3>;
|
||||
};
|
||||
|
||||
clcd@90000000 {
|
||||
@ -130,7 +130,7 @@
|
||||
interrupt-controller;
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
gpio-ranges = <&pinmux 0 102>;
|
||||
gpio-ranges = <&pinmux 0 0 102>;
|
||||
status = "disabled";
|
||||
|
||||
st-plgpio,ngpio = <102>;
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include <linux/io.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/irqdomain.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/gpio.h>
|
||||
@ -22,6 +23,7 @@
|
||||
#include <linux/amba/bus.h>
|
||||
#include <linux/amba/pl061.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/pinctrl/consumer.h>
|
||||
#include <linux/pm.h>
|
||||
#include <asm/mach/irq.h>
|
||||
|
||||
@ -51,8 +53,7 @@ struct pl061_gpio {
|
||||
spinlock_t lock;
|
||||
|
||||
void __iomem *base;
|
||||
int irq_base;
|
||||
struct irq_chip_generic *irq_gc;
|
||||
struct irq_domain *domain;
|
||||
struct gpio_chip gc;
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
@ -60,6 +61,24 @@ struct pl061_gpio {
|
||||
#endif
|
||||
};
|
||||
|
||||
static int pl061_gpio_request(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
/*
|
||||
* Map back to global GPIO space and request muxing, the direction
|
||||
* parameter does not matter for this controller.
|
||||
*/
|
||||
int gpio = chip->base + offset;
|
||||
|
||||
return pinctrl_request_gpio(gpio);
|
||||
}
|
||||
|
||||
static void pl061_gpio_free(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
int gpio = chip->base + offset;
|
||||
|
||||
pinctrl_free_gpio(gpio);
|
||||
}
|
||||
|
||||
static int pl061_direction_input(struct gpio_chip *gc, unsigned offset)
|
||||
{
|
||||
struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc);
|
||||
@ -122,24 +141,20 @@ static int pl061_to_irq(struct gpio_chip *gc, unsigned offset)
|
||||
{
|
||||
struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc);
|
||||
|
||||
if (chip->irq_base <= 0)
|
||||
return -EINVAL;
|
||||
|
||||
return chip->irq_base + offset;
|
||||
return irq_create_mapping(chip->domain, offset);
|
||||
}
|
||||
|
||||
static int pl061_irq_type(struct irq_data *d, unsigned trigger)
|
||||
{
|
||||
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
|
||||
struct pl061_gpio *chip = gc->private;
|
||||
int offset = d->irq - chip->irq_base;
|
||||
struct pl061_gpio *chip = irq_data_get_irq_chip_data(d);
|
||||
int offset = irqd_to_hwirq(d);
|
||||
unsigned long flags;
|
||||
u8 gpiois, gpioibe, gpioiev;
|
||||
|
||||
if (offset < 0 || offset >= PL061_GPIO_NR)
|
||||
return -EINVAL;
|
||||
|
||||
raw_spin_lock_irqsave(&gc->lock, flags);
|
||||
spin_lock_irqsave(&chip->lock, flags);
|
||||
|
||||
gpioiev = readb(chip->base + GPIOIEV);
|
||||
|
||||
@ -168,7 +183,7 @@ static int pl061_irq_type(struct irq_data *d, unsigned trigger)
|
||||
|
||||
writeb(gpioiev, chip->base + GPIOIEV);
|
||||
|
||||
raw_spin_unlock_irqrestore(&gc->lock, flags);
|
||||
spin_unlock_irqrestore(&chip->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -192,31 +207,61 @@ static void pl061_irq_handler(unsigned irq, struct irq_desc *desc)
|
||||
chained_irq_exit(irqchip, desc);
|
||||
}
|
||||
|
||||
static void __init pl061_init_gc(struct pl061_gpio *chip, int irq_base)
|
||||
static void pl061_irq_mask(struct irq_data *d)
|
||||
{
|
||||
struct irq_chip_type *ct;
|
||||
struct pl061_gpio *chip = irq_data_get_irq_chip_data(d);
|
||||
u8 mask = 1 << (irqd_to_hwirq(d) % PL061_GPIO_NR);
|
||||
u8 gpioie;
|
||||
|
||||
chip->irq_gc = irq_alloc_generic_chip("gpio-pl061", 1, irq_base,
|
||||
chip->base, handle_simple_irq);
|
||||
chip->irq_gc->private = chip;
|
||||
|
||||
ct = chip->irq_gc->chip_types;
|
||||
ct->chip.irq_mask = irq_gc_mask_clr_bit;
|
||||
ct->chip.irq_unmask = irq_gc_mask_set_bit;
|
||||
ct->chip.irq_set_type = pl061_irq_type;
|
||||
ct->chip.irq_set_wake = irq_gc_set_wake;
|
||||
ct->regs.mask = GPIOIE;
|
||||
|
||||
irq_setup_generic_chip(chip->irq_gc, IRQ_MSK(PL061_GPIO_NR),
|
||||
IRQ_GC_INIT_NESTED_LOCK, IRQ_NOREQUEST, 0);
|
||||
spin_lock(&chip->lock);
|
||||
gpioie = readb(chip->base + GPIOIE) & ~mask;
|
||||
writeb(gpioie, chip->base + GPIOIE);
|
||||
spin_unlock(&chip->lock);
|
||||
}
|
||||
|
||||
static void pl061_irq_unmask(struct irq_data *d)
|
||||
{
|
||||
struct pl061_gpio *chip = irq_data_get_irq_chip_data(d);
|
||||
u8 mask = 1 << (irqd_to_hwirq(d) % PL061_GPIO_NR);
|
||||
u8 gpioie;
|
||||
|
||||
spin_lock(&chip->lock);
|
||||
gpioie = readb(chip->base + GPIOIE) | mask;
|
||||
writeb(gpioie, chip->base + GPIOIE);
|
||||
spin_unlock(&chip->lock);
|
||||
}
|
||||
|
||||
static struct irq_chip pl061_irqchip = {
|
||||
.name = "pl061 gpio",
|
||||
.irq_mask = pl061_irq_mask,
|
||||
.irq_unmask = pl061_irq_unmask,
|
||||
.irq_set_type = pl061_irq_type,
|
||||
};
|
||||
|
||||
static int pl061_irq_map(struct irq_domain *d, unsigned int virq,
|
||||
irq_hw_number_t hw)
|
||||
{
|
||||
struct pl061_gpio *chip = d->host_data;
|
||||
|
||||
irq_set_chip_and_handler_name(virq, &pl061_irqchip, handle_simple_irq,
|
||||
"pl061");
|
||||
irq_set_chip_data(virq, chip);
|
||||
irq_set_irq_type(virq, IRQ_TYPE_NONE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct irq_domain_ops pl061_domain_ops = {
|
||||
.map = pl061_irq_map,
|
||||
.xlate = irq_domain_xlate_twocell,
|
||||
};
|
||||
|
||||
static int pl061_probe(struct amba_device *adev, const struct amba_id *id)
|
||||
{
|
||||
struct device *dev = &adev->dev;
|
||||
struct pl061_platform_data *pdata = dev->platform_data;
|
||||
struct pl061_gpio *chip;
|
||||
int ret, irq, i;
|
||||
int ret, irq, i, irq_base;
|
||||
|
||||
chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
|
||||
if (chip == NULL)
|
||||
@ -224,24 +269,32 @@ static int pl061_probe(struct amba_device *adev, const struct amba_id *id)
|
||||
|
||||
if (pdata) {
|
||||
chip->gc.base = pdata->gpio_base;
|
||||
chip->irq_base = pdata->irq_base;
|
||||
} else if (adev->dev.of_node) {
|
||||
irq_base = pdata->irq_base;
|
||||
if (irq_base <= 0)
|
||||
return -ENODEV;
|
||||
} else {
|
||||
chip->gc.base = -1;
|
||||
chip->irq_base = 0;
|
||||
} else
|
||||
return -ENODEV;
|
||||
irq_base = 0;
|
||||
}
|
||||
|
||||
if (!devm_request_mem_region(dev, adev->res.start,
|
||||
resource_size(&adev->res), "pl061"))
|
||||
resource_size(&adev->res), "pl061"))
|
||||
return -EBUSY;
|
||||
|
||||
chip->base = devm_ioremap(dev, adev->res.start,
|
||||
resource_size(&adev->res));
|
||||
if (chip->base == NULL)
|
||||
resource_size(&adev->res));
|
||||
if (!chip->base)
|
||||
return -ENOMEM;
|
||||
|
||||
chip->domain = irq_domain_add_simple(adev->dev.of_node, PL061_GPIO_NR,
|
||||
irq_base, &pl061_domain_ops, chip);
|
||||
if (!chip->domain)
|
||||
return -ENODEV;
|
||||
|
||||
spin_lock_init(&chip->lock);
|
||||
|
||||
chip->gc.request = pl061_gpio_request;
|
||||
chip->gc.free = pl061_gpio_free;
|
||||
chip->gc.direction_input = pl061_direction_input;
|
||||
chip->gc.direction_output = pl061_direction_output;
|
||||
chip->gc.get = pl061_get_value;
|
||||
@ -259,12 +312,6 @@ static int pl061_probe(struct amba_device *adev, const struct amba_id *id)
|
||||
/*
|
||||
* irq_chip support
|
||||
*/
|
||||
|
||||
if (chip->irq_base <= 0)
|
||||
return 0;
|
||||
|
||||
pl061_init_gc(chip, chip->irq_base);
|
||||
|
||||
writeb(0, chip->base + GPIOIE); /* disable irqs */
|
||||
irq = adev->irq[0];
|
||||
if (irq < 0)
|
||||
|
@ -203,22 +203,11 @@ static void of_gpiochip_add_pin_range(struct gpio_chip *chip)
|
||||
if (!pctldev)
|
||||
break;
|
||||
|
||||
/*
|
||||
* This assumes that the n GPIO pins are consecutive in the
|
||||
* GPIO number space, and that the pins are also consecutive
|
||||
* in their local number space. Currently it is not possible
|
||||
* to add different ranges for one and the same GPIO chip,
|
||||
* as the code assumes that we have one consecutive range
|
||||
* on both, mapping 1-to-1.
|
||||
*
|
||||
* TODO: make the OF bindings handle multiple sparse ranges
|
||||
* on the same GPIO chip.
|
||||
*/
|
||||
ret = gpiochip_add_pin_range(chip,
|
||||
pinctrl_dev_get_devname(pctldev),
|
||||
0, /* offset in gpiochip */
|
||||
pinspec.args[0],
|
||||
pinspec.args[1]);
|
||||
pinspec.args[1],
|
||||
pinspec.args[2]);
|
||||
|
||||
if (ret)
|
||||
break;
|
||||
|
@ -106,20 +106,11 @@ config PINCTRL_LANTIQ
|
||||
select PINMUX
|
||||
select PINCONF
|
||||
|
||||
config PINCTRL_PXA3xx
|
||||
bool
|
||||
select PINMUX
|
||||
|
||||
config PINCTRL_FALCON
|
||||
bool
|
||||
depends on SOC_FALCON
|
||||
depends on PINCTRL_LANTIQ
|
||||
|
||||
config PINCTRL_MMP2
|
||||
bool "MMP2 pin controller driver"
|
||||
depends on ARCH_MMP
|
||||
select PINCTRL_PXA3xx
|
||||
|
||||
config PINCTRL_MXS
|
||||
bool
|
||||
select PINMUX
|
||||
@ -151,21 +142,12 @@ config PINCTRL_DB8540
|
||||
bool "DB8540 pin controller driver"
|
||||
depends on PINCTRL_NOMADIK && ARCH_U8500
|
||||
|
||||
config PINCTRL_PXA168
|
||||
bool "PXA168 pin controller driver"
|
||||
depends on ARCH_MMP
|
||||
select PINCTRL_PXA3xx
|
||||
|
||||
config PINCTRL_PXA910
|
||||
bool "PXA910 pin controller driver"
|
||||
depends on ARCH_MMP
|
||||
select PINCTRL_PXA3xx
|
||||
|
||||
config PINCTRL_SINGLE
|
||||
tristate "One-register-per-pin type device tree based pinctrl driver"
|
||||
depends on OF
|
||||
select PINMUX
|
||||
select PINCONF
|
||||
select GENERIC_PINCONF
|
||||
help
|
||||
This selects the device tree based generic pinctrl driver.
|
||||
|
||||
@ -226,6 +208,11 @@ config PINCTRL_EXYNOS5440
|
||||
select PINMUX
|
||||
select PINCONF
|
||||
|
||||
config PINCTRL_S3C64XX
|
||||
bool "Samsung S3C64XX SoC pinctrl driver"
|
||||
depends on ARCH_S3C64XX
|
||||
select PINCTRL_SAMSUNG
|
||||
|
||||
source "drivers/pinctrl/mvebu/Kconfig"
|
||||
source "drivers/pinctrl/sh-pfc/Kconfig"
|
||||
source "drivers/pinctrl/spear/Kconfig"
|
||||
|
@ -21,9 +21,7 @@ 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_PXA3xx) += pinctrl-pxa3xx.o
|
||||
obj-$(CONFIG_PINCTRL_FALCON) += pinctrl-falcon.o
|
||||
obj-$(CONFIG_PINCTRL_MMP2) += pinctrl-mmp2.o
|
||||
obj-$(CONFIG_PINCTRL_MXS) += pinctrl-mxs.o
|
||||
obj-$(CONFIG_PINCTRL_IMX23) += pinctrl-imx23.o
|
||||
obj-$(CONFIG_PINCTRL_IMX28) += pinctrl-imx28.o
|
||||
@ -31,8 +29,6 @@ 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_PXA168) += pinctrl-pxa168.o
|
||||
obj-$(CONFIG_PINCTRL_PXA910) += pinctrl-pxa910.o
|
||||
obj-$(CONFIG_PINCTRL_SINGLE) += pinctrl-single.o
|
||||
obj-$(CONFIG_PINCTRL_SIRF) += pinctrl-sirf.o
|
||||
obj-$(CONFIG_PINCTRL_SUNXI) += pinctrl-sunxi.o
|
||||
@ -45,6 +41,7 @@ obj-$(CONFIG_PINCTRL_COH901) += pinctrl-coh901.o
|
||||
obj-$(CONFIG_PINCTRL_SAMSUNG) += pinctrl-samsung.o
|
||||
obj-$(CONFIG_PINCTRL_EXYNOS) += pinctrl-exynos.o
|
||||
obj-$(CONFIG_PINCTRL_EXYNOS5440) += pinctrl-exynos5440.o
|
||||
obj-$(CONFIG_PINCTRL_S3C64XX) += pinctrl-s3c64xx.o
|
||||
obj-$(CONFIG_PINCTRL_XWAY) += pinctrl-xway.o
|
||||
obj-$(CONFIG_PINCTRL_LANTIQ) += pinctrl-lantiq.o
|
||||
|
||||
|
@ -27,6 +27,11 @@
|
||||
#include <linux/pinctrl/consumer.h>
|
||||
#include <linux/pinctrl/pinctrl.h>
|
||||
#include <linux/pinctrl/machine.h>
|
||||
|
||||
#ifdef CONFIG_GPIOLIB
|
||||
#include <asm-generic/gpio.h>
|
||||
#endif
|
||||
|
||||
#include "core.h"
|
||||
#include "devicetree.h"
|
||||
#include "pinmux.h"
|
||||
@ -35,11 +40,17 @@
|
||||
|
||||
static bool pinctrl_dummy_state;
|
||||
|
||||
/* Mutex taken by all entry points */
|
||||
DEFINE_MUTEX(pinctrl_mutex);
|
||||
/* Mutex taken to protect pinctrl_list */
|
||||
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);
|
||||
|
||||
/* Global list of pin control devices (struct pinctrl_dev) */
|
||||
LIST_HEAD(pinctrldev_list);
|
||||
static LIST_HEAD(pinctrldev_list);
|
||||
|
||||
/* List of pin controller handles (struct pinctrl) */
|
||||
static LIST_HEAD(pinctrl_list);
|
||||
@ -106,6 +117,23 @@ struct pinctrl_dev *get_pinctrl_dev_from_devname(const char *devname)
|
||||
return found ? pctldev : NULL;
|
||||
}
|
||||
|
||||
struct pinctrl_dev *get_pinctrl_dev_from_of_node(struct device_node *np)
|
||||
{
|
||||
struct pinctrl_dev *pctldev;
|
||||
|
||||
mutex_lock(&pinctrldev_list_mutex);
|
||||
|
||||
list_for_each_entry(pctldev, &pinctrldev_list, node)
|
||||
if (pctldev->dev->of_node == np) {
|
||||
mutex_unlock(&pinctrldev_list_mutex);
|
||||
return pctldev;
|
||||
}
|
||||
|
||||
mutex_lock(&pinctrldev_list_mutex);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* pin_get_from_name() - look up a pin number from a name
|
||||
* @pctldev: the pin control device to lookup the pin on
|
||||
@ -165,9 +193,9 @@ bool pin_is_valid(struct pinctrl_dev *pctldev, int pin)
|
||||
if (pin < 0)
|
||||
return false;
|
||||
|
||||
mutex_lock(&pinctrl_mutex);
|
||||
mutex_lock(&pctldev->mutex);
|
||||
pindesc = pin_desc_get(pctldev, pin);
|
||||
mutex_unlock(&pinctrl_mutex);
|
||||
mutex_unlock(&pctldev->mutex);
|
||||
|
||||
return pindesc != NULL;
|
||||
}
|
||||
@ -264,18 +292,57 @@ pinctrl_match_gpio_range(struct pinctrl_dev *pctldev, unsigned gpio)
|
||||
{
|
||||
struct pinctrl_gpio_range *range = NULL;
|
||||
|
||||
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 (gpio >= range->base &&
|
||||
gpio < range->base + range->npins) {
|
||||
mutex_unlock(&pctldev->mutex);
|
||||
return range;
|
||||
}
|
||||
}
|
||||
|
||||
mutex_unlock(&pctldev->mutex);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* pinctrl_ready_for_gpio_range() - check if other GPIO pins of
|
||||
* the same GPIO chip are in range
|
||||
* @gpio: gpio pin to check taken from the global GPIO pin space
|
||||
*
|
||||
* This function is complement of pinctrl_match_gpio_range(). If the return
|
||||
* value of pinctrl_match_gpio_range() is NULL, this function could be used
|
||||
* to check whether pinctrl device is ready or not. Maybe some GPIO pins
|
||||
* of the same GPIO chip don't have back-end pinctrl interface.
|
||||
* If the return value is true, it means that pinctrl device is ready & the
|
||||
* certain GPIO pin doesn't have back-end pinctrl device. If the return value
|
||||
* is false, it means that pinctrl device may not be ready.
|
||||
*/
|
||||
#ifdef CONFIG_GPIOLIB
|
||||
static bool pinctrl_ready_for_gpio_range(unsigned gpio)
|
||||
{
|
||||
struct pinctrl_dev *pctldev;
|
||||
struct pinctrl_gpio_range *range = NULL;
|
||||
struct gpio_chip *chip = gpio_to_chip(gpio);
|
||||
|
||||
/* Loop over the pin controllers */
|
||||
list_for_each_entry(pctldev, &pinctrldev_list, node) {
|
||||
/* Loop over the ranges */
|
||||
list_for_each_entry(range, &pctldev->gpio_ranges, node) {
|
||||
/* Check if any gpio range overlapped with gpio chip */
|
||||
if (range->base + range->npins - 1 < chip->base ||
|
||||
range->base > chip->base + chip->ngpio - 1)
|
||||
continue;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
static bool pinctrl_ready_for_gpio_range(unsigned gpio) { return true; }
|
||||
#endif
|
||||
|
||||
/**
|
||||
* pinctrl_get_device_gpio_range() - find device for GPIO range
|
||||
* @gpio: the pin to locate the pin controller for
|
||||
@ -319,9 +386,9 @@ static int pinctrl_get_device_gpio_range(unsigned gpio,
|
||||
void pinctrl_add_gpio_range(struct pinctrl_dev *pctldev,
|
||||
struct pinctrl_gpio_range *range)
|
||||
{
|
||||
mutex_lock(&pinctrl_mutex);
|
||||
mutex_lock(&pctldev->mutex);
|
||||
list_add_tail(&range->node, &pctldev->gpio_ranges);
|
||||
mutex_unlock(&pinctrl_mutex);
|
||||
mutex_unlock(&pctldev->mutex);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pinctrl_add_gpio_range);
|
||||
|
||||
@ -339,17 +406,25 @@ EXPORT_SYMBOL_GPL(pinctrl_add_gpio_ranges);
|
||||
struct pinctrl_dev *pinctrl_find_and_add_gpio_range(const char *devname,
|
||||
struct pinctrl_gpio_range *range)
|
||||
{
|
||||
struct pinctrl_dev *pctldev = get_pinctrl_dev_from_devname(devname);
|
||||
struct pinctrl_dev *pctldev;
|
||||
|
||||
mutex_lock(&pinctrldev_list_mutex);
|
||||
|
||||
pctldev = get_pinctrl_dev_from_devname(devname);
|
||||
|
||||
/*
|
||||
* If we can't find this device, let's assume that is because
|
||||
* it has not probed yet, so the driver trying to register this
|
||||
* range need to defer probing.
|
||||
*/
|
||||
if (!pctldev)
|
||||
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);
|
||||
@ -365,14 +440,17 @@ pinctrl_find_gpio_range_from_pin(struct pinctrl_dev *pctldev,
|
||||
{
|
||||
struct pinctrl_gpio_range *range = NULL;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
mutex_unlock(&pctldev->mutex);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@ -386,9 +464,9 @@ EXPORT_SYMBOL_GPL(pinctrl_find_gpio_range_from_pin);
|
||||
void pinctrl_remove_gpio_range(struct pinctrl_dev *pctldev,
|
||||
struct pinctrl_gpio_range *range)
|
||||
{
|
||||
mutex_lock(&pinctrl_mutex);
|
||||
mutex_lock(&pctldev->mutex);
|
||||
list_del(&range->node);
|
||||
mutex_unlock(&pinctrl_mutex);
|
||||
mutex_unlock(&pctldev->mutex);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pinctrl_remove_gpio_range);
|
||||
|
||||
@ -439,11 +517,13 @@ int pinctrl_request_gpio(unsigned gpio)
|
||||
int ret;
|
||||
int pin;
|
||||
|
||||
mutex_lock(&pinctrl_mutex);
|
||||
mutex_lock(&pinctrldev_list_mutex);
|
||||
|
||||
ret = pinctrl_get_device_gpio_range(gpio, &pctldev, &range);
|
||||
if (ret) {
|
||||
mutex_unlock(&pinctrl_mutex);
|
||||
if (pinctrl_ready_for_gpio_range(gpio))
|
||||
ret = 0;
|
||||
mutex_unlock(&pinctrldev_list_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -452,7 +532,7 @@ int pinctrl_request_gpio(unsigned gpio)
|
||||
|
||||
ret = pinmux_request_gpio(pctldev, range, pin, gpio);
|
||||
|
||||
mutex_unlock(&pinctrl_mutex);
|
||||
mutex_unlock(&pinctrldev_list_mutex);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pinctrl_request_gpio);
|
||||
@ -472,20 +552,22 @@ void pinctrl_free_gpio(unsigned gpio)
|
||||
int ret;
|
||||
int pin;
|
||||
|
||||
mutex_lock(&pinctrl_mutex);
|
||||
mutex_lock(&pinctrldev_list_mutex);
|
||||
|
||||
ret = pinctrl_get_device_gpio_range(gpio, &pctldev, &range);
|
||||
if (ret) {
|
||||
mutex_unlock(&pinctrl_mutex);
|
||||
mutex_unlock(&pinctrldev_list_mutex);
|
||||
return;
|
||||
}
|
||||
mutex_lock(&pctldev->mutex);
|
||||
|
||||
/* Convert to the pin controllers number space */
|
||||
pin = gpio - range->base + range->pin_base;
|
||||
|
||||
pinmux_free_gpio(pctldev, pin, range);
|
||||
|
||||
mutex_unlock(&pinctrl_mutex);
|
||||
mutex_unlock(&pctldev->mutex);
|
||||
mutex_unlock(&pinctrldev_list_mutex);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pinctrl_free_gpio);
|
||||
|
||||
@ -496,14 +578,24 @@ 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)
|
||||
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;
|
||||
ret = pinmux_gpio_direction(pctldev, range, pin, input);
|
||||
|
||||
return pinmux_gpio_direction(pctldev, range, pin, input);
|
||||
mutex_unlock(&pctldev->mutex);
|
||||
mutex_unlock(&pinctrldev_list_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -516,11 +608,7 @@ static int pinctrl_gpio_direction(unsigned gpio, bool input)
|
||||
*/
|
||||
int pinctrl_gpio_direction_input(unsigned gpio)
|
||||
{
|
||||
int ret;
|
||||
mutex_lock(&pinctrl_mutex);
|
||||
ret = pinctrl_gpio_direction(gpio, true);
|
||||
mutex_unlock(&pinctrl_mutex);
|
||||
return ret;
|
||||
return pinctrl_gpio_direction(gpio, true);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pinctrl_gpio_direction_input);
|
||||
|
||||
@ -534,11 +622,7 @@ EXPORT_SYMBOL_GPL(pinctrl_gpio_direction_input);
|
||||
*/
|
||||
int pinctrl_gpio_direction_output(unsigned gpio)
|
||||
{
|
||||
int ret;
|
||||
mutex_lock(&pinctrl_mutex);
|
||||
ret = pinctrl_gpio_direction(gpio, false);
|
||||
mutex_unlock(&pinctrl_mutex);
|
||||
return ret;
|
||||
return pinctrl_gpio_direction(gpio, false);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pinctrl_gpio_direction_output);
|
||||
|
||||
@ -641,14 +725,18 @@ static struct pinctrl *find_pinctrl(struct device *dev)
|
||||
{
|
||||
struct pinctrl *p;
|
||||
|
||||
mutex_lock(&pinctrl_list_mutex);
|
||||
list_for_each_entry(p, &pinctrl_list, node)
|
||||
if (p->dev == dev)
|
||||
if (p->dev == dev) {
|
||||
mutex_unlock(&pinctrl_list_mutex);
|
||||
return p;
|
||||
}
|
||||
|
||||
mutex_unlock(&pinctrl_list_mutex);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void pinctrl_put_locked(struct pinctrl *p, bool inlist);
|
||||
static void pinctrl_free(struct pinctrl *p, bool inlist);
|
||||
|
||||
static struct pinctrl *create_pinctrl(struct device *dev)
|
||||
{
|
||||
@ -681,6 +769,7 @@ static struct pinctrl *create_pinctrl(struct device *dev)
|
||||
|
||||
devname = dev_name(dev);
|
||||
|
||||
mutex_lock(&pinctrl_maps_mutex);
|
||||
/* Iterate over the pin control maps to locate the right ones */
|
||||
for_each_maps(maps_node, i, map) {
|
||||
/* Map must be for this device */
|
||||
@ -702,13 +791,16 @@ static struct pinctrl *create_pinctrl(struct device *dev)
|
||||
* an -EPROBE_DEFER later, as that is the worst case.
|
||||
*/
|
||||
if (ret == -EPROBE_DEFER) {
|
||||
pinctrl_put_locked(p, false);
|
||||
pinctrl_free(p, false);
|
||||
mutex_unlock(&pinctrl_maps_mutex);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
}
|
||||
mutex_unlock(&pinctrl_maps_mutex);
|
||||
|
||||
if (ret < 0) {
|
||||
/* If some other error than deferral occured, return here */
|
||||
pinctrl_put_locked(p, false);
|
||||
pinctrl_free(p, false);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
@ -720,7 +812,11 @@ static struct pinctrl *create_pinctrl(struct device *dev)
|
||||
return p;
|
||||
}
|
||||
|
||||
static struct pinctrl *pinctrl_get_locked(struct device *dev)
|
||||
/**
|
||||
* pinctrl_get() - retrieves the pinctrl handle for a device
|
||||
* @dev: the device to obtain the handle for
|
||||
*/
|
||||
struct pinctrl *pinctrl_get(struct device *dev)
|
||||
{
|
||||
struct pinctrl *p;
|
||||
|
||||
@ -741,43 +837,35 @@ static struct pinctrl *pinctrl_get_locked(struct device *dev)
|
||||
|
||||
return create_pinctrl(dev);
|
||||
}
|
||||
|
||||
/**
|
||||
* pinctrl_get() - retrieves the pinctrl handle for a device
|
||||
* @dev: the device to obtain the handle for
|
||||
*/
|
||||
struct pinctrl *pinctrl_get(struct device *dev)
|
||||
{
|
||||
struct pinctrl *p;
|
||||
|
||||
mutex_lock(&pinctrl_mutex);
|
||||
p = pinctrl_get_locked(dev);
|
||||
mutex_unlock(&pinctrl_mutex);
|
||||
|
||||
return p;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pinctrl_get);
|
||||
|
||||
static void pinctrl_put_locked(struct pinctrl *p, bool inlist)
|
||||
static void pinctrl_free_setting(bool disable_setting,
|
||||
struct pinctrl_setting *setting)
|
||||
{
|
||||
switch (setting->type) {
|
||||
case PIN_MAP_TYPE_MUX_GROUP:
|
||||
if (disable_setting)
|
||||
pinmux_disable_setting(setting);
|
||||
pinmux_free_setting(setting);
|
||||
break;
|
||||
case PIN_MAP_TYPE_CONFIGS_PIN:
|
||||
case PIN_MAP_TYPE_CONFIGS_GROUP:
|
||||
pinconf_free_setting(setting);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void pinctrl_free(struct pinctrl *p, bool inlist)
|
||||
{
|
||||
struct pinctrl_state *state, *n1;
|
||||
struct pinctrl_setting *setting, *n2;
|
||||
|
||||
mutex_lock(&pinctrl_list_mutex);
|
||||
list_for_each_entry_safe(state, n1, &p->states, node) {
|
||||
list_for_each_entry_safe(setting, n2, &state->settings, node) {
|
||||
switch (setting->type) {
|
||||
case PIN_MAP_TYPE_MUX_GROUP:
|
||||
if (state == p->state)
|
||||
pinmux_disable_setting(setting);
|
||||
pinmux_free_setting(setting);
|
||||
break;
|
||||
case PIN_MAP_TYPE_CONFIGS_PIN:
|
||||
case PIN_MAP_TYPE_CONFIGS_GROUP:
|
||||
pinconf_free_setting(setting);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
pinctrl_free_setting(state == p->state, setting);
|
||||
list_del(&setting->node);
|
||||
kfree(setting);
|
||||
}
|
||||
@ -790,6 +878,7 @@ static void pinctrl_put_locked(struct pinctrl *p, bool inlist)
|
||||
if (inlist)
|
||||
list_del(&p->node);
|
||||
kfree(p);
|
||||
mutex_unlock(&pinctrl_list_mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -800,7 +889,7 @@ static void pinctrl_release(struct kref *kref)
|
||||
{
|
||||
struct pinctrl *p = container_of(kref, struct pinctrl, users);
|
||||
|
||||
pinctrl_put_locked(p, true);
|
||||
pinctrl_free(p, true);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -809,14 +898,17 @@ static void pinctrl_release(struct kref *kref)
|
||||
*/
|
||||
void pinctrl_put(struct pinctrl *p)
|
||||
{
|
||||
mutex_lock(&pinctrl_mutex);
|
||||
kref_put(&p->users, pinctrl_release);
|
||||
mutex_unlock(&pinctrl_mutex);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pinctrl_put);
|
||||
|
||||
static struct pinctrl_state *pinctrl_lookup_state_locked(struct pinctrl *p,
|
||||
const char *name)
|
||||
/**
|
||||
* pinctrl_lookup_state() - retrieves a state handle from a pinctrl handle
|
||||
* @p: the pinctrl handle to retrieve the state from
|
||||
* @name: the state name to retrieve
|
||||
*/
|
||||
struct pinctrl_state *pinctrl_lookup_state(struct pinctrl *p,
|
||||
const char *name)
|
||||
{
|
||||
struct pinctrl_state *state;
|
||||
|
||||
@ -833,28 +925,17 @@ static struct pinctrl_state *pinctrl_lookup_state_locked(struct pinctrl *p,
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
/**
|
||||
* pinctrl_lookup_state() - retrieves a state handle from a pinctrl handle
|
||||
* @p: the pinctrl handle to retrieve the state from
|
||||
* @name: the state name to retrieve
|
||||
*/
|
||||
struct pinctrl_state *pinctrl_lookup_state(struct pinctrl *p, const char *name)
|
||||
{
|
||||
struct pinctrl_state *s;
|
||||
|
||||
mutex_lock(&pinctrl_mutex);
|
||||
s = pinctrl_lookup_state_locked(p, name);
|
||||
mutex_unlock(&pinctrl_mutex);
|
||||
|
||||
return s;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pinctrl_lookup_state);
|
||||
|
||||
static int pinctrl_select_state_locked(struct pinctrl *p,
|
||||
struct pinctrl_state *state)
|
||||
/**
|
||||
* pinctrl_select_state() - select/activate/program a pinctrl state to HW
|
||||
* @p: the pinctrl handle for the device that requests configuration
|
||||
* @state: the state handle to select/activate/program
|
||||
*/
|
||||
int pinctrl_select_state(struct pinctrl *p, struct pinctrl_state *state)
|
||||
{
|
||||
struct pinctrl_setting *setting, *setting2;
|
||||
struct pinctrl_state *old_state = p->state;
|
||||
int ret;
|
||||
|
||||
if (p->state == state)
|
||||
@ -888,7 +969,7 @@ static int pinctrl_select_state_locked(struct pinctrl *p,
|
||||
}
|
||||
}
|
||||
|
||||
p->state = state;
|
||||
p->state = NULL;
|
||||
|
||||
/* Apply all the settings for the new state */
|
||||
list_for_each_entry(setting, &state->settings, node) {
|
||||
@ -904,27 +985,36 @@ static int pinctrl_select_state_locked(struct pinctrl *p,
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
/* FIXME: Difficult to return to prev state */
|
||||
return ret;
|
||||
goto unapply_new_state;
|
||||
}
|
||||
}
|
||||
|
||||
p->state = state;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* pinctrl_select() - select/activate/program a pinctrl state to HW
|
||||
* @p: the pinctrl handle for the device that requests configuratio
|
||||
* @state: the state handle to select/activate/program
|
||||
*/
|
||||
int pinctrl_select_state(struct pinctrl *p, struct pinctrl_state *state)
|
||||
{
|
||||
int ret;
|
||||
unapply_new_state:
|
||||
dev_err(p->dev, "Error applying setting, reverse things back\n");
|
||||
|
||||
mutex_lock(&pinctrl_mutex);
|
||||
ret = pinctrl_select_state_locked(p, state);
|
||||
mutex_unlock(&pinctrl_mutex);
|
||||
list_for_each_entry(setting2, &state->settings, node) {
|
||||
if (&setting2->node == &setting->node)
|
||||
break;
|
||||
/*
|
||||
* All we can do here is pinmux_disable_setting.
|
||||
* That means that some pins are muxed differently now
|
||||
* than they were before applying the setting (We can't
|
||||
* "unmux a pin"!), but it's not a big deal since the pins
|
||||
* are free to be muxed by another apply_setting.
|
||||
*/
|
||||
if (setting2->type == PIN_MAP_TYPE_MUX_GROUP)
|
||||
pinmux_disable_setting(setting2);
|
||||
}
|
||||
|
||||
/* There's no infinite recursive loop here because p->state is NULL */
|
||||
if (old_state)
|
||||
pinctrl_select_state(p, old_state);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -979,9 +1069,8 @@ static int devm_pinctrl_match(struct device *dev, void *res, void *data)
|
||||
*/
|
||||
void devm_pinctrl_put(struct pinctrl *p)
|
||||
{
|
||||
WARN_ON(devres_destroy(p->dev, devm_pinctrl_release,
|
||||
WARN_ON(devres_release(p->dev, devm_pinctrl_release,
|
||||
devm_pinctrl_match, p));
|
||||
pinctrl_put(p);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devm_pinctrl_put);
|
||||
|
||||
@ -1055,10 +1144,10 @@ int pinctrl_register_map(struct pinctrl_map const *maps, unsigned num_maps,
|
||||
}
|
||||
|
||||
if (!locked)
|
||||
mutex_lock(&pinctrl_mutex);
|
||||
mutex_lock(&pinctrl_maps_mutex);
|
||||
list_add_tail(&maps_node->node, &pinctrl_maps);
|
||||
if (!locked)
|
||||
mutex_unlock(&pinctrl_mutex);
|
||||
mutex_unlock(&pinctrl_maps_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1080,12 +1169,15 @@ void pinctrl_unregister_map(struct pinctrl_map const *map)
|
||||
{
|
||||
struct pinctrl_maps *maps_node;
|
||||
|
||||
mutex_lock(&pinctrl_maps_mutex);
|
||||
list_for_each_entry(maps_node, &pinctrl_maps, node) {
|
||||
if (maps_node->maps == map) {
|
||||
list_del(&maps_node->node);
|
||||
mutex_unlock(&pinctrl_maps_mutex);
|
||||
return;
|
||||
}
|
||||
}
|
||||
mutex_unlock(&pinctrl_maps_mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1122,7 +1214,7 @@ static int pinctrl_pins_show(struct seq_file *s, void *what)
|
||||
|
||||
seq_printf(s, "registered pins: %d\n", pctldev->desc->npins);
|
||||
|
||||
mutex_lock(&pinctrl_mutex);
|
||||
mutex_lock(&pctldev->mutex);
|
||||
|
||||
/* The pin number can be retrived from the pin controller descriptor */
|
||||
for (i = 0; i < pctldev->desc->npins; i++) {
|
||||
@ -1144,7 +1236,7 @@ static int pinctrl_pins_show(struct seq_file *s, void *what)
|
||||
seq_puts(s, "\n");
|
||||
}
|
||||
|
||||
mutex_unlock(&pinctrl_mutex);
|
||||
mutex_unlock(&pctldev->mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1155,8 +1247,9 @@ static int pinctrl_groups_show(struct seq_file *s, void *what)
|
||||
const struct pinctrl_ops *ops = pctldev->desc->pctlops;
|
||||
unsigned ngroups, selector = 0;
|
||||
|
||||
mutex_lock(&pctldev->mutex);
|
||||
|
||||
ngroups = ops->get_groups_count(pctldev);
|
||||
mutex_lock(&pinctrl_mutex);
|
||||
|
||||
seq_puts(s, "registered pin groups:\n");
|
||||
while (selector < ngroups) {
|
||||
@ -1177,7 +1270,7 @@ static int pinctrl_groups_show(struct seq_file *s, void *what)
|
||||
for (i = 0; i < num_pins; i++) {
|
||||
pname = pin_get_name(pctldev, pins[i]);
|
||||
if (WARN_ON(!pname)) {
|
||||
mutex_unlock(&pinctrl_mutex);
|
||||
mutex_unlock(&pctldev->mutex);
|
||||
return -EINVAL;
|
||||
}
|
||||
seq_printf(s, "pin %d (%s)\n", pins[i], pname);
|
||||
@ -1187,7 +1280,7 @@ static int pinctrl_groups_show(struct seq_file *s, void *what)
|
||||
selector++;
|
||||
}
|
||||
|
||||
mutex_unlock(&pinctrl_mutex);
|
||||
mutex_unlock(&pctldev->mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1199,7 +1292,7 @@ static int pinctrl_gpioranges_show(struct seq_file *s, void *what)
|
||||
|
||||
seq_puts(s, "GPIO ranges handled:\n");
|
||||
|
||||
mutex_lock(&pinctrl_mutex);
|
||||
mutex_lock(&pctldev->mutex);
|
||||
|
||||
/* Loop over the ranges */
|
||||
list_for_each_entry(range, &pctldev->gpio_ranges, node) {
|
||||
@ -1210,7 +1303,7 @@ static int pinctrl_gpioranges_show(struct seq_file *s, void *what)
|
||||
(range->pin_base + range->npins - 1));
|
||||
}
|
||||
|
||||
mutex_unlock(&pinctrl_mutex);
|
||||
mutex_unlock(&pctldev->mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1221,7 +1314,7 @@ static int pinctrl_devices_show(struct seq_file *s, void *what)
|
||||
|
||||
seq_puts(s, "name [pinmux] [pinconf]\n");
|
||||
|
||||
mutex_lock(&pinctrl_mutex);
|
||||
mutex_lock(&pinctrldev_list_mutex);
|
||||
|
||||
list_for_each_entry(pctldev, &pinctrldev_list, node) {
|
||||
seq_printf(s, "%s ", pctldev->desc->name);
|
||||
@ -1236,7 +1329,7 @@ static int pinctrl_devices_show(struct seq_file *s, void *what)
|
||||
seq_puts(s, "\n");
|
||||
}
|
||||
|
||||
mutex_unlock(&pinctrl_mutex);
|
||||
mutex_unlock(&pinctrldev_list_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1265,8 +1358,7 @@ static int pinctrl_maps_show(struct seq_file *s, void *what)
|
||||
|
||||
seq_puts(s, "Pinctrl maps:\n");
|
||||
|
||||
mutex_lock(&pinctrl_mutex);
|
||||
|
||||
mutex_lock(&pinctrl_maps_mutex);
|
||||
for_each_maps(maps_node, i, map) {
|
||||
seq_printf(s, "device %s\nstate %s\ntype %s (%d)\n",
|
||||
map->dev_name, map->name, map_type(map->type),
|
||||
@ -1290,8 +1382,7 @@ static int pinctrl_maps_show(struct seq_file *s, void *what)
|
||||
|
||||
seq_printf(s, "\n");
|
||||
}
|
||||
|
||||
mutex_unlock(&pinctrl_mutex);
|
||||
mutex_unlock(&pinctrl_maps_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1304,7 +1395,7 @@ static int pinctrl_show(struct seq_file *s, void *what)
|
||||
|
||||
seq_puts(s, "Requested pin control handlers their pinmux maps:\n");
|
||||
|
||||
mutex_lock(&pinctrl_mutex);
|
||||
mutex_lock(&pinctrl_list_mutex);
|
||||
|
||||
list_for_each_entry(p, &pinctrl_list, node) {
|
||||
seq_printf(s, "device: %s current state: %s\n",
|
||||
@ -1336,7 +1427,7 @@ static int pinctrl_show(struct seq_file *s, void *what)
|
||||
}
|
||||
}
|
||||
|
||||
mutex_unlock(&pinctrl_mutex);
|
||||
mutex_unlock(&pinctrl_list_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1522,6 +1613,7 @@ struct pinctrl_dev *pinctrl_register(struct pinctrl_desc *pctldesc,
|
||||
INIT_RADIX_TREE(&pctldev->pin_desc_tree, GFP_KERNEL);
|
||||
INIT_LIST_HEAD(&pctldev->gpio_ranges);
|
||||
pctldev->dev = dev;
|
||||
mutex_init(&pctldev->mutex);
|
||||
|
||||
/* check core ops for sanity */
|
||||
if (pinctrl_check_ops(pctldev)) {
|
||||
@ -1551,38 +1643,37 @@ struct pinctrl_dev *pinctrl_register(struct pinctrl_desc *pctldesc,
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
mutex_lock(&pinctrl_mutex);
|
||||
|
||||
mutex_lock(&pinctrldev_list_mutex);
|
||||
list_add_tail(&pctldev->node, &pinctrldev_list);
|
||||
mutex_unlock(&pinctrldev_list_mutex);
|
||||
|
||||
pctldev->p = pinctrl_get(pctldev->dev);
|
||||
|
||||
pctldev->p = pinctrl_get_locked(pctldev->dev);
|
||||
if (!IS_ERR(pctldev->p)) {
|
||||
pctldev->hog_default =
|
||||
pinctrl_lookup_state_locked(pctldev->p,
|
||||
PINCTRL_STATE_DEFAULT);
|
||||
pinctrl_lookup_state(pctldev->p, PINCTRL_STATE_DEFAULT);
|
||||
if (IS_ERR(pctldev->hog_default)) {
|
||||
dev_dbg(dev, "failed to lookup the default state\n");
|
||||
} else {
|
||||
if (pinctrl_select_state_locked(pctldev->p,
|
||||
if (pinctrl_select_state(pctldev->p,
|
||||
pctldev->hog_default))
|
||||
dev_err(dev,
|
||||
"failed to select default state\n");
|
||||
}
|
||||
|
||||
pctldev->hog_sleep =
|
||||
pinctrl_lookup_state_locked(pctldev->p,
|
||||
pinctrl_lookup_state(pctldev->p,
|
||||
PINCTRL_STATE_SLEEP);
|
||||
if (IS_ERR(pctldev->hog_sleep))
|
||||
dev_dbg(dev, "failed to lookup the sleep state\n");
|
||||
}
|
||||
|
||||
mutex_unlock(&pinctrl_mutex);
|
||||
|
||||
pinctrl_init_device_debugfs(pctldev);
|
||||
|
||||
return pctldev;
|
||||
|
||||
out_err:
|
||||
mutex_destroy(&pctldev->mutex);
|
||||
kfree(pctldev);
|
||||
return NULL;
|
||||
}
|
||||
@ -1600,12 +1691,13 @@ void pinctrl_unregister(struct pinctrl_dev *pctldev)
|
||||
if (pctldev == NULL)
|
||||
return;
|
||||
|
||||
mutex_lock(&pinctrldev_list_mutex);
|
||||
mutex_lock(&pctldev->mutex);
|
||||
|
||||
pinctrl_remove_device_debugfs(pctldev);
|
||||
|
||||
mutex_lock(&pinctrl_mutex);
|
||||
|
||||
if (!IS_ERR(pctldev->p))
|
||||
pinctrl_put_locked(pctldev->p, true);
|
||||
pinctrl_put(pctldev->p);
|
||||
|
||||
/* TODO: check that no pinmuxes are still active? */
|
||||
list_del(&pctldev->node);
|
||||
@ -1616,9 +1708,10 @@ void pinctrl_unregister(struct pinctrl_dev *pctldev)
|
||||
list_for_each_entry_safe(range, n, &pctldev->gpio_ranges, node)
|
||||
list_del(&range->node);
|
||||
|
||||
mutex_unlock(&pctldev->mutex);
|
||||
mutex_destroy(&pctldev->mutex);
|
||||
kfree(pctldev);
|
||||
|
||||
mutex_unlock(&pinctrl_mutex);
|
||||
mutex_unlock(&pinctrldev_list_mutex);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pinctrl_unregister);
|
||||
|
||||
|
@ -33,6 +33,7 @@ struct pinctrl_gpio_range;
|
||||
* @p: result of pinctrl_get() for this device
|
||||
* @hog_default: default state for pins hogged by this device
|
||||
* @hog_sleep: sleep state for pins hogged by this device
|
||||
* @mutex: mutex taken on each pin controller specific action
|
||||
* @device_root: debugfs root for this device
|
||||
*/
|
||||
struct pinctrl_dev {
|
||||
@ -46,6 +47,7 @@ struct pinctrl_dev {
|
||||
struct pinctrl *p;
|
||||
struct pinctrl_state *hog_default;
|
||||
struct pinctrl_state *hog_sleep;
|
||||
struct mutex mutex;
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
struct dentry *device_root;
|
||||
#endif
|
||||
@ -72,7 +74,7 @@ struct pinctrl {
|
||||
|
||||
/**
|
||||
* struct pinctrl_state - a pinctrl state for a device
|
||||
* @node: list not for struct pinctrl's @states field
|
||||
* @node: list node for struct pinctrl's @states field
|
||||
* @name: the name of this state
|
||||
* @settings: a list of settings for this state
|
||||
*/
|
||||
@ -168,6 +170,7 @@ struct pinctrl_maps {
|
||||
};
|
||||
|
||||
struct pinctrl_dev *get_pinctrl_dev_from_devname(const char *dev_name);
|
||||
struct pinctrl_dev *get_pinctrl_dev_from_of_node(struct device_node *np);
|
||||
int pin_get_from_name(struct pinctrl_dev *pctldev, const char *name);
|
||||
const char *pin_get_name(struct pinctrl_dev *pctldev, const unsigned pin);
|
||||
int pinctrl_get_group_selector(struct pinctrl_dev *pctldev,
|
||||
@ -186,8 +189,7 @@ void pinctrl_unregister_map(struct pinctrl_map const *map);
|
||||
extern int pinctrl_force_sleep(struct pinctrl_dev *pctldev);
|
||||
extern int pinctrl_force_default(struct pinctrl_dev *pctldev);
|
||||
|
||||
extern struct mutex pinctrl_mutex;
|
||||
extern struct list_head pinctrldev_list;
|
||||
extern struct mutex pinctrl_maps_mutex;
|
||||
extern struct list_head pinctrl_maps;
|
||||
|
||||
#define for_each_maps(_maps_node_, _i_, _map_) \
|
||||
|
@ -41,7 +41,7 @@ static void dt_free_map(struct pinctrl_dev *pctldev,
|
||||
struct pinctrl_map *map, unsigned num_maps)
|
||||
{
|
||||
if (pctldev) {
|
||||
struct pinctrl_ops *ops = pctldev->desc->pctlops;
|
||||
const struct pinctrl_ops *ops = pctldev->desc->pctlops;
|
||||
ops->dt_free_map(pctldev, map, num_maps);
|
||||
} else {
|
||||
/* There is no pctldev for PIN_MAP_TYPE_DUMMY_STATE */
|
||||
@ -95,22 +95,11 @@ static int dt_remember_or_free_map(struct pinctrl *p, const char *statename,
|
||||
return pinctrl_register_map(map, num_maps, false, true);
|
||||
}
|
||||
|
||||
static struct pinctrl_dev *find_pinctrl_by_of_node(struct device_node *np)
|
||||
{
|
||||
struct pinctrl_dev *pctldev;
|
||||
|
||||
list_for_each_entry(pctldev, &pinctrldev_list, node)
|
||||
if (pctldev->dev->of_node == np)
|
||||
return pctldev;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct pinctrl_dev *of_pinctrl_get(struct device_node *np)
|
||||
{
|
||||
struct pinctrl_dev *pctldev;
|
||||
|
||||
pctldev = find_pinctrl_by_of_node(np);
|
||||
pctldev = get_pinctrl_dev_from_of_node(np);
|
||||
if (!pctldev)
|
||||
return NULL;
|
||||
|
||||
@ -122,7 +111,7 @@ static int dt_to_map_one_config(struct pinctrl *p, const char *statename,
|
||||
{
|
||||
struct device_node *np_pctldev;
|
||||
struct pinctrl_dev *pctldev;
|
||||
struct pinctrl_ops *ops;
|
||||
const struct pinctrl_ops *ops;
|
||||
int ret;
|
||||
struct pinctrl_map *map;
|
||||
unsigned num_maps;
|
||||
@ -138,7 +127,7 @@ static int dt_to_map_one_config(struct pinctrl *p, const char *statename,
|
||||
/* OK let's just assume this will appear later then */
|
||||
return -EPROBE_DEFER;
|
||||
}
|
||||
pctldev = find_pinctrl_by_of_node(np_pctldev);
|
||||
pctldev = get_pinctrl_dev_from_of_node(np_pctldev);
|
||||
if (pctldev)
|
||||
break;
|
||||
/* Do not defer probing of hogs (circular loop) */
|
||||
|
@ -263,7 +263,7 @@ static void mvebu_pinconf_group_dbg_show(struct pinctrl_dev *pctldev,
|
||||
return;
|
||||
}
|
||||
|
||||
static struct pinconf_ops mvebu_pinconf_ops = {
|
||||
static const struct pinconf_ops mvebu_pinconf_ops = {
|
||||
.pin_config_group_get = mvebu_pinconf_group_get,
|
||||
.pin_config_group_set = mvebu_pinconf_group_set,
|
||||
.pin_config_group_dbg_show = mvebu_pinconf_group_dbg_show,
|
||||
@ -369,7 +369,7 @@ static int mvebu_pinmux_gpio_set_direction(struct pinctrl_dev *pctldev,
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
static struct pinmux_ops mvebu_pinmux_ops = {
|
||||
static const struct pinmux_ops mvebu_pinmux_ops = {
|
||||
.get_functions_count = mvebu_pinmux_get_funcs_count,
|
||||
.get_function_name = mvebu_pinmux_get_func_name,
|
||||
.get_function_groups = mvebu_pinmux_get_groups,
|
||||
@ -470,7 +470,7 @@ static void mvebu_pinctrl_dt_free_map(struct pinctrl_dev *pctldev,
|
||||
kfree(map);
|
||||
}
|
||||
|
||||
static struct pinctrl_ops mvebu_pinctrl_ops = {
|
||||
static const struct pinctrl_ops mvebu_pinctrl_ops = {
|
||||
.get_groups_count = mvebu_pinctrl_get_groups_count,
|
||||
.get_group_name = mvebu_pinctrl_get_group_name,
|
||||
.get_group_pins = mvebu_pinctrl_get_group_pins,
|
||||
@ -478,8 +478,12 @@ static struct pinctrl_ops mvebu_pinctrl_ops = {
|
||||
.dt_free_map = mvebu_pinctrl_dt_free_map,
|
||||
};
|
||||
|
||||
static int _add_function(struct mvebu_pinctrl_function *funcs, const char *name)
|
||||
static int _add_function(struct mvebu_pinctrl_function *funcs, int *funcsize,
|
||||
const char *name)
|
||||
{
|
||||
if (*funcsize <= 0)
|
||||
return -EOVERFLOW;
|
||||
|
||||
while (funcs->num_groups) {
|
||||
/* function already there */
|
||||
if (strcmp(funcs->name, name) == 0) {
|
||||
@ -488,8 +492,12 @@ static int _add_function(struct mvebu_pinctrl_function *funcs, const char *name)
|
||||
}
|
||||
funcs++;
|
||||
}
|
||||
|
||||
/* append new unique function */
|
||||
funcs->name = name;
|
||||
funcs->num_groups = 1;
|
||||
(*funcsize)--;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -497,12 +505,12 @@ static int mvebu_pinctrl_build_functions(struct platform_device *pdev,
|
||||
struct mvebu_pinctrl *pctl)
|
||||
{
|
||||
struct mvebu_pinctrl_function *funcs;
|
||||
int num = 0;
|
||||
int num = 0, funcsize = pctl->desc.npins;
|
||||
int n, s;
|
||||
|
||||
/* we allocate functions for number of pins and hope
|
||||
* there are less unique functions than pins available */
|
||||
funcs = devm_kzalloc(&pdev->dev, pctl->desc.npins *
|
||||
* there are fewer unique functions than pins available */
|
||||
funcs = devm_kzalloc(&pdev->dev, funcsize *
|
||||
sizeof(struct mvebu_pinctrl_function), GFP_KERNEL);
|
||||
if (!funcs)
|
||||
return -ENOMEM;
|
||||
@ -510,26 +518,27 @@ static int mvebu_pinctrl_build_functions(struct platform_device *pdev,
|
||||
for (n = 0; n < pctl->num_groups; n++) {
|
||||
struct mvebu_pinctrl_group *grp = &pctl->groups[n];
|
||||
for (s = 0; s < grp->num_settings; s++) {
|
||||
int ret;
|
||||
|
||||
/* skip unsupported settings on this variant */
|
||||
if (pctl->variant &&
|
||||
!(pctl->variant & grp->settings[s].variant))
|
||||
continue;
|
||||
|
||||
/* check for unique functions and count groups */
|
||||
if (_add_function(funcs, grp->settings[s].name))
|
||||
ret = _add_function(funcs, &funcsize,
|
||||
grp->settings[s].name);
|
||||
if (ret == -EOVERFLOW)
|
||||
dev_err(&pdev->dev,
|
||||
"More functions than pins(%d)\n",
|
||||
pctl->desc.npins);
|
||||
if (ret < 0)
|
||||
continue;
|
||||
|
||||
num++;
|
||||
}
|
||||
}
|
||||
|
||||
/* with the number of unique functions and it's groups known,
|
||||
reallocate functions and assign group names */
|
||||
funcs = krealloc(funcs, num * sizeof(struct mvebu_pinctrl_function),
|
||||
GFP_KERNEL);
|
||||
if (!funcs)
|
||||
return -ENOMEM;
|
||||
|
||||
pctl->num_functions = num;
|
||||
pctl->functions = funcs;
|
||||
|
||||
|
@ -12,6 +12,7 @@
|
||||
#define pr_fmt(fmt) "generic pinconfig core: " fmt
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/slab.h>
|
||||
@ -33,7 +34,7 @@ struct pin_config_item {
|
||||
|
||||
#define PCONFDUMP(a, b, c) { .param = a, .display = b, .format = c }
|
||||
|
||||
struct pin_config_item conf_items[] = {
|
||||
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_PULL_UP, "input bias pull up", NULL),
|
||||
@ -59,7 +60,7 @@ void pinconf_generic_dump_pin(struct pinctrl_dev *pctldev,
|
||||
if (!ops->is_generic)
|
||||
return;
|
||||
|
||||
for(i = 0; i < ARRAY_SIZE(conf_items); i++) {
|
||||
for (i = 0; i < ARRAY_SIZE(conf_items); i++) {
|
||||
unsigned long config;
|
||||
int ret;
|
||||
|
||||
@ -94,7 +95,7 @@ void pinconf_generic_dump_group(struct pinctrl_dev *pctldev,
|
||||
if (!ops->is_generic)
|
||||
return;
|
||||
|
||||
for(i = 0; i < ARRAY_SIZE(conf_items); i++) {
|
||||
for (i = 0; i < ARRAY_SIZE(conf_items); i++) {
|
||||
unsigned long config;
|
||||
int ret;
|
||||
|
||||
@ -120,4 +121,17 @@ void pinconf_generic_dump_group(struct pinctrl_dev *pctldev,
|
||||
}
|
||||
}
|
||||
|
||||
void pinconf_generic_dump_config(struct pinctrl_dev *pctldev,
|
||||
struct seq_file *s, unsigned long config)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(conf_items); i++) {
|
||||
if (pinconf_to_config_param(config) != conf_items[i].param)
|
||||
continue;
|
||||
seq_printf(s, "%s: 0x%x", conf_items[i].display,
|
||||
pinconf_to_config_argument(config));
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pinconf_generic_dump_config);
|
||||
#endif
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/pinctrl/machine.h>
|
||||
#include <linux/pinctrl/pinctrl.h>
|
||||
#include <linux/pinctrl/pinconf.h>
|
||||
@ -88,14 +89,14 @@ int pin_config_get(const char *dev_name, const char *name,
|
||||
struct pinctrl_dev *pctldev;
|
||||
int pin;
|
||||
|
||||
mutex_lock(&pinctrl_mutex);
|
||||
|
||||
pctldev = get_pinctrl_dev_from_devname(dev_name);
|
||||
if (!pctldev) {
|
||||
pin = -EINVAL;
|
||||
goto unlock;
|
||||
return pin;
|
||||
}
|
||||
|
||||
mutex_lock(&pctldev->mutex);
|
||||
|
||||
pin = pin_get_from_name(pctldev, name);
|
||||
if (pin < 0)
|
||||
goto unlock;
|
||||
@ -103,7 +104,7 @@ int pin_config_get(const char *dev_name, const char *name,
|
||||
pin = pin_config_get_for_pin(pctldev, pin, config);
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&pinctrl_mutex);
|
||||
mutex_unlock(&pctldev->mutex);
|
||||
return pin;
|
||||
}
|
||||
EXPORT_SYMBOL(pin_config_get);
|
||||
@ -144,14 +145,14 @@ int pin_config_set(const char *dev_name, const char *name,
|
||||
struct pinctrl_dev *pctldev;
|
||||
int pin, ret;
|
||||
|
||||
mutex_lock(&pinctrl_mutex);
|
||||
|
||||
pctldev = get_pinctrl_dev_from_devname(dev_name);
|
||||
if (!pctldev) {
|
||||
ret = -EINVAL;
|
||||
goto unlock;
|
||||
return ret;
|
||||
}
|
||||
|
||||
mutex_lock(&pctldev->mutex);
|
||||
|
||||
pin = pin_get_from_name(pctldev, name);
|
||||
if (pin < 0) {
|
||||
ret = pin;
|
||||
@ -161,7 +162,7 @@ int pin_config_set(const char *dev_name, const char *name,
|
||||
ret = pin_config_set_for_pin(pctldev, pin, config);
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&pinctrl_mutex);
|
||||
mutex_unlock(&pctldev->mutex);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(pin_config_set);
|
||||
@ -173,13 +174,14 @@ int pin_config_group_get(const char *dev_name, const char *pin_group,
|
||||
const struct pinconf_ops *ops;
|
||||
int selector, ret;
|
||||
|
||||
mutex_lock(&pinctrl_mutex);
|
||||
|
||||
pctldev = get_pinctrl_dev_from_devname(dev_name);
|
||||
if (!pctldev) {
|
||||
ret = -EINVAL;
|
||||
goto unlock;
|
||||
return ret;
|
||||
}
|
||||
|
||||
mutex_lock(&pctldev->mutex);
|
||||
|
||||
ops = pctldev->desc->confops;
|
||||
|
||||
if (!ops || !ops->pin_config_group_get) {
|
||||
@ -199,7 +201,7 @@ int pin_config_group_get(const char *dev_name, const char *pin_group,
|
||||
ret = ops->pin_config_group_get(pctldev, selector, config);
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&pinctrl_mutex);
|
||||
mutex_unlock(&pctldev->mutex);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(pin_config_group_get);
|
||||
@ -216,13 +218,14 @@ int pin_config_group_set(const char *dev_name, const char *pin_group,
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
mutex_lock(&pinctrl_mutex);
|
||||
|
||||
pctldev = get_pinctrl_dev_from_devname(dev_name);
|
||||
if (!pctldev) {
|
||||
ret = -EINVAL;
|
||||
goto unlock;
|
||||
return ret;
|
||||
}
|
||||
|
||||
mutex_lock(&pctldev->mutex);
|
||||
|
||||
ops = pctldev->desc->confops;
|
||||
pctlops = pctldev->desc->pctlops;
|
||||
|
||||
@ -278,7 +281,7 @@ int pin_config_group_set(const char *dev_name, const char *pin_group,
|
||||
ret = 0;
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&pinctrl_mutex);
|
||||
mutex_unlock(&pctldev->mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -486,7 +489,7 @@ static int pinconf_pins_show(struct seq_file *s, void *what)
|
||||
seq_puts(s, "Pin config settings per pin\n");
|
||||
seq_puts(s, "Format: pin (name): configs\n");
|
||||
|
||||
mutex_lock(&pinctrl_mutex);
|
||||
mutex_lock(&pctldev->mutex);
|
||||
|
||||
/* The pin number can be retrived from the pin controller descriptor */
|
||||
for (i = 0; i < pctldev->desc->npins; i++) {
|
||||
@ -506,7 +509,7 @@ static int pinconf_pins_show(struct seq_file *s, void *what)
|
||||
seq_printf(s, "\n");
|
||||
}
|
||||
|
||||
mutex_unlock(&pinctrl_mutex);
|
||||
mutex_unlock(&pctldev->mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -574,122 +577,58 @@ static const struct file_operations pinconf_groups_ops = {
|
||||
.release = single_release,
|
||||
};
|
||||
|
||||
/* 32bit read/write ressources */
|
||||
#define MAX_NAME_LEN 16
|
||||
char dbg_pinname[MAX_NAME_LEN]; /* shared: name of the state of the pin*/
|
||||
char dbg_state_name[MAX_NAME_LEN]; /* shared: state of the pin*/
|
||||
static u32 dbg_config; /* shared: config to be read/set for the pin & state*/
|
||||
#define MAX_NAME_LEN 15
|
||||
|
||||
static int pinconf_dbg_pinname_print(struct seq_file *s, void *d)
|
||||
{
|
||||
if (strlen(dbg_pinname))
|
||||
seq_printf(s, "%s\n", dbg_pinname);
|
||||
else
|
||||
seq_printf(s, "No pin name set\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pinconf_dbg_pinname_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, pinconf_dbg_pinname_print, inode->i_private);
|
||||
}
|
||||
|
||||
static int pinconf_dbg_pinname_write(struct file *file,
|
||||
const char __user *user_buf, size_t count, loff_t *ppos)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (count > MAX_NAME_LEN)
|
||||
return -EINVAL;
|
||||
|
||||
err = sscanf(user_buf, "%15s", dbg_pinname);
|
||||
|
||||
if (err != 1)
|
||||
return -EINVAL;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static const struct file_operations pinconf_dbg_pinname_fops = {
|
||||
.open = pinconf_dbg_pinname_open,
|
||||
.write = pinconf_dbg_pinname_write,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
.owner = THIS_MODULE,
|
||||
struct dbg_cfg {
|
||||
enum pinctrl_map_type map_type;
|
||||
char dev_name[MAX_NAME_LEN+1];
|
||||
char state_name[MAX_NAME_LEN+1];
|
||||
char pin_name[MAX_NAME_LEN+1];
|
||||
};
|
||||
|
||||
static int pinconf_dbg_state_print(struct seq_file *s, void *d)
|
||||
{
|
||||
if (strlen(dbg_state_name))
|
||||
seq_printf(s, "%s\n", dbg_state_name);
|
||||
else
|
||||
seq_printf(s, "No pin state set\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pinconf_dbg_state_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, pinconf_dbg_state_print, inode->i_private);
|
||||
}
|
||||
|
||||
static int pinconf_dbg_state_write(struct file *file,
|
||||
const char __user *user_buf, size_t count, loff_t *ppos)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (count > MAX_NAME_LEN)
|
||||
return -EINVAL;
|
||||
|
||||
err = sscanf(user_buf, "%15s", dbg_state_name);
|
||||
|
||||
if (err != 1)
|
||||
return -EINVAL;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static const struct file_operations pinconf_dbg_pinstate_fops = {
|
||||
.open = pinconf_dbg_state_open,
|
||||
.write = pinconf_dbg_state_write,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
/*
|
||||
* Goal is to keep this structure as global in order to simply read the
|
||||
* pinconf-config file after a write to check config is as expected
|
||||
*/
|
||||
static struct dbg_cfg pinconf_dbg_conf;
|
||||
|
||||
/**
|
||||
* pinconf_dbg_config_print() - display the pinctrl config from the pinctrl
|
||||
* map, of a pin/state pair based on pinname and state that have been
|
||||
* selected with the debugfs entries pinconf-name and pinconf-state
|
||||
* @s: contains the 32bits config to be written
|
||||
* map, of the dev/pin/state that was last written to pinconf-config file.
|
||||
* @s: string filled in with config description
|
||||
* @d: not used
|
||||
*/
|
||||
static int pinconf_dbg_config_print(struct seq_file *s, void *d)
|
||||
{
|
||||
struct pinctrl_maps *maps_node;
|
||||
struct pinctrl_map const *map;
|
||||
const struct pinctrl_map *map;
|
||||
struct pinctrl_dev *pctldev = NULL;
|
||||
struct pinconf_ops *confops = NULL;
|
||||
const struct pinconf_ops *confops = NULL;
|
||||
const struct pinctrl_map_configs *configs;
|
||||
struct dbg_cfg *dbg = &pinconf_dbg_conf;
|
||||
int i, j;
|
||||
bool found = false;
|
||||
unsigned long config;
|
||||
|
||||
mutex_lock(&pinctrl_mutex);
|
||||
mutex_lock(&pctldev->mutex);
|
||||
|
||||
/* Parse the pinctrl map and look for the elected pin/state */
|
||||
for_each_maps(maps_node, i, map) {
|
||||
if (map->type != PIN_MAP_TYPE_CONFIGS_PIN)
|
||||
if (map->type != dbg->map_type)
|
||||
continue;
|
||||
|
||||
if (strncmp(map->name, dbg_state_name, MAX_NAME_LEN) > 0)
|
||||
if (strcmp(map->dev_name, dbg->dev_name))
|
||||
continue;
|
||||
if (strcmp(map->name, dbg->state_name))
|
||||
continue;
|
||||
|
||||
for (j = 0; j < map->data.configs.num_configs; j++) {
|
||||
if (0 == strncmp(map->data.configs.group_or_pin,
|
||||
dbg_pinname, MAX_NAME_LEN)) {
|
||||
/* We found the right pin / state, read the
|
||||
* config and store the pctldev */
|
||||
dbg_config = map->data.configs.configs[j];
|
||||
if (!strcmp(map->data.configs.group_or_pin,
|
||||
dbg->pin_name)) {
|
||||
/*
|
||||
* We found the right pin / state, read the
|
||||
* config and he pctldev for later use
|
||||
*/
|
||||
configs = &map->data.configs;
|
||||
pctldev = get_pinctrl_dev_from_devname
|
||||
(map->ctrl_dev_name);
|
||||
found = true;
|
||||
@ -698,74 +637,166 @@ static int pinconf_dbg_config_print(struct seq_file *s, void *d)
|
||||
}
|
||||
}
|
||||
|
||||
mutex_unlock(&pinctrl_mutex);
|
||||
|
||||
if (found) {
|
||||
seq_printf(s, "Config of %s in state %s: 0x%08X\n", dbg_pinname,
|
||||
dbg_state_name, dbg_config);
|
||||
|
||||
if (pctldev)
|
||||
confops = pctldev->desc->confops;
|
||||
|
||||
if (confops && confops->pin_config_config_dbg_show)
|
||||
confops->pin_config_config_dbg_show(pctldev,
|
||||
s, dbg_config);
|
||||
} else {
|
||||
seq_printf(s, "No pin found for defined name/state\n");
|
||||
if (!found) {
|
||||
seq_printf(s, "No config found for dev/state/pin, expected:\n");
|
||||
seq_printf(s, "Searched dev:%s\n", dbg->dev_name);
|
||||
seq_printf(s, "Searched state:%s\n", dbg->state_name);
|
||||
seq_printf(s, "Searched pin:%s\n", dbg->pin_name);
|
||||
seq_printf(s, "Use: modify config_pin <devname> "\
|
||||
"<state> <pinname> <value>\n");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
config = *(configs->configs);
|
||||
seq_printf(s, "Dev %s has config of %s in state %s: 0x%08lX\n",
|
||||
dbg->dev_name, dbg->pin_name,
|
||||
dbg->state_name, config);
|
||||
|
||||
if (pctldev)
|
||||
confops = pctldev->desc->confops;
|
||||
|
||||
if (confops && confops->pin_config_config_dbg_show)
|
||||
confops->pin_config_config_dbg_show(pctldev, s, config);
|
||||
|
||||
exit:
|
||||
mutex_unlock(&pctldev->mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* pinconf_dbg_config_write() - modify the pinctrl config in the pinctrl
|
||||
* map, of a dev/pin/state entry based on user entries to pinconf-config
|
||||
* @user_buf: contains the modification request with expected format:
|
||||
* modify config_pin <devicename> <state> <pinname> <newvalue>
|
||||
* modify is literal string, alternatives like add/delete not supported yet
|
||||
* config_pin is literal, alternatives like config_mux not supported yet
|
||||
* <devicename> <state> <pinname> are values that should match the pinctrl-maps
|
||||
* <newvalue> reflects the new config and is driver dependant
|
||||
*/
|
||||
static int pinconf_dbg_config_write(struct file *file,
|
||||
const char __user *user_buf, size_t count, loff_t *ppos)
|
||||
{
|
||||
struct pinctrl_maps *maps_node;
|
||||
const struct pinctrl_map *map;
|
||||
struct pinctrl_dev *pctldev = NULL;
|
||||
const struct pinconf_ops *confops = NULL;
|
||||
struct dbg_cfg *dbg = &pinconf_dbg_conf;
|
||||
const struct pinctrl_map_configs *configs;
|
||||
char config[MAX_NAME_LEN+1];
|
||||
bool found = false;
|
||||
char buf[128];
|
||||
char *b = &buf[0];
|
||||
int buf_size;
|
||||
char *token;
|
||||
int i;
|
||||
|
||||
/* Get userspace string and assure termination */
|
||||
buf_size = min(count, (sizeof(buf)-1));
|
||||
if (copy_from_user(buf, user_buf, buf_size))
|
||||
return -EFAULT;
|
||||
buf[buf_size] = 0;
|
||||
|
||||
/*
|
||||
* need to parse entry and extract parameters:
|
||||
* modify configs_pin devicename state pinname newvalue
|
||||
*/
|
||||
|
||||
/* Get arg: 'modify' */
|
||||
token = strsep(&b, " ");
|
||||
if (!token)
|
||||
return -EINVAL;
|
||||
if (strcmp(token, "modify"))
|
||||
return -EINVAL;
|
||||
|
||||
/* Get arg type: "config_pin" type supported so far */
|
||||
token = strsep(&b, " ");
|
||||
if (!token)
|
||||
return -EINVAL;
|
||||
if (strcmp(token, "config_pin"))
|
||||
return -EINVAL;
|
||||
dbg->map_type = PIN_MAP_TYPE_CONFIGS_PIN;
|
||||
|
||||
/* get arg 'device_name' */
|
||||
token = strsep(&b, " ");
|
||||
if (token == NULL)
|
||||
return -EINVAL;
|
||||
if (strlen(token) >= MAX_NAME_LEN)
|
||||
return -EINVAL;
|
||||
strncpy(dbg->dev_name, token, MAX_NAME_LEN);
|
||||
|
||||
/* get arg 'state_name' */
|
||||
token = strsep(&b, " ");
|
||||
if (token == NULL)
|
||||
return -EINVAL;
|
||||
if (strlen(token) >= MAX_NAME_LEN)
|
||||
return -EINVAL;
|
||||
strncpy(dbg->state_name, token, MAX_NAME_LEN);
|
||||
|
||||
/* get arg 'pin_name' */
|
||||
token = strsep(&b, " ");
|
||||
if (token == NULL)
|
||||
return -EINVAL;
|
||||
if (strlen(token) >= MAX_NAME_LEN)
|
||||
return -EINVAL;
|
||||
strncpy(dbg->pin_name, token, MAX_NAME_LEN);
|
||||
|
||||
/* get new_value of config' */
|
||||
token = strsep(&b, " ");
|
||||
if (token == NULL)
|
||||
return -EINVAL;
|
||||
if (strlen(token) >= MAX_NAME_LEN)
|
||||
return -EINVAL;
|
||||
strncpy(config, token, MAX_NAME_LEN);
|
||||
|
||||
mutex_lock(&pinctrl_maps_mutex);
|
||||
|
||||
/* Parse the pinctrl map and look for the selected dev/state/pin */
|
||||
for_each_maps(maps_node, i, map) {
|
||||
if (strcmp(map->dev_name, dbg->dev_name))
|
||||
continue;
|
||||
if (map->type != dbg->map_type)
|
||||
continue;
|
||||
if (strcmp(map->name, dbg->state_name))
|
||||
continue;
|
||||
|
||||
/* we found the right pin / state, so overwrite config */
|
||||
if (!strcmp(map->data.configs.group_or_pin, dbg->pin_name)) {
|
||||
found = true;
|
||||
pctldev = get_pinctrl_dev_from_devname(
|
||||
map->ctrl_dev_name);
|
||||
configs = &map->data.configs;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
count = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (pctldev)
|
||||
confops = pctldev->desc->confops;
|
||||
|
||||
if (confops && confops->pin_config_dbg_parse_modify) {
|
||||
for (i = 0; i < configs->num_configs; i++) {
|
||||
confops->pin_config_dbg_parse_modify(pctldev,
|
||||
config,
|
||||
&configs->configs[i]);
|
||||
}
|
||||
}
|
||||
|
||||
exit:
|
||||
mutex_unlock(&pinctrl_maps_mutex);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static int pinconf_dbg_config_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, pinconf_dbg_config_print, inode->i_private);
|
||||
}
|
||||
|
||||
/**
|
||||
* pinconf_dbg_config_write() - overwrite the pinctrl config in thepinctrl
|
||||
* map, of a pin/state pair based on pinname and state that have been
|
||||
* selected with the debugfs entries pinconf-name and pinconf-state
|
||||
*/
|
||||
static int pinconf_dbg_config_write(struct file *file,
|
||||
const char __user *user_buf, size_t count, loff_t *ppos)
|
||||
{
|
||||
int err;
|
||||
unsigned long config;
|
||||
struct pinctrl_maps *maps_node;
|
||||
struct pinctrl_map const *map;
|
||||
int i, j;
|
||||
|
||||
err = kstrtoul_from_user(user_buf, count, 0, &config);
|
||||
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
dbg_config = config;
|
||||
|
||||
mutex_lock(&pinctrl_mutex);
|
||||
|
||||
/* Parse the pinctrl map and look for the selected pin/state */
|
||||
for_each_maps(maps_node, i, map) {
|
||||
if (map->type != PIN_MAP_TYPE_CONFIGS_PIN)
|
||||
continue;
|
||||
|
||||
if (strncmp(map->name, dbg_state_name, MAX_NAME_LEN) > 0)
|
||||
continue;
|
||||
|
||||
/* we found the right pin / state, so overwrite config */
|
||||
for (j = 0; j < map->data.configs.num_configs; j++) {
|
||||
if (strncmp(map->data.configs.group_or_pin, dbg_pinname,
|
||||
MAX_NAME_LEN) == 0)
|
||||
map->data.configs.configs[j] = dbg_config;
|
||||
}
|
||||
}
|
||||
|
||||
mutex_unlock(&pinctrl_mutex);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static const struct file_operations pinconf_dbg_pinconfig_fops = {
|
||||
.open = pinconf_dbg_config_open,
|
||||
.write = pinconf_dbg_config_write,
|
||||
@ -782,10 +813,6 @@ void pinconf_init_device_debugfs(struct dentry *devroot,
|
||||
devroot, pctldev, &pinconf_pins_ops);
|
||||
debugfs_create_file("pinconf-groups", S_IFREG | S_IRUGO,
|
||||
devroot, pctldev, &pinconf_groups_ops);
|
||||
debugfs_create_file("pinconf-name", (S_IRUGO | S_IWUSR | S_IWGRP),
|
||||
devroot, pctldev, &pinconf_dbg_pinname_fops);
|
||||
debugfs_create_file("pinconf-state", (S_IRUGO | S_IWUSR | S_IWGRP),
|
||||
devroot, pctldev, &pinconf_dbg_pinstate_fops);
|
||||
debugfs_create_file("pinconf-config", (S_IRUGO | S_IWUSR | S_IWGRP),
|
||||
devroot, pctldev, &pinconf_dbg_pinconfig_fops);
|
||||
}
|
||||
|
@ -98,6 +98,8 @@ void pinconf_generic_dump_pin(struct pinctrl_dev *pctldev,
|
||||
void pinconf_generic_dump_group(struct pinctrl_dev *pctldev,
|
||||
struct seq_file *s, const char *gname);
|
||||
|
||||
void pinconf_generic_dump_config(struct pinctrl_dev *pctldev,
|
||||
struct seq_file *s, unsigned long config);
|
||||
#else
|
||||
|
||||
static inline void pinconf_generic_dump_pin(struct pinctrl_dev *pctldev,
|
||||
@ -114,4 +116,10 @@ static inline void pinconf_generic_dump_group(struct pinctrl_dev *pctldev,
|
||||
return;
|
||||
}
|
||||
|
||||
static inline void pinconf_generic_dump_config(struct pinctrl_dev *pctldev,
|
||||
struct seq_file *s,
|
||||
unsigned long config)
|
||||
{
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
@ -389,7 +389,8 @@ static const struct abx500_function ab8500_functions[] = {
|
||||
* alt_A | 1 | 0 | 0
|
||||
*/
|
||||
|
||||
struct alternate_functions ab8500_alternate_functions[AB8500_GPIO_MAX_NUMBER + 1] = {
|
||||
static struct
|
||||
alternate_functions ab8500_alternate_functions[AB8500_GPIO_MAX_NUMBER + 1] = {
|
||||
ALTERNATE_FUNCTIONS(0, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO0 */
|
||||
ALTERNATE_FUNCTIONS(1, 0, UNUSED, UNUSED, 0, 0, 0), /* GPIO1, altA controlled by bit 0 */
|
||||
ALTERNATE_FUNCTIONS(2, 1, UNUSED, UNUSED, 0, 0, 0), /* GPIO2, altA controlled by bit 1 */
|
||||
@ -455,7 +456,7 @@ struct alternate_functions ab8500_alternate_functions[AB8500_GPIO_MAX_NUMBER + 1
|
||||
* GPIO24 and GPIO25
|
||||
* GPIO36 to GPIO41
|
||||
*/
|
||||
struct abx500_gpio_irq_cluster ab8500_gpio_irq_cluster[] = {
|
||||
static struct abx500_gpio_irq_cluster ab8500_gpio_irq_cluster[] = {
|
||||
GPIO_IRQ_CLUSTER(6, 13, AB8500_INT_GPIO6R),
|
||||
GPIO_IRQ_CLUSTER(24, 25, AB8500_INT_GPIO24R),
|
||||
GPIO_IRQ_CLUSTER(36, 41, AB8500_INT_GPIO36R),
|
||||
|
@ -271,7 +271,8 @@ static const struct abx500_function ab8505_functions[] = {
|
||||
* alt_A | 1 | 0 | 0
|
||||
*/
|
||||
|
||||
struct alternate_functions ab8505_alternate_functions[AB8505_GPIO_MAX_NUMBER + 1] = {
|
||||
static struct
|
||||
alternate_functions ab8505_alternate_functions[AB8505_GPIO_MAX_NUMBER + 1] = {
|
||||
ALTERNATE_FUNCTIONS(0, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO0 */
|
||||
ALTERNATE_FUNCTIONS(1, 0, UNUSED, UNUSED, 0, 0, 0), /* GPIO1, altA controlled by bit 0 */
|
||||
ALTERNATE_FUNCTIONS(2, 1, UNUSED, UNUSED, 0, 0, 0), /* GPIO2, altA controlled by bit 1 */
|
||||
@ -284,7 +285,7 @@ struct alternate_functions ab8505_alternate_functions[AB8505_GPIO_MAX_NUMBER + 1
|
||||
|
||||
ALTERNATE_FUNCTIONS(9, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO9, bit 0 reserved */
|
||||
ALTERNATE_FUNCTIONS(10, 1, 0, UNUSED, 1, 0, 0), /* GPIO10, altA and altB controlled by bit 0 */
|
||||
ALTERNATE_FUNCTIONS(11, 2, UNUSED, UNUSED, 0, 0, 0), /* GPIO11, altA controlled by bit 2 */
|
||||
ALTERNATE_FUNCTIONS(11, 2, 1, UNUSED, 0, 0, 0), /* GPIO11, altA controlled by bit 2 */
|
||||
ALTERNATE_FUNCTIONS(12, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO12, bit3 reseved */
|
||||
ALTERNATE_FUNCTIONS(13, 4, 3, 4, 1, 0, 2), /* GPIO13, altA altB and altC controlled by bit 3 and 4 */
|
||||
ALTERNATE_FUNCTIONS(14, 5, UNUSED, UNUSED, 0, 0, 0), /* GPIO14, altA controlled by bit 5 */
|
||||
@ -348,7 +349,7 @@ struct alternate_functions ab8505_alternate_functions[AB8505_GPIO_MAX_NUMBER + 1
|
||||
* GPIO50
|
||||
* GPIO52 to GPIO53
|
||||
*/
|
||||
struct abx500_gpio_irq_cluster ab8505_gpio_irq_cluster[] = {
|
||||
static struct abx500_gpio_irq_cluster ab8505_gpio_irq_cluster[] = {
|
||||
GPIO_IRQ_CLUSTER(10, 11, AB8500_INT_GPIO10R),
|
||||
GPIO_IRQ_CLUSTER(13, 13, AB8500_INT_GPIO13R),
|
||||
GPIO_IRQ_CLUSTER(40, 41, AB8500_INT_GPIO40R),
|
||||
|
@ -299,7 +299,8 @@ static const struct abx500_function ab8540_functions[] = {
|
||||
*
|
||||
*/
|
||||
|
||||
struct alternate_functions ab8540_alternate_functions[AB8540_GPIO_MAX_NUMBER + 1] = {
|
||||
static struct
|
||||
alternate_functions ab8540_alternate_functions[AB8540_GPIO_MAX_NUMBER + 1] = {
|
||||
/* GPIOSEL1 - bit 4-7 reserved */
|
||||
ALTERNATE_FUNCTIONS(0, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO0 */
|
||||
ALTERNATE_FUNCTIONS(1, 0, UNUSED, UNUSED, 0, 0, 0), /* GPIO1, altA controlled by bit 0 */
|
||||
@ -376,7 +377,7 @@ static struct pullud ab8540_pullud = {
|
||||
* GPIO43 to GPIO44
|
||||
* GPIO51 to GPIO54
|
||||
*/
|
||||
struct abx500_gpio_irq_cluster ab8540_gpio_irq_cluster[] = {
|
||||
static struct abx500_gpio_irq_cluster ab8540_gpio_irq_cluster[] = {
|
||||
GPIO_IRQ_CLUSTER(43, 43, AB8540_INT_GPIO43F),
|
||||
GPIO_IRQ_CLUSTER(44, 44, AB8540_INT_GPIO44F),
|
||||
GPIO_IRQ_CLUSTER(51, 54, AB9540_INT_GPIO51R),
|
||||
|
@ -379,7 +379,8 @@ static const struct abx500_function ab9540_functions[] = {
|
||||
* alt_A | 1 | 0 | 0
|
||||
*/
|
||||
|
||||
struct alternate_functions ab9540alternate_functions[AB9540_GPIO_MAX_NUMBER + 1] = {
|
||||
static struct
|
||||
alternate_functions ab9540alternate_functions[AB9540_GPIO_MAX_NUMBER + 1] = {
|
||||
/* GPIOSEL1 - bits 4-7 are reserved */
|
||||
ALTERNATE_FUNCTIONS(0, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO0 */
|
||||
ALTERNATE_FUNCTIONS(1, 0, UNUSED, UNUSED, 0, 0, 0), /* GPIO1, altA controlled by bit 0 */
|
||||
@ -393,7 +394,7 @@ struct alternate_functions ab9540alternate_functions[AB9540_GPIO_MAX_NUMBER + 1]
|
||||
/* GPIOSEL2 - bits 0 and 3 are reserved */
|
||||
ALTERNATE_FUNCTIONS(9, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO9 */
|
||||
ALTERNATE_FUNCTIONS(10, 1, 0, UNUSED, 1, 0, 0), /* GPIO10, altA and altB controlled by bit 0 */
|
||||
ALTERNATE_FUNCTIONS(11, 2, UNUSED, UNUSED, 0, 0, 0), /* GPIO11, altA controlled by bit 1 */
|
||||
ALTERNATE_FUNCTIONS(11, 2, 1, UNUSED, 0, 0, 0), /* GPIO11, altA controlled by bit 1 */
|
||||
ALTERNATE_FUNCTIONS(12, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO12 */
|
||||
ALTERNATE_FUNCTIONS(13, 4, 3, 4, 1, 0, 2), /* GPIO13, altA altB and altC controlled by bit 3 and 4 */
|
||||
ALTERNATE_FUNCTIONS(14, 5, UNUSED, UNUSED, 0, 0, 0), /* GPIO14, altA controlled by bit 5 */
|
||||
@ -454,7 +455,7 @@ struct alternate_functions ab9540alternate_functions[AB9540_GPIO_MAX_NUMBER + 1]
|
||||
ALTERNATE_FUNCTIONS(54, 5, UNUSED, UNUSED, 0, 0, 0), /* GPIO54 = GPIO60, altA controlled by bit 5 */
|
||||
};
|
||||
|
||||
struct abx500_gpio_irq_cluster ab9540_gpio_irq_cluster[] = {
|
||||
static struct abx500_gpio_irq_cluster ab9540_gpio_irq_cluster[] = {
|
||||
GPIO_IRQ_CLUSTER(10, 13, AB8500_INT_GPIO10R),
|
||||
GPIO_IRQ_CLUSTER(24, 25, AB8500_INT_GPIO24R),
|
||||
GPIO_IRQ_CLUSTER(40, 41, AB8500_INT_GPIO40R),
|
||||
|
@ -517,14 +517,14 @@ static inline void abx500_gpio_dbg_show_one(struct seq_file *s,
|
||||
#define abx500_gpio_dbg_show NULL
|
||||
#endif
|
||||
|
||||
int abx500_gpio_request(struct gpio_chip *chip, unsigned offset)
|
||||
static int abx500_gpio_request(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
int gpio = chip->base + offset;
|
||||
|
||||
return pinctrl_request_gpio(gpio);
|
||||
}
|
||||
|
||||
void abx500_gpio_free(struct gpio_chip *chip, unsigned offset)
|
||||
static void abx500_gpio_free(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
int gpio = chip->base + offset;
|
||||
|
||||
@ -611,7 +611,7 @@ static void abx500_pmx_disable(struct pinctrl_dev *pctldev,
|
||||
dev_dbg(pct->dev, "disable group %s, %u pins\n", g->name, g->npins);
|
||||
}
|
||||
|
||||
int abx500_gpio_request_enable(struct pinctrl_dev *pctldev,
|
||||
static int abx500_gpio_request_enable(struct pinctrl_dev *pctldev,
|
||||
struct pinctrl_gpio_range *range,
|
||||
unsigned offset)
|
||||
{
|
||||
@ -656,7 +656,7 @@ static void abx500_gpio_disable_free(struct pinctrl_dev *pctldev,
|
||||
{
|
||||
}
|
||||
|
||||
static struct pinmux_ops abx500_pinmux_ops = {
|
||||
static const struct pinmux_ops abx500_pinmux_ops = {
|
||||
.get_functions_count = abx500_pmx_get_funcs_cnt,
|
||||
.get_function_name = abx500_pmx_get_func_name,
|
||||
.get_function_groups = abx500_pmx_get_func_groups,
|
||||
@ -704,21 +704,21 @@ static void abx500_pin_dbg_show(struct pinctrl_dev *pctldev,
|
||||
chip->base + offset - 1);
|
||||
}
|
||||
|
||||
static struct pinctrl_ops abx500_pinctrl_ops = {
|
||||
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,
|
||||
};
|
||||
|
||||
int abx500_pin_config_get(struct pinctrl_dev *pctldev,
|
||||
static int abx500_pin_config_get(struct pinctrl_dev *pctldev,
|
||||
unsigned pin,
|
||||
unsigned long *config)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
int abx500_pin_config_set(struct pinctrl_dev *pctldev,
|
||||
static int abx500_pin_config_set(struct pinctrl_dev *pctldev,
|
||||
unsigned pin,
|
||||
unsigned long config)
|
||||
{
|
||||
@ -778,7 +778,7 @@ int abx500_pin_config_set(struct pinctrl_dev *pctldev,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct pinconf_ops abx500_pinconf_ops = {
|
||||
static const struct pinconf_ops abx500_pinconf_ops = {
|
||||
.pin_config_get = abx500_pin_config_get,
|
||||
.pin_config_set = abx500_pin_config_set,
|
||||
};
|
||||
@ -834,6 +834,7 @@ static const struct of_device_id abx500_gpio_match[] = {
|
||||
{ .compatible = "stericsson,ab8505-gpio", .data = (void *)PINCTRL_AB8505, },
|
||||
{ .compatible = "stericsson,ab8540-gpio", .data = (void *)PINCTRL_AB8540, },
|
||||
{ .compatible = "stericsson,ab9540-gpio", .data = (void *)PINCTRL_AB9540, },
|
||||
{ }
|
||||
};
|
||||
|
||||
static int abx500_gpio_probe(struct platform_device *pdev)
|
||||
@ -879,7 +880,6 @@ static int abx500_gpio_probe(struct platform_device *pdev)
|
||||
pct->parent = dev_get_drvdata(pdev->dev.parent);
|
||||
pct->chip = abx500gpio_chip;
|
||||
pct->chip.dev = &pdev->dev;
|
||||
pct->chip.base = pdata->gpio_base;
|
||||
pct->chip.base = (np) ? -1 : pdata->gpio_base;
|
||||
|
||||
/* initialize the lock */
|
||||
|
@ -294,7 +294,7 @@ static void at91_dt_free_map(struct pinctrl_dev *pctldev,
|
||||
{
|
||||
}
|
||||
|
||||
static struct pinctrl_ops at91_pctrl_ops = {
|
||||
static const struct pinctrl_ops at91_pctrl_ops = {
|
||||
.get_groups_count = at91_get_groups_count,
|
||||
.get_group_name = at91_get_group_name,
|
||||
.get_group_pins = at91_get_group_pins,
|
||||
@ -303,7 +303,7 @@ static struct pinctrl_ops at91_pctrl_ops = {
|
||||
.dt_free_map = at91_dt_free_map,
|
||||
};
|
||||
|
||||
static void __iomem * pin_to_controller(struct at91_pinctrl *info,
|
||||
static void __iomem *pin_to_controller(struct at91_pinctrl *info,
|
||||
unsigned int bank)
|
||||
{
|
||||
return gpio_chips[bank]->regbase;
|
||||
@ -501,7 +501,7 @@ static void at91_pin_dbg(const struct device *dev, const struct at91_pmx_pin *pi
|
||||
}
|
||||
}
|
||||
|
||||
static int pin_check_config(struct at91_pinctrl *info, const char* name,
|
||||
static int pin_check_config(struct at91_pinctrl *info, const char *name,
|
||||
int index, const struct at91_pmx_pin *pin)
|
||||
{
|
||||
int mux;
|
||||
@ -579,7 +579,7 @@ static int at91_pmx_enable(struct pinctrl_dev *pctldev, unsigned selector,
|
||||
pio = pin_to_controller(info, pin->bank);
|
||||
mask = pin_to_mask(pin->pin);
|
||||
at91_mux_disable_interrupt(pio, mask);
|
||||
switch(pin->mux) {
|
||||
switch (pin->mux) {
|
||||
case AT91_MUX_GPIO:
|
||||
at91_mux_gpio_enable(pio, mask, 1);
|
||||
break;
|
||||
@ -696,7 +696,7 @@ static void at91_gpio_disable_free(struct pinctrl_dev *pctldev,
|
||||
/* Set the pin to some default state, GPIO is usually default */
|
||||
}
|
||||
|
||||
static struct pinmux_ops at91_pmx_ops = {
|
||||
static const struct pinmux_ops at91_pmx_ops = {
|
||||
.get_functions_count = at91_pmx_get_funcs_count,
|
||||
.get_function_name = at91_pmx_get_func_name,
|
||||
.get_function_groups = at91_pmx_get_groups,
|
||||
@ -776,7 +776,7 @@ static void at91_pinconf_group_dbg_show(struct pinctrl_dev *pctldev,
|
||||
{
|
||||
}
|
||||
|
||||
static struct pinconf_ops at91_pinconf_ops = {
|
||||
static const struct pinconf_ops at91_pinconf_ops = {
|
||||
.pin_config_get = at91_pinconf_get,
|
||||
.pin_config_set = at91_pinconf_set,
|
||||
.pin_config_dbg_show = at91_pinconf_dbg_show,
|
||||
@ -812,7 +812,7 @@ static int at91_pinctrl_mux_mask(struct at91_pinctrl *info,
|
||||
{
|
||||
int ret = 0;
|
||||
int size;
|
||||
const const __be32 *list;
|
||||
const __be32 *list;
|
||||
|
||||
list = of_get_property(np, "atmel,mux-mask", &size);
|
||||
if (!list) {
|
||||
@ -846,7 +846,7 @@ static int at91_pinctrl_parse_groups(struct device_node *np,
|
||||
{
|
||||
struct at91_pmx_pin *pin;
|
||||
int size;
|
||||
const const __be32 *list;
|
||||
const __be32 *list;
|
||||
int i, j;
|
||||
|
||||
dev_dbg(info->dev, "group(%d): %s\n", index, np->name);
|
||||
@ -944,7 +944,7 @@ static int at91_pinctrl_probe_dt(struct platform_device *pdev,
|
||||
return -ENODEV;
|
||||
|
||||
info->dev = &pdev->dev;
|
||||
info->ops = (struct at91_pinctrl_mux_ops*)
|
||||
info->ops = (struct at91_pinctrl_mux_ops *)
|
||||
of_match_device(at91_pinctrl_of_match, &pdev->dev)->data;
|
||||
at91_pinctrl_child_count(info, np);
|
||||
|
||||
@ -1002,7 +1002,7 @@ static int at91_pinctrl_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct at91_pinctrl *info;
|
||||
struct pinctrl_pin_desc *pdesc;
|
||||
int ret, i, j ,k;
|
||||
int ret, i, j, k;
|
||||
|
||||
info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
|
||||
if (!info)
|
||||
@ -1568,7 +1568,7 @@ static int at91_gpio_probe(struct platform_device *pdev)
|
||||
goto err;
|
||||
}
|
||||
|
||||
at91_chip->ops = (struct at91_pinctrl_mux_ops*)
|
||||
at91_chip->ops = (struct at91_pinctrl_mux_ops *)
|
||||
of_match_device(at91_gpio_of_match, &pdev->dev)->data;
|
||||
at91_chip->pioc_virq = irq;
|
||||
at91_chip->pioc_idx = alias_idx;
|
||||
@ -1605,7 +1605,8 @@ static int at91_gpio_probe(struct platform_device *pdev)
|
||||
chip->ngpio = ngpio;
|
||||
}
|
||||
|
||||
names = devm_kzalloc(&pdev->dev, sizeof(char*) * chip->ngpio, GFP_KERNEL);
|
||||
names = devm_kzalloc(&pdev->dev, sizeof(char *) * chip->ngpio,
|
||||
GFP_KERNEL);
|
||||
|
||||
if (!names) {
|
||||
ret = -ENOMEM;
|
||||
@ -1615,7 +1616,7 @@ static int at91_gpio_probe(struct platform_device *pdev)
|
||||
for (i = 0; i < chip->ngpio; i++)
|
||||
names[i] = kasprintf(GFP_KERNEL, "pio%c%d", alias_idx + 'A', i);
|
||||
|
||||
chip->names = (const char*const*)names;
|
||||
chip->names = (const char *const *)names;
|
||||
|
||||
range = &at91_chip->range;
|
||||
range->name = chip->label;
|
||||
|
@ -795,7 +795,7 @@ out:
|
||||
return err;
|
||||
}
|
||||
|
||||
static struct pinctrl_ops bcm2835_pctl_ops = {
|
||||
static const struct pinctrl_ops bcm2835_pctl_ops = {
|
||||
.get_groups_count = bcm2835_pctl_get_groups_count,
|
||||
.get_group_name = bcm2835_pctl_get_group_name,
|
||||
.get_group_pins = bcm2835_pctl_get_group_pins,
|
||||
@ -872,7 +872,7 @@ static int bcm2835_pmx_gpio_set_direction(struct pinctrl_dev *pctldev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct pinmux_ops bcm2835_pmx_ops = {
|
||||
static const struct pinmux_ops bcm2835_pmx_ops = {
|
||||
.get_functions_count = bcm2835_pmx_get_functions_count,
|
||||
.get_function_name = bcm2835_pmx_get_function_name,
|
||||
.get_function_groups = bcm2835_pmx_get_function_groups,
|
||||
@ -916,7 +916,7 @@ static int bcm2835_pinconf_set(struct pinctrl_dev *pctldev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct pinconf_ops bcm2835_pinconf_ops = {
|
||||
static const struct pinconf_ops bcm2835_pinconf_ops = {
|
||||
.pin_config_get = bcm2835_pinconf_get,
|
||||
.pin_config_set = bcm2835_pinconf_set,
|
||||
};
|
||||
|
@ -318,13 +318,16 @@ static int u300_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
|
||||
struct u300_gpio_port *port = NULL;
|
||||
struct list_head *p;
|
||||
int retirq;
|
||||
bool found = false;
|
||||
|
||||
list_for_each(p, &gpio->port_list) {
|
||||
port = list_entry(p, struct u300_gpio_port, node);
|
||||
if (port->number == portno)
|
||||
if (port->number == portno) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (port == NULL) {
|
||||
if (!found) {
|
||||
dev_err(gpio->dev, "could not locate port for GPIO %d IRQ\n",
|
||||
offset);
|
||||
return -EINVAL;
|
||||
@ -359,7 +362,7 @@ int u300_gpio_config_get(struct gpio_chip *chip,
|
||||
drmode &= (U300_GPIO_PXPCR_PIN_MODE_MASK << ((offset & 0x07) << 1));
|
||||
drmode >>= ((offset & 0x07) << 1);
|
||||
|
||||
switch(param) {
|
||||
switch (param) {
|
||||
case PIN_CONFIG_BIAS_HIGH_IMPEDANCE:
|
||||
*config = 0;
|
||||
if (biasmode)
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/err.h>
|
||||
|
||||
#include <asm/mach/irq.h>
|
||||
@ -33,6 +34,17 @@
|
||||
#include "pinctrl-samsung.h"
|
||||
#include "pinctrl-exynos.h"
|
||||
|
||||
|
||||
static struct samsung_pin_bank_type bank_type_off = {
|
||||
.fld_width = { 4, 1, 2, 2, 2, 2, },
|
||||
.reg_offset = { 0x00, 0x04, 0x08, 0x0c, 0x10, 0x14, },
|
||||
};
|
||||
|
||||
static struct samsung_pin_bank_type bank_type_alive = {
|
||||
.fld_width = { 4, 1, 2, 2, },
|
||||
.reg_offset = { 0x00, 0x04, 0x08, 0x0c, },
|
||||
};
|
||||
|
||||
/* list of external wakeup controllers supported */
|
||||
static const struct of_device_id exynos_wkup_irq_ids[] = {
|
||||
{ .compatible = "samsung,exynos4210-wakeup-eint", },
|
||||
@ -75,12 +87,14 @@ static void exynos_gpio_irq_ack(struct irq_data *irqd)
|
||||
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);
|
||||
struct samsung_pin_bank_type *bank_type = bank->type;
|
||||
struct samsung_pinctrl_drv_data *d = bank->drvdata;
|
||||
struct samsung_pin_ctrl *ctrl = d->ctrl;
|
||||
unsigned int pin = irqd->hwirq;
|
||||
unsigned int shift = EXYNOS_EINT_CON_LEN * pin;
|
||||
unsigned int con, trig_type;
|
||||
unsigned long reg_con = ctrl->geint_con + bank->eint_offset;
|
||||
unsigned long flags;
|
||||
unsigned int mask;
|
||||
|
||||
switch (type) {
|
||||
@ -114,15 +128,19 @@ static int exynos_gpio_irq_set_type(struct irq_data *irqd, unsigned int type)
|
||||
con |= trig_type << shift;
|
||||
writel(con, d->virt_base + reg_con);
|
||||
|
||||
reg_con = bank->pctl_offset;
|
||||
shift = pin * bank->func_width;
|
||||
mask = (1 << bank->func_width) - 1;
|
||||
reg_con = bank->pctl_offset + bank_type->reg_offset[PINCFG_TYPE_FUNC];
|
||||
shift = pin * bank_type->fld_width[PINCFG_TYPE_FUNC];
|
||||
mask = (1 << bank_type->fld_width[PINCFG_TYPE_FUNC]) - 1;
|
||||
|
||||
spin_lock_irqsave(&bank->slock, flags);
|
||||
|
||||
con = readl(d->virt_base + reg_con);
|
||||
con &= ~(mask << shift);
|
||||
con |= EXYNOS_EINT_FUNC << shift;
|
||||
writel(con, d->virt_base + reg_con);
|
||||
|
||||
spin_unlock_irqrestore(&bank->slock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -253,11 +271,13 @@ static void exynos_wkup_irq_ack(struct irq_data *irqd)
|
||||
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);
|
||||
struct samsung_pin_bank_type *bank_type = bank->type;
|
||||
struct samsung_pinctrl_drv_data *d = bank->drvdata;
|
||||
unsigned int pin = irqd->hwirq;
|
||||
unsigned long reg_con = d->ctrl->weint_con + bank->eint_offset;
|
||||
unsigned long shift = EXYNOS_EINT_CON_LEN * pin;
|
||||
unsigned long con, trig_type;
|
||||
unsigned long flags;
|
||||
unsigned int mask;
|
||||
|
||||
switch (type) {
|
||||
@ -291,15 +311,19 @@ static int exynos_wkup_irq_set_type(struct irq_data *irqd, unsigned int type)
|
||||
con |= trig_type << shift;
|
||||
writel(con, d->virt_base + reg_con);
|
||||
|
||||
reg_con = bank->pctl_offset;
|
||||
shift = pin * bank->func_width;
|
||||
mask = (1 << bank->func_width) - 1;
|
||||
reg_con = bank->pctl_offset + bank_type->reg_offset[PINCFG_TYPE_FUNC];
|
||||
shift = pin * bank_type->fld_width[PINCFG_TYPE_FUNC];
|
||||
mask = (1 << bank_type->fld_width[PINCFG_TYPE_FUNC]) - 1;
|
||||
|
||||
spin_lock_irqsave(&bank->slock, flags);
|
||||
|
||||
con = readl(d->virt_base + reg_con);
|
||||
con &= ~(mask << shift);
|
||||
con |= EXYNOS_EINT_FUNC << shift;
|
||||
writel(con, d->virt_base + reg_con);
|
||||
|
||||
spin_unlock_irqrestore(&bank->slock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -48,26 +48,18 @@
|
||||
|
||||
#define EXYNOS_PIN_BANK_EINTN(pins, reg, id) \
|
||||
{ \
|
||||
.type = &bank_type_off, \
|
||||
.pctl_offset = reg, \
|
||||
.nr_pins = pins, \
|
||||
.func_width = 4, \
|
||||
.pud_width = 2, \
|
||||
.drv_width = 2, \
|
||||
.conpdn_width = 2, \
|
||||
.pudpdn_width = 2, \
|
||||
.eint_type = EINT_TYPE_NONE, \
|
||||
.name = id \
|
||||
}
|
||||
|
||||
#define EXYNOS_PIN_BANK_EINTG(pins, reg, id, offs) \
|
||||
{ \
|
||||
.type = &bank_type_off, \
|
||||
.pctl_offset = reg, \
|
||||
.nr_pins = pins, \
|
||||
.func_width = 4, \
|
||||
.pud_width = 2, \
|
||||
.drv_width = 2, \
|
||||
.conpdn_width = 2, \
|
||||
.pudpdn_width = 2, \
|
||||
.eint_type = EINT_TYPE_GPIO, \
|
||||
.eint_offset = offs, \
|
||||
.name = id \
|
||||
@ -75,11 +67,9 @@
|
||||
|
||||
#define EXYNOS_PIN_BANK_EINTW(pins, reg, id, offs) \
|
||||
{ \
|
||||
.type = &bank_type_alive, \
|
||||
.pctl_offset = reg, \
|
||||
.nr_pins = pins, \
|
||||
.func_width = 4, \
|
||||
.pud_width = 2, \
|
||||
.drv_width = 2, \
|
||||
.eint_type = EINT_TYPE_WKUP, \
|
||||
.eint_offset = offs, \
|
||||
.name = id \
|
||||
|
@ -20,6 +20,9 @@
|
||||
#include <linux/pinctrl/pinctrl.h>
|
||||
#include <linux/pinctrl/pinmux.h>
|
||||
#include <linux/pinctrl/pinconf.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/irqdomain.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include "core.h"
|
||||
|
||||
/* EXYNOS5440 GPIO and Pinctrl register offsets */
|
||||
@ -37,6 +40,7 @@
|
||||
#define GPIO_DS1 0x2C
|
||||
|
||||
#define EXYNOS5440_MAX_PINS 23
|
||||
#define EXYNOS5440_MAX_GPIO_INT 8
|
||||
#define PIN_NAME_LENGTH 10
|
||||
|
||||
#define GROUP_SUFFIX "-grp"
|
||||
@ -109,6 +113,7 @@ struct exynos5440_pmx_func {
|
||||
struct exynos5440_pinctrl_priv_data {
|
||||
void __iomem *reg_base;
|
||||
struct gpio_chip *gc;
|
||||
struct irq_domain *irq_domain;
|
||||
|
||||
const struct exynos5440_pin_group *pin_groups;
|
||||
unsigned int nr_groups;
|
||||
@ -116,6 +121,16 @@ struct exynos5440_pinctrl_priv_data {
|
||||
unsigned int nr_functions;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct exynos5440_gpio_intr_data: private data for gpio interrupts.
|
||||
* @priv: driver's private runtime data.
|
||||
* @gpio_int: gpio interrupt number.
|
||||
*/
|
||||
struct exynos5440_gpio_intr_data {
|
||||
struct exynos5440_pinctrl_priv_data *priv;
|
||||
unsigned int gpio_int;
|
||||
};
|
||||
|
||||
/* list of all possible config options supported */
|
||||
static struct pin_config {
|
||||
char *prop_cfg;
|
||||
@ -286,7 +301,7 @@ static void exynos5440_dt_free_map(struct pinctrl_dev *pctldev,
|
||||
}
|
||||
|
||||
/* list of pinctrl callbacks for the pinctrl core */
|
||||
static struct pinctrl_ops exynos5440_pctrl_ops = {
|
||||
static const struct pinctrl_ops exynos5440_pctrl_ops = {
|
||||
.get_groups_count = exynos5440_get_group_count,
|
||||
.get_group_name = exynos5440_get_group_name,
|
||||
.get_group_pins = exynos5440_get_group_pins,
|
||||
@ -374,7 +389,7 @@ static int exynos5440_pinmux_gpio_set_direction(struct pinctrl_dev *pctldev,
|
||||
}
|
||||
|
||||
/* list of pinmux callbacks for the pinmux vertical in pinctrl core */
|
||||
static struct pinmux_ops exynos5440_pinmux_ops = {
|
||||
static const struct pinmux_ops exynos5440_pinmux_ops = {
|
||||
.get_functions_count = exynos5440_get_functions_count,
|
||||
.get_function_name = exynos5440_pinmux_get_fname,
|
||||
.get_function_groups = exynos5440_pinmux_get_groups,
|
||||
@ -523,7 +538,7 @@ static int exynos5440_pinconf_group_get(struct pinctrl_dev *pctldev,
|
||||
}
|
||||
|
||||
/* list of pinconfig callbacks for pinconfig vertical in the pinctrl code */
|
||||
static struct pinconf_ops exynos5440_pinconf_ops = {
|
||||
static const struct pinconf_ops exynos5440_pinconf_ops = {
|
||||
.pin_config_get = exynos5440_pinconf_get,
|
||||
.pin_config_set = exynos5440_pinconf_set,
|
||||
.pin_config_group_get = exynos5440_pinconf_group_get,
|
||||
@ -598,6 +613,22 @@ static int exynos5440_gpio_direction_output(struct gpio_chip *gc, unsigned offse
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* gpiolib gpio_to_irq callback function */
|
||||
static int exynos5440_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
|
||||
{
|
||||
struct exynos5440_pinctrl_priv_data *priv = dev_get_drvdata(gc->dev);
|
||||
unsigned int virq;
|
||||
|
||||
if (offset < 16 || offset > 23)
|
||||
return -ENXIO;
|
||||
|
||||
if (!priv->irq_domain)
|
||||
return -ENXIO;
|
||||
|
||||
virq = irq_create_mapping(priv->irq_domain, offset - 16);
|
||||
return virq ? : -ENXIO;
|
||||
}
|
||||
|
||||
/* parse the pin numbers listed in the 'samsung,exynos5440-pins' property */
|
||||
static int exynos5440_pinctrl_parse_dt_pins(struct platform_device *pdev,
|
||||
struct device_node *cfg_np, unsigned int **pin_list,
|
||||
@ -670,8 +701,10 @@ static int exynos5440_pinctrl_parse_dt(struct platform_device *pdev,
|
||||
|
||||
ret = exynos5440_pinctrl_parse_dt_pins(pdev, cfg_np,
|
||||
&pin_list, &npins);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (ret) {
|
||||
gname = NULL;
|
||||
goto skip_to_pin_function;
|
||||
}
|
||||
|
||||
/* derive pin group name from the node name */
|
||||
gname = devm_kzalloc(dev, strlen(cfg_np->name) + GSUFFIX_LEN,
|
||||
@ -687,6 +720,7 @@ static int exynos5440_pinctrl_parse_dt(struct platform_device *pdev,
|
||||
grp->num_pins = npins;
|
||||
grp++;
|
||||
|
||||
skip_to_pin_function:
|
||||
ret = of_property_read_u32(cfg_np, "samsung,exynos5440-pin-function",
|
||||
&function);
|
||||
if (ret)
|
||||
@ -709,7 +743,7 @@ static int exynos5440_pinctrl_parse_dt(struct platform_device *pdev,
|
||||
return -ENOMEM;
|
||||
}
|
||||
func->groups[0] = gname;
|
||||
func->num_groups = 1;
|
||||
func->num_groups = gname ? 1 : 0;
|
||||
func->function = function;
|
||||
func++;
|
||||
func_idx++;
|
||||
@ -818,6 +852,7 @@ static int exynos5440_gpiolib_register(struct platform_device *pdev,
|
||||
gc->get = exynos5440_gpio_get;
|
||||
gc->direction_input = exynos5440_gpio_direction_input;
|
||||
gc->direction_output = exynos5440_gpio_direction_output;
|
||||
gc->to_irq = exynos5440_gpio_to_irq;
|
||||
gc->label = "gpiolib-exynos5440";
|
||||
gc->owner = THIS_MODULE;
|
||||
ret = gpiochip_add(gc);
|
||||
@ -842,6 +877,110 @@ static int exynos5440_gpiolib_unregister(struct platform_device *pdev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void exynos5440_gpio_irq_unmask(struct irq_data *irqd)
|
||||
{
|
||||
struct exynos5440_pinctrl_priv_data *d;
|
||||
unsigned long gpio_int;
|
||||
|
||||
d = irq_data_get_irq_chip_data(irqd);
|
||||
gpio_int = readl(d->reg_base + GPIO_INT);
|
||||
gpio_int |= 1 << irqd->hwirq;
|
||||
writel(gpio_int, d->reg_base + GPIO_INT);
|
||||
}
|
||||
|
||||
static void exynos5440_gpio_irq_mask(struct irq_data *irqd)
|
||||
{
|
||||
struct exynos5440_pinctrl_priv_data *d;
|
||||
unsigned long gpio_int;
|
||||
|
||||
d = irq_data_get_irq_chip_data(irqd);
|
||||
gpio_int = readl(d->reg_base + GPIO_INT);
|
||||
gpio_int &= ~(1 << irqd->hwirq);
|
||||
writel(gpio_int, d->reg_base + GPIO_INT);
|
||||
}
|
||||
|
||||
/* irq_chip for gpio interrupts */
|
||||
static struct irq_chip exynos5440_gpio_irq_chip = {
|
||||
.name = "exynos5440_gpio_irq_chip",
|
||||
.irq_unmask = exynos5440_gpio_irq_unmask,
|
||||
.irq_mask = exynos5440_gpio_irq_mask,
|
||||
};
|
||||
|
||||
/* interrupt handler for GPIO interrupts 0..7 */
|
||||
static irqreturn_t exynos5440_gpio_irq(int irq, void *data)
|
||||
{
|
||||
struct exynos5440_gpio_intr_data *intd = data;
|
||||
struct exynos5440_pinctrl_priv_data *d = intd->priv;
|
||||
int virq;
|
||||
|
||||
virq = irq_linear_revmap(d->irq_domain, intd->gpio_int);
|
||||
if (!virq)
|
||||
return IRQ_NONE;
|
||||
generic_handle_irq(virq);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int exynos5440_gpio_irq_map(struct irq_domain *h, unsigned int virq,
|
||||
irq_hw_number_t hw)
|
||||
{
|
||||
struct exynos5440_pinctrl_priv_data *d = h->host_data;
|
||||
|
||||
irq_set_chip_data(virq, d);
|
||||
irq_set_chip_and_handler(virq, &exynos5440_gpio_irq_chip,
|
||||
handle_level_irq);
|
||||
set_irq_flags(virq, IRQF_VALID);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* irq domain callbacks for gpio interrupt controller */
|
||||
static const struct irq_domain_ops exynos5440_gpio_irqd_ops = {
|
||||
.map = exynos5440_gpio_irq_map,
|
||||
.xlate = irq_domain_xlate_twocell,
|
||||
};
|
||||
|
||||
/* setup handling of gpio interrupts */
|
||||
static int exynos5440_gpio_irq_init(struct platform_device *pdev,
|
||||
struct exynos5440_pinctrl_priv_data *priv)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct exynos5440_gpio_intr_data *intd;
|
||||
int i, irq, ret;
|
||||
|
||||
intd = devm_kzalloc(dev, sizeof(*intd) * EXYNOS5440_MAX_GPIO_INT,
|
||||
GFP_KERNEL);
|
||||
if (!intd) {
|
||||
dev_err(dev, "failed to allocate memory for gpio intr data\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
for (i = 0; i < EXYNOS5440_MAX_GPIO_INT; i++) {
|
||||
irq = irq_of_parse_and_map(dev->of_node, i);
|
||||
if (irq <= 0) {
|
||||
dev_err(dev, "irq parsing failed\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
intd->gpio_int = i;
|
||||
intd->priv = priv;
|
||||
ret = devm_request_irq(dev, irq, exynos5440_gpio_irq,
|
||||
0, dev_name(dev), intd++);
|
||||
if (ret) {
|
||||
dev_err(dev, "irq request failed\n");
|
||||
return -ENXIO;
|
||||
}
|
||||
}
|
||||
|
||||
priv->irq_domain = irq_domain_add_linear(dev->of_node,
|
||||
EXYNOS5440_MAX_GPIO_INT,
|
||||
&exynos5440_gpio_irqd_ops, priv);
|
||||
if (!priv->irq_domain) {
|
||||
dev_err(dev, "failed to create irq domain\n");
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int exynos5440_pinctrl_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
@ -854,7 +993,7 @@ static int exynos5440_pinctrl_probe(struct platform_device *pdev)
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
priv = devm_kzalloc(dev, sizeof(priv), GFP_KERNEL);
|
||||
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv) {
|
||||
dev_err(dev, "could not allocate memory for private data\n");
|
||||
return -ENOMEM;
|
||||
@ -880,6 +1019,12 @@ static int exynos5440_pinctrl_probe(struct platform_device *pdev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = exynos5440_gpio_irq_init(pdev, priv);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to setup gpio interrupts\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, priv);
|
||||
dev_info(dev, "EXYNOS5440 pinctrl driver registered\n");
|
||||
return 0;
|
||||
|
@ -353,7 +353,7 @@ static void falcon_pinconf_group_dbg_show(struct pinctrl_dev *pctrldev,
|
||||
{
|
||||
}
|
||||
|
||||
static struct pinconf_ops falcon_pinconf_ops = {
|
||||
static const struct pinconf_ops falcon_pinconf_ops = {
|
||||
.pin_config_get = falcon_pinconf_get,
|
||||
.pin_config_set = falcon_pinconf_set,
|
||||
.pin_config_group_get = falcon_pinconf_group_get,
|
||||
|
@ -207,7 +207,7 @@ static void imx_dt_free_map(struct pinctrl_dev *pctldev,
|
||||
kfree(map);
|
||||
}
|
||||
|
||||
static struct pinctrl_ops imx_pctrl_ops = {
|
||||
static const struct pinctrl_ops imx_pctrl_ops = {
|
||||
.get_groups_count = imx_get_groups_count,
|
||||
.get_group_name = imx_get_group_name,
|
||||
.get_group_pins = imx_get_group_pins,
|
||||
@ -299,7 +299,7 @@ static int imx_pmx_get_groups(struct pinctrl_dev *pctldev, unsigned selector,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct pinmux_ops imx_pmx_ops = {
|
||||
static const struct pinmux_ops imx_pmx_ops = {
|
||||
.get_functions_count = imx_pmx_get_funcs_count,
|
||||
.get_function_name = imx_pmx_get_func_name,
|
||||
.get_function_groups = imx_pmx_get_groups,
|
||||
@ -397,7 +397,7 @@ static void imx_pinconf_group_dbg_show(struct pinctrl_dev *pctldev,
|
||||
}
|
||||
}
|
||||
|
||||
static struct pinconf_ops imx_pinconf_ops = {
|
||||
static const struct pinconf_ops imx_pinconf_ops = {
|
||||
.pin_config_get = imx_pinconf_get,
|
||||
.pin_config_set = imx_pinconf_set,
|
||||
.pin_config_dbg_show = imx_pinconf_dbg_show,
|
||||
|
@ -169,7 +169,7 @@ static int ltq_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct pinctrl_ops ltq_pctrl_ops = {
|
||||
static const struct pinctrl_ops ltq_pctrl_ops = {
|
||||
.get_groups_count = ltq_get_group_count,
|
||||
.get_group_name = ltq_get_group_name,
|
||||
.get_group_pins = ltq_get_group_pins,
|
||||
@ -311,7 +311,7 @@ static int ltq_pmx_gpio_request_enable(struct pinctrl_dev *pctrldev,
|
||||
return info->apply_mux(pctrldev, mfp, pin_func);
|
||||
}
|
||||
|
||||
static struct pinmux_ops ltq_pmx_ops = {
|
||||
static const struct pinmux_ops ltq_pmx_ops = {
|
||||
.get_functions_count = ltq_pmx_func_count,
|
||||
.get_function_name = ltq_pmx_func_name,
|
||||
.get_function_groups = ltq_pmx_get_groups,
|
||||
|
@ -1,722 +0,0 @@
|
||||
/*
|
||||
* linux/drivers/pinctrl/pinmux-mmp2.c
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* publishhed by the Free Software Foundation.
|
||||
*
|
||||
* Copyright (C) 2011, Marvell Technology Group Ltd.
|
||||
*
|
||||
* Author: Haojian Zhuang <haojian.zhuang@marvell.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include "pinctrl-pxa3xx.h"
|
||||
|
||||
#define MMP2_DS_MASK 0x1800
|
||||
#define MMP2_DS_SHIFT 11
|
||||
#define MMP2_SLEEP_MASK 0x38
|
||||
#define MMP2_SLEEP_SELECT (1 << 9)
|
||||
#define MMP2_SLEEP_DATA (1 << 8)
|
||||
#define MMP2_SLEEP_DIR (1 << 7)
|
||||
|
||||
#define MFPR_MMP2(a, r, f0, f1, f2, f3, f4, f5, f6, f7) \
|
||||
{ \
|
||||
.name = #a, \
|
||||
.pin = a, \
|
||||
.mfpr = r, \
|
||||
.func = { \
|
||||
MMP2_MUX_##f0, \
|
||||
MMP2_MUX_##f1, \
|
||||
MMP2_MUX_##f2, \
|
||||
MMP2_MUX_##f3, \
|
||||
MMP2_MUX_##f4, \
|
||||
MMP2_MUX_##f5, \
|
||||
MMP2_MUX_##f6, \
|
||||
MMP2_MUX_##f7, \
|
||||
}, \
|
||||
}
|
||||
|
||||
#define GRP_MMP2(a, m, p) \
|
||||
{ .name = a, .mux = MMP2_MUX_##m, .pins = p, .npins = ARRAY_SIZE(p), }
|
||||
|
||||
/* 174 pins */
|
||||
enum mmp2_pin_list {
|
||||
/* 0~168: GPIO0~GPIO168 */
|
||||
TWSI4_SCL = 169,
|
||||
TWSI4_SDA, /* 170 */
|
||||
G_CLKREQ,
|
||||
VCXO_REQ,
|
||||
VCXO_OUT,
|
||||
};
|
||||
|
||||
enum mmp2_mux {
|
||||
/* PXA3xx_MUX_GPIO = 0 (predefined in pinctrl-pxa3xx.h) */
|
||||
MMP2_MUX_GPIO = 0,
|
||||
MMP2_MUX_G_CLKREQ,
|
||||
MMP2_MUX_VCXO_REQ,
|
||||
MMP2_MUX_VCXO_OUT,
|
||||
MMP2_MUX_KP_MK,
|
||||
MMP2_MUX_KP_DK,
|
||||
MMP2_MUX_CCIC1,
|
||||
MMP2_MUX_CCIC2,
|
||||
MMP2_MUX_SPI,
|
||||
MMP2_MUX_SSPA2,
|
||||
MMP2_MUX_ROT,
|
||||
MMP2_MUX_I2S,
|
||||
MMP2_MUX_TB,
|
||||
MMP2_MUX_CAM2,
|
||||
MMP2_MUX_HDMI,
|
||||
MMP2_MUX_TWSI2,
|
||||
MMP2_MUX_TWSI3,
|
||||
MMP2_MUX_TWSI4,
|
||||
MMP2_MUX_TWSI5,
|
||||
MMP2_MUX_TWSI6,
|
||||
MMP2_MUX_UART1,
|
||||
MMP2_MUX_UART2,
|
||||
MMP2_MUX_UART3,
|
||||
MMP2_MUX_UART4,
|
||||
MMP2_MUX_SSP1_RX,
|
||||
MMP2_MUX_SSP1_FRM,
|
||||
MMP2_MUX_SSP1_TXRX,
|
||||
MMP2_MUX_SSP2_RX,
|
||||
MMP2_MUX_SSP2_FRM,
|
||||
MMP2_MUX_SSP1,
|
||||
MMP2_MUX_SSP2,
|
||||
MMP2_MUX_SSP3,
|
||||
MMP2_MUX_SSP4,
|
||||
MMP2_MUX_MMC1,
|
||||
MMP2_MUX_MMC2,
|
||||
MMP2_MUX_MMC3,
|
||||
MMP2_MUX_MMC4,
|
||||
MMP2_MUX_ULPI,
|
||||
MMP2_MUX_AC,
|
||||
MMP2_MUX_CA,
|
||||
MMP2_MUX_PWM,
|
||||
MMP2_MUX_USIM,
|
||||
MMP2_MUX_TIPU,
|
||||
MMP2_MUX_PLL,
|
||||
MMP2_MUX_NAND,
|
||||
MMP2_MUX_FSIC,
|
||||
MMP2_MUX_SLEEP_IND,
|
||||
MMP2_MUX_EXT_DMA,
|
||||
MMP2_MUX_ONE_WIRE,
|
||||
MMP2_MUX_LCD,
|
||||
MMP2_MUX_SMC,
|
||||
MMP2_MUX_SMC_INT,
|
||||
MMP2_MUX_MSP,
|
||||
MMP2_MUX_G_CLKOUT,
|
||||
MMP2_MUX_32K_CLKOUT,
|
||||
MMP2_MUX_PRI_JTAG,
|
||||
MMP2_MUX_AAS_JTAG,
|
||||
MMP2_MUX_AAS_GPIO,
|
||||
MMP2_MUX_AAS_SPI,
|
||||
MMP2_MUX_AAS_TWSI,
|
||||
MMP2_MUX_AAS_DEU_EX,
|
||||
MMP2_MUX_NONE = 0xffff,
|
||||
};
|
||||
|
||||
static struct pinctrl_pin_desc mmp2_pads[] = {
|
||||
/*
|
||||
* The name indicates function 0 of this pin.
|
||||
* After reset, function 0 is the default function of pin.
|
||||
*/
|
||||
PINCTRL_PIN(GPIO0, "GPIO0"),
|
||||
PINCTRL_PIN(GPIO1, "GPIO1"),
|
||||
PINCTRL_PIN(GPIO2, "GPIO2"),
|
||||
PINCTRL_PIN(GPIO3, "GPIO3"),
|
||||
PINCTRL_PIN(GPIO4, "GPIO4"),
|
||||
PINCTRL_PIN(GPIO5, "GPIO5"),
|
||||
PINCTRL_PIN(GPIO6, "GPIO6"),
|
||||
PINCTRL_PIN(GPIO7, "GPIO7"),
|
||||
PINCTRL_PIN(GPIO8, "GPIO8"),
|
||||
PINCTRL_PIN(GPIO9, "GPIO9"),
|
||||
PINCTRL_PIN(GPIO10, "GPIO10"),
|
||||
PINCTRL_PIN(GPIO11, "GPIO11"),
|
||||
PINCTRL_PIN(GPIO12, "GPIO12"),
|
||||
PINCTRL_PIN(GPIO13, "GPIO13"),
|
||||
PINCTRL_PIN(GPIO14, "GPIO14"),
|
||||
PINCTRL_PIN(GPIO15, "GPIO15"),
|
||||
PINCTRL_PIN(GPIO16, "GPIO16"),
|
||||
PINCTRL_PIN(GPIO17, "GPIO17"),
|
||||
PINCTRL_PIN(GPIO18, "GPIO18"),
|
||||
PINCTRL_PIN(GPIO19, "GPIO19"),
|
||||
PINCTRL_PIN(GPIO20, "GPIO20"),
|
||||
PINCTRL_PIN(GPIO21, "GPIO21"),
|
||||
PINCTRL_PIN(GPIO22, "GPIO22"),
|
||||
PINCTRL_PIN(GPIO23, "GPIO23"),
|
||||
PINCTRL_PIN(GPIO24, "GPIO24"),
|
||||
PINCTRL_PIN(GPIO25, "GPIO25"),
|
||||
PINCTRL_PIN(GPIO26, "GPIO26"),
|
||||
PINCTRL_PIN(GPIO27, "GPIO27"),
|
||||
PINCTRL_PIN(GPIO28, "GPIO28"),
|
||||
PINCTRL_PIN(GPIO29, "GPIO29"),
|
||||
PINCTRL_PIN(GPIO30, "GPIO30"),
|
||||
PINCTRL_PIN(GPIO31, "GPIO31"),
|
||||
PINCTRL_PIN(GPIO32, "GPIO32"),
|
||||
PINCTRL_PIN(GPIO33, "GPIO33"),
|
||||
PINCTRL_PIN(GPIO34, "GPIO34"),
|
||||
PINCTRL_PIN(GPIO35, "GPIO35"),
|
||||
PINCTRL_PIN(GPIO36, "GPIO36"),
|
||||
PINCTRL_PIN(GPIO37, "GPIO37"),
|
||||
PINCTRL_PIN(GPIO38, "GPIO38"),
|
||||
PINCTRL_PIN(GPIO39, "GPIO39"),
|
||||
PINCTRL_PIN(GPIO40, "GPIO40"),
|
||||
PINCTRL_PIN(GPIO41, "GPIO41"),
|
||||
PINCTRL_PIN(GPIO42, "GPIO42"),
|
||||
PINCTRL_PIN(GPIO43, "GPIO43"),
|
||||
PINCTRL_PIN(GPIO44, "GPIO44"),
|
||||
PINCTRL_PIN(GPIO45, "GPIO45"),
|
||||
PINCTRL_PIN(GPIO46, "GPIO46"),
|
||||
PINCTRL_PIN(GPIO47, "GPIO47"),
|
||||
PINCTRL_PIN(GPIO48, "GPIO48"),
|
||||
PINCTRL_PIN(GPIO49, "GPIO49"),
|
||||
PINCTRL_PIN(GPIO50, "GPIO50"),
|
||||
PINCTRL_PIN(GPIO51, "GPIO51"),
|
||||
PINCTRL_PIN(GPIO52, "GPIO52"),
|
||||
PINCTRL_PIN(GPIO53, "GPIO53"),
|
||||
PINCTRL_PIN(GPIO54, "GPIO54"),
|
||||
PINCTRL_PIN(GPIO55, "GPIO55"),
|
||||
PINCTRL_PIN(GPIO56, "GPIO56"),
|
||||
PINCTRL_PIN(GPIO57, "GPIO57"),
|
||||
PINCTRL_PIN(GPIO58, "GPIO58"),
|
||||
PINCTRL_PIN(GPIO59, "GPIO59"),
|
||||
PINCTRL_PIN(GPIO60, "GPIO60"),
|
||||
PINCTRL_PIN(GPIO61, "GPIO61"),
|
||||
PINCTRL_PIN(GPIO62, "GPIO62"),
|
||||
PINCTRL_PIN(GPIO63, "GPIO63"),
|
||||
PINCTRL_PIN(GPIO64, "GPIO64"),
|
||||
PINCTRL_PIN(GPIO65, "GPIO65"),
|
||||
PINCTRL_PIN(GPIO66, "GPIO66"),
|
||||
PINCTRL_PIN(GPIO67, "GPIO67"),
|
||||
PINCTRL_PIN(GPIO68, "GPIO68"),
|
||||
PINCTRL_PIN(GPIO69, "GPIO69"),
|
||||
PINCTRL_PIN(GPIO70, "GPIO70"),
|
||||
PINCTRL_PIN(GPIO71, "GPIO71"),
|
||||
PINCTRL_PIN(GPIO72, "GPIO72"),
|
||||
PINCTRL_PIN(GPIO73, "GPIO73"),
|
||||
PINCTRL_PIN(GPIO74, "GPIO74"),
|
||||
PINCTRL_PIN(GPIO75, "GPIO75"),
|
||||
PINCTRL_PIN(GPIO76, "GPIO76"),
|
||||
PINCTRL_PIN(GPIO77, "GPIO77"),
|
||||
PINCTRL_PIN(GPIO78, "GPIO78"),
|
||||
PINCTRL_PIN(GPIO79, "GPIO79"),
|
||||
PINCTRL_PIN(GPIO80, "GPIO80"),
|
||||
PINCTRL_PIN(GPIO81, "GPIO81"),
|
||||
PINCTRL_PIN(GPIO82, "GPIO82"),
|
||||
PINCTRL_PIN(GPIO83, "GPIO83"),
|
||||
PINCTRL_PIN(GPIO84, "GPIO84"),
|
||||
PINCTRL_PIN(GPIO85, "GPIO85"),
|
||||
PINCTRL_PIN(GPIO86, "GPIO86"),
|
||||
PINCTRL_PIN(GPIO87, "GPIO87"),
|
||||
PINCTRL_PIN(GPIO88, "GPIO88"),
|
||||
PINCTRL_PIN(GPIO89, "GPIO89"),
|
||||
PINCTRL_PIN(GPIO90, "GPIO90"),
|
||||
PINCTRL_PIN(GPIO91, "GPIO91"),
|
||||
PINCTRL_PIN(GPIO92, "GPIO92"),
|
||||
PINCTRL_PIN(GPIO93, "GPIO93"),
|
||||
PINCTRL_PIN(GPIO94, "GPIO94"),
|
||||
PINCTRL_PIN(GPIO95, "GPIO95"),
|
||||
PINCTRL_PIN(GPIO96, "GPIO96"),
|
||||
PINCTRL_PIN(GPIO97, "GPIO97"),
|
||||
PINCTRL_PIN(GPIO98, "GPIO98"),
|
||||
PINCTRL_PIN(GPIO99, "GPIO99"),
|
||||
PINCTRL_PIN(GPIO100, "GPIO100"),
|
||||
PINCTRL_PIN(GPIO101, "GPIO101"),
|
||||
PINCTRL_PIN(GPIO102, "GPIO102"),
|
||||
PINCTRL_PIN(GPIO103, "GPIO103"),
|
||||
PINCTRL_PIN(GPIO104, "GPIO104"),
|
||||
PINCTRL_PIN(GPIO105, "GPIO105"),
|
||||
PINCTRL_PIN(GPIO106, "GPIO106"),
|
||||
PINCTRL_PIN(GPIO107, "GPIO107"),
|
||||
PINCTRL_PIN(GPIO108, "GPIO108"),
|
||||
PINCTRL_PIN(GPIO109, "GPIO109"),
|
||||
PINCTRL_PIN(GPIO110, "GPIO110"),
|
||||
PINCTRL_PIN(GPIO111, "GPIO111"),
|
||||
PINCTRL_PIN(GPIO112, "GPIO112"),
|
||||
PINCTRL_PIN(GPIO113, "GPIO113"),
|
||||
PINCTRL_PIN(GPIO114, "GPIO114"),
|
||||
PINCTRL_PIN(GPIO115, "GPIO115"),
|
||||
PINCTRL_PIN(GPIO116, "GPIO116"),
|
||||
PINCTRL_PIN(GPIO117, "GPIO117"),
|
||||
PINCTRL_PIN(GPIO118, "GPIO118"),
|
||||
PINCTRL_PIN(GPIO119, "GPIO119"),
|
||||
PINCTRL_PIN(GPIO120, "GPIO120"),
|
||||
PINCTRL_PIN(GPIO121, "GPIO121"),
|
||||
PINCTRL_PIN(GPIO122, "GPIO122"),
|
||||
PINCTRL_PIN(GPIO123, "GPIO123"),
|
||||
PINCTRL_PIN(GPIO124, "GPIO124"),
|
||||
PINCTRL_PIN(GPIO125, "GPIO125"),
|
||||
PINCTRL_PIN(GPIO126, "GPIO126"),
|
||||
PINCTRL_PIN(GPIO127, "GPIO127"),
|
||||
PINCTRL_PIN(GPIO128, "GPIO128"),
|
||||
PINCTRL_PIN(GPIO129, "GPIO129"),
|
||||
PINCTRL_PIN(GPIO130, "GPIO130"),
|
||||
PINCTRL_PIN(GPIO131, "GPIO131"),
|
||||
PINCTRL_PIN(GPIO132, "GPIO132"),
|
||||
PINCTRL_PIN(GPIO133, "GPIO133"),
|
||||
PINCTRL_PIN(GPIO134, "GPIO134"),
|
||||
PINCTRL_PIN(GPIO135, "GPIO135"),
|
||||
PINCTRL_PIN(GPIO136, "GPIO136"),
|
||||
PINCTRL_PIN(GPIO137, "GPIO137"),
|
||||
PINCTRL_PIN(GPIO138, "GPIO138"),
|
||||
PINCTRL_PIN(GPIO139, "GPIO139"),
|
||||
PINCTRL_PIN(GPIO140, "GPIO140"),
|
||||
PINCTRL_PIN(GPIO141, "GPIO141"),
|
||||
PINCTRL_PIN(GPIO142, "GPIO142"),
|
||||
PINCTRL_PIN(GPIO143, "GPIO143"),
|
||||
PINCTRL_PIN(GPIO144, "GPIO144"),
|
||||
PINCTRL_PIN(GPIO145, "GPIO145"),
|
||||
PINCTRL_PIN(GPIO146, "GPIO146"),
|
||||
PINCTRL_PIN(GPIO147, "GPIO147"),
|
||||
PINCTRL_PIN(GPIO148, "GPIO148"),
|
||||
PINCTRL_PIN(GPIO149, "GPIO149"),
|
||||
PINCTRL_PIN(GPIO150, "GPIO150"),
|
||||
PINCTRL_PIN(GPIO151, "GPIO151"),
|
||||
PINCTRL_PIN(GPIO152, "GPIO152"),
|
||||
PINCTRL_PIN(GPIO153, "GPIO153"),
|
||||
PINCTRL_PIN(GPIO154, "GPIO154"),
|
||||
PINCTRL_PIN(GPIO155, "GPIO155"),
|
||||
PINCTRL_PIN(GPIO156, "GPIO156"),
|
||||
PINCTRL_PIN(GPIO157, "GPIO157"),
|
||||
PINCTRL_PIN(GPIO158, "GPIO158"),
|
||||
PINCTRL_PIN(GPIO159, "GPIO159"),
|
||||
PINCTRL_PIN(GPIO160, "GPIO160"),
|
||||
PINCTRL_PIN(GPIO161, "GPIO161"),
|
||||
PINCTRL_PIN(GPIO162, "GPIO162"),
|
||||
PINCTRL_PIN(GPIO163, "GPIO163"),
|
||||
PINCTRL_PIN(GPIO164, "GPIO164"),
|
||||
PINCTRL_PIN(GPIO165, "GPIO165"),
|
||||
PINCTRL_PIN(GPIO166, "GPIO166"),
|
||||
PINCTRL_PIN(GPIO167, "GPIO167"),
|
||||
PINCTRL_PIN(GPIO168, "GPIO168"),
|
||||
PINCTRL_PIN(TWSI4_SCL, "TWSI4_SCL"),
|
||||
PINCTRL_PIN(TWSI4_SDA, "TWSI4_SDA"),
|
||||
PINCTRL_PIN(G_CLKREQ, "G_CLKREQ"),
|
||||
PINCTRL_PIN(VCXO_REQ, "VCXO_REQ"),
|
||||
PINCTRL_PIN(VCXO_OUT, "VCXO_OUT"),
|
||||
};
|
||||
|
||||
struct pxa3xx_mfp_pin mmp2_mfp[] = {
|
||||
/* pin offs f0 f1 f2 f3 f4 f5 f6 f7 */
|
||||
MFPR_MMP2(GPIO0, 0x054, GPIO, KP_MK, NONE, SPI, NONE, NONE, NONE, NONE),
|
||||
MFPR_MMP2(GPIO1, 0x058, GPIO, KP_MK, NONE, SPI, NONE, NONE, NONE, NONE),
|
||||
MFPR_MMP2(GPIO2, 0x05C, GPIO, KP_MK, NONE, SPI, NONE, NONE, NONE, NONE),
|
||||
MFPR_MMP2(GPIO3, 0x060, GPIO, KP_MK, NONE, SPI, NONE, NONE, NONE, NONE),
|
||||
MFPR_MMP2(GPIO4, 0x064, GPIO, KP_MK, NONE, NONE, NONE, NONE, NONE, NONE),
|
||||
MFPR_MMP2(GPIO5, 0x068, GPIO, KP_MK, NONE, SPI, NONE, NONE, NONE, NONE),
|
||||
MFPR_MMP2(GPIO6, 0x06C, GPIO, KP_MK, NONE, SPI, NONE, NONE, NONE, NONE),
|
||||
MFPR_MMP2(GPIO7, 0x070, GPIO, KP_MK, NONE, SPI, NONE, NONE, NONE, NONE),
|
||||
MFPR_MMP2(GPIO8, 0x074, GPIO, KP_MK, NONE, NONE, NONE, NONE, NONE, NONE),
|
||||
MFPR_MMP2(GPIO9, 0x078, GPIO, KP_MK, NONE, NONE, NONE, NONE, NONE, NONE),
|
||||
MFPR_MMP2(GPIO10, 0x07C, GPIO, KP_MK, NONE, NONE, NONE, NONE, NONE, NONE),
|
||||
MFPR_MMP2(GPIO11, 0x080, GPIO, KP_MK, NONE, NONE, NONE, NONE, NONE, NONE),
|
||||
MFPR_MMP2(GPIO12, 0x084, GPIO, KP_MK, NONE, CCIC1, NONE, NONE, NONE, NONE),
|
||||
MFPR_MMP2(GPIO13, 0x088, GPIO, KP_MK, NONE, CCIC1, NONE, NONE, NONE, NONE),
|
||||
MFPR_MMP2(GPIO14, 0x08C, GPIO, KP_MK, NONE, CCIC1, NONE, NONE, NONE, NONE),
|
||||
MFPR_MMP2(GPIO15, 0x090, GPIO, KP_MK, KP_DK, CCIC1, NONE, NONE, NONE, NONE),
|
||||
MFPR_MMP2(GPIO16, 0x094, GPIO, KP_DK, ROT, CCIC1, NONE, NONE, NONE, NONE),
|
||||
MFPR_MMP2(GPIO17, 0x098, GPIO, KP_DK, ROT, CCIC1, NONE, NONE, NONE, NONE),
|
||||
MFPR_MMP2(GPIO18, 0x09C, GPIO, KP_DK, ROT, CCIC1, NONE, NONE, NONE, NONE),
|
||||
MFPR_MMP2(GPIO19, 0x0A0, GPIO, KP_DK, ROT, CCIC1, NONE, NONE, NONE, NONE),
|
||||
MFPR_MMP2(GPIO20, 0x0A4, GPIO, KP_DK, TB, CCIC1, NONE, NONE, NONE, NONE),
|
||||
MFPR_MMP2(GPIO21, 0x0A8, GPIO, KP_DK, TB, CCIC1, NONE, NONE, NONE, NONE),
|
||||
MFPR_MMP2(GPIO22, 0x0AC, GPIO, KP_DK, TB, CCIC1, NONE, NONE, NONE, NONE),
|
||||
MFPR_MMP2(GPIO23, 0x0B0, GPIO, KP_DK, TB, CCIC1, NONE, NONE, NONE, NONE),
|
||||
MFPR_MMP2(GPIO24, 0x0B4, GPIO, I2S, VCXO_OUT, NONE, NONE, NONE, NONE, NONE),
|
||||
MFPR_MMP2(GPIO25, 0x0B8, GPIO, I2S, HDMI, SSPA2, NONE, NONE, NONE, NONE),
|
||||
MFPR_MMP2(GPIO26, 0x0BC, GPIO, I2S, HDMI, SSPA2, NONE, NONE, NONE, NONE),
|
||||
MFPR_MMP2(GPIO27, 0x0C0, GPIO, I2S, HDMI, SSPA2, NONE, NONE, NONE, NONE),
|
||||
MFPR_MMP2(GPIO28, 0x0C4, GPIO, I2S, NONE, SSPA2, NONE, NONE, NONE, NONE),
|
||||
MFPR_MMP2(GPIO29, 0x0C8, GPIO, UART1, KP_MK, NONE, NONE, NONE, AAS_SPI, NONE),
|
||||
MFPR_MMP2(GPIO30, 0x0CC, GPIO, UART1, KP_MK, NONE, NONE, NONE, AAS_SPI, NONE),
|
||||
MFPR_MMP2(GPIO31, 0x0D0, GPIO, UART1, KP_MK, NONE, NONE, NONE, AAS_SPI, NONE),
|
||||
MFPR_MMP2(GPIO32, 0x0D4, GPIO, UART1, KP_MK, NONE, NONE, NONE, AAS_SPI, NONE),
|
||||
MFPR_MMP2(GPIO33, 0x0D8, GPIO, SSPA2, I2S, NONE, NONE, NONE, NONE, NONE),
|
||||
MFPR_MMP2(GPIO34, 0x0DC, GPIO, SSPA2, I2S, NONE, NONE, NONE, NONE, NONE),
|
||||
MFPR_MMP2(GPIO35, 0x0E0, GPIO, SSPA2, I2S, NONE, NONE, NONE, NONE, NONE),
|
||||
MFPR_MMP2(GPIO36, 0x0E4, GPIO, SSPA2, I2S, NONE, NONE, NONE, NONE, NONE),
|
||||
MFPR_MMP2(GPIO37, 0x0E8, GPIO, MMC2, SSP1, TWSI2, UART2, UART3, AAS_SPI, AAS_TWSI),
|
||||
MFPR_MMP2(GPIO38, 0x0EC, GPIO, MMC2, SSP1, TWSI2, UART2, UART3, AAS_SPI, AAS_TWSI),
|
||||
MFPR_MMP2(GPIO39, 0x0F0, GPIO, MMC2, SSP1, TWSI2, UART2, UART3, AAS_SPI, AAS_TWSI),
|
||||
MFPR_MMP2(GPIO40, 0x0F4, GPIO, MMC2, SSP1, TWSI2, UART2, UART3, AAS_SPI, AAS_TWSI),
|
||||
MFPR_MMP2(GPIO41, 0x0F8, GPIO, MMC2, TWSI5, NONE, NONE, NONE, NONE, NONE),
|
||||
MFPR_MMP2(GPIO42, 0x0FC, GPIO, MMC2, TWSI5, NONE, NONE, NONE, NONE, NONE),
|
||||
MFPR_MMP2(GPIO43, 0x100, GPIO, TWSI2, UART4, SSP1, UART2, UART3, NONE, AAS_TWSI),
|
||||
MFPR_MMP2(GPIO44, 0x104, GPIO, TWSI2, UART4, SSP1, UART2, UART3, NONE, AAS_TWSI),
|
||||
MFPR_MMP2(GPIO45, 0x108, GPIO, UART1, UART4, SSP1, UART2, UART3, NONE, NONE),
|
||||
MFPR_MMP2(GPIO46, 0x10C, GPIO, UART1, UART4, SSP1, UART2, UART3, NONE, NONE),
|
||||
MFPR_MMP2(GPIO47, 0x110, GPIO, UART2, SSP2, TWSI6, CAM2, AAS_SPI, AAS_GPIO, NONE),
|
||||
MFPR_MMP2(GPIO48, 0x114, GPIO, UART2, SSP2, TWSI6, CAM2, AAS_SPI, AAS_GPIO, NONE),
|
||||
MFPR_MMP2(GPIO49, 0x118, GPIO, UART2, SSP2, PWM, CCIC2, AAS_SPI, NONE, NONE),
|
||||
MFPR_MMP2(GPIO50, 0x11C, GPIO, UART2, SSP2, PWM, CCIC2, AAS_SPI, NONE, NONE),
|
||||
MFPR_MMP2(GPIO51, 0x120, GPIO, UART3, ROT, AAS_GPIO, PWM, NONE, NONE, NONE),
|
||||
MFPR_MMP2(GPIO52, 0x124, GPIO, UART3, ROT, AAS_GPIO, PWM, NONE, NONE, NONE),
|
||||
MFPR_MMP2(GPIO53, 0x128, GPIO, UART3, TWSI2, VCXO_REQ, NONE, PWM, NONE, AAS_TWSI),
|
||||
MFPR_MMP2(GPIO54, 0x12C, GPIO, UART3, TWSI2, VCXO_OUT, HDMI, PWM, NONE, AAS_TWSI),
|
||||
MFPR_MMP2(GPIO55, 0x130, GPIO, SSP2, SSP1, UART2, ROT, TWSI2, SSP3, AAS_TWSI),
|
||||
MFPR_MMP2(GPIO56, 0x134, GPIO, SSP2, SSP1, UART2, ROT, TWSI2, KP_DK, AAS_TWSI),
|
||||
MFPR_MMP2(GPIO57, 0x138, GPIO, SSP2_RX, SSP1_TXRX, SSP2_FRM, SSP1_RX, VCXO_REQ, KP_DK, NONE),
|
||||
MFPR_MMP2(GPIO58, 0x13C, GPIO, SSP2, SSP1_RX, SSP1_FRM, SSP1_TXRX, VCXO_REQ, KP_DK, NONE),
|
||||
MFPR_MMP2(GPIO59, 0x280, GPIO, CCIC1, ULPI, MMC3, CCIC2, UART3, UART4, NONE),
|
||||
MFPR_MMP2(GPIO60, 0x284, GPIO, CCIC1, ULPI, MMC3, CCIC2, UART3, UART4, NONE),
|
||||
MFPR_MMP2(GPIO61, 0x288, GPIO, CCIC1, ULPI, MMC3, CCIC2, UART3, HDMI, NONE),
|
||||
MFPR_MMP2(GPIO62, 0x28C, GPIO, CCIC1, ULPI, MMC3, CCIC2, UART3, NONE, NONE),
|
||||
MFPR_MMP2(GPIO63, 0x290, GPIO, CCIC1, ULPI, MMC3, CCIC2, MSP, UART4, NONE),
|
||||
MFPR_MMP2(GPIO64, 0x294, GPIO, CCIC1, ULPI, MMC3, CCIC2, MSP, UART4, NONE),
|
||||
MFPR_MMP2(GPIO65, 0x298, GPIO, CCIC1, ULPI, MMC3, CCIC2, MSP, UART4, NONE),
|
||||
MFPR_MMP2(GPIO66, 0x29C, GPIO, CCIC1, ULPI, MMC3, CCIC2, MSP, UART4, NONE),
|
||||
MFPR_MMP2(GPIO67, 0x2A0, GPIO, CCIC1, ULPI, MMC3, CCIC2, MSP, NONE, NONE),
|
||||
MFPR_MMP2(GPIO68, 0x2A4, GPIO, CCIC1, ULPI, MMC3, CCIC2, MSP, LCD, NONE),
|
||||
MFPR_MMP2(GPIO69, 0x2A8, GPIO, CCIC1, ULPI, MMC3, CCIC2, NONE, LCD, NONE),
|
||||
MFPR_MMP2(GPIO70, 0x2AC, GPIO, CCIC1, ULPI, MMC3, CCIC2, MSP, LCD, NONE),
|
||||
MFPR_MMP2(GPIO71, 0x2B0, GPIO, TWSI3, NONE, PWM, NONE, NONE, LCD, AAS_TWSI),
|
||||
MFPR_MMP2(GPIO72, 0x2B4, GPIO, TWSI3, HDMI, PWM, NONE, NONE, LCD, AAS_TWSI),
|
||||
MFPR_MMP2(GPIO73, 0x2B8, GPIO, VCXO_REQ, 32K_CLKOUT, PWM, VCXO_OUT, NONE, LCD, NONE),
|
||||
MFPR_MMP2(GPIO74, 0x170, GPIO, LCD, SMC, MMC4, SSP3, UART2, UART4, TIPU),
|
||||
MFPR_MMP2(GPIO75, 0x174, GPIO, LCD, SMC, MMC4, SSP3, UART2, UART4, TIPU),
|
||||
MFPR_MMP2(GPIO76, 0x178, GPIO, LCD, SMC, MMC4, SSP3, UART2, UART4, TIPU),
|
||||
MFPR_MMP2(GPIO77, 0x17C, GPIO, LCD, SMC, MMC4, SSP3, UART2, UART4, TIPU),
|
||||
MFPR_MMP2(GPIO78, 0x180, GPIO, LCD, HDMI, MMC4, NONE, SSP4, AAS_SPI, TIPU),
|
||||
MFPR_MMP2(GPIO79, 0x184, GPIO, LCD, AAS_GPIO, MMC4, NONE, SSP4, AAS_SPI, TIPU),
|
||||
MFPR_MMP2(GPIO80, 0x188, GPIO, LCD, AAS_GPIO, MMC4, NONE, SSP4, AAS_SPI, TIPU),
|
||||
MFPR_MMP2(GPIO81, 0x18C, GPIO, LCD, AAS_GPIO, MMC4, NONE, SSP4, AAS_SPI, TIPU),
|
||||
MFPR_MMP2(GPIO82, 0x190, GPIO, LCD, NONE, MMC4, NONE, NONE, CCIC2, TIPU),
|
||||
MFPR_MMP2(GPIO83, 0x194, GPIO, LCD, NONE, MMC4, NONE, NONE, CCIC2, TIPU),
|
||||
MFPR_MMP2(GPIO84, 0x198, GPIO, LCD, SMC, MMC2, NONE, TWSI5, AAS_TWSI, TIPU),
|
||||
MFPR_MMP2(GPIO85, 0x19C, GPIO, LCD, SMC, MMC2, NONE, TWSI5, AAS_TWSI, TIPU),
|
||||
MFPR_MMP2(GPIO86, 0x1A0, GPIO, LCD, SMC, MMC2, NONE, TWSI6, CCIC2, TIPU),
|
||||
MFPR_MMP2(GPIO87, 0x1A4, GPIO, LCD, SMC, MMC2, NONE, TWSI6, CCIC2, TIPU),
|
||||
MFPR_MMP2(GPIO88, 0x1A8, GPIO, LCD, AAS_GPIO, MMC2, NONE, NONE, CCIC2, TIPU),
|
||||
MFPR_MMP2(GPIO89, 0x1AC, GPIO, LCD, AAS_GPIO, MMC2, NONE, NONE, CCIC2, TIPU),
|
||||
MFPR_MMP2(GPIO90, 0x1B0, GPIO, LCD, AAS_GPIO, MMC2, NONE, NONE, CCIC2, TIPU),
|
||||
MFPR_MMP2(GPIO91, 0x1B4, GPIO, LCD, AAS_GPIO, MMC2, NONE, NONE, CCIC2, TIPU),
|
||||
MFPR_MMP2(GPIO92, 0x1B8, GPIO, LCD, AAS_GPIO, MMC2, NONE, NONE, CCIC2, TIPU),
|
||||
MFPR_MMP2(GPIO93, 0x1BC, GPIO, LCD, AAS_GPIO, MMC2, NONE, NONE, CCIC2, TIPU),
|
||||
MFPR_MMP2(GPIO94, 0x1C0, GPIO, LCD, AAS_GPIO, SPI, NONE, AAS_SPI, CCIC2, TIPU),
|
||||
MFPR_MMP2(GPIO95, 0x1C4, GPIO, LCD, TWSI3, SPI, AAS_DEU_EX, AAS_SPI, CCIC2, TIPU),
|
||||
MFPR_MMP2(GPIO96, 0x1C8, GPIO, LCD, TWSI3, SPI, AAS_DEU_EX, AAS_SPI, NONE, TIPU),
|
||||
MFPR_MMP2(GPIO97, 0x1CC, GPIO, LCD, TWSI6, SPI, AAS_DEU_EX, AAS_SPI, NONE, TIPU),
|
||||
MFPR_MMP2(GPIO98, 0x1D0, GPIO, LCD, TWSI6, SPI, ONE_WIRE, NONE, NONE, TIPU),
|
||||
MFPR_MMP2(GPIO99, 0x1D4, GPIO, LCD, SMC, SPI, TWSI5, NONE, NONE, TIPU),
|
||||
MFPR_MMP2(GPIO100, 0x1D8, GPIO, LCD, SMC, SPI, TWSI5, NONE, NONE, TIPU),
|
||||
MFPR_MMP2(GPIO101, 0x1DC, GPIO, LCD, SMC, SPI, NONE, NONE, NONE, TIPU),
|
||||
MFPR_MMP2(GPIO102, 0x000, USIM, GPIO, FSIC, KP_DK, LCD, NONE, NONE, NONE),
|
||||
MFPR_MMP2(GPIO103, 0x004, USIM, GPIO, FSIC, KP_DK, LCD, NONE, NONE, NONE),
|
||||
MFPR_MMP2(GPIO104, 0x1FC, NAND, GPIO, NONE, NONE, NAND, NONE, NONE, NONE),
|
||||
MFPR_MMP2(GPIO105, 0x1F8, NAND, GPIO, NONE, NONE, NAND, NONE, NONE, NONE),
|
||||
MFPR_MMP2(GPIO106, 0x1F4, NAND, GPIO, NONE, NONE, NAND, NONE, NONE, NONE),
|
||||
MFPR_MMP2(GPIO107, 0x1F0, NAND, GPIO, NONE, NONE, NAND, NONE, NONE, NONE),
|
||||
MFPR_MMP2(GPIO108, 0x21C, NAND, GPIO, NONE, NONE, NAND, NONE, NONE, NONE),
|
||||
MFPR_MMP2(GPIO109, 0x218, NAND, GPIO, NONE, NONE, NAND, NONE, NONE, NONE),
|
||||
MFPR_MMP2(GPIO110, 0x214, NAND, GPIO, NONE, NONE, NAND, NONE, NONE, NONE),
|
||||
MFPR_MMP2(GPIO111, 0x200, NAND, GPIO, MMC3, NONE, NONE, NONE, NONE, NONE),
|
||||
MFPR_MMP2(GPIO112, 0x244, NAND, GPIO, MMC3, SMC, NONE, NONE, NONE, NONE),
|
||||
MFPR_MMP2(GPIO113, 0x25C, SMC, GPIO, EXT_DMA, MMC3, SMC, HDMI, NONE, NONE),
|
||||
MFPR_MMP2(GPIO114, 0x164, G_CLKOUT, 32K_CLKOUT, HDMI, NONE, NONE, NONE, NONE, NONE),
|
||||
MFPR_MMP2(GPIO115, 0x260, GPIO, NONE, AC, UART4, UART3, SSP1, NONE, NONE),
|
||||
MFPR_MMP2(GPIO116, 0x264, GPIO, NONE, AC, UART4, UART3, SSP1, NONE, NONE),
|
||||
MFPR_MMP2(GPIO117, 0x268, GPIO, NONE, AC, UART4, UART3, SSP1, NONE, NONE),
|
||||
MFPR_MMP2(GPIO118, 0x26C, GPIO, NONE, AC, UART4, UART3, SSP1, NONE, NONE),
|
||||
MFPR_MMP2(GPIO119, 0x270, GPIO, NONE, CA, SSP3, NONE, NONE, NONE, NONE),
|
||||
MFPR_MMP2(GPIO120, 0x274, GPIO, NONE, CA, SSP3, NONE, NONE, NONE, NONE),
|
||||
MFPR_MMP2(GPIO121, 0x278, GPIO, NONE, CA, SSP3, NONE, NONE, NONE, NONE),
|
||||
MFPR_MMP2(GPIO122, 0x27C, GPIO, NONE, CA, SSP3, NONE, NONE, NONE, NONE),
|
||||
MFPR_MMP2(GPIO123, 0x148, GPIO, SLEEP_IND, ONE_WIRE, 32K_CLKOUT, NONE, NONE, NONE, NONE),
|
||||
MFPR_MMP2(GPIO124, 0x00C, GPIO, MMC1, LCD, MMC3, NAND, NONE, NONE, NONE),
|
||||
MFPR_MMP2(GPIO125, 0x010, GPIO, MMC1, LCD, MMC3, NAND, NONE, NONE, NONE),
|
||||
MFPR_MMP2(GPIO126, 0x014, GPIO, MMC1, LCD, MMC3, NAND, NONE, NONE, NONE),
|
||||
MFPR_MMP2(GPIO127, 0x018, GPIO, NONE, LCD, MMC3, NAND, NONE, NONE, NONE),
|
||||
MFPR_MMP2(GPIO128, 0x01C, GPIO, NONE, LCD, MMC3, NAND, NONE, NONE, NONE),
|
||||
MFPR_MMP2(GPIO129, 0x020, GPIO, MMC1, LCD, MMC3, NAND, NONE, NONE, NONE),
|
||||
MFPR_MMP2(GPIO130, 0x024, GPIO, MMC1, LCD, MMC3, NAND, NONE, NONE, NONE),
|
||||
MFPR_MMP2(GPIO131, 0x028, GPIO, MMC1, NONE, MSP, NONE, NONE, NONE, NONE),
|
||||
MFPR_MMP2(GPIO132, 0x02C, GPIO, MMC1, PRI_JTAG, MSP, SSP3, AAS_JTAG, NONE, NONE),
|
||||
MFPR_MMP2(GPIO133, 0x030, GPIO, MMC1, PRI_JTAG, MSP, SSP3, AAS_JTAG, NONE, NONE),
|
||||
MFPR_MMP2(GPIO134, 0x034, GPIO, MMC1, PRI_JTAG, MSP, SSP3, AAS_JTAG, NONE, NONE),
|
||||
MFPR_MMP2(GPIO135, 0x038, GPIO, NONE, LCD, MMC3, NAND, NONE, NONE, NONE),
|
||||
MFPR_MMP2(GPIO136, 0x03C, GPIO, MMC1, PRI_JTAG, MSP, SSP3, AAS_JTAG, NONE, NONE),
|
||||
MFPR_MMP2(GPIO137, 0x040, GPIO, HDMI, LCD, MSP, NONE, NONE, NONE, NONE),
|
||||
MFPR_MMP2(GPIO138, 0x044, GPIO, NONE, LCD, MMC3, SMC, NONE, NONE, NONE),
|
||||
MFPR_MMP2(GPIO139, 0x048, GPIO, MMC1, PRI_JTAG, MSP, NONE, AAS_JTAG, NONE, NONE),
|
||||
MFPR_MMP2(GPIO140, 0x04C, GPIO, MMC1, LCD, NONE, NONE, UART2, UART1, NONE),
|
||||
MFPR_MMP2(GPIO141, 0x050, GPIO, MMC1, LCD, NONE, NONE, UART2, UART1, NONE),
|
||||
MFPR_MMP2(GPIO142, 0x008, USIM, GPIO, FSIC, KP_DK, NONE, NONE, NONE, NONE),
|
||||
MFPR_MMP2(GPIO143, 0x220, NAND, GPIO, SMC, NONE, NAND, NONE, NONE, NONE),
|
||||
MFPR_MMP2(GPIO144, 0x224, NAND, GPIO, SMC_INT, SMC, NAND, NONE, NONE, NONE),
|
||||
MFPR_MMP2(GPIO145, 0x228, SMC, GPIO, NONE, NONE, SMC, NONE, NONE, NONE),
|
||||
MFPR_MMP2(GPIO146, 0x22C, SMC, GPIO, NONE, NONE, SMC, NONE, NONE, NONE),
|
||||
MFPR_MMP2(GPIO147, 0x230, NAND, GPIO, NONE, NONE, NAND, NONE, NONE, NONE),
|
||||
MFPR_MMP2(GPIO148, 0x234, NAND, GPIO, NONE, NONE, NAND, NONE, NONE, NONE),
|
||||
MFPR_MMP2(GPIO149, 0x238, NAND, GPIO, NONE, NONE, NONE, NONE, NONE, NONE),
|
||||
MFPR_MMP2(GPIO150, 0x23C, NAND, GPIO, NONE, NONE, NAND, NONE, NONE, NONE),
|
||||
MFPR_MMP2(GPIO151, 0x240, SMC, GPIO, MMC3, NONE, NONE, NONE, NONE, NONE),
|
||||
MFPR_MMP2(GPIO152, 0x248, SMC, GPIO, NONE, NONE, SMC, NONE, NONE, NONE),
|
||||
MFPR_MMP2(GPIO153, 0x24C, SMC, GPIO, NONE, NONE, SMC, NONE, NONE, NONE),
|
||||
MFPR_MMP2(GPIO154, 0x254, SMC_INT, GPIO, SMC, NONE, NAND, NONE, NONE, NONE),
|
||||
MFPR_MMP2(GPIO155, 0x258, EXT_DMA, GPIO, SMC, NONE, EXT_DMA, NONE, NONE, NONE),
|
||||
MFPR_MMP2(GPIO156, 0x14C, PRI_JTAG, GPIO, PWM, NONE, NONE, NONE, NONE, NONE),
|
||||
MFPR_MMP2(GPIO157, 0x150, PRI_JTAG, GPIO, PWM, NONE, NONE, NONE, NONE, NONE),
|
||||
MFPR_MMP2(GPIO158, 0x154, PRI_JTAG, GPIO, PWM, NONE, NONE, NONE, NONE, NONE),
|
||||
MFPR_MMP2(GPIO159, 0x158, PRI_JTAG, GPIO, PWM, NONE, NONE, NONE, NONE, NONE),
|
||||
MFPR_MMP2(GPIO160, 0x250, NAND, GPIO, SMC, NONE, NAND, NONE, NONE, NONE),
|
||||
MFPR_MMP2(GPIO161, 0x210, NAND, GPIO, NONE, NONE, NAND, NONE, NONE, NONE),
|
||||
MFPR_MMP2(GPIO162, 0x20C, NAND, GPIO, MMC3, NONE, NONE, NONE, NONE, NONE),
|
||||
MFPR_MMP2(GPIO163, 0x208, NAND, GPIO, MMC3, NONE, NONE, NONE, NONE, NONE),
|
||||
MFPR_MMP2(GPIO164, 0x204, NAND, GPIO, MMC3, NONE, NONE, NONE, NONE, NONE),
|
||||
MFPR_MMP2(GPIO165, 0x1EC, NAND, GPIO, MMC3, NONE, NONE, NONE, NONE, NONE),
|
||||
MFPR_MMP2(GPIO166, 0x1E8, NAND, GPIO, MMC3, NONE, NONE, NONE, NONE, NONE),
|
||||
MFPR_MMP2(GPIO167, 0x1E4, NAND, GPIO, MMC3, NONE, NONE, NONE, NONE, NONE),
|
||||
MFPR_MMP2(GPIO168, 0x1E0, NAND, GPIO, MMC3, NONE, NONE, NONE, NONE, NONE),
|
||||
MFPR_MMP2(TWSI4_SCL, 0x2BC, TWSI4, LCD, NONE, NONE, NONE, NONE, NONE, NONE),
|
||||
MFPR_MMP2(TWSI4_SDA, 0x2C0, TWSI4, LCD, NONE, NONE, NONE, NONE, NONE, NONE),
|
||||
MFPR_MMP2(G_CLKREQ, 0x160, G_CLKREQ, ONE_WIRE, NONE, NONE, NONE, NONE, NONE, NONE),
|
||||
MFPR_MMP2(VCXO_REQ, 0x168, VCXO_REQ, ONE_WIRE, PLL, NONE, NONE, NONE, NONE, NONE),
|
||||
MFPR_MMP2(VCXO_OUT, 0x16C, VCXO_OUT, 32K_CLKOUT, NONE, NONE, NONE, NONE, NONE, NONE),
|
||||
};
|
||||
|
||||
static const unsigned mmp2_uart1_pin1[] = {GPIO29, GPIO30, GPIO31, GPIO32};
|
||||
static const unsigned mmp2_uart1_pin2[] = {GPIO45, GPIO46};
|
||||
static const unsigned mmp2_uart1_pin3[] = {GPIO140, GPIO141};
|
||||
static const unsigned mmp2_uart2_pin1[] = {GPIO37, GPIO38, GPIO39, GPIO40};
|
||||
static const unsigned mmp2_uart2_pin2[] = {GPIO43, GPIO44, GPIO45, GPIO46};
|
||||
static const unsigned mmp2_uart2_pin3[] = {GPIO47, GPIO48, GPIO49, GPIO50};
|
||||
static const unsigned mmp2_uart2_pin4[] = {GPIO74, GPIO75, GPIO76, GPIO77};
|
||||
static const unsigned mmp2_uart2_pin5[] = {GPIO55, GPIO56};
|
||||
static const unsigned mmp2_uart2_pin6[] = {GPIO140, GPIO141};
|
||||
static const unsigned mmp2_uart3_pin1[] = {GPIO37, GPIO38, GPIO39, GPIO40};
|
||||
static const unsigned mmp2_uart3_pin2[] = {GPIO43, GPIO44, GPIO45, GPIO46};
|
||||
static const unsigned mmp2_uart3_pin3[] = {GPIO51, GPIO52, GPIO53, GPIO54};
|
||||
static const unsigned mmp2_uart3_pin4[] = {GPIO59, GPIO60, GPIO61, GPIO62};
|
||||
static const unsigned mmp2_uart3_pin5[] = {GPIO115, GPIO116, GPIO117, GPIO118};
|
||||
static const unsigned mmp2_uart3_pin6[] = {GPIO51, GPIO52};
|
||||
static const unsigned mmp2_uart4_pin1[] = {GPIO43, GPIO44, GPIO45, GPIO46};
|
||||
static const unsigned mmp2_uart4_pin2[] = {GPIO63, GPIO64, GPIO65, GPIO66};
|
||||
static const unsigned mmp2_uart4_pin3[] = {GPIO74, GPIO75, GPIO76, GPIO77};
|
||||
static const unsigned mmp2_uart4_pin4[] = {GPIO115, GPIO116, GPIO117, GPIO118};
|
||||
static const unsigned mmp2_uart4_pin5[] = {GPIO59, GPIO60};
|
||||
static const unsigned mmp2_kpdk_pin1[] = {GPIO16, GPIO17, GPIO18, GPIO19};
|
||||
static const unsigned mmp2_kpdk_pin2[] = {GPIO16, GPIO17};
|
||||
static const unsigned mmp2_twsi2_pin1[] = {GPIO37, GPIO38};
|
||||
static const unsigned mmp2_twsi2_pin2[] = {GPIO39, GPIO40};
|
||||
static const unsigned mmp2_twsi2_pin3[] = {GPIO43, GPIO44};
|
||||
static const unsigned mmp2_twsi2_pin4[] = {GPIO53, GPIO54};
|
||||
static const unsigned mmp2_twsi2_pin5[] = {GPIO55, GPIO56};
|
||||
static const unsigned mmp2_twsi3_pin1[] = {GPIO71, GPIO72};
|
||||
static const unsigned mmp2_twsi3_pin2[] = {GPIO95, GPIO96};
|
||||
static const unsigned mmp2_twsi4_pin1[] = {TWSI4_SCL, TWSI4_SDA};
|
||||
static const unsigned mmp2_twsi5_pin1[] = {GPIO41, GPIO42};
|
||||
static const unsigned mmp2_twsi5_pin2[] = {GPIO84, GPIO85};
|
||||
static const unsigned mmp2_twsi5_pin3[] = {GPIO99, GPIO100};
|
||||
static const unsigned mmp2_twsi6_pin1[] = {GPIO47, GPIO48};
|
||||
static const unsigned mmp2_twsi6_pin2[] = {GPIO86, GPIO87};
|
||||
static const unsigned mmp2_twsi6_pin3[] = {GPIO97, GPIO98};
|
||||
static const unsigned mmp2_ccic1_pin1[] = {GPIO12, GPIO13, GPIO14, GPIO15,
|
||||
GPIO16, GPIO17, GPIO18, GPIO19, GPIO20, GPIO21, GPIO22, GPIO23};
|
||||
static const unsigned mmp2_ccic1_pin2[] = {GPIO59, GPIO60, GPIO61, GPIO62,
|
||||
GPIO63, GPIO64, GPIO65, GPIO66, GPIO67, GPIO68, GPIO69, GPIO70};
|
||||
static const unsigned mmp2_ccic2_pin1[] = {GPIO59, GPIO60, GPIO61, GPIO62,
|
||||
GPIO63, GPIO64, GPIO65, GPIO66, GPIO67, GPIO68, GPIO69, GPIO70};
|
||||
static const unsigned mmp2_ccic2_pin2[] = {GPIO82, GPIO83, GPIO86, GPIO87,
|
||||
GPIO88, GPIO89, GPIO90, GPIO91, GPIO92, GPIO93, GPIO94, GPIO95};
|
||||
static const unsigned mmp2_ulpi_pin1[] = {GPIO59, GPIO60, GPIO61, GPIO62,
|
||||
GPIO63, GPIO64, GPIO65, GPIO66, GPIO67, GPIO68, GPIO69, GPIO70};
|
||||
static const unsigned mmp2_ro_pin1[] = {GPIO16, GPIO17};
|
||||
static const unsigned mmp2_ro_pin2[] = {GPIO18, GPIO19};
|
||||
static const unsigned mmp2_ro_pin3[] = {GPIO51, GPIO52};
|
||||
static const unsigned mmp2_ro_pin4[] = {GPIO55, GPIO56};
|
||||
static const unsigned mmp2_i2s_pin1[] = {GPIO24, GPIO25, GPIO26, GPIO27,
|
||||
GPIO28};
|
||||
static const unsigned mmp2_i2s_pin2[] = {GPIO33, GPIO34, GPIO35, GPIO36};
|
||||
static const unsigned mmp2_ssp1_pin1[] = {GPIO37, GPIO38, GPIO39, GPIO40};
|
||||
static const unsigned mmp2_ssp1_pin2[] = {GPIO43, GPIO44, GPIO45, GPIO46};
|
||||
static const unsigned mmp2_ssp1_pin3[] = {GPIO115, GPIO116, GPIO117, GPIO118};
|
||||
static const unsigned mmp2_ssp2_pin1[] = {GPIO47, GPIO48, GPIO49, GPIO50};
|
||||
static const unsigned mmp2_ssp3_pin1[] = {GPIO119, GPIO120, GPIO121, GPIO122};
|
||||
static const unsigned mmp2_ssp3_pin2[] = {GPIO132, GPIO133, GPIO133, GPIO136};
|
||||
static const unsigned mmp2_sspa2_pin1[] = {GPIO25, GPIO26, GPIO27, GPIO28};
|
||||
static const unsigned mmp2_sspa2_pin2[] = {GPIO33, GPIO34, GPIO35, GPIO36};
|
||||
static const unsigned mmp2_mmc1_pin1[] = {GPIO131, GPIO132, GPIO133, GPIO134,
|
||||
GPIO136, GPIO139, GPIO140, GPIO141};
|
||||
static const unsigned mmp2_mmc2_pin1[] = {GPIO37, GPIO38, GPIO39, GPIO40,
|
||||
GPIO41, GPIO42};
|
||||
static const unsigned mmp2_mmc3_pin1[] = {GPIO111, GPIO112, GPIO151, GPIO162,
|
||||
GPIO163, GPIO164, GPIO165, GPIO166, GPIO167, GPIO168};
|
||||
|
||||
static struct pxa3xx_pin_group mmp2_grps[] = {
|
||||
GRP_MMP2("uart1 4p1", UART1, mmp2_uart1_pin1),
|
||||
GRP_MMP2("uart1 2p2", UART1, mmp2_uart1_pin2),
|
||||
GRP_MMP2("uart1 2p3", UART1, mmp2_uart1_pin3),
|
||||
GRP_MMP2("uart2 4p1", UART2, mmp2_uart2_pin1),
|
||||
GRP_MMP2("uart2 4p2", UART2, mmp2_uart2_pin2),
|
||||
GRP_MMP2("uart2 4p3", UART2, mmp2_uart2_pin3),
|
||||
GRP_MMP2("uart2 4p4", UART2, mmp2_uart2_pin4),
|
||||
GRP_MMP2("uart2 2p5", UART2, mmp2_uart2_pin5),
|
||||
GRP_MMP2("uart2 2p6", UART2, mmp2_uart2_pin6),
|
||||
GRP_MMP2("uart3 4p1", UART3, mmp2_uart3_pin1),
|
||||
GRP_MMP2("uart3 4p2", UART3, mmp2_uart3_pin2),
|
||||
GRP_MMP2("uart3 4p3", UART3, mmp2_uart3_pin3),
|
||||
GRP_MMP2("uart3 4p4", UART3, mmp2_uart3_pin4),
|
||||
GRP_MMP2("uart3 4p5", UART3, mmp2_uart3_pin5),
|
||||
GRP_MMP2("uart3 2p6", UART3, mmp2_uart3_pin6),
|
||||
GRP_MMP2("uart4 4p1", UART4, mmp2_uart4_pin1),
|
||||
GRP_MMP2("uart4 4p2", UART4, mmp2_uart4_pin2),
|
||||
GRP_MMP2("uart4 4p3", UART4, mmp2_uart4_pin3),
|
||||
GRP_MMP2("uart4 4p4", UART4, mmp2_uart4_pin4),
|
||||
GRP_MMP2("uart4 2p5", UART4, mmp2_uart4_pin5),
|
||||
GRP_MMP2("kpdk 4p1", KP_DK, mmp2_kpdk_pin1),
|
||||
GRP_MMP2("kpdk 4p2", KP_DK, mmp2_kpdk_pin2),
|
||||
GRP_MMP2("twsi2-1", TWSI2, mmp2_twsi2_pin1),
|
||||
GRP_MMP2("twsi2-2", TWSI2, mmp2_twsi2_pin2),
|
||||
GRP_MMP2("twsi2-3", TWSI2, mmp2_twsi2_pin3),
|
||||
GRP_MMP2("twsi2-4", TWSI2, mmp2_twsi2_pin4),
|
||||
GRP_MMP2("twsi2-5", TWSI2, mmp2_twsi2_pin5),
|
||||
GRP_MMP2("twsi3-1", TWSI3, mmp2_twsi3_pin1),
|
||||
GRP_MMP2("twsi3-2", TWSI3, mmp2_twsi3_pin2),
|
||||
GRP_MMP2("twsi4", TWSI4, mmp2_twsi4_pin1),
|
||||
GRP_MMP2("twsi5-1", TWSI5, mmp2_twsi5_pin1),
|
||||
GRP_MMP2("twsi5-2", TWSI5, mmp2_twsi5_pin2),
|
||||
GRP_MMP2("twsi5-3", TWSI5, mmp2_twsi5_pin3),
|
||||
GRP_MMP2("twsi6-1", TWSI6, mmp2_twsi6_pin1),
|
||||
GRP_MMP2("twsi6-2", TWSI6, mmp2_twsi6_pin2),
|
||||
GRP_MMP2("twsi6-3", TWSI6, mmp2_twsi6_pin3),
|
||||
GRP_MMP2("ccic1-1", CCIC1, mmp2_ccic1_pin1),
|
||||
GRP_MMP2("ccic1-2", CCIC1, mmp2_ccic1_pin2),
|
||||
GRP_MMP2("ccic2-1", CCIC2, mmp2_ccic2_pin1),
|
||||
GRP_MMP2("ccic2-1", CCIC2, mmp2_ccic2_pin2),
|
||||
GRP_MMP2("ulpi", ULPI, mmp2_ulpi_pin1),
|
||||
GRP_MMP2("ro-1", ROT, mmp2_ro_pin1),
|
||||
GRP_MMP2("ro-2", ROT, mmp2_ro_pin2),
|
||||
GRP_MMP2("ro-3", ROT, mmp2_ro_pin3),
|
||||
GRP_MMP2("ro-4", ROT, mmp2_ro_pin4),
|
||||
GRP_MMP2("i2s 5p1", I2S, mmp2_i2s_pin1),
|
||||
GRP_MMP2("i2s 4p2", I2S, mmp2_i2s_pin2),
|
||||
GRP_MMP2("ssp1 4p1", SSP1, mmp2_ssp1_pin1),
|
||||
GRP_MMP2("ssp1 4p2", SSP1, mmp2_ssp1_pin2),
|
||||
GRP_MMP2("ssp1 4p3", SSP1, mmp2_ssp1_pin3),
|
||||
GRP_MMP2("ssp2 4p1", SSP2, mmp2_ssp2_pin1),
|
||||
GRP_MMP2("ssp3 4p1", SSP3, mmp2_ssp3_pin1),
|
||||
GRP_MMP2("ssp3 4p2", SSP3, mmp2_ssp3_pin2),
|
||||
GRP_MMP2("sspa2 4p1", SSPA2, mmp2_sspa2_pin1),
|
||||
GRP_MMP2("sspa2 4p2", SSPA2, mmp2_sspa2_pin2),
|
||||
GRP_MMP2("mmc1 8p1", MMC1, mmp2_mmc1_pin1),
|
||||
GRP_MMP2("mmc2 6p1", MMC2, mmp2_mmc2_pin1),
|
||||
GRP_MMP2("mmc3 10p1", MMC3, mmp2_mmc3_pin1),
|
||||
};
|
||||
|
||||
static const char * const mmp2_uart1_grps[] = {"uart1 4p1", "uart1 2p2",
|
||||
"uart1 2p3"};
|
||||
static const char * const mmp2_uart2_grps[] = {"uart2 4p1", "uart2 4p2",
|
||||
"uart2 4p3", "uart2 4p4", "uart2 4p5", "uart2 4p6"};
|
||||
static const char * const mmp2_uart3_grps[] = {"uart3 4p1", "uart3 4p2",
|
||||
"uart3 4p3", "uart3 4p4", "uart3 4p5", "uart3 2p6"};
|
||||
static const char * const mmp2_uart4_grps[] = {"uart4 4p1", "uart4 4p2",
|
||||
"uart4 4p3", "uart4 4p4", "uart4 2p5"};
|
||||
static const char * const mmp2_kpdk_grps[] = {"kpdk 4p1", "kpdk 4p2"};
|
||||
static const char * const mmp2_twsi2_grps[] = {"twsi2-1", "twsi2-2",
|
||||
"twsi2-3", "twsi2-4", "twsi2-5"};
|
||||
static const char * const mmp2_twsi3_grps[] = {"twsi3-1", "twsi3-2"};
|
||||
static const char * const mmp2_twsi4_grps[] = {"twsi4"};
|
||||
static const char * const mmp2_twsi5_grps[] = {"twsi5-1", "twsi5-2",
|
||||
"twsi5-3"};
|
||||
static const char * const mmp2_twsi6_grps[] = {"twsi6-1", "twsi6-2",
|
||||
"twsi6-3"};
|
||||
static const char * const mmp2_ccic1_grps[] = {"ccic1-1", "ccic1-2"};
|
||||
static const char * const mmp2_ccic2_grps[] = {"ccic2-1", "ccic2-2"};
|
||||
static const char * const mmp2_ulpi_grps[] = {"ulpi"};
|
||||
static const char * const mmp2_ro_grps[] = {"ro-1", "ro-2", "ro-3", "ro-4"};
|
||||
static const char * const mmp2_i2s_grps[] = {"i2s 5p1", "i2s 4p2"};
|
||||
static const char * const mmp2_ssp1_grps[] = {"ssp1 4p1", "ssp1 4p2",
|
||||
"ssp1 4p3"};
|
||||
static const char * const mmp2_ssp2_grps[] = {"ssp2 4p1"};
|
||||
static const char * const mmp2_ssp3_grps[] = {"ssp3 4p1", "ssp3 4p2"};
|
||||
static const char * const mmp2_sspa2_grps[] = {"sspa2 4p1", "sspa2 4p2"};
|
||||
static const char * const mmp2_mmc1_grps[] = {"mmc1 8p1"};
|
||||
static const char * const mmp2_mmc2_grps[] = {"mmc2 6p1"};
|
||||
static const char * const mmp2_mmc3_grps[] = {"mmc3 10p1"};
|
||||
|
||||
static struct pxa3xx_pmx_func mmp2_funcs[] = {
|
||||
{"uart1", ARRAY_AND_SIZE(mmp2_uart1_grps)},
|
||||
{"uart2", ARRAY_AND_SIZE(mmp2_uart2_grps)},
|
||||
{"uart3", ARRAY_AND_SIZE(mmp2_uart3_grps)},
|
||||
{"uart4", ARRAY_AND_SIZE(mmp2_uart4_grps)},
|
||||
{"kpdk", ARRAY_AND_SIZE(mmp2_kpdk_grps)},
|
||||
{"twsi2", ARRAY_AND_SIZE(mmp2_twsi2_grps)},
|
||||
{"twsi3", ARRAY_AND_SIZE(mmp2_twsi3_grps)},
|
||||
{"twsi4", ARRAY_AND_SIZE(mmp2_twsi4_grps)},
|
||||
{"twsi5", ARRAY_AND_SIZE(mmp2_twsi5_grps)},
|
||||
{"twsi6", ARRAY_AND_SIZE(mmp2_twsi6_grps)},
|
||||
{"ccic1", ARRAY_AND_SIZE(mmp2_ccic1_grps)},
|
||||
{"ccic2", ARRAY_AND_SIZE(mmp2_ccic2_grps)},
|
||||
{"ulpi", ARRAY_AND_SIZE(mmp2_ulpi_grps)},
|
||||
{"ro", ARRAY_AND_SIZE(mmp2_ro_grps)},
|
||||
{"i2s", ARRAY_AND_SIZE(mmp2_i2s_grps)},
|
||||
{"ssp1", ARRAY_AND_SIZE(mmp2_ssp1_grps)},
|
||||
{"ssp2", ARRAY_AND_SIZE(mmp2_ssp2_grps)},
|
||||
{"ssp3", ARRAY_AND_SIZE(mmp2_ssp3_grps)},
|
||||
{"sspa2", ARRAY_AND_SIZE(mmp2_sspa2_grps)},
|
||||
{"mmc1", ARRAY_AND_SIZE(mmp2_mmc1_grps)},
|
||||
{"mmc2", ARRAY_AND_SIZE(mmp2_mmc2_grps)},
|
||||
{"mmc3", ARRAY_AND_SIZE(mmp2_mmc3_grps)},
|
||||
};
|
||||
|
||||
static struct pinctrl_desc mmp2_pctrl_desc = {
|
||||
.name = "mmp2-pinctrl",
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
static struct pxa3xx_pinmux_info mmp2_info = {
|
||||
.mfp = mmp2_mfp,
|
||||
.num_mfp = ARRAY_SIZE(mmp2_mfp),
|
||||
.grps = mmp2_grps,
|
||||
.num_grps = ARRAY_SIZE(mmp2_grps),
|
||||
.funcs = mmp2_funcs,
|
||||
.num_funcs = ARRAY_SIZE(mmp2_funcs),
|
||||
.num_gpio = 169,
|
||||
.desc = &mmp2_pctrl_desc,
|
||||
.pads = mmp2_pads,
|
||||
.num_pads = ARRAY_SIZE(mmp2_pads),
|
||||
|
||||
.cputype = PINCTRL_MMP2,
|
||||
.ds_mask = MMP2_DS_MASK,
|
||||
.ds_shift = MMP2_DS_SHIFT,
|
||||
};
|
||||
|
||||
static int mmp2_pinmux_probe(struct platform_device *pdev)
|
||||
{
|
||||
return pxa3xx_pinctrl_register(pdev, &mmp2_info);
|
||||
}
|
||||
|
||||
static int mmp2_pinmux_remove(struct platform_device *pdev)
|
||||
{
|
||||
return pxa3xx_pinctrl_unregister(pdev);
|
||||
}
|
||||
|
||||
static struct platform_driver mmp2_pinmux_driver = {
|
||||
.driver = {
|
||||
.name = "mmp2-pinmux",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = mmp2_pinmux_probe,
|
||||
.remove = mmp2_pinmux_remove,
|
||||
};
|
||||
|
||||
static int __init mmp2_pinmux_init(void)
|
||||
{
|
||||
return platform_driver_register(&mmp2_pinmux_driver);
|
||||
}
|
||||
core_initcall_sync(mmp2_pinmux_init);
|
||||
|
||||
static void __exit mmp2_pinmux_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&mmp2_pinmux_driver);
|
||||
}
|
||||
module_exit(mmp2_pinmux_exit);
|
||||
|
||||
MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
|
||||
MODULE_DESCRIPTION("PXA3xx pin control driver");
|
||||
MODULE_LICENSE("GPL v2");
|
@ -158,7 +158,7 @@ static void mxs_dt_free_map(struct pinctrl_dev *pctldev,
|
||||
kfree(map);
|
||||
}
|
||||
|
||||
static struct pinctrl_ops mxs_pinctrl_ops = {
|
||||
static const struct pinctrl_ops mxs_pinctrl_ops = {
|
||||
.get_groups_count = mxs_get_groups_count,
|
||||
.get_group_name = mxs_get_group_name,
|
||||
.get_group_pins = mxs_get_group_pins,
|
||||
@ -219,7 +219,7 @@ static int mxs_pinctrl_enable(struct pinctrl_dev *pctldev, unsigned selector,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct pinmux_ops mxs_pinmux_ops = {
|
||||
static const struct pinmux_ops mxs_pinmux_ops = {
|
||||
.get_functions_count = mxs_pinctrl_get_funcs_count,
|
||||
.get_function_name = mxs_pinctrl_get_func_name,
|
||||
.get_function_groups = mxs_pinctrl_get_func_groups,
|
||||
@ -319,7 +319,7 @@ static void mxs_pinconf_group_dbg_show(struct pinctrl_dev *pctldev,
|
||||
seq_printf(s, "0x%lx", config);
|
||||
}
|
||||
|
||||
static struct pinconf_ops mxs_pinconf_ops = {
|
||||
static const struct pinconf_ops mxs_pinconf_ops = {
|
||||
.pin_config_get = mxs_pinconf_get,
|
||||
.pin_config_set = mxs_pinconf_set,
|
||||
.pin_config_group_get = mxs_pinconf_group_get,
|
||||
|
@ -466,7 +466,7 @@ static const unsigned mc1_a_1_pins[] = { DB8500_PIN_AH16, DB8500_PIN_AG15,
|
||||
DB8500_PIN_AJ15, DB8500_PIN_AG14, DB8500_PIN_AF13, DB8500_PIN_AG13,
|
||||
DB8500_PIN_AH15 };
|
||||
static const unsigned mc1_a_2_pins[] = { DB8500_PIN_AH16, DB8500_PIN_AJ15,
|
||||
DB8500_PIN_AG14, DB8500_PIN_AF13, DB8500_PIN_AG13,DB8500_PIN_AH15 };
|
||||
DB8500_PIN_AG14, DB8500_PIN_AF13, DB8500_PIN_AG13, DB8500_PIN_AH15 };
|
||||
static const unsigned mc1dir_a_1_pins[] = { DB8500_PIN_AH13, DB8500_PIN_AG12,
|
||||
DB8500_PIN_AH12, DB8500_PIN_AH11 };
|
||||
static const unsigned hsir_a_1_pins[] = { DB8500_PIN_AG10, DB8500_PIN_AH10,
|
||||
@ -663,7 +663,7 @@ static const unsigned hwobs_oc4_1_pins[] = { DB8500_PIN_D17, DB8500_PIN_D16,
|
||||
DB8500_PIN_D21, DB8500_PIN_D20, DB8500_PIN_C20, DB8500_PIN_B21,
|
||||
DB8500_PIN_C21, DB8500_PIN_A22, DB8500_PIN_B24, DB8500_PIN_C22 };
|
||||
|
||||
#define DB8500_PIN_GROUP(a,b) { .name = #a, .pins = a##_pins, \
|
||||
#define DB8500_PIN_GROUP(a, b) { .name = #a, .pins = a##_pins, \
|
||||
.npins = ARRAY_SIZE(a##_pins), .altsetting = b }
|
||||
|
||||
static const struct nmk_pingroup nmk_db8500_groups[] = {
|
||||
|
@ -299,7 +299,7 @@ static const unsigned i2c0_a_1_pins[] = { STN8815_PIN_D3, STN8815_PIN_D2 };
|
||||
static const unsigned u1_b_1_pins[] = { STN8815_PIN_B16, STN8815_PIN_A16 };
|
||||
static const unsigned i2cusb_b_1_pins[] = { STN8815_PIN_C21, STN8815_PIN_C20 };
|
||||
|
||||
#define STN8815_PIN_GROUP(a,b) { .name = #a, .pins = a##_pins, \
|
||||
#define STN8815_PIN_GROUP(a, b) { .name = #a, .pins = a##_pins, \
|
||||
.npins = ARRAY_SIZE(a##_pins), .altsetting = b }
|
||||
|
||||
static const struct nmk_pingroup nmk_stn8815_groups[] = {
|
||||
|
@ -1565,8 +1565,8 @@ static int nmk_dt_add_map_configs(struct pinctrl_map **map,
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define NMK_CONFIG_PIN(x,y) { .property = x, .config = y, }
|
||||
#define NMK_CONFIG_PIN_ARRAY(x,y) { .property = x, .choice = y, \
|
||||
#define NMK_CONFIG_PIN(x, y) { .property = x, .config = y, }
|
||||
#define NMK_CONFIG_PIN_ARRAY(x, y) { .property = x, .choice = y, \
|
||||
.size = ARRAY_SIZE(y), }
|
||||
|
||||
static const unsigned long nmk_pin_input_modes[] = {
|
||||
@ -1764,7 +1764,7 @@ int nmk_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct pinctrl_ops nmk_pinctrl_ops = {
|
||||
static const struct pinctrl_ops nmk_pinctrl_ops = {
|
||||
.get_groups_count = nmk_get_groups_cnt,
|
||||
.get_group_name = nmk_get_group_name,
|
||||
.get_group_pins = nmk_get_group_pins,
|
||||
@ -1975,7 +1975,7 @@ static void nmk_gpio_disable_free(struct pinctrl_dev *pctldev,
|
||||
/* Set the pin to some default state, GPIO is usually default */
|
||||
}
|
||||
|
||||
static struct pinmux_ops nmk_pinmux_ops = {
|
||||
static const struct pinmux_ops nmk_pinmux_ops = {
|
||||
.get_functions_count = nmk_pmx_get_funcs_cnt,
|
||||
.get_function_name = nmk_pmx_get_func_name,
|
||||
.get_function_groups = nmk_pmx_get_func_groups,
|
||||
@ -2068,7 +2068,7 @@ static int nmk_pin_config_set(struct pinctrl_dev *pctldev, unsigned pin,
|
||||
pin, cfg, pullnames[pull], slpmnames[slpm],
|
||||
output ? "output " : "input",
|
||||
output ? (val ? "high" : "low") : "",
|
||||
lowemi ? "on" : "off" );
|
||||
lowemi ? "on" : "off");
|
||||
|
||||
clk_enable(nmk_chip->clk);
|
||||
bit = pin % NMK_GPIO_PER_CHIP;
|
||||
@ -2089,7 +2089,7 @@ static int nmk_pin_config_set(struct pinctrl_dev *pctldev, unsigned pin,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct pinconf_ops nmk_pinconf_ops = {
|
||||
static const struct pinconf_ops nmk_pinconf_ops = {
|
||||
.pin_config_get = nmk_pin_config_get,
|
||||
.pin_config_set = nmk_pin_config_set,
|
||||
};
|
||||
@ -2111,6 +2111,10 @@ static const struct of_device_id nmk_pinctrl_match[] = {
|
||||
.compatible = "stericsson,nmk-pinctrl",
|
||||
.data = (void *)PINCTRL_NMK_DB8500,
|
||||
},
|
||||
{
|
||||
.compatible = "stericsson,nmk-pinctrl-db8540",
|
||||
.data = (void *)PINCTRL_NMK_DB8540,
|
||||
},
|
||||
{},
|
||||
};
|
||||
|
||||
|
@ -1,651 +0,0 @@
|
||||
/*
|
||||
* linux/drivers/pinctrl/pinmux-pxa168.c
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* publishhed by the Free Software Foundation.
|
||||
*
|
||||
* Copyright (C) 2011, Marvell Technology Group Ltd.
|
||||
*
|
||||
* Author: Haojian Zhuang <haojian.zhuang@marvell.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include "pinctrl-pxa3xx.h"
|
||||
|
||||
#define PXA168_DS_MASK 0x1800
|
||||
#define PXA168_DS_SHIFT 11
|
||||
#define PXA168_SLEEP_MASK 0x38
|
||||
#define PXA168_SLEEP_SELECT (1 << 9)
|
||||
#define PXA168_SLEEP_DATA (1 << 8)
|
||||
#define PXA168_SLEEP_DIR (1 << 7)
|
||||
|
||||
#define MFPR_168(a, r, f0, f1, f2, f3, f4, f5, f6, f7) \
|
||||
{ \
|
||||
.name = #a, \
|
||||
.pin = a, \
|
||||
.mfpr = r, \
|
||||
.func = { \
|
||||
PXA168_MUX_##f0, \
|
||||
PXA168_MUX_##f1, \
|
||||
PXA168_MUX_##f2, \
|
||||
PXA168_MUX_##f3, \
|
||||
PXA168_MUX_##f4, \
|
||||
PXA168_MUX_##f5, \
|
||||
PXA168_MUX_##f6, \
|
||||
PXA168_MUX_##f7, \
|
||||
}, \
|
||||
}
|
||||
|
||||
#define GRP_168(a, m, p) \
|
||||
{ .name = a, .mux = PXA168_MUX_##m, .pins = p, .npins = ARRAY_SIZE(p), }
|
||||
|
||||
/* 131 pins */
|
||||
enum pxa168_pin_list {
|
||||
/* 0~122: GPIO0~GPIO122 */
|
||||
PWR_SCL = 123,
|
||||
PWR_SDA,
|
||||
TDI,
|
||||
TMS,
|
||||
TCK,
|
||||
TDO,
|
||||
TRST,
|
||||
WAKEUP = 130,
|
||||
};
|
||||
|
||||
enum pxa168_mux {
|
||||
/* PXA3xx_MUX_GPIO = 0 (predefined in pinctrl-pxa3xx.h) */
|
||||
PXA168_MUX_GPIO = 0,
|
||||
PXA168_MUX_DFIO,
|
||||
PXA168_MUX_NAND,
|
||||
PXA168_MUX_SMC,
|
||||
PXA168_MUX_SMC_CS0,
|
||||
PXA168_MUX_SMC_CS1,
|
||||
PXA168_MUX_SMC_INT,
|
||||
PXA168_MUX_SMC_RDY,
|
||||
PXA168_MUX_MMC1,
|
||||
PXA168_MUX_MMC2,
|
||||
PXA168_MUX_MMC2_CMD,
|
||||
PXA168_MUX_MMC2_CLK,
|
||||
PXA168_MUX_MMC3,
|
||||
PXA168_MUX_MMC3_CMD,
|
||||
PXA168_MUX_MMC3_CLK,
|
||||
PXA168_MUX_MMC4,
|
||||
PXA168_MUX_MSP,
|
||||
PXA168_MUX_MSP_DAT3,
|
||||
PXA168_MUX_MSP_INS,
|
||||
PXA168_MUX_I2C,
|
||||
PXA168_MUX_PWRI2C,
|
||||
PXA168_MUX_AC97,
|
||||
PXA168_MUX_AC97_SYSCLK,
|
||||
PXA168_MUX_PWM,
|
||||
PXA168_MUX_PWM1,
|
||||
PXA168_MUX_XD,
|
||||
PXA168_MUX_XP,
|
||||
PXA168_MUX_LCD,
|
||||
PXA168_MUX_CCIC,
|
||||
PXA168_MUX_CF,
|
||||
PXA168_MUX_CF_RDY,
|
||||
PXA168_MUX_CF_nINPACK,
|
||||
PXA168_MUX_CF_nWAIT,
|
||||
PXA168_MUX_KP_MKOUT,
|
||||
PXA168_MUX_KP_MKIN,
|
||||
PXA168_MUX_KP_DK,
|
||||
PXA168_MUX_ETH,
|
||||
PXA168_MUX_ETH_TX,
|
||||
PXA168_MUX_ETH_RX,
|
||||
PXA168_MUX_ONE_WIRE,
|
||||
PXA168_MUX_UART1,
|
||||
PXA168_MUX_UART1_TX,
|
||||
PXA168_MUX_UART1_CTS,
|
||||
PXA168_MUX_UART1_nRI,
|
||||
PXA168_MUX_UART1_DTR,
|
||||
PXA168_MUX_UART2,
|
||||
PXA168_MUX_UART2_TX,
|
||||
PXA168_MUX_UART3,
|
||||
PXA168_MUX_UART3_TX,
|
||||
PXA168_MUX_UART3_CTS,
|
||||
PXA168_MUX_SSP1,
|
||||
PXA168_MUX_SSP1_TX,
|
||||
PXA168_MUX_SSP2,
|
||||
PXA168_MUX_SSP2_TX,
|
||||
PXA168_MUX_SSP3,
|
||||
PXA168_MUX_SSP3_TX,
|
||||
PXA168_MUX_SSP4,
|
||||
PXA168_MUX_SSP4_TX,
|
||||
PXA168_MUX_SSP5,
|
||||
PXA168_MUX_SSP5_TX,
|
||||
PXA168_MUX_USB,
|
||||
PXA168_MUX_JTAG,
|
||||
PXA168_MUX_RESET,
|
||||
PXA168_MUX_WAKEUP,
|
||||
PXA168_MUX_EXT_32K_IN,
|
||||
PXA168_MUX_NONE = 0xffff,
|
||||
};
|
||||
|
||||
static struct pinctrl_pin_desc pxa168_pads[] = {
|
||||
PINCTRL_PIN(GPIO0, "GPIO0"),
|
||||
PINCTRL_PIN(GPIO1, "GPIO1"),
|
||||
PINCTRL_PIN(GPIO2, "GPIO2"),
|
||||
PINCTRL_PIN(GPIO3, "GPIO3"),
|
||||
PINCTRL_PIN(GPIO4, "GPIO4"),
|
||||
PINCTRL_PIN(GPIO5, "GPIO5"),
|
||||
PINCTRL_PIN(GPIO6, "GPIO6"),
|
||||
PINCTRL_PIN(GPIO7, "GPIO7"),
|
||||
PINCTRL_PIN(GPIO8, "GPIO8"),
|
||||
PINCTRL_PIN(GPIO9, "GPIO9"),
|
||||
PINCTRL_PIN(GPIO10, "GPIO10"),
|
||||
PINCTRL_PIN(GPIO11, "GPIO11"),
|
||||
PINCTRL_PIN(GPIO12, "GPIO12"),
|
||||
PINCTRL_PIN(GPIO13, "GPIO13"),
|
||||
PINCTRL_PIN(GPIO14, "GPIO14"),
|
||||
PINCTRL_PIN(GPIO15, "GPIO15"),
|
||||
PINCTRL_PIN(GPIO16, "GPIO16"),
|
||||
PINCTRL_PIN(GPIO17, "GPIO17"),
|
||||
PINCTRL_PIN(GPIO18, "GPIO18"),
|
||||
PINCTRL_PIN(GPIO19, "GPIO19"),
|
||||
PINCTRL_PIN(GPIO20, "GPIO20"),
|
||||
PINCTRL_PIN(GPIO21, "GPIO21"),
|
||||
PINCTRL_PIN(GPIO22, "GPIO22"),
|
||||
PINCTRL_PIN(GPIO23, "GPIO23"),
|
||||
PINCTRL_PIN(GPIO24, "GPIO24"),
|
||||
PINCTRL_PIN(GPIO25, "GPIO25"),
|
||||
PINCTRL_PIN(GPIO26, "GPIO26"),
|
||||
PINCTRL_PIN(GPIO27, "GPIO27"),
|
||||
PINCTRL_PIN(GPIO28, "GPIO28"),
|
||||
PINCTRL_PIN(GPIO29, "GPIO29"),
|
||||
PINCTRL_PIN(GPIO30, "GPIO30"),
|
||||
PINCTRL_PIN(GPIO31, "GPIO31"),
|
||||
PINCTRL_PIN(GPIO32, "GPIO32"),
|
||||
PINCTRL_PIN(GPIO33, "GPIO33"),
|
||||
PINCTRL_PIN(GPIO34, "GPIO34"),
|
||||
PINCTRL_PIN(GPIO35, "GPIO35"),
|
||||
PINCTRL_PIN(GPIO36, "GPIO36"),
|
||||
PINCTRL_PIN(GPIO37, "GPIO37"),
|
||||
PINCTRL_PIN(GPIO38, "GPIO38"),
|
||||
PINCTRL_PIN(GPIO39, "GPIO39"),
|
||||
PINCTRL_PIN(GPIO40, "GPIO40"),
|
||||
PINCTRL_PIN(GPIO41, "GPIO41"),
|
||||
PINCTRL_PIN(GPIO42, "GPIO42"),
|
||||
PINCTRL_PIN(GPIO43, "GPIO43"),
|
||||
PINCTRL_PIN(GPIO44, "GPIO44"),
|
||||
PINCTRL_PIN(GPIO45, "GPIO45"),
|
||||
PINCTRL_PIN(GPIO46, "GPIO46"),
|
||||
PINCTRL_PIN(GPIO47, "GPIO47"),
|
||||
PINCTRL_PIN(GPIO48, "GPIO48"),
|
||||
PINCTRL_PIN(GPIO49, "GPIO49"),
|
||||
PINCTRL_PIN(GPIO50, "GPIO50"),
|
||||
PINCTRL_PIN(GPIO51, "GPIO51"),
|
||||
PINCTRL_PIN(GPIO52, "GPIO52"),
|
||||
PINCTRL_PIN(GPIO53, "GPIO53"),
|
||||
PINCTRL_PIN(GPIO54, "GPIO54"),
|
||||
PINCTRL_PIN(GPIO55, "GPIO55"),
|
||||
PINCTRL_PIN(GPIO56, "GPIO56"),
|
||||
PINCTRL_PIN(GPIO57, "GPIO57"),
|
||||
PINCTRL_PIN(GPIO58, "GPIO58"),
|
||||
PINCTRL_PIN(GPIO59, "GPIO59"),
|
||||
PINCTRL_PIN(GPIO60, "GPIO60"),
|
||||
PINCTRL_PIN(GPIO61, "GPIO61"),
|
||||
PINCTRL_PIN(GPIO62, "GPIO62"),
|
||||
PINCTRL_PIN(GPIO63, "GPIO63"),
|
||||
PINCTRL_PIN(GPIO64, "GPIO64"),
|
||||
PINCTRL_PIN(GPIO65, "GPIO65"),
|
||||
PINCTRL_PIN(GPIO66, "GPIO66"),
|
||||
PINCTRL_PIN(GPIO67, "GPIO67"),
|
||||
PINCTRL_PIN(GPIO68, "GPIO68"),
|
||||
PINCTRL_PIN(GPIO69, "GPIO69"),
|
||||
PINCTRL_PIN(GPIO70, "GPIO70"),
|
||||
PINCTRL_PIN(GPIO71, "GPIO71"),
|
||||
PINCTRL_PIN(GPIO72, "GPIO72"),
|
||||
PINCTRL_PIN(GPIO73, "GPIO73"),
|
||||
PINCTRL_PIN(GPIO74, "GPIO74"),
|
||||
PINCTRL_PIN(GPIO75, "GPIO75"),
|
||||
PINCTRL_PIN(GPIO76, "GPIO76"),
|
||||
PINCTRL_PIN(GPIO77, "GPIO77"),
|
||||
PINCTRL_PIN(GPIO78, "GPIO78"),
|
||||
PINCTRL_PIN(GPIO79, "GPIO79"),
|
||||
PINCTRL_PIN(GPIO80, "GPIO80"),
|
||||
PINCTRL_PIN(GPIO81, "GPIO81"),
|
||||
PINCTRL_PIN(GPIO82, "GPIO82"),
|
||||
PINCTRL_PIN(GPIO83, "GPIO83"),
|
||||
PINCTRL_PIN(GPIO84, "GPIO84"),
|
||||
PINCTRL_PIN(GPIO85, "GPIO85"),
|
||||
PINCTRL_PIN(GPIO86, "GPIO86"),
|
||||
PINCTRL_PIN(GPIO87, "GPIO87"),
|
||||
PINCTRL_PIN(GPIO88, "GPIO88"),
|
||||
PINCTRL_PIN(GPIO89, "GPIO89"),
|
||||
PINCTRL_PIN(GPIO90, "GPIO90"),
|
||||
PINCTRL_PIN(GPIO91, "GPIO91"),
|
||||
PINCTRL_PIN(GPIO92, "GPIO92"),
|
||||
PINCTRL_PIN(GPIO93, "GPIO93"),
|
||||
PINCTRL_PIN(GPIO94, "GPIO94"),
|
||||
PINCTRL_PIN(GPIO95, "GPIO95"),
|
||||
PINCTRL_PIN(GPIO96, "GPIO96"),
|
||||
PINCTRL_PIN(GPIO97, "GPIO97"),
|
||||
PINCTRL_PIN(GPIO98, "GPIO98"),
|
||||
PINCTRL_PIN(GPIO99, "GPIO99"),
|
||||
PINCTRL_PIN(GPIO100, "GPIO100"),
|
||||
PINCTRL_PIN(GPIO101, "GPIO101"),
|
||||
PINCTRL_PIN(GPIO102, "GPIO102"),
|
||||
PINCTRL_PIN(GPIO103, "GPIO103"),
|
||||
PINCTRL_PIN(GPIO104, "GPIO104"),
|
||||
PINCTRL_PIN(GPIO105, "GPIO105"),
|
||||
PINCTRL_PIN(GPIO106, "GPIO106"),
|
||||
PINCTRL_PIN(GPIO107, "GPIO107"),
|
||||
PINCTRL_PIN(GPIO108, "GPIO108"),
|
||||
PINCTRL_PIN(GPIO109, "GPIO109"),
|
||||
PINCTRL_PIN(GPIO110, "GPIO110"),
|
||||
PINCTRL_PIN(GPIO111, "GPIO111"),
|
||||
PINCTRL_PIN(GPIO112, "GPIO112"),
|
||||
PINCTRL_PIN(GPIO113, "GPIO113"),
|
||||
PINCTRL_PIN(GPIO114, "GPIO114"),
|
||||
PINCTRL_PIN(GPIO115, "GPIO115"),
|
||||
PINCTRL_PIN(GPIO116, "GPIO116"),
|
||||
PINCTRL_PIN(GPIO117, "GPIO117"),
|
||||
PINCTRL_PIN(GPIO118, "GPIO118"),
|
||||
PINCTRL_PIN(GPIO119, "GPIO119"),
|
||||
PINCTRL_PIN(GPIO120, "GPIO120"),
|
||||
PINCTRL_PIN(GPIO121, "GPIO121"),
|
||||
PINCTRL_PIN(GPIO122, "GPIO122"),
|
||||
PINCTRL_PIN(PWR_SCL, "PWR_SCL"),
|
||||
PINCTRL_PIN(PWR_SDA, "PWR_SDA"),
|
||||
PINCTRL_PIN(TDI, "TDI"),
|
||||
PINCTRL_PIN(TMS, "TMS"),
|
||||
PINCTRL_PIN(TCK, "TCK"),
|
||||
PINCTRL_PIN(TDO, "TDO"),
|
||||
PINCTRL_PIN(TRST, "TRST"),
|
||||
PINCTRL_PIN(WAKEUP, "WAKEUP"),
|
||||
};
|
||||
|
||||
struct pxa3xx_mfp_pin pxa168_mfp[] = {
|
||||
/* pin offs f0 f1 f2 f3 f4 f5 f6 f7 */
|
||||
MFPR_168(GPIO0, 0x04C, DFIO, NONE, NONE, MSP, MMC3_CMD, GPIO, MMC3, NONE),
|
||||
MFPR_168(GPIO1, 0x050, DFIO, NONE, NONE, MSP, MMC3_CLK, GPIO, MMC3, NONE),
|
||||
MFPR_168(GPIO2, 0x054, DFIO, NONE, NONE, MSP, NONE, GPIO, MMC3, NONE),
|
||||
MFPR_168(GPIO3, 0x058, DFIO, NONE, NONE, NONE, NONE, GPIO, MMC3, NONE),
|
||||
MFPR_168(GPIO4, 0x05C, DFIO, NONE, NONE, MSP_DAT3, NONE, GPIO, MMC3, NONE),
|
||||
MFPR_168(GPIO5, 0x060, DFIO, NONE, NONE, MSP, NONE, GPIO, MMC3, NONE),
|
||||
MFPR_168(GPIO6, 0x064, DFIO, NONE, NONE, MSP, NONE, GPIO, MMC3, NONE),
|
||||
MFPR_168(GPIO7, 0x068, DFIO, NONE, NONE, MSP, NONE, GPIO, MMC3, NONE),
|
||||
MFPR_168(GPIO8, 0x06C, DFIO, MMC2, UART3_TX, NONE, MMC2_CMD, GPIO, MMC3_CLK, NONE),
|
||||
MFPR_168(GPIO9, 0x070, DFIO, MMC2, UART3, NONE, MMC2_CLK, GPIO, MMC3_CMD, NONE),
|
||||
MFPR_168(GPIO10, 0x074, DFIO, MMC2, UART3, NONE, NONE, GPIO, MSP_DAT3, NONE),
|
||||
MFPR_168(GPIO11, 0x078, DFIO, MMC2, UART3, NONE, NONE, GPIO, MSP, NONE),
|
||||
MFPR_168(GPIO12, 0x07C, DFIO, MMC2, UART3, NONE, NONE, GPIO, MSP, NONE),
|
||||
MFPR_168(GPIO13, 0x080, DFIO, MMC2, UART3, NONE, NONE, GPIO, MSP, NONE),
|
||||
MFPR_168(GPIO14, 0x084, DFIO, MMC2, NONE, NONE, NONE, GPIO, MSP, NONE),
|
||||
MFPR_168(GPIO15, 0x088, DFIO, MMC2, NONE, NONE, NONE, GPIO, MSP, NONE),
|
||||
MFPR_168(GPIO16, 0x08C, GPIO, NAND, SMC_CS0, SMC_CS1, NONE, NONE, MMC3, NONE),
|
||||
MFPR_168(GPIO17, 0x090, NAND, NONE, NONE, NONE, NONE, GPIO, MSP, NONE),
|
||||
MFPR_168(GPIO18, 0x094, GPIO, NAND, SMC_CS1, SMC_CS0, NONE, NONE, NONE, NONE),
|
||||
MFPR_168(GPIO19, 0x098, SMC_CS0, NONE, NONE, CF, NONE, GPIO, NONE, NONE),
|
||||
MFPR_168(GPIO20, 0x09C, GPIO, NONE, SMC_CS1, CF, CF_RDY, NONE, NONE, NONE),
|
||||
MFPR_168(GPIO21, 0x0A0, NAND, MMC2_CLK, NONE, NONE, NONE, GPIO, NONE, NONE),
|
||||
MFPR_168(GPIO22, 0x0A4, NAND, MMC2_CMD, NONE, NONE, NONE, GPIO, NONE, NONE),
|
||||
MFPR_168(GPIO23, 0x0A8, SMC, NAND, NONE, CF, NONE, GPIO, NONE, NONE),
|
||||
MFPR_168(GPIO24, 0x0AC, NAND, NONE, NONE, NONE, NONE, GPIO, NONE, NONE),
|
||||
MFPR_168(GPIO25, 0x0B0, SMC, NAND, NONE, CF, NONE, GPIO, NONE, NONE),
|
||||
MFPR_168(GPIO26, 0x0B4, GPIO, NAND, NONE, NONE, CF, NONE, NONE, NONE),
|
||||
MFPR_168(GPIO27, 0x0B8, SMC_INT, NAND, SMC, NONE, SMC_RDY, GPIO, NONE, NONE),
|
||||
MFPR_168(GPIO28, 0x0BC, SMC_RDY, MMC4, SMC, CF_RDY, NONE, GPIO, MMC2_CMD, NONE),
|
||||
MFPR_168(GPIO29, 0x0C0, SMC, MMC4, NONE, CF, NONE, GPIO, MMC2_CLK, KP_DK),
|
||||
MFPR_168(GPIO30, 0x0C4, SMC, MMC4, UART3_TX, CF, NONE, GPIO, MMC2, KP_DK),
|
||||
MFPR_168(GPIO31, 0x0C8, SMC, MMC4, UART3, CF, NONE, GPIO, MMC2, KP_DK),
|
||||
MFPR_168(GPIO32, 0x0CC, SMC, MMC4, UART3, CF, NONE, GPIO, MMC2, KP_DK),
|
||||
MFPR_168(GPIO33, 0x0D0, SMC, MMC4, UART3, CF, CF_nINPACK, GPIO, MMC2, KP_DK),
|
||||
MFPR_168(GPIO34, 0x0D4, GPIO, NONE, SMC_CS1, CF, CF_nWAIT, NONE, MMC3, KP_DK),
|
||||
MFPR_168(GPIO35, 0x0D8, GPIO, NONE, SMC, CF_nINPACK, NONE, NONE, MMC3_CMD, KP_DK),
|
||||
MFPR_168(GPIO36, 0x0DC, GPIO, NONE, SMC, CF_nWAIT, NONE, NONE, MMC3_CLK, KP_DK),
|
||||
MFPR_168(GPIO37, 0x000, GPIO, MMC1, NONE, KP_MKOUT, CCIC, XP, KP_MKIN, KP_DK),
|
||||
MFPR_168(GPIO38, 0x004, GPIO, MMC1, NONE, KP_MKOUT, CCIC, XP, KP_MKIN, KP_DK),
|
||||
MFPR_168(GPIO39, 0x008, GPIO, NONE, NONE, KP_MKOUT, CCIC, XP, KP_MKIN, KP_DK),
|
||||
MFPR_168(GPIO40, 0x00C, GPIO, MMC1, MSP, KP_MKOUT, CCIC, XP, KP_MKIN, KP_DK),
|
||||
MFPR_168(GPIO41, 0x010, GPIO, MMC1, MSP, NONE, CCIC, XP, KP_MKIN, KP_DK),
|
||||
MFPR_168(GPIO42, 0x014, GPIO, I2C, NONE, MSP, CCIC, XP, KP_MKIN, KP_DK),
|
||||
MFPR_168(GPIO43, 0x018, GPIO, MMC1, MSP, MSP_INS, NONE, NONE, KP_MKIN, KP_DK),
|
||||
MFPR_168(GPIO44, 0x01C, GPIO, MMC1, MSP_DAT3, MSP, CCIC, XP, KP_MKIN, KP_DK),
|
||||
MFPR_168(GPIO45, 0x020, GPIO, NONE, NONE, MSP, CCIC, XP, NONE, KP_DK),
|
||||
MFPR_168(GPIO46, 0x024, GPIO, MMC1, MSP_INS, MSP, CCIC, NONE, KP_MKOUT, KP_DK),
|
||||
MFPR_168(GPIO47, 0x028, GPIO, NONE, NONE, MSP_INS, NONE, XP, NONE, KP_DK),
|
||||
MFPR_168(GPIO48, 0x02C, GPIO, MMC1, NONE, MSP_DAT3, CCIC, NONE, NONE, KP_DK),
|
||||
MFPR_168(GPIO49, 0x030, GPIO, MMC1, NONE, MSP, NONE, XD, KP_MKOUT, NONE),
|
||||
MFPR_168(GPIO50, 0x034, GPIO, I2C, NONE, MSP, CCIC, XD, KP_MKOUT, NONE),
|
||||
MFPR_168(GPIO51, 0x038, GPIO, MMC1, NONE, MSP, NONE, XD, KP_MKOUT, NONE),
|
||||
MFPR_168(GPIO52, 0x03C, GPIO, MMC1, NONE, MSP, NONE, XD, KP_MKOUT, NONE),
|
||||
MFPR_168(GPIO53, 0x040, GPIO, MMC1, NONE, NONE, NONE, XD, KP_MKOUT, NONE),
|
||||
MFPR_168(GPIO54, 0x044, GPIO, MMC1, NONE, NONE, CCIC, XD, KP_MKOUT, NONE),
|
||||
MFPR_168(GPIO55, 0x048, GPIO, NONE, NONE, MSP, CCIC, XD, KP_MKOUT, NONE),
|
||||
MFPR_168(GPIO56, 0x0E0, GPIO, LCD, NONE, NONE, NONE, NONE, NONE, NONE),
|
||||
MFPR_168(GPIO57, 0x0E4, GPIO, LCD, NONE, NONE, NONE, NONE, NONE, NONE),
|
||||
MFPR_168(GPIO58, 0x0E8, GPIO, LCD, NONE, NONE, NONE, NONE, NONE, NONE),
|
||||
MFPR_168(GPIO59, 0x0EC, GPIO, LCD, NONE, NONE, NONE, NONE, NONE, NONE),
|
||||
MFPR_168(GPIO60, 0x0F0, GPIO, LCD, NONE, NONE, NONE, NONE, NONE, NONE),
|
||||
MFPR_168(GPIO61, 0x0F4, GPIO, LCD, NONE, NONE, NONE, NONE, NONE, NONE),
|
||||
MFPR_168(GPIO62, 0x0F8, GPIO, LCD, NONE, NONE, NONE, NONE, NONE, NONE),
|
||||
MFPR_168(GPIO63, 0x0FC, GPIO, LCD, NONE, NONE, NONE, NONE, NONE, NONE),
|
||||
MFPR_168(GPIO64, 0x100, GPIO, LCD, NONE, NONE, NONE, NONE, NONE, NONE),
|
||||
MFPR_168(GPIO65, 0x104, GPIO, LCD, NONE, NONE, NONE, NONE, NONE, NONE),
|
||||
MFPR_168(GPIO66, 0x108, GPIO, LCD, NONE, NONE, NONE, NONE, NONE, NONE),
|
||||
MFPR_168(GPIO67, 0x10C, GPIO, LCD, NONE, NONE, NONE, NONE, NONE, NONE),
|
||||
MFPR_168(GPIO68, 0x110, GPIO, LCD, NONE, XD, NONE, NONE, NONE, NONE),
|
||||
MFPR_168(GPIO69, 0x114, GPIO, LCD, NONE, XD, NONE, NONE, NONE, NONE),
|
||||
MFPR_168(GPIO70, 0x118, GPIO, LCD, NONE, XD, NONE, NONE, NONE, NONE),
|
||||
MFPR_168(GPIO71, 0x11C, GPIO, LCD, NONE, XD, NONE, NONE, NONE, NONE),
|
||||
MFPR_168(GPIO72, 0x120, GPIO, LCD, NONE, XD, NONE, NONE, NONE, NONE),
|
||||
MFPR_168(GPIO73, 0x124, GPIO, LCD, NONE, XD, NONE, NONE, NONE, NONE),
|
||||
MFPR_168(GPIO74, 0x128, GPIO, LCD, PWM, XD, NONE, NONE, NONE, NONE),
|
||||
MFPR_168(GPIO75, 0x12C, GPIO, LCD, PWM, XD, ONE_WIRE, NONE, NONE, NONE),
|
||||
MFPR_168(GPIO76, 0x130, GPIO, LCD, PWM, I2C, NONE, NONE, MSP_INS, NONE),
|
||||
MFPR_168(GPIO77, 0x134, GPIO, LCD, PWM1, I2C, ONE_WIRE, NONE, XD, NONE),
|
||||
MFPR_168(GPIO78, 0x138, GPIO, LCD, NONE, NONE, NONE, MMC4, NONE, NONE),
|
||||
MFPR_168(GPIO79, 0x13C, GPIO, LCD, NONE, NONE, ONE_WIRE, MMC4, NONE, NONE),
|
||||
MFPR_168(GPIO80, 0x140, GPIO, LCD, NONE, I2C, NONE, MMC4, NONE, NONE),
|
||||
MFPR_168(GPIO81, 0x144, GPIO, LCD, NONE, I2C, ONE_WIRE, MMC4, NONE, NONE),
|
||||
MFPR_168(GPIO82, 0x148, GPIO, LCD, PWM, NONE, NONE, MMC4, NONE, NONE),
|
||||
MFPR_168(GPIO83, 0x14C, GPIO, LCD, PWM, NONE, RESET, MMC4, NONE, NONE),
|
||||
MFPR_168(GPIO84, 0x150, GPIO, NONE, PWM, ONE_WIRE, PWM1, NONE, NONE, EXT_32K_IN),
|
||||
MFPR_168(GPIO85, 0x154, GPIO, NONE, PWM1, NONE, NONE, NONE, NONE, USB),
|
||||
MFPR_168(GPIO86, 0x158, GPIO, MMC2, UART2, NONE, JTAG, ETH_TX, SSP5_TX, SSP5),
|
||||
MFPR_168(GPIO87, 0x15C, GPIO, MMC2, UART2, NONE, JTAG, ETH_TX, SSP5, SSP5_TX),
|
||||
MFPR_168(GPIO88, 0x160, GPIO, MMC2, UART2, UART2_TX, JTAG, ETH_TX, ETH_RX, SSP5),
|
||||
MFPR_168(GPIO89, 0x164, GPIO, MMC2, UART2_TX, UART2, JTAG, ETH_TX, ETH_RX, SSP5),
|
||||
MFPR_168(GPIO90, 0x168, GPIO, MMC2, NONE, SSP3, JTAG, ETH_TX, ETH_RX, NONE),
|
||||
MFPR_168(GPIO91, 0x16C, GPIO, MMC2, NONE, SSP3, SSP4, ETH_TX, ETH_RX, NONE),
|
||||
MFPR_168(GPIO92, 0x170, GPIO, MMC2, NONE, SSP3, SSP3_TX, ETH, NONE, NONE),
|
||||
MFPR_168(GPIO93, 0x174, GPIO, MMC2, NONE, SSP3_TX, SSP3, ETH, NONE, NONE),
|
||||
MFPR_168(GPIO94, 0x178, GPIO, MMC2_CMD, SSP3, AC97_SYSCLK, AC97, ETH, NONE, NONE),
|
||||
MFPR_168(GPIO95, 0x17C, GPIO, MMC2_CLK, NONE, NONE, AC97, ETH, NONE, NONE),
|
||||
MFPR_168(GPIO96, 0x180, GPIO, PWM, NONE, MMC2, NONE, ETH_RX, ETH_TX, NONE),
|
||||
MFPR_168(GPIO97, 0x184, GPIO, PWM, ONE_WIRE, NONE, NONE, ETH_RX, ETH_TX, NONE),
|
||||
MFPR_168(GPIO98, 0x188, GPIO, PWM1, UART3_TX, UART3, NONE, ETH_RX, ETH_TX, NONE),
|
||||
MFPR_168(GPIO99, 0x18C, GPIO, ONE_WIRE, UART3, UART3_TX, NONE, ETH_RX, ETH_TX, NONE),
|
||||
MFPR_168(GPIO100, 0x190, GPIO, NONE, UART3_CTS, UART3, NONE, ETH, NONE, NONE),
|
||||
MFPR_168(GPIO101, 0x194, GPIO, NONE, UART3, UART3_CTS, NONE, ETH, NONE, NONE),
|
||||
MFPR_168(GPIO102, 0x198, GPIO, I2C, UART3, SSP4, NONE, NONE, NONE, NONE),
|
||||
MFPR_168(GPIO103, 0x19C, GPIO, I2C, UART3, SSP4, SSP2, ETH, NONE, NONE),
|
||||
MFPR_168(GPIO104, 0x1A0, GPIO, PWM, UART1, SSP4, SSP4_TX, AC97, KP_MKOUT, NONE),
|
||||
MFPR_168(GPIO105, 0x1A4, GPIO, I2C, UART1, SSP4_TX, SSP4, AC97, KP_MKOUT, NONE),
|
||||
MFPR_168(GPIO106, 0x1A8, GPIO, I2C, PWM1, AC97_SYSCLK, MMC2, NONE, KP_MKOUT, NONE),
|
||||
MFPR_168(GPIO107, 0x1AC, GPIO, UART1_TX, UART1, NONE, SSP2, MSP_DAT3, NONE, KP_MKIN),
|
||||
MFPR_168(GPIO108, 0x1B0, GPIO, UART1, UART1_TX, NONE, SSP2_TX, MSP, NONE, KP_MKIN),
|
||||
MFPR_168(GPIO109, 0x1B4, GPIO, UART1_CTS, UART1, NONE, AC97_SYSCLK, MSP, NONE, KP_MKIN),
|
||||
MFPR_168(GPIO110, 0x1B8, GPIO, UART1, UART1_CTS, NONE, SMC_RDY, MSP, NONE, KP_MKIN),
|
||||
MFPR_168(GPIO111, 0x1BC, GPIO, UART1_nRI, UART1, SSP3, SSP2, MSP, XD, KP_MKOUT),
|
||||
MFPR_168(GPIO112, 0x1C0, GPIO, UART1_DTR, UART1, ONE_WIRE, SSP2, MSP, XD, KP_MKOUT),
|
||||
MFPR_168(GPIO113, 0x1C4, GPIO, NONE, NONE, NONE, NONE, NONE, AC97_SYSCLK, NONE),
|
||||
MFPR_168(GPIO114, 0x1C8, GPIO, SSP1, NONE, NONE, NONE, NONE, AC97, NONE),
|
||||
MFPR_168(GPIO115, 0x1CC, GPIO, SSP1, NONE, NONE, NONE, NONE, AC97, NONE),
|
||||
MFPR_168(GPIO116, 0x1D0, GPIO, SSP1_TX, SSP1, NONE, NONE, NONE, AC97, NONE),
|
||||
MFPR_168(GPIO117, 0x1D4, GPIO, SSP1, SSP1_TX, NONE, MMC2_CMD, NONE, AC97, NONE),
|
||||
MFPR_168(GPIO118, 0x1D8, GPIO, SSP2, NONE, NONE, MMC2_CLK, NONE, AC97, KP_MKIN),
|
||||
MFPR_168(GPIO119, 0x1DC, GPIO, SSP2, NONE, NONE, MMC2, NONE, AC97, KP_MKIN),
|
||||
MFPR_168(GPIO120, 0x1E0, GPIO, SSP2, SSP2_TX, NONE, MMC2, NONE, NONE, KP_MKIN),
|
||||
MFPR_168(GPIO121, 0x1E4, GPIO, SSP2_TX, SSP2, NONE, MMC2, NONE, NONE, KP_MKIN),
|
||||
MFPR_168(GPIO122, 0x1E8, GPIO, AC97_SYSCLK, SSP2, PWM, MMC2, NONE, NONE, NONE),
|
||||
MFPR_168(PWR_SCL, 0x1EC, PWRI2C, NONE, NONE, NONE, NONE, NONE, GPIO, MMC4),
|
||||
MFPR_168(PWR_SDA, 0x1F0, PWRI2C, NONE, NONE, NONE, NONE, NONE, GPIO, NONE),
|
||||
MFPR_168(TDI, 0x1F4, JTAG, PWM1, UART2, MMC4, SSP5, NONE, XD, MMC4),
|
||||
MFPR_168(TMS, 0x1F8, JTAG, PWM, UART2, NONE, SSP5, NONE, XD, MMC4),
|
||||
MFPR_168(TCK, 0x1FC, JTAG, PWM, UART2, UART2_TX, SSP5, NONE, XD, MMC4),
|
||||
MFPR_168(TDO, 0x200, JTAG, PWM, UART2_TX, UART2, SSP5_TX, NONE, XD, MMC4),
|
||||
MFPR_168(TRST, 0x204, JTAG, ONE_WIRE, SSP2, SSP3, AC97_SYSCLK, NONE, XD, MMC4),
|
||||
MFPR_168(WAKEUP, 0x208, WAKEUP, ONE_WIRE, PWM1, PWM, SSP2, NONE, GPIO, MMC4),
|
||||
};
|
||||
|
||||
static const unsigned p168_jtag_pin1[] = {TDI, TMS, TCK, TDO, TRST};
|
||||
static const unsigned p168_wakeup_pin1[] = {WAKEUP};
|
||||
static const unsigned p168_ssp1rx_pin1[] = {GPIO114, GPIO115, GPIO116};
|
||||
static const unsigned p168_ssp1tx_pin1[] = {GPIO117};
|
||||
static const unsigned p168_ssp4rx_pin1[] = {GPIO102, GPIO103, GPIO104};
|
||||
static const unsigned p168_ssp4tx_pin1[] = {GPIO105};
|
||||
static const unsigned p168_ssp5rx_pin1[] = {GPIO86, GPIO88, GPIO89};
|
||||
static const unsigned p168_ssp5tx_pin1[] = {GPIO87};
|
||||
static const unsigned p168_i2c_pin1[] = {GPIO105, GPIO106};
|
||||
static const unsigned p168_pwri2c_pin1[] = {PWR_SCL, PWR_SDA};
|
||||
static const unsigned p168_mmc1_pin1[] = {GPIO40, GPIO41, GPIO43, GPIO46,
|
||||
GPIO49, GPIO51, GPIO52, GPIO53};
|
||||
static const unsigned p168_mmc2_data_pin1[] = {GPIO90, GPIO91, GPIO92, GPIO93};
|
||||
static const unsigned p168_mmc2_cmd_pin1[] = {GPIO94};
|
||||
static const unsigned p168_mmc2_clk_pin1[] = {GPIO95};
|
||||
static const unsigned p168_mmc3_data_pin1[] = {GPIO0, GPIO1, GPIO2, GPIO3,
|
||||
GPIO4, GPIO5, GPIO6, GPIO7};
|
||||
static const unsigned p168_mmc3_cmd_pin1[] = {GPIO9};
|
||||
static const unsigned p168_mmc3_clk_pin1[] = {GPIO8};
|
||||
static const unsigned p168_eth_pin1[] = {GPIO92, GPIO93, GPIO100, GPIO101,
|
||||
GPIO103};
|
||||
static const unsigned p168_ethtx_pin1[] = {GPIO86, GPIO87, GPIO88, GPIO89,
|
||||
GPIO90, GPIO91};
|
||||
static const unsigned p168_ethrx_pin1[] = {GPIO94, GPIO95, GPIO96, GPIO97,
|
||||
GPIO98, GPIO99};
|
||||
static const unsigned p168_uart1rx_pin1[] = {GPIO107};
|
||||
static const unsigned p168_uart1tx_pin1[] = {GPIO108};
|
||||
static const unsigned p168_uart3rx_pin1[] = {GPIO98, GPIO100, GPIO101};
|
||||
static const unsigned p168_uart3tx_pin1[] = {GPIO99};
|
||||
static const unsigned p168_msp_pin1[] = {GPIO40, GPIO41, GPIO42, GPIO43,
|
||||
GPIO44, GPIO50};
|
||||
static const unsigned p168_ccic_pin1[] = {GPIO37, GPIO38, GPIO39, GPIO40,
|
||||
GPIO41, GPIO42, GPIO44, GPIO45, GPIO46, GPIO48, GPIO54, GPIO55};
|
||||
static const unsigned p168_xd_pin1[] = {GPIO37, GPIO38, GPIO39, GPIO40,
|
||||
GPIO41, GPIO42, GPIO44, GPIO45, GPIO47, GPIO48, GPIO49, GPIO50,
|
||||
GPIO51, GPIO52};
|
||||
static const unsigned p168_lcd_pin1[] = {GPIO56, GPIO57, GPIO58, GPIO59,
|
||||
GPIO60, GPIO61, GPIO62, GPIO63, GPIO64, GPIO65, GPIO66, GPIO67,
|
||||
GPIO68, GPIO69, GPIO70, GPIO71, GPIO72, GPIO73, GPIO74, GPIO75,
|
||||
GPIO76, GPIO77, GPIO78, GPIO79, GPIO80, GPIO81, GPIO82, GPIO83};
|
||||
static const unsigned p168_dfio_pin1[] = {GPIO0, GPIO1, GPIO2, GPIO3,
|
||||
GPIO4, GPIO5, GPIO6, GPIO7, GPIO8, GPIO9, GPIO10, GPIO11, GPIO12,
|
||||
GPIO13, GPIO14, GPIO15};
|
||||
static const unsigned p168_nand_pin1[] = {GPIO16, GPIO17, GPIO21, GPIO22,
|
||||
GPIO24, GPIO26};
|
||||
static const unsigned p168_smc_pin1[] = {GPIO23, GPIO25, GPIO29, GPIO35,
|
||||
GPIO36};
|
||||
static const unsigned p168_smccs0_pin1[] = {GPIO18};
|
||||
static const unsigned p168_smccs1_pin1[] = {GPIO34};
|
||||
static const unsigned p168_smcrdy_pin1[] = {GPIO28};
|
||||
static const unsigned p168_ac97sysclk_pin1[] = {GPIO113};
|
||||
static const unsigned p168_ac97_pin1[] = {GPIO114, GPIO115, GPIO117, GPIO118,
|
||||
GPIO119};
|
||||
static const unsigned p168_cf_pin1[] = {GPIO19, GPIO20, GPIO23, GPIO25,
|
||||
GPIO28, GPIO29, GPIO30, GPIO31, GPIO32, GPIO33, GPIO34, GPIO35,
|
||||
GPIO36};
|
||||
static const unsigned p168_kpmkin_pin1[] = {GPIO109, GPIO110, GPIO121};
|
||||
static const unsigned p168_kpmkout_pin1[] = {GPIO111, GPIO112};
|
||||
static const unsigned p168_gpio86_pin1[] = {WAKEUP};
|
||||
static const unsigned p168_gpio86_pin2[] = {GPIO86};
|
||||
static const unsigned p168_gpio87_pin1[] = {GPIO87};
|
||||
static const unsigned p168_gpio87_pin2[] = {PWR_SDA};
|
||||
static const unsigned p168_gpio88_pin1[] = {GPIO88};
|
||||
static const unsigned p168_gpio88_pin2[] = {PWR_SCL};
|
||||
|
||||
static struct pxa3xx_pin_group pxa168_grps[] = {
|
||||
GRP_168("uart1rx-1", UART1, p168_uart1rx_pin1),
|
||||
GRP_168("uart1tx-1", UART1_TX, p168_uart1tx_pin1),
|
||||
GRP_168("uart3rx-1", UART3, p168_uart3rx_pin1),
|
||||
GRP_168("uart3tx-1", UART3_TX, p168_uart3tx_pin1),
|
||||
GRP_168("ssp1rx-1", SSP1, p168_ssp1rx_pin1),
|
||||
GRP_168("ssp1tx-1", SSP1_TX, p168_ssp1tx_pin1),
|
||||
GRP_168("ssp4rx-1", SSP4, p168_ssp4rx_pin1),
|
||||
GRP_168("ssp4tx-1", SSP4_TX, p168_ssp4tx_pin1),
|
||||
GRP_168("ssp5rx-1", SSP5, p168_ssp5rx_pin1),
|
||||
GRP_168("ssp5tx-1", SSP5_TX, p168_ssp5tx_pin1),
|
||||
GRP_168("jtag", JTAG, p168_jtag_pin1),
|
||||
GRP_168("wakeup", WAKEUP, p168_wakeup_pin1),
|
||||
GRP_168("i2c", I2C, p168_i2c_pin1),
|
||||
GRP_168("pwri2c", PWRI2C, p168_pwri2c_pin1),
|
||||
GRP_168("mmc1 8p1", MMC1, p168_mmc1_pin1),
|
||||
GRP_168("mmc2 4p1", MMC2, p168_mmc2_data_pin1),
|
||||
GRP_168("mmc2 cmd1", MMC2_CMD, p168_mmc2_cmd_pin1),
|
||||
GRP_168("mmc2 clk1", MMC2_CLK, p168_mmc2_clk_pin1),
|
||||
GRP_168("mmc3 8p1", MMC3, p168_mmc3_data_pin1),
|
||||
GRP_168("mmc3 cmd1", MMC3_CMD, p168_mmc3_cmd_pin1),
|
||||
GRP_168("mmc3 clk1", MMC3_CLK, p168_mmc3_clk_pin1),
|
||||
GRP_168("eth", ETH, p168_eth_pin1),
|
||||
GRP_168("eth rx", ETH_RX, p168_ethrx_pin1),
|
||||
GRP_168("eth tx", ETH_TX, p168_ethtx_pin1),
|
||||
GRP_168("msp", MSP, p168_msp_pin1),
|
||||
GRP_168("ccic", CCIC, p168_ccic_pin1),
|
||||
GRP_168("xd", XD, p168_xd_pin1),
|
||||
GRP_168("lcd", LCD, p168_lcd_pin1),
|
||||
GRP_168("dfio", DFIO, p168_dfio_pin1),
|
||||
GRP_168("nand", NAND, p168_nand_pin1),
|
||||
GRP_168("smc", SMC, p168_smc_pin1),
|
||||
GRP_168("smc cs0", SMC_CS0, p168_smccs0_pin1),
|
||||
GRP_168("smc cs1", SMC_CS1, p168_smccs1_pin1),
|
||||
GRP_168("smc rdy", SMC_RDY, p168_smcrdy_pin1),
|
||||
GRP_168("ac97 sysclk", AC97_SYSCLK, p168_ac97sysclk_pin1),
|
||||
GRP_168("ac97", AC97, p168_ac97_pin1),
|
||||
GRP_168("cf", CF, p168_cf_pin1),
|
||||
GRP_168("kp mkin 3p1", KP_MKIN, p168_kpmkin_pin1),
|
||||
GRP_168("kp mkout 2p1", KP_MKOUT, p168_kpmkout_pin1),
|
||||
GRP_168("gpio86-1", GPIO, p168_gpio86_pin1),
|
||||
GRP_168("gpio86-2", GPIO, p168_gpio86_pin2),
|
||||
GRP_168("gpio87-1", GPIO, p168_gpio87_pin1),
|
||||
GRP_168("gpio87-2", GPIO, p168_gpio87_pin2),
|
||||
GRP_168("gpio88-1", GPIO, p168_gpio88_pin1),
|
||||
GRP_168("gpio88-2", GPIO, p168_gpio88_pin2),
|
||||
};
|
||||
|
||||
static const char * const p168_uart1rx_grps[] = {"uart1rx-1"};
|
||||
static const char * const p168_uart1tx_grps[] = {"uart1tx-1"};
|
||||
static const char * const p168_uart3rx_grps[] = {"uart3rx-1"};
|
||||
static const char * const p168_uart3tx_grps[] = {"uart3tx-1"};
|
||||
static const char * const p168_ssp1rx_grps[] = {"ssp1rx-1"};
|
||||
static const char * const p168_ssp1tx_grps[] = {"ssp1tx-1"};
|
||||
static const char * const p168_ssp4rx_grps[] = {"ssp4rx-1"};
|
||||
static const char * const p168_ssp4tx_grps[] = {"ssp4tx-1"};
|
||||
static const char * const p168_ssp5rx_grps[] = {"ssp5rx-1"};
|
||||
static const char * const p168_ssp5tx_grps[] = {"ssp5tx-1"};
|
||||
static const char * const p168_i2c_grps[] = {"i2c"};
|
||||
static const char * const p168_pwri2c_grps[] = {"pwri2c"};
|
||||
static const char * const p168_mmc1_grps[] = {"mmc1 8p1"};
|
||||
static const char * const p168_mmc2_data_grps[] = {"mmc2 4p1"};
|
||||
static const char * const p168_mmc2_cmd_grps[] = {"mmc2 cmd1"};
|
||||
static const char * const p168_mmc2_clk_grps[] = {"mmc2 clk1"};
|
||||
static const char * const p168_mmc3_data_grps[] = {"mmc3 8p1"};
|
||||
static const char * const p168_mmc3_cmd_grps[] = {"mmc3 cmd1"};
|
||||
static const char * const p168_mmc3_clk_grps[] = {"mmc3 clk1"};
|
||||
static const char * const p168_eth_grps[] = {"eth"};
|
||||
static const char * const p168_ethrx_grps[] = {"eth rx"};
|
||||
static const char * const p168_ethtx_grps[] = {"eth tx"};
|
||||
static const char * const p168_msp_grps[] = {"msp"};
|
||||
static const char * const p168_ccic_grps[] = {"ccic"};
|
||||
static const char * const p168_xd_grps[] = {"xd"};
|
||||
static const char * const p168_lcd_grps[] = {"lcd"};
|
||||
static const char * const p168_dfio_grps[] = {"dfio"};
|
||||
static const char * const p168_nand_grps[] = {"nand"};
|
||||
static const char * const p168_smc_grps[] = {"smc"};
|
||||
static const char * const p168_smccs0_grps[] = {"smc cs0"};
|
||||
static const char * const p168_smccs1_grps[] = {"smc cs1"};
|
||||
static const char * const p168_smcrdy_grps[] = {"smc rdy"};
|
||||
static const char * const p168_ac97sysclk_grps[] = {"ac97 sysclk"};
|
||||
static const char * const p168_ac97_grps[] = {"ac97"};
|
||||
static const char * const p168_cf_grps[] = {"cf"};
|
||||
static const char * const p168_kpmkin_grps[] = {"kp mkin 3p1"};
|
||||
static const char * const p168_kpmkout_grps[] = {"kp mkout 2p1"};
|
||||
static const char * const p168_gpio86_grps[] = {"gpio86-1", "gpio86-2"};
|
||||
static const char * const p168_gpio87_grps[] = {"gpio87-1", "gpio87-2"};
|
||||
static const char * const p168_gpio88_grps[] = {"gpio88-1", "gpio88-2"};
|
||||
|
||||
static struct pxa3xx_pmx_func pxa168_funcs[] = {
|
||||
{"uart1 rx", ARRAY_AND_SIZE(p168_uart1rx_grps)},
|
||||
{"uart1 tx", ARRAY_AND_SIZE(p168_uart1tx_grps)},
|
||||
{"uart3 rx", ARRAY_AND_SIZE(p168_uart3rx_grps)},
|
||||
{"uart3 tx", ARRAY_AND_SIZE(p168_uart3tx_grps)},
|
||||
{"ssp1 rx", ARRAY_AND_SIZE(p168_ssp1rx_grps)},
|
||||
{"ssp1 tx", ARRAY_AND_SIZE(p168_ssp1tx_grps)},
|
||||
{"ssp4 rx", ARRAY_AND_SIZE(p168_ssp4rx_grps)},
|
||||
{"ssp4 tx", ARRAY_AND_SIZE(p168_ssp4tx_grps)},
|
||||
{"ssp5 rx", ARRAY_AND_SIZE(p168_ssp5rx_grps)},
|
||||
{"ssp5 tx", ARRAY_AND_SIZE(p168_ssp5tx_grps)},
|
||||
{"i2c", ARRAY_AND_SIZE(p168_i2c_grps)},
|
||||
{"pwri2c", ARRAY_AND_SIZE(p168_pwri2c_grps)},
|
||||
{"mmc1", ARRAY_AND_SIZE(p168_mmc1_grps)},
|
||||
{"mmc2", ARRAY_AND_SIZE(p168_mmc2_data_grps)},
|
||||
{"mmc2 cmd", ARRAY_AND_SIZE(p168_mmc2_cmd_grps)},
|
||||
{"mmc2 clk", ARRAY_AND_SIZE(p168_mmc2_clk_grps)},
|
||||
{"mmc3", ARRAY_AND_SIZE(p168_mmc3_data_grps)},
|
||||
{"mmc3 cmd", ARRAY_AND_SIZE(p168_mmc3_cmd_grps)},
|
||||
{"mmc3 clk", ARRAY_AND_SIZE(p168_mmc3_clk_grps)},
|
||||
{"eth", ARRAY_AND_SIZE(p168_eth_grps)},
|
||||
{"eth rx", ARRAY_AND_SIZE(p168_ethrx_grps)},
|
||||
{"eth tx", ARRAY_AND_SIZE(p168_ethtx_grps)},
|
||||
{"msp", ARRAY_AND_SIZE(p168_msp_grps)},
|
||||
{"ccic", ARRAY_AND_SIZE(p168_ccic_grps)},
|
||||
{"xd", ARRAY_AND_SIZE(p168_xd_grps)},
|
||||
{"lcd", ARRAY_AND_SIZE(p168_lcd_grps)},
|
||||
{"dfio", ARRAY_AND_SIZE(p168_dfio_grps)},
|
||||
{"nand", ARRAY_AND_SIZE(p168_nand_grps)},
|
||||
{"smc", ARRAY_AND_SIZE(p168_smc_grps)},
|
||||
{"smc cs0", ARRAY_AND_SIZE(p168_smccs0_grps)},
|
||||
{"smc cs1", ARRAY_AND_SIZE(p168_smccs1_grps)},
|
||||
{"smc rdy", ARRAY_AND_SIZE(p168_smcrdy_grps)},
|
||||
{"ac97", ARRAY_AND_SIZE(p168_ac97_grps)},
|
||||
{"ac97 sysclk", ARRAY_AND_SIZE(p168_ac97sysclk_grps)},
|
||||
{"cf", ARRAY_AND_SIZE(p168_cf_grps)},
|
||||
{"kpmkin", ARRAY_AND_SIZE(p168_kpmkin_grps)},
|
||||
{"kpmkout", ARRAY_AND_SIZE(p168_kpmkout_grps)},
|
||||
{"gpio86", ARRAY_AND_SIZE(p168_gpio86_grps)},
|
||||
{"gpio87", ARRAY_AND_SIZE(p168_gpio87_grps)},
|
||||
{"gpio88", ARRAY_AND_SIZE(p168_gpio88_grps)},
|
||||
};
|
||||
|
||||
static struct pinctrl_desc pxa168_pctrl_desc = {
|
||||
.name = "pxa168-pinctrl",
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
static struct pxa3xx_pinmux_info pxa168_info = {
|
||||
.mfp = pxa168_mfp,
|
||||
.num_mfp = ARRAY_SIZE(pxa168_mfp),
|
||||
.grps = pxa168_grps,
|
||||
.num_grps = ARRAY_SIZE(pxa168_grps),
|
||||
.funcs = pxa168_funcs,
|
||||
.num_funcs = ARRAY_SIZE(pxa168_funcs),
|
||||
.num_gpio = 128,
|
||||
.desc = &pxa168_pctrl_desc,
|
||||
.pads = pxa168_pads,
|
||||
.num_pads = ARRAY_SIZE(pxa168_pads),
|
||||
|
||||
.cputype = PINCTRL_PXA168,
|
||||
.ds_mask = PXA168_DS_MASK,
|
||||
.ds_shift = PXA168_DS_SHIFT,
|
||||
};
|
||||
|
||||
static int pxa168_pinmux_probe(struct platform_device *pdev)
|
||||
{
|
||||
return pxa3xx_pinctrl_register(pdev, &pxa168_info);
|
||||
}
|
||||
|
||||
static int pxa168_pinmux_remove(struct platform_device *pdev)
|
||||
{
|
||||
return pxa3xx_pinctrl_unregister(pdev);
|
||||
}
|
||||
|
||||
static struct platform_driver pxa168_pinmux_driver = {
|
||||
.driver = {
|
||||
.name = "pxa168-pinmux",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = pxa168_pinmux_probe,
|
||||
.remove = pxa168_pinmux_remove,
|
||||
};
|
||||
|
||||
static int __init pxa168_pinmux_init(void)
|
||||
{
|
||||
return platform_driver_register(&pxa168_pinmux_driver);
|
||||
}
|
||||
core_initcall_sync(pxa168_pinmux_init);
|
||||
|
||||
static void __exit pxa168_pinmux_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&pxa168_pinmux_driver);
|
||||
}
|
||||
module_exit(pxa168_pinmux_exit);
|
||||
|
||||
MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
|
||||
MODULE_DESCRIPTION("PXA3xx pin control driver");
|
||||
MODULE_LICENSE("GPL v2");
|
@ -1,227 +0,0 @@
|
||||
/*
|
||||
* linux/drivers/pinctrl/pinctrl-pxa3xx.c
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* publishhed by the Free Software Foundation.
|
||||
*
|
||||
* Copyright (C) 2011, Marvell Technology Group Ltd.
|
||||
*
|
||||
* Author: Haojian Zhuang <haojian.zhuang@marvell.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/err.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
#include "pinctrl-pxa3xx.h"
|
||||
|
||||
static struct pinctrl_gpio_range pxa3xx_pinctrl_gpio_range = {
|
||||
.name = "PXA3xx GPIO",
|
||||
.id = 0,
|
||||
.base = 0,
|
||||
.pin_base = 0,
|
||||
};
|
||||
|
||||
static int pxa3xx_get_groups_count(struct pinctrl_dev *pctrldev)
|
||||
{
|
||||
struct pxa3xx_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
|
||||
|
||||
return info->num_grps;
|
||||
}
|
||||
|
||||
static const char *pxa3xx_get_group_name(struct pinctrl_dev *pctrldev,
|
||||
unsigned selector)
|
||||
{
|
||||
struct pxa3xx_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
|
||||
|
||||
return info->grps[selector].name;
|
||||
}
|
||||
|
||||
static int pxa3xx_get_group_pins(struct pinctrl_dev *pctrldev,
|
||||
unsigned selector,
|
||||
const unsigned **pins,
|
||||
unsigned *num_pins)
|
||||
{
|
||||
struct pxa3xx_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
|
||||
|
||||
*pins = info->grps[selector].pins;
|
||||
*num_pins = info->grps[selector].npins;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct pinctrl_ops pxa3xx_pctrl_ops = {
|
||||
.get_groups_count = pxa3xx_get_groups_count,
|
||||
.get_group_name = pxa3xx_get_group_name,
|
||||
.get_group_pins = pxa3xx_get_group_pins,
|
||||
};
|
||||
|
||||
static int pxa3xx_pmx_get_funcs_count(struct pinctrl_dev *pctrldev)
|
||||
{
|
||||
struct pxa3xx_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
|
||||
|
||||
return info->num_funcs;
|
||||
}
|
||||
|
||||
static const char *pxa3xx_pmx_get_func_name(struct pinctrl_dev *pctrldev,
|
||||
unsigned func)
|
||||
{
|
||||
struct pxa3xx_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
|
||||
return info->funcs[func].name;
|
||||
}
|
||||
|
||||
static int pxa3xx_pmx_get_groups(struct pinctrl_dev *pctrldev, unsigned func,
|
||||
const char * const **groups,
|
||||
unsigned * const num_groups)
|
||||
{
|
||||
struct pxa3xx_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
|
||||
*groups = info->funcs[func].groups;
|
||||
*num_groups = info->funcs[func].num_groups;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Return function number. If failure, return negative value. */
|
||||
static int match_mux(struct pxa3xx_mfp_pin *mfp, unsigned mux)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < PXA3xx_MAX_MUX; i++) {
|
||||
if (mfp->func[i] == mux)
|
||||
break;
|
||||
}
|
||||
if (i >= PXA3xx_MAX_MUX)
|
||||
return -EINVAL;
|
||||
return i;
|
||||
}
|
||||
|
||||
/* check whether current pin configuration is valid. Negative for failure */
|
||||
static int match_group_mux(struct pxa3xx_pin_group *grp,
|
||||
struct pxa3xx_pinmux_info *info,
|
||||
unsigned mux)
|
||||
{
|
||||
int i, pin, ret = 0;
|
||||
for (i = 0; i < grp->npins; i++) {
|
||||
pin = grp->pins[i];
|
||||
ret = match_mux(&info->mfp[pin], mux);
|
||||
if (ret < 0) {
|
||||
dev_err(info->dev, "Can't find mux %d on pin%d\n",
|
||||
mux, pin);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int pxa3xx_pmx_enable(struct pinctrl_dev *pctrldev, unsigned func,
|
||||
unsigned group)
|
||||
{
|
||||
struct pxa3xx_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
|
||||
struct pxa3xx_pin_group *pin_grp = &info->grps[group];
|
||||
unsigned int data;
|
||||
int i, mfpr, pin, pin_func;
|
||||
|
||||
if (!pin_grp->npins ||
|
||||
(match_group_mux(pin_grp, info, pin_grp->mux) < 0)) {
|
||||
dev_err(info->dev, "Failed to set the pin group: %d\n", group);
|
||||
return -EINVAL;
|
||||
}
|
||||
for (i = 0; i < pin_grp->npins; i++) {
|
||||
pin = pin_grp->pins[i];
|
||||
pin_func = match_mux(&info->mfp[pin], pin_grp->mux);
|
||||
mfpr = info->mfp[pin].mfpr;
|
||||
data = readl_relaxed(info->virt_base + mfpr);
|
||||
data &= ~MFPR_FUNC_MASK;
|
||||
data |= pin_func;
|
||||
writel_relaxed(data, info->virt_base + mfpr);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pxa3xx_pmx_request_gpio(struct pinctrl_dev *pctrldev,
|
||||
struct pinctrl_gpio_range *range,
|
||||
unsigned pin)
|
||||
{
|
||||
struct pxa3xx_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
|
||||
unsigned int data;
|
||||
int pin_func, mfpr;
|
||||
|
||||
pin_func = match_mux(&info->mfp[pin], PXA3xx_MUX_GPIO);
|
||||
if (pin_func < 0) {
|
||||
dev_err(info->dev, "No GPIO function on pin%d (%s)\n",
|
||||
pin, info->pads[pin].name);
|
||||
return -EINVAL;
|
||||
}
|
||||
mfpr = info->mfp[pin].mfpr;
|
||||
/* write gpio function into mfpr register */
|
||||
data = readl_relaxed(info->virt_base + mfpr) & ~MFPR_FUNC_MASK;
|
||||
data |= pin_func;
|
||||
writel_relaxed(data, info->virt_base + mfpr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct pinmux_ops pxa3xx_pmx_ops = {
|
||||
.get_functions_count = pxa3xx_pmx_get_funcs_count,
|
||||
.get_function_name = pxa3xx_pmx_get_func_name,
|
||||
.get_function_groups = pxa3xx_pmx_get_groups,
|
||||
.enable = pxa3xx_pmx_enable,
|
||||
.gpio_request_enable = pxa3xx_pmx_request_gpio,
|
||||
};
|
||||
|
||||
int pxa3xx_pinctrl_register(struct platform_device *pdev,
|
||||
struct pxa3xx_pinmux_info *info)
|
||||
{
|
||||
struct pinctrl_desc *desc;
|
||||
struct resource *res;
|
||||
|
||||
if (!info || !info->cputype)
|
||||
return -EINVAL;
|
||||
desc = info->desc;
|
||||
desc->pins = info->pads;
|
||||
desc->npins = info->num_pads;
|
||||
desc->pctlops = &pxa3xx_pctrl_ops;
|
||||
desc->pmxops = &pxa3xx_pmx_ops;
|
||||
info->dev = &pdev->dev;
|
||||
pxa3xx_pinctrl_gpio_range.npins = info->num_gpio;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!res)
|
||||
return -ENOENT;
|
||||
info->virt_base = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(info->virt_base))
|
||||
return PTR_ERR(info->virt_base);
|
||||
info->pctrl = pinctrl_register(desc, &pdev->dev, info);
|
||||
if (!info->pctrl) {
|
||||
dev_err(&pdev->dev, "failed to register PXA pinmux driver\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
pinctrl_add_gpio_range(info->pctrl, &pxa3xx_pinctrl_gpio_range);
|
||||
platform_set_drvdata(pdev, info);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pxa3xx_pinctrl_unregister(struct platform_device *pdev)
|
||||
{
|
||||
struct pxa3xx_pinmux_info *info = platform_get_drvdata(pdev);
|
||||
|
||||
pinctrl_unregister(info->pctrl);
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __init pxa3xx_pinctrl_init(void)
|
||||
{
|
||||
pr_info("pxa3xx-pinctrl: PXA3xx pinctrl driver initializing\n");
|
||||
return 0;
|
||||
}
|
||||
core_initcall_sync(pxa3xx_pinctrl_init);
|
||||
|
||||
static void __exit pxa3xx_pinctrl_exit(void)
|
||||
{
|
||||
}
|
||||
module_exit(pxa3xx_pinctrl_exit);
|
||||
|
||||
MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
|
||||
MODULE_DESCRIPTION("PXA3xx pin control driver");
|
||||
MODULE_LICENSE("GPL v2");
|
@ -1,262 +0,0 @@
|
||||
/*
|
||||
* linux/drivers/pinctrl/pinctrl-pxa3xx.h
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* publishhed by the Free Software Foundation.
|
||||
*
|
||||
* Copyright (C) 2011, Marvell Technology Group Ltd.
|
||||
*
|
||||
* Author: Haojian Zhuang <haojian.zhuang@marvell.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __PINCTRL_PXA3XX_H
|
||||
|
||||
#include <linux/pinctrl/pinctrl.h>
|
||||
#include <linux/pinctrl/pinmux.h>
|
||||
|
||||
#define ARRAY_AND_SIZE(x) (x), ARRAY_SIZE(x)
|
||||
|
||||
#define PXA3xx_MUX_GPIO 0
|
||||
|
||||
#define PXA3xx_MAX_MUX 8
|
||||
#define MFPR_FUNC_MASK 0x7
|
||||
|
||||
enum pxa_cpu_type {
|
||||
PINCTRL_INVALID = 0,
|
||||
PINCTRL_PXA300,
|
||||
PINCTRL_PXA310,
|
||||
PINCTRL_PXA320,
|
||||
PINCTRL_PXA168,
|
||||
PINCTRL_PXA910,
|
||||
PINCTRL_PXA930,
|
||||
PINCTRL_PXA955,
|
||||
PINCTRL_MMP2,
|
||||
PINCTRL_MAX,
|
||||
};
|
||||
|
||||
struct pxa3xx_mfp_pin {
|
||||
const char *name;
|
||||
const unsigned int pin;
|
||||
const unsigned int mfpr; /* register offset */
|
||||
const unsigned short func[8];
|
||||
};
|
||||
|
||||
struct pxa3xx_pin_group {
|
||||
const char *name;
|
||||
const unsigned mux;
|
||||
const unsigned *pins;
|
||||
const unsigned npins;
|
||||
};
|
||||
|
||||
struct pxa3xx_pmx_func {
|
||||
const char *name;
|
||||
const char * const * groups;
|
||||
const unsigned num_groups;
|
||||
};
|
||||
|
||||
struct pxa3xx_pinmux_info {
|
||||
struct device *dev;
|
||||
struct pinctrl_dev *pctrl;
|
||||
enum pxa_cpu_type cputype;
|
||||
void __iomem *virt_base;
|
||||
|
||||
struct pxa3xx_mfp_pin *mfp;
|
||||
unsigned int num_mfp;
|
||||
struct pxa3xx_pin_group *grps;
|
||||
unsigned int num_grps;
|
||||
struct pxa3xx_pmx_func *funcs;
|
||||
unsigned int num_funcs;
|
||||
unsigned int num_gpio;
|
||||
struct pinctrl_desc *desc;
|
||||
struct pinctrl_pin_desc *pads;
|
||||
unsigned int num_pads;
|
||||
|
||||
unsigned ds_mask; /* drive strength mask */
|
||||
unsigned ds_shift; /* drive strength shift */
|
||||
unsigned slp_mask; /* sleep mask */
|
||||
unsigned slp_input_low;
|
||||
unsigned slp_input_high;
|
||||
unsigned slp_output_low;
|
||||
unsigned slp_output_high;
|
||||
unsigned slp_float;
|
||||
};
|
||||
|
||||
enum pxa3xx_pin_list {
|
||||
GPIO0 = 0,
|
||||
GPIO1,
|
||||
GPIO2,
|
||||
GPIO3,
|
||||
GPIO4,
|
||||
GPIO5,
|
||||
GPIO6,
|
||||
GPIO7,
|
||||
GPIO8,
|
||||
GPIO9,
|
||||
GPIO10, /* 10 */
|
||||
GPIO11,
|
||||
GPIO12,
|
||||
GPIO13,
|
||||
GPIO14,
|
||||
GPIO15,
|
||||
GPIO16,
|
||||
GPIO17,
|
||||
GPIO18,
|
||||
GPIO19,
|
||||
GPIO20, /* 20 */
|
||||
GPIO21,
|
||||
GPIO22,
|
||||
GPIO23,
|
||||
GPIO24,
|
||||
GPIO25,
|
||||
GPIO26,
|
||||
GPIO27,
|
||||
GPIO28,
|
||||
GPIO29,
|
||||
GPIO30, /* 30 */
|
||||
GPIO31,
|
||||
GPIO32,
|
||||
GPIO33,
|
||||
GPIO34,
|
||||
GPIO35,
|
||||
GPIO36,
|
||||
GPIO37,
|
||||
GPIO38,
|
||||
GPIO39,
|
||||
GPIO40, /* 40 */
|
||||
GPIO41,
|
||||
GPIO42,
|
||||
GPIO43,
|
||||
GPIO44,
|
||||
GPIO45,
|
||||
GPIO46,
|
||||
GPIO47,
|
||||
GPIO48,
|
||||
GPIO49,
|
||||
GPIO50, /* 50 */
|
||||
GPIO51,
|
||||
GPIO52,
|
||||
GPIO53,
|
||||
GPIO54,
|
||||
GPIO55,
|
||||
GPIO56,
|
||||
GPIO57,
|
||||
GPIO58,
|
||||
GPIO59,
|
||||
GPIO60, /* 60 */
|
||||
GPIO61,
|
||||
GPIO62,
|
||||
GPIO63,
|
||||
GPIO64,
|
||||
GPIO65,
|
||||
GPIO66,
|
||||
GPIO67,
|
||||
GPIO68,
|
||||
GPIO69,
|
||||
GPIO70, /* 70 */
|
||||
GPIO71,
|
||||
GPIO72,
|
||||
GPIO73,
|
||||
GPIO74,
|
||||
GPIO75,
|
||||
GPIO76,
|
||||
GPIO77,
|
||||
GPIO78,
|
||||
GPIO79,
|
||||
GPIO80, /* 80 */
|
||||
GPIO81,
|
||||
GPIO82,
|
||||
GPIO83,
|
||||
GPIO84,
|
||||
GPIO85,
|
||||
GPIO86,
|
||||
GPIO87,
|
||||
GPIO88,
|
||||
GPIO89,
|
||||
GPIO90, /* 90 */
|
||||
GPIO91,
|
||||
GPIO92,
|
||||
GPIO93,
|
||||
GPIO94,
|
||||
GPIO95,
|
||||
GPIO96,
|
||||
GPIO97,
|
||||
GPIO98,
|
||||
GPIO99,
|
||||
GPIO100, /* 100 */
|
||||
GPIO101,
|
||||
GPIO102,
|
||||
GPIO103,
|
||||
GPIO104,
|
||||
GPIO105,
|
||||
GPIO106,
|
||||
GPIO107,
|
||||
GPIO108,
|
||||
GPIO109,
|
||||
GPIO110, /* 110 */
|
||||
GPIO111,
|
||||
GPIO112,
|
||||
GPIO113,
|
||||
GPIO114,
|
||||
GPIO115,
|
||||
GPIO116,
|
||||
GPIO117,
|
||||
GPIO118,
|
||||
GPIO119,
|
||||
GPIO120, /* 120 */
|
||||
GPIO121,
|
||||
GPIO122,
|
||||
GPIO123,
|
||||
GPIO124,
|
||||
GPIO125,
|
||||
GPIO126,
|
||||
GPIO127,
|
||||
GPIO128,
|
||||
GPIO129,
|
||||
GPIO130, /* 130 */
|
||||
GPIO131,
|
||||
GPIO132,
|
||||
GPIO133,
|
||||
GPIO134,
|
||||
GPIO135,
|
||||
GPIO136,
|
||||
GPIO137,
|
||||
GPIO138,
|
||||
GPIO139,
|
||||
GPIO140, /* 140 */
|
||||
GPIO141,
|
||||
GPIO142,
|
||||
GPIO143,
|
||||
GPIO144,
|
||||
GPIO145,
|
||||
GPIO146,
|
||||
GPIO147,
|
||||
GPIO148,
|
||||
GPIO149,
|
||||
GPIO150, /* 150 */
|
||||
GPIO151,
|
||||
GPIO152,
|
||||
GPIO153,
|
||||
GPIO154,
|
||||
GPIO155,
|
||||
GPIO156,
|
||||
GPIO157,
|
||||
GPIO158,
|
||||
GPIO159,
|
||||
GPIO160, /* 160 */
|
||||
GPIO161,
|
||||
GPIO162,
|
||||
GPIO163,
|
||||
GPIO164,
|
||||
GPIO165,
|
||||
GPIO166,
|
||||
GPIO167,
|
||||
GPIO168,
|
||||
GPIO169,
|
||||
};
|
||||
|
||||
extern int pxa3xx_pinctrl_register(struct platform_device *pdev,
|
||||
struct pxa3xx_pinmux_info *info);
|
||||
extern int pxa3xx_pinctrl_unregister(struct platform_device *pdev);
|
||||
#endif /* __PINCTRL_PXA3XX_H */
|
File diff suppressed because it is too large
Load Diff
816
drivers/pinctrl/pinctrl-s3c64xx.c
Normal file
816
drivers/pinctrl/pinctrl-s3c64xx.c
Normal file
@ -0,0 +1,816 @@
|
||||
/*
|
||||
* S3C64xx specific support for pinctrl-samsung driver.
|
||||
*
|
||||
* Copyright (c) 2013 Tomasz Figa <tomasz.figa@gmail.com>
|
||||
*
|
||||
* Based on pinctrl-exynos.c, please see the file for original copyrights.
|
||||
*
|
||||
* 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 file contains the Samsung S3C64xx specific information required by the
|
||||
* the Samsung pinctrl/gpiolib driver. It also includes the implementation of
|
||||
* external gpio and wakeup interrupt support.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/irqdomain.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/irqchip/chained_irq.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/err.h>
|
||||
|
||||
#include "pinctrl-samsung.h"
|
||||
|
||||
#define NUM_EINT0 28
|
||||
#define NUM_EINT0_IRQ 4
|
||||
#define EINT_MAX_PER_REG 16
|
||||
#define EINT_MAX_PER_GROUP 16
|
||||
|
||||
/* External GPIO and wakeup interrupt related definitions */
|
||||
#define SVC_GROUP_SHIFT 4
|
||||
#define SVC_GROUP_MASK 0xf
|
||||
#define SVC_NUM_MASK 0xf
|
||||
#define SVC_GROUP(x) ((x >> SVC_GROUP_SHIFT) & \
|
||||
SVC_GROUP_MASK)
|
||||
|
||||
#define EINT12CON_REG 0x200
|
||||
#define EINT12MASK_REG 0x240
|
||||
#define EINT12PEND_REG 0x260
|
||||
|
||||
#define EINT_OFFS(i) ((i) % (2 * EINT_MAX_PER_GROUP))
|
||||
#define EINT_GROUP(i) ((i) / EINT_MAX_PER_GROUP)
|
||||
#define EINT_REG(g) (4 * ((g) / 2))
|
||||
|
||||
#define EINTCON_REG(i) (EINT12CON_REG + EINT_REG(EINT_GROUP(i)))
|
||||
#define EINTMASK_REG(i) (EINT12MASK_REG + EINT_REG(EINT_GROUP(i)))
|
||||
#define EINTPEND_REG(i) (EINT12PEND_REG + EINT_REG(EINT_GROUP(i)))
|
||||
|
||||
#define SERVICE_REG 0x284
|
||||
#define SERVICEPEND_REG 0x288
|
||||
|
||||
#define EINT0CON0_REG 0x900
|
||||
#define EINT0MASK_REG 0x920
|
||||
#define EINT0PEND_REG 0x924
|
||||
|
||||
/* S3C64xx specific external interrupt trigger types */
|
||||
#define EINT_LEVEL_LOW 0
|
||||
#define EINT_LEVEL_HIGH 1
|
||||
#define EINT_EDGE_FALLING 2
|
||||
#define EINT_EDGE_RISING 4
|
||||
#define EINT_EDGE_BOTH 6
|
||||
#define EINT_CON_MASK 0xF
|
||||
#define EINT_CON_LEN 4
|
||||
|
||||
static struct samsung_pin_bank_type bank_type_4bit_off = {
|
||||
.fld_width = { 4, 1, 2, 0, 2, 2, },
|
||||
.reg_offset = { 0x00, 0x04, 0x08, 0, 0x0c, 0x10, },
|
||||
};
|
||||
|
||||
static struct samsung_pin_bank_type bank_type_4bit_alive = {
|
||||
.fld_width = { 4, 1, 2, },
|
||||
.reg_offset = { 0x00, 0x04, 0x08, },
|
||||
};
|
||||
|
||||
static struct samsung_pin_bank_type bank_type_4bit2_off = {
|
||||
.fld_width = { 4, 1, 2, 0, 2, 2, },
|
||||
.reg_offset = { 0x00, 0x08, 0x0c, 0, 0x10, 0x14, },
|
||||
};
|
||||
|
||||
static struct samsung_pin_bank_type bank_type_4bit2_alive = {
|
||||
.fld_width = { 4, 1, 2, },
|
||||
.reg_offset = { 0x00, 0x08, 0x0c, },
|
||||
};
|
||||
|
||||
static struct samsung_pin_bank_type bank_type_2bit_off = {
|
||||
.fld_width = { 2, 1, 2, 0, 2, 2, },
|
||||
.reg_offset = { 0x00, 0x04, 0x08, 0, 0x0c, 0x10, },
|
||||
};
|
||||
|
||||
static struct samsung_pin_bank_type bank_type_2bit_alive = {
|
||||
.fld_width = { 2, 1, 2, },
|
||||
.reg_offset = { 0x00, 0x04, 0x08, },
|
||||
};
|
||||
|
||||
#define PIN_BANK_4BIT(pins, reg, id) \
|
||||
{ \
|
||||
.type = &bank_type_4bit_off, \
|
||||
.pctl_offset = reg, \
|
||||
.nr_pins = pins, \
|
||||
.eint_type = EINT_TYPE_NONE, \
|
||||
.name = id \
|
||||
}
|
||||
|
||||
#define PIN_BANK_4BIT_EINTG(pins, reg, id, eoffs) \
|
||||
{ \
|
||||
.type = &bank_type_4bit_off, \
|
||||
.pctl_offset = reg, \
|
||||
.nr_pins = pins, \
|
||||
.eint_type = EINT_TYPE_GPIO, \
|
||||
.eint_func = 7, \
|
||||
.eint_mask = (1 << (pins)) - 1, \
|
||||
.eint_offset = eoffs, \
|
||||
.name = id \
|
||||
}
|
||||
|
||||
#define PIN_BANK_4BIT_EINTW(pins, reg, id, eoffs, emask) \
|
||||
{ \
|
||||
.type = &bank_type_4bit_alive,\
|
||||
.pctl_offset = reg, \
|
||||
.nr_pins = pins, \
|
||||
.eint_type = EINT_TYPE_WKUP, \
|
||||
.eint_func = 3, \
|
||||
.eint_mask = emask, \
|
||||
.eint_offset = eoffs, \
|
||||
.name = id \
|
||||
}
|
||||
|
||||
#define PIN_BANK_4BIT2_EINTG(pins, reg, id, eoffs) \
|
||||
{ \
|
||||
.type = &bank_type_4bit2_off, \
|
||||
.pctl_offset = reg, \
|
||||
.nr_pins = pins, \
|
||||
.eint_type = EINT_TYPE_GPIO, \
|
||||
.eint_func = 7, \
|
||||
.eint_mask = (1 << (pins)) - 1, \
|
||||
.eint_offset = eoffs, \
|
||||
.name = id \
|
||||
}
|
||||
|
||||
#define PIN_BANK_4BIT2_EINTW(pins, reg, id, eoffs, emask) \
|
||||
{ \
|
||||
.type = &bank_type_4bit2_alive,\
|
||||
.pctl_offset = reg, \
|
||||
.nr_pins = pins, \
|
||||
.eint_type = EINT_TYPE_WKUP, \
|
||||
.eint_func = 3, \
|
||||
.eint_mask = emask, \
|
||||
.eint_offset = eoffs, \
|
||||
.name = id \
|
||||
}
|
||||
|
||||
#define PIN_BANK_4BIT2_ALIVE(pins, reg, id) \
|
||||
{ \
|
||||
.type = &bank_type_4bit2_alive,\
|
||||
.pctl_offset = reg, \
|
||||
.nr_pins = pins, \
|
||||
.eint_type = EINT_TYPE_NONE, \
|
||||
.name = id \
|
||||
}
|
||||
|
||||
#define PIN_BANK_2BIT(pins, reg, id) \
|
||||
{ \
|
||||
.type = &bank_type_2bit_off, \
|
||||
.pctl_offset = reg, \
|
||||
.nr_pins = pins, \
|
||||
.eint_type = EINT_TYPE_NONE, \
|
||||
.name = id \
|
||||
}
|
||||
|
||||
#define PIN_BANK_2BIT_EINTG(pins, reg, id, eoffs, emask) \
|
||||
{ \
|
||||
.type = &bank_type_2bit_off, \
|
||||
.pctl_offset = reg, \
|
||||
.nr_pins = pins, \
|
||||
.eint_type = EINT_TYPE_GPIO, \
|
||||
.eint_func = 3, \
|
||||
.eint_mask = emask, \
|
||||
.eint_offset = eoffs, \
|
||||
.name = id \
|
||||
}
|
||||
|
||||
#define PIN_BANK_2BIT_EINTW(pins, reg, id, eoffs) \
|
||||
{ \
|
||||
.type = &bank_type_2bit_alive,\
|
||||
.pctl_offset = reg, \
|
||||
.nr_pins = pins, \
|
||||
.eint_type = EINT_TYPE_WKUP, \
|
||||
.eint_func = 2, \
|
||||
.eint_mask = (1 << (pins)) - 1, \
|
||||
.eint_offset = eoffs, \
|
||||
.name = id \
|
||||
}
|
||||
|
||||
/**
|
||||
* struct s3c64xx_eint0_data: EINT0 common data
|
||||
* @drvdata: pin controller driver data
|
||||
* @domains: IRQ domains of particular EINT0 interrupts
|
||||
* @pins: pin offsets inside of banks of particular EINT0 interrupts
|
||||
*/
|
||||
struct s3c64xx_eint0_data {
|
||||
struct samsung_pinctrl_drv_data *drvdata;
|
||||
struct irq_domain *domains[NUM_EINT0];
|
||||
u8 pins[NUM_EINT0];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct s3c64xx_eint0_domain_data: EINT0 per-domain data
|
||||
* @bank: pin bank related to the domain
|
||||
* @eints: EINT0 interrupts related to the domain
|
||||
*/
|
||||
struct s3c64xx_eint0_domain_data {
|
||||
struct samsung_pin_bank *bank;
|
||||
u8 eints[];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct s3c64xx_eint_gpio_data: GPIO EINT data
|
||||
* @drvdata: pin controller driver data
|
||||
* @domains: array of domains related to EINT interrupt groups
|
||||
*/
|
||||
struct s3c64xx_eint_gpio_data {
|
||||
struct samsung_pinctrl_drv_data *drvdata;
|
||||
struct irq_domain *domains[];
|
||||
};
|
||||
|
||||
/*
|
||||
* Common functions for S3C64xx EINT configuration
|
||||
*/
|
||||
|
||||
static int s3c64xx_irq_get_trigger(unsigned int type)
|
||||
{
|
||||
int trigger;
|
||||
|
||||
switch (type) {
|
||||
case IRQ_TYPE_EDGE_RISING:
|
||||
trigger = EINT_EDGE_RISING;
|
||||
break;
|
||||
case IRQ_TYPE_EDGE_FALLING:
|
||||
trigger = EINT_EDGE_FALLING;
|
||||
break;
|
||||
case IRQ_TYPE_EDGE_BOTH:
|
||||
trigger = EINT_EDGE_BOTH;
|
||||
break;
|
||||
case IRQ_TYPE_LEVEL_HIGH:
|
||||
trigger = EINT_LEVEL_HIGH;
|
||||
break;
|
||||
case IRQ_TYPE_LEVEL_LOW:
|
||||
trigger = EINT_LEVEL_LOW;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return trigger;
|
||||
}
|
||||
|
||||
static void s3c64xx_irq_set_handler(unsigned int irq, unsigned int type)
|
||||
{
|
||||
/* Edge- and level-triggered interrupts need different handlers */
|
||||
if (type & IRQ_TYPE_EDGE_BOTH)
|
||||
__irq_set_handler_locked(irq, handle_edge_irq);
|
||||
else
|
||||
__irq_set_handler_locked(irq, handle_level_irq);
|
||||
}
|
||||
|
||||
static void s3c64xx_irq_set_function(struct samsung_pinctrl_drv_data *d,
|
||||
struct samsung_pin_bank *bank, int pin)
|
||||
{
|
||||
struct samsung_pin_bank_type *bank_type = bank->type;
|
||||
unsigned long flags;
|
||||
void __iomem *reg;
|
||||
u8 shift;
|
||||
u32 mask;
|
||||
u32 val;
|
||||
|
||||
/* Make sure that pin is configured as interrupt */
|
||||
reg = d->virt_base + bank->pctl_offset;
|
||||
shift = pin;
|
||||
if (bank_type->fld_width[PINCFG_TYPE_FUNC] * shift >= 32) {
|
||||
/* 4-bit bank type with 2 con regs */
|
||||
reg += 4;
|
||||
shift -= 8;
|
||||
}
|
||||
|
||||
shift = shift * bank_type->fld_width[PINCFG_TYPE_FUNC];
|
||||
mask = (1 << bank_type->fld_width[PINCFG_TYPE_FUNC]) - 1;
|
||||
|
||||
spin_lock_irqsave(&bank->slock, flags);
|
||||
|
||||
val = readl(reg);
|
||||
val &= ~(mask << shift);
|
||||
val |= bank->eint_func << shift;
|
||||
writel(val, reg);
|
||||
|
||||
spin_unlock_irqrestore(&bank->slock, flags);
|
||||
}
|
||||
|
||||
/*
|
||||
* Functions for EINT GPIO configuration (EINT groups 1-9)
|
||||
*/
|
||||
|
||||
static inline void s3c64xx_gpio_irq_set_mask(struct irq_data *irqd, bool mask)
|
||||
{
|
||||
struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
|
||||
struct samsung_pinctrl_drv_data *d = bank->drvdata;
|
||||
unsigned char index = EINT_OFFS(bank->eint_offset) + irqd->hwirq;
|
||||
void __iomem *reg = d->virt_base + EINTMASK_REG(bank->eint_offset);
|
||||
u32 val;
|
||||
|
||||
val = readl(reg);
|
||||
if (mask)
|
||||
val |= 1 << index;
|
||||
else
|
||||
val &= ~(1 << index);
|
||||
writel(val, reg);
|
||||
}
|
||||
|
||||
static void s3c64xx_gpio_irq_unmask(struct irq_data *irqd)
|
||||
{
|
||||
s3c64xx_gpio_irq_set_mask(irqd, false);
|
||||
}
|
||||
|
||||
static void s3c64xx_gpio_irq_mask(struct irq_data *irqd)
|
||||
{
|
||||
s3c64xx_gpio_irq_set_mask(irqd, true);
|
||||
}
|
||||
|
||||
static void s3c64xx_gpio_irq_ack(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 char index = EINT_OFFS(bank->eint_offset) + irqd->hwirq;
|
||||
void __iomem *reg = d->virt_base + EINTPEND_REG(bank->eint_offset);
|
||||
|
||||
writel(1 << index, reg);
|
||||
}
|
||||
|
||||
static int s3c64xx_gpio_irq_set_type(struct irq_data *irqd, unsigned int type)
|
||||
{
|
||||
struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
|
||||
struct samsung_pinctrl_drv_data *d = bank->drvdata;
|
||||
void __iomem *reg;
|
||||
int trigger;
|
||||
u8 shift;
|
||||
u32 val;
|
||||
|
||||
trigger = s3c64xx_irq_get_trigger(type);
|
||||
if (trigger < 0) {
|
||||
pr_err("unsupported external interrupt type\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
s3c64xx_irq_set_handler(irqd->irq, type);
|
||||
|
||||
/* Set up interrupt trigger */
|
||||
reg = d->virt_base + EINTCON_REG(bank->eint_offset);
|
||||
shift = EINT_OFFS(bank->eint_offset) + irqd->hwirq;
|
||||
shift = 4 * (shift / 4); /* 4 EINTs per trigger selector */
|
||||
|
||||
val = readl(reg);
|
||||
val &= ~(EINT_CON_MASK << shift);
|
||||
val |= trigger << shift;
|
||||
writel(val, reg);
|
||||
|
||||
s3c64xx_irq_set_function(d, bank, irqd->hwirq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* irq_chip for gpio interrupts.
|
||||
*/
|
||||
static struct irq_chip s3c64xx_gpio_irq_chip = {
|
||||
.name = "GPIO",
|
||||
.irq_unmask = s3c64xx_gpio_irq_unmask,
|
||||
.irq_mask = s3c64xx_gpio_irq_mask,
|
||||
.irq_ack = s3c64xx_gpio_irq_ack,
|
||||
.irq_set_type = s3c64xx_gpio_irq_set_type,
|
||||
};
|
||||
|
||||
static int s3c64xx_gpio_irq_map(struct irq_domain *h, unsigned int virq,
|
||||
irq_hw_number_t hw)
|
||||
{
|
||||
struct samsung_pin_bank *bank = h->host_data;
|
||||
|
||||
if (!(bank->eint_mask & (1 << hw)))
|
||||
return -EINVAL;
|
||||
|
||||
irq_set_chip_and_handler(virq,
|
||||
&s3c64xx_gpio_irq_chip, handle_level_irq);
|
||||
irq_set_chip_data(virq, bank);
|
||||
set_irq_flags(virq, IRQF_VALID);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* irq domain callbacks for external gpio interrupt controller.
|
||||
*/
|
||||
static const struct irq_domain_ops s3c64xx_gpio_irqd_ops = {
|
||||
.map = s3c64xx_gpio_irq_map,
|
||||
.xlate = irq_domain_xlate_twocell,
|
||||
};
|
||||
|
||||
static void s3c64xx_eint_gpio_irq(unsigned int irq, struct irq_desc *desc)
|
||||
{
|
||||
struct irq_chip *chip = irq_get_chip(irq);
|
||||
struct s3c64xx_eint_gpio_data *data = irq_get_handler_data(irq);
|
||||
struct samsung_pinctrl_drv_data *drvdata = data->drvdata;
|
||||
|
||||
chained_irq_enter(chip, desc);
|
||||
|
||||
do {
|
||||
unsigned int svc;
|
||||
unsigned int group;
|
||||
unsigned int pin;
|
||||
unsigned int virq;
|
||||
|
||||
svc = readl(drvdata->virt_base + SERVICE_REG);
|
||||
group = SVC_GROUP(svc);
|
||||
pin = svc & SVC_NUM_MASK;
|
||||
|
||||
if (!group)
|
||||
break;
|
||||
|
||||
/* Group 1 is used for two pin banks */
|
||||
if (group == 1) {
|
||||
if (pin < 8)
|
||||
group = 0;
|
||||
else
|
||||
pin -= 8;
|
||||
}
|
||||
|
||||
virq = irq_linear_revmap(data->domains[group], pin);
|
||||
/*
|
||||
* Something must be really wrong if an unmapped EINT
|
||||
* was unmasked...
|
||||
*/
|
||||
BUG_ON(!virq);
|
||||
|
||||
generic_handle_irq(virq);
|
||||
} while (1);
|
||||
|
||||
chained_irq_exit(chip, desc);
|
||||
}
|
||||
|
||||
/**
|
||||
* s3c64xx_eint_gpio_init() - setup handling of external gpio interrupts.
|
||||
* @d: driver data of samsung pinctrl driver.
|
||||
*/
|
||||
static int s3c64xx_eint_gpio_init(struct samsung_pinctrl_drv_data *d)
|
||||
{
|
||||
struct s3c64xx_eint_gpio_data *data;
|
||||
struct samsung_pin_bank *bank;
|
||||
struct device *dev = d->dev;
|
||||
unsigned int nr_domains;
|
||||
unsigned int i;
|
||||
|
||||
if (!d->irq) {
|
||||
dev_err(dev, "irq number not available\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
nr_domains = 0;
|
||||
bank = d->ctrl->pin_banks;
|
||||
for (i = 0; i < d->ctrl->nr_banks; ++i, ++bank) {
|
||||
unsigned int nr_eints;
|
||||
unsigned int mask;
|
||||
|
||||
if (bank->eint_type != EINT_TYPE_GPIO)
|
||||
continue;
|
||||
|
||||
mask = bank->eint_mask;
|
||||
nr_eints = fls(mask);
|
||||
|
||||
bank->irq_domain = irq_domain_add_linear(bank->of_node,
|
||||
nr_eints, &s3c64xx_gpio_irqd_ops, bank);
|
||||
if (!bank->irq_domain) {
|
||||
dev_err(dev, "gpio irq domain add failed\n");
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
++nr_domains;
|
||||
}
|
||||
|
||||
data = devm_kzalloc(dev, sizeof(*data)
|
||||
+ nr_domains * sizeof(*data->domains), GFP_KERNEL);
|
||||
if (!data) {
|
||||
dev_err(dev, "failed to allocate handler data\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
data->drvdata = d;
|
||||
|
||||
bank = d->ctrl->pin_banks;
|
||||
nr_domains = 0;
|
||||
for (i = 0; i < d->ctrl->nr_banks; ++i, ++bank) {
|
||||
if (bank->eint_type != EINT_TYPE_GPIO)
|
||||
continue;
|
||||
|
||||
data->domains[nr_domains++] = bank->irq_domain;
|
||||
}
|
||||
|
||||
irq_set_chained_handler(d->irq, s3c64xx_eint_gpio_irq);
|
||||
irq_set_handler_data(d->irq, data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Functions for configuration of EINT0 wake-up interrupts
|
||||
*/
|
||||
|
||||
static inline void s3c64xx_eint0_irq_set_mask(struct irq_data *irqd, bool mask)
|
||||
{
|
||||
struct s3c64xx_eint0_domain_data *ddata =
|
||||
irq_data_get_irq_chip_data(irqd);
|
||||
struct samsung_pinctrl_drv_data *d = ddata->bank->drvdata;
|
||||
u32 val;
|
||||
|
||||
val = readl(d->virt_base + EINT0MASK_REG);
|
||||
if (mask)
|
||||
val |= 1 << ddata->eints[irqd->hwirq];
|
||||
else
|
||||
val &= ~(1 << ddata->eints[irqd->hwirq]);
|
||||
writel(val, d->virt_base + EINT0MASK_REG);
|
||||
}
|
||||
|
||||
static void s3c64xx_eint0_irq_unmask(struct irq_data *irqd)
|
||||
{
|
||||
s3c64xx_eint0_irq_set_mask(irqd, false);
|
||||
}
|
||||
|
||||
static void s3c64xx_eint0_irq_mask(struct irq_data *irqd)
|
||||
{
|
||||
s3c64xx_eint0_irq_set_mask(irqd, true);
|
||||
}
|
||||
|
||||
static void s3c64xx_eint0_irq_ack(struct irq_data *irqd)
|
||||
{
|
||||
struct s3c64xx_eint0_domain_data *ddata =
|
||||
irq_data_get_irq_chip_data(irqd);
|
||||
struct samsung_pinctrl_drv_data *d = ddata->bank->drvdata;
|
||||
|
||||
writel(1 << ddata->eints[irqd->hwirq],
|
||||
d->virt_base + EINT0PEND_REG);
|
||||
}
|
||||
|
||||
static int s3c64xx_eint0_irq_set_type(struct irq_data *irqd, unsigned int type)
|
||||
{
|
||||
struct s3c64xx_eint0_domain_data *ddata =
|
||||
irq_data_get_irq_chip_data(irqd);
|
||||
struct samsung_pin_bank *bank = ddata->bank;
|
||||
struct samsung_pinctrl_drv_data *d = bank->drvdata;
|
||||
void __iomem *reg;
|
||||
int trigger;
|
||||
u8 shift;
|
||||
u32 val;
|
||||
|
||||
trigger = s3c64xx_irq_get_trigger(type);
|
||||
if (trigger < 0) {
|
||||
pr_err("unsupported external interrupt type\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
s3c64xx_irq_set_handler(irqd->irq, type);
|
||||
|
||||
/* Set up interrupt trigger */
|
||||
reg = d->virt_base + EINT0CON0_REG;
|
||||
shift = ddata->eints[irqd->hwirq];
|
||||
if (shift >= EINT_MAX_PER_REG) {
|
||||
reg += 4;
|
||||
shift -= EINT_MAX_PER_REG;
|
||||
}
|
||||
shift = EINT_CON_LEN * (shift / 2);
|
||||
|
||||
val = readl(reg);
|
||||
val &= ~(EINT_CON_MASK << shift);
|
||||
val |= trigger << shift;
|
||||
writel(val, reg);
|
||||
|
||||
s3c64xx_irq_set_function(d, bank, irqd->hwirq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* irq_chip for wakeup interrupts
|
||||
*/
|
||||
static struct irq_chip s3c64xx_eint0_irq_chip = {
|
||||
.name = "EINT0",
|
||||
.irq_unmask = s3c64xx_eint0_irq_unmask,
|
||||
.irq_mask = s3c64xx_eint0_irq_mask,
|
||||
.irq_ack = s3c64xx_eint0_irq_ack,
|
||||
.irq_set_type = s3c64xx_eint0_irq_set_type,
|
||||
};
|
||||
|
||||
static inline void s3c64xx_irq_demux_eint(unsigned int irq,
|
||||
struct irq_desc *desc, u32 range)
|
||||
{
|
||||
struct irq_chip *chip = irq_get_chip(irq);
|
||||
struct s3c64xx_eint0_data *data = irq_get_handler_data(irq);
|
||||
struct samsung_pinctrl_drv_data *drvdata = data->drvdata;
|
||||
unsigned int pend, mask;
|
||||
|
||||
chained_irq_enter(chip, desc);
|
||||
|
||||
pend = readl(drvdata->virt_base + EINT0PEND_REG);
|
||||
mask = readl(drvdata->virt_base + EINT0MASK_REG);
|
||||
|
||||
pend = pend & range & ~mask;
|
||||
pend &= range;
|
||||
|
||||
while (pend) {
|
||||
unsigned int virq;
|
||||
|
||||
irq = fls(pend) - 1;
|
||||
pend &= ~(1 << irq);
|
||||
|
||||
virq = irq_linear_revmap(data->domains[irq], data->pins[irq]);
|
||||
/*
|
||||
* Something must be really wrong if an unmapped EINT
|
||||
* was unmasked...
|
||||
*/
|
||||
BUG_ON(!virq);
|
||||
|
||||
generic_handle_irq(virq);
|
||||
}
|
||||
|
||||
chained_irq_exit(chip, desc);
|
||||
}
|
||||
|
||||
static void s3c64xx_demux_eint0_3(unsigned int irq, struct irq_desc *desc)
|
||||
{
|
||||
s3c64xx_irq_demux_eint(irq, desc, 0xf);
|
||||
}
|
||||
|
||||
static void s3c64xx_demux_eint4_11(unsigned int irq, struct irq_desc *desc)
|
||||
{
|
||||
s3c64xx_irq_demux_eint(irq, desc, 0xff0);
|
||||
}
|
||||
|
||||
static void s3c64xx_demux_eint12_19(unsigned int irq, struct irq_desc *desc)
|
||||
{
|
||||
s3c64xx_irq_demux_eint(irq, desc, 0xff000);
|
||||
}
|
||||
|
||||
static void s3c64xx_demux_eint20_27(unsigned int irq, struct irq_desc *desc)
|
||||
{
|
||||
s3c64xx_irq_demux_eint(irq, desc, 0xff00000);
|
||||
}
|
||||
|
||||
static irq_flow_handler_t s3c64xx_eint0_handlers[NUM_EINT0_IRQ] = {
|
||||
s3c64xx_demux_eint0_3,
|
||||
s3c64xx_demux_eint4_11,
|
||||
s3c64xx_demux_eint12_19,
|
||||
s3c64xx_demux_eint20_27,
|
||||
};
|
||||
|
||||
static int s3c64xx_eint0_irq_map(struct irq_domain *h, unsigned int virq,
|
||||
irq_hw_number_t hw)
|
||||
{
|
||||
struct s3c64xx_eint0_domain_data *ddata = h->host_data;
|
||||
struct samsung_pin_bank *bank = ddata->bank;
|
||||
|
||||
if (!(bank->eint_mask & (1 << hw)))
|
||||
return -EINVAL;
|
||||
|
||||
irq_set_chip_and_handler(virq,
|
||||
&s3c64xx_eint0_irq_chip, handle_level_irq);
|
||||
irq_set_chip_data(virq, ddata);
|
||||
set_irq_flags(virq, IRQF_VALID);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* irq domain callbacks for external wakeup interrupt controller.
|
||||
*/
|
||||
static const struct irq_domain_ops s3c64xx_eint0_irqd_ops = {
|
||||
.map = s3c64xx_eint0_irq_map,
|
||||
.xlate = irq_domain_xlate_twocell,
|
||||
};
|
||||
|
||||
/* list of external wakeup controllers supported */
|
||||
static const struct of_device_id s3c64xx_eint0_irq_ids[] = {
|
||||
{ .compatible = "samsung,s3c64xx-wakeup-eint", },
|
||||
{ }
|
||||
};
|
||||
|
||||
/**
|
||||
* s3c64xx_eint_eint0_init() - setup handling of external wakeup interrupts.
|
||||
* @d: driver data of samsung pinctrl driver.
|
||||
*/
|
||||
static int s3c64xx_eint_eint0_init(struct samsung_pinctrl_drv_data *d)
|
||||
{
|
||||
struct device *dev = d->dev;
|
||||
struct device_node *eint0_np = NULL;
|
||||
struct device_node *np;
|
||||
struct samsung_pin_bank *bank;
|
||||
struct s3c64xx_eint0_data *data;
|
||||
unsigned int i;
|
||||
|
||||
for_each_child_of_node(dev->of_node, np) {
|
||||
if (of_match_node(s3c64xx_eint0_irq_ids, np)) {
|
||||
eint0_np = np;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!eint0_np)
|
||||
return -ENODEV;
|
||||
|
||||
data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
|
||||
if (!data) {
|
||||
dev_err(dev, "could not allocate memory for wkup eint data\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
data->drvdata = d;
|
||||
|
||||
for (i = 0; i < NUM_EINT0_IRQ; ++i) {
|
||||
unsigned int irq;
|
||||
|
||||
irq = irq_of_parse_and_map(eint0_np, i);
|
||||
if (!irq) {
|
||||
dev_err(dev, "failed to get wakeup EINT IRQ %d\n", i);
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
irq_set_chained_handler(irq, s3c64xx_eint0_handlers[i]);
|
||||
irq_set_handler_data(irq, data);
|
||||
}
|
||||
|
||||
bank = d->ctrl->pin_banks;
|
||||
for (i = 0; i < d->ctrl->nr_banks; ++i, ++bank) {
|
||||
struct s3c64xx_eint0_domain_data *ddata;
|
||||
unsigned int nr_eints;
|
||||
unsigned int mask;
|
||||
unsigned int irq;
|
||||
unsigned int pin;
|
||||
|
||||
if (bank->eint_type != EINT_TYPE_WKUP)
|
||||
continue;
|
||||
|
||||
mask = bank->eint_mask;
|
||||
nr_eints = fls(mask);
|
||||
|
||||
ddata = devm_kzalloc(dev,
|
||||
sizeof(*ddata) + nr_eints, GFP_KERNEL);
|
||||
if (!ddata) {
|
||||
dev_err(dev, "failed to allocate domain data\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
ddata->bank = bank;
|
||||
|
||||
bank->irq_domain = irq_domain_add_linear(bank->of_node,
|
||||
nr_eints, &s3c64xx_eint0_irqd_ops, ddata);
|
||||
if (!bank->irq_domain) {
|
||||
dev_err(dev, "wkup irq domain add failed\n");
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
irq = bank->eint_offset;
|
||||
mask = bank->eint_mask;
|
||||
for (pin = 0; mask; ++pin, mask >>= 1) {
|
||||
if (!(mask & 1))
|
||||
continue;
|
||||
data->domains[irq] = bank->irq_domain;
|
||||
data->pins[irq] = pin;
|
||||
ddata->eints[pin] = irq;
|
||||
++irq;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* pin banks of s3c64xx pin-controller 0 */
|
||||
static struct samsung_pin_bank s3c64xx_pin_banks0[] = {
|
||||
PIN_BANK_4BIT_EINTG(8, 0x000, "gpa", 0),
|
||||
PIN_BANK_4BIT_EINTG(7, 0x020, "gpb", 8),
|
||||
PIN_BANK_4BIT_EINTG(8, 0x040, "gpc", 16),
|
||||
PIN_BANK_4BIT_EINTG(5, 0x060, "gpd", 32),
|
||||
PIN_BANK_4BIT(5, 0x080, "gpe"),
|
||||
PIN_BANK_2BIT_EINTG(16, 0x0a0, "gpf", 48, 0x3fff),
|
||||
PIN_BANK_4BIT_EINTG(7, 0x0c0, "gpg", 64),
|
||||
PIN_BANK_4BIT2_EINTG(10, 0x0e0, "gph", 80),
|
||||
PIN_BANK_2BIT(16, 0x100, "gpi"),
|
||||
PIN_BANK_2BIT(12, 0x120, "gpj"),
|
||||
PIN_BANK_4BIT2_ALIVE(16, 0x800, "gpk"),
|
||||
PIN_BANK_4BIT2_EINTW(15, 0x810, "gpl", 16, 0x7f00),
|
||||
PIN_BANK_4BIT_EINTW(6, 0x820, "gpm", 23, 0x1f),
|
||||
PIN_BANK_2BIT_EINTW(16, 0x830, "gpn", 0),
|
||||
PIN_BANK_2BIT_EINTG(16, 0x140, "gpo", 96, 0xffff),
|
||||
PIN_BANK_2BIT_EINTG(15, 0x160, "gpp", 112, 0x7fff),
|
||||
PIN_BANK_2BIT_EINTG(9, 0x180, "gpq", 128, 0x1ff),
|
||||
};
|
||||
|
||||
/*
|
||||
* Samsung pinctrl driver data for S3C64xx SoC. S3C64xx SoC includes
|
||||
* one gpio/pin-mux/pinconfig controller.
|
||||
*/
|
||||
struct samsung_pin_ctrl s3c64xx_pin_ctrl[] = {
|
||||
{
|
||||
/* pin-controller instance 1 data */
|
||||
.pin_banks = s3c64xx_pin_banks0,
|
||||
.nr_banks = ARRAY_SIZE(s3c64xx_pin_banks0),
|
||||
.eint_gpio_init = s3c64xx_eint_gpio_init,
|
||||
.eint_wkup_init = s3c64xx_eint_eint0_init,
|
||||
.label = "S3C64xx-GPIO",
|
||||
},
|
||||
};
|
@ -27,6 +27,7 @@
|
||||
#include <linux/err.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/irqdomain.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
#include "core.h"
|
||||
#include "pinctrl-samsung.h"
|
||||
@ -214,7 +215,7 @@ static void samsung_dt_free_map(struct pinctrl_dev *pctldev,
|
||||
}
|
||||
|
||||
/* list of pinctrl callbacks for the pinctrl core */
|
||||
static struct pinctrl_ops samsung_pctrl_ops = {
|
||||
static const struct pinctrl_ops samsung_pctrl_ops = {
|
||||
.get_groups_count = samsung_get_group_count,
|
||||
.get_group_name = samsung_get_group_name,
|
||||
.get_group_pins = samsung_get_group_pins,
|
||||
@ -274,10 +275,6 @@ static void pin_to_reg_bank(struct samsung_pinctrl_drv_data *drvdata,
|
||||
*offset = pin - b->pin_base;
|
||||
if (bank)
|
||||
*bank = b;
|
||||
|
||||
/* some banks have two config registers in a single bank */
|
||||
if (*offset * b->func_width > BITS_PER_LONG)
|
||||
*reg += 4;
|
||||
}
|
||||
|
||||
/* enable or disable a pinmux function */
|
||||
@ -289,6 +286,7 @@ static void samsung_pinmux_setup(struct pinctrl_dev *pctldev, unsigned selector,
|
||||
struct samsung_pin_bank *bank;
|
||||
void __iomem *reg;
|
||||
u32 mask, shift, data, pin_offset, cnt;
|
||||
unsigned long flags;
|
||||
|
||||
drvdata = pinctrl_dev_get_drvdata(pctldev);
|
||||
pins = drvdata->pin_groups[group].pins;
|
||||
@ -298,16 +296,28 @@ static void samsung_pinmux_setup(struct pinctrl_dev *pctldev, unsigned selector,
|
||||
* pin function number in the config register.
|
||||
*/
|
||||
for (cnt = 0; cnt < drvdata->pin_groups[group].num_pins; cnt++) {
|
||||
struct samsung_pin_bank_type *type;
|
||||
|
||||
pin_to_reg_bank(drvdata, pins[cnt] - drvdata->ctrl->base,
|
||||
®, &pin_offset, &bank);
|
||||
mask = (1 << bank->func_width) - 1;
|
||||
shift = pin_offset * bank->func_width;
|
||||
type = bank->type;
|
||||
mask = (1 << type->fld_width[PINCFG_TYPE_FUNC]) - 1;
|
||||
shift = pin_offset * type->fld_width[PINCFG_TYPE_FUNC];
|
||||
if (shift >= 32) {
|
||||
/* Some banks have two config registers */
|
||||
shift -= 32;
|
||||
reg += 4;
|
||||
}
|
||||
|
||||
data = readl(reg);
|
||||
spin_lock_irqsave(&bank->slock, flags);
|
||||
|
||||
data = readl(reg + type->reg_offset[PINCFG_TYPE_FUNC]);
|
||||
data &= ~(mask << shift);
|
||||
if (enable)
|
||||
data |= drvdata->pin_groups[group].func << shift;
|
||||
writel(data, reg);
|
||||
writel(data, reg + type->reg_offset[PINCFG_TYPE_FUNC]);
|
||||
|
||||
spin_unlock_irqrestore(&bank->slock, flags);
|
||||
}
|
||||
}
|
||||
|
||||
@ -334,30 +344,44 @@ static void samsung_pinmux_disable(struct pinctrl_dev *pctldev,
|
||||
static int samsung_pinmux_gpio_set_direction(struct pinctrl_dev *pctldev,
|
||||
struct pinctrl_gpio_range *range, unsigned offset, bool input)
|
||||
{
|
||||
struct samsung_pin_bank_type *type;
|
||||
struct samsung_pin_bank *bank;
|
||||
struct samsung_pinctrl_drv_data *drvdata;
|
||||
void __iomem *reg;
|
||||
u32 data, pin_offset, mask, shift;
|
||||
unsigned long flags;
|
||||
|
||||
bank = gc_to_pin_bank(range->gc);
|
||||
type = bank->type;
|
||||
drvdata = pinctrl_dev_get_drvdata(pctldev);
|
||||
|
||||
pin_offset = offset - bank->pin_base;
|
||||
reg = drvdata->virt_base + bank->pctl_offset;
|
||||
reg = drvdata->virt_base + bank->pctl_offset +
|
||||
type->reg_offset[PINCFG_TYPE_FUNC];
|
||||
|
||||
mask = (1 << bank->func_width) - 1;
|
||||
shift = pin_offset * bank->func_width;
|
||||
mask = (1 << type->fld_width[PINCFG_TYPE_FUNC]) - 1;
|
||||
shift = pin_offset * type->fld_width[PINCFG_TYPE_FUNC];
|
||||
if (shift >= 32) {
|
||||
/* Some banks have two config registers */
|
||||
shift -= 32;
|
||||
reg += 4;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&bank->slock, flags);
|
||||
|
||||
data = readl(reg);
|
||||
data &= ~(mask << shift);
|
||||
if (!input)
|
||||
data |= FUNC_OUTPUT << shift;
|
||||
writel(data, reg);
|
||||
|
||||
spin_unlock_irqrestore(&bank->slock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* list of pinmux callbacks for the pinmux vertical in pinctrl core */
|
||||
static struct pinmux_ops samsung_pinmux_ops = {
|
||||
static const struct pinmux_ops samsung_pinmux_ops = {
|
||||
.get_functions_count = samsung_get_functions_count,
|
||||
.get_function_name = samsung_pinmux_get_fname,
|
||||
.get_function_groups = samsung_pinmux_get_groups,
|
||||
@ -371,40 +395,26 @@ static int samsung_pinconf_rw(struct pinctrl_dev *pctldev, unsigned int pin,
|
||||
unsigned long *config, bool set)
|
||||
{
|
||||
struct samsung_pinctrl_drv_data *drvdata;
|
||||
struct samsung_pin_bank_type *type;
|
||||
struct samsung_pin_bank *bank;
|
||||
void __iomem *reg_base;
|
||||
enum pincfg_type cfg_type = PINCFG_UNPACK_TYPE(*config);
|
||||
u32 data, width, pin_offset, mask, shift;
|
||||
u32 cfg_value, cfg_reg;
|
||||
unsigned long flags;
|
||||
|
||||
drvdata = pinctrl_dev_get_drvdata(pctldev);
|
||||
pin_to_reg_bank(drvdata, pin - drvdata->ctrl->base, ®_base,
|
||||
&pin_offset, &bank);
|
||||
type = bank->type;
|
||||
|
||||
switch (cfg_type) {
|
||||
case PINCFG_TYPE_PUD:
|
||||
width = bank->pud_width;
|
||||
cfg_reg = PUD_REG;
|
||||
break;
|
||||
case PINCFG_TYPE_DRV:
|
||||
width = bank->drv_width;
|
||||
cfg_reg = DRV_REG;
|
||||
break;
|
||||
case PINCFG_TYPE_CON_PDN:
|
||||
width = bank->conpdn_width;
|
||||
cfg_reg = CONPDN_REG;
|
||||
break;
|
||||
case PINCFG_TYPE_PUD_PDN:
|
||||
width = bank->pudpdn_width;
|
||||
cfg_reg = PUDPDN_REG;
|
||||
break;
|
||||
default:
|
||||
WARN_ON(1);
|
||||
if (cfg_type >= PINCFG_TYPE_NUM || !type->fld_width[cfg_type])
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!width)
|
||||
return -EINVAL;
|
||||
width = type->fld_width[cfg_type];
|
||||
cfg_reg = type->reg_offset[cfg_type];
|
||||
|
||||
spin_lock_irqsave(&bank->slock, flags);
|
||||
|
||||
mask = (1 << width) - 1;
|
||||
shift = pin_offset * width;
|
||||
@ -420,6 +430,9 @@ static int samsung_pinconf_rw(struct pinctrl_dev *pctldev, unsigned int pin,
|
||||
data &= mask;
|
||||
*config = PINCFG_PACK(cfg_type, data);
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&bank->slock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -468,7 +481,7 @@ static int samsung_pinconf_group_get(struct pinctrl_dev *pctldev,
|
||||
}
|
||||
|
||||
/* list of pinconfig callbacks for pinconfig vertical in the pinctrl code */
|
||||
static struct pinconf_ops samsung_pinconf_ops = {
|
||||
static const struct pinconf_ops samsung_pinconf_ops = {
|
||||
.pin_config_get = samsung_pinconf_get,
|
||||
.pin_config_set = samsung_pinconf_set,
|
||||
.pin_config_group_get = samsung_pinconf_group_get,
|
||||
@ -479,16 +492,22 @@ static struct pinconf_ops samsung_pinconf_ops = {
|
||||
static void samsung_gpio_set(struct gpio_chip *gc, unsigned offset, int value)
|
||||
{
|
||||
struct samsung_pin_bank *bank = gc_to_pin_bank(gc);
|
||||
struct samsung_pin_bank_type *type = bank->type;
|
||||
unsigned long flags;
|
||||
void __iomem *reg;
|
||||
u32 data;
|
||||
|
||||
reg = bank->drvdata->virt_base + bank->pctl_offset;
|
||||
|
||||
data = readl(reg + DAT_REG);
|
||||
spin_lock_irqsave(&bank->slock, flags);
|
||||
|
||||
data = readl(reg + type->reg_offset[PINCFG_TYPE_DAT]);
|
||||
data &= ~(1 << offset);
|
||||
if (value)
|
||||
data |= 1 << offset;
|
||||
writel(data, reg + DAT_REG);
|
||||
writel(data, reg + type->reg_offset[PINCFG_TYPE_DAT]);
|
||||
|
||||
spin_unlock_irqrestore(&bank->slock, flags);
|
||||
}
|
||||
|
||||
/* gpiolib gpio_get callback function */
|
||||
@ -497,10 +516,11 @@ static int samsung_gpio_get(struct gpio_chip *gc, unsigned offset)
|
||||
void __iomem *reg;
|
||||
u32 data;
|
||||
struct samsung_pin_bank *bank = gc_to_pin_bank(gc);
|
||||
struct samsung_pin_bank_type *type = bank->type;
|
||||
|
||||
reg = bank->drvdata->virt_base + bank->pctl_offset;
|
||||
|
||||
data = readl(reg + DAT_REG);
|
||||
data = readl(reg + type->reg_offset[PINCFG_TYPE_DAT]);
|
||||
data >>= offset;
|
||||
data &= 1;
|
||||
return data;
|
||||
@ -859,6 +879,7 @@ static struct samsung_pin_ctrl *samsung_pinctrl_get_soc_data(
|
||||
|
||||
bank = ctrl->pin_banks;
|
||||
for (i = 0; i < ctrl->nr_banks; ++i, ++bank) {
|
||||
spin_lock_init(&bank->slock);
|
||||
bank->drvdata = d;
|
||||
bank->pin_base = ctrl->nr_pins;
|
||||
ctrl->nr_pins += bank->nr_pins;
|
||||
@ -944,10 +965,16 @@ static int samsung_pinctrl_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
static const struct of_device_id samsung_pinctrl_dt_match[] = {
|
||||
#ifdef CONFIG_PINCTRL_EXYNOS
|
||||
{ .compatible = "samsung,exynos4210-pinctrl",
|
||||
.data = (void *)exynos4210_pin_ctrl },
|
||||
{ .compatible = "samsung,exynos4x12-pinctrl",
|
||||
.data = (void *)exynos4x12_pin_ctrl },
|
||||
#endif
|
||||
#ifdef CONFIG_PINCTRL_S3C64XX
|
||||
{ .compatible = "samsung,s3c64xx-pinctrl",
|
||||
.data = s3c64xx_pin_ctrl },
|
||||
#endif
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, samsung_pinctrl_dt_match);
|
||||
|
@ -25,28 +25,27 @@
|
||||
|
||||
#include <linux/gpio.h>
|
||||
|
||||
/* register offsets within a pin bank */
|
||||
#define DAT_REG 0x4
|
||||
#define PUD_REG 0x8
|
||||
#define DRV_REG 0xC
|
||||
#define CONPDN_REG 0x10
|
||||
#define PUDPDN_REG 0x14
|
||||
|
||||
/* pinmux function number for pin as gpio output line */
|
||||
#define FUNC_OUTPUT 0x1
|
||||
|
||||
/**
|
||||
* enum pincfg_type - possible pin configuration types supported.
|
||||
* @PINCFG_TYPE_FUNC: Function configuration.
|
||||
* @PINCFG_TYPE_DAT: Pin value configuration.
|
||||
* @PINCFG_TYPE_PUD: Pull up/down configuration.
|
||||
* @PINCFG_TYPE_DRV: Drive strength configuration.
|
||||
* @PINCFG_TYPE_CON_PDN: Pin function in power down mode.
|
||||
* @PINCFG_TYPE_PUD_PDN: Pull up/down configuration in power down mode.
|
||||
*/
|
||||
enum pincfg_type {
|
||||
PINCFG_TYPE_FUNC,
|
||||
PINCFG_TYPE_DAT,
|
||||
PINCFG_TYPE_PUD,
|
||||
PINCFG_TYPE_DRV,
|
||||
PINCFG_TYPE_CON_PDN,
|
||||
PINCFG_TYPE_PUD_PDN,
|
||||
|
||||
PINCFG_TYPE_NUM
|
||||
};
|
||||
|
||||
/*
|
||||
@ -102,34 +101,41 @@ enum eint_type {
|
||||
|
||||
struct samsung_pinctrl_drv_data;
|
||||
|
||||
/**
|
||||
* struct samsung_pin_bank_type: pin bank type description
|
||||
* @fld_width: widths of configuration bitfields (0 if unavailable)
|
||||
* @reg_offset: offsets of configuration registers (don't care of width is 0)
|
||||
*/
|
||||
struct samsung_pin_bank_type {
|
||||
u8 fld_width[PINCFG_TYPE_NUM];
|
||||
u8 reg_offset[PINCFG_TYPE_NUM];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct samsung_pin_bank: represent a controller pin-bank.
|
||||
* @type: type of the bank (register offsets and bitfield widths)
|
||||
* @pctl_offset: starting offset of the pin-bank registers.
|
||||
* @pin_base: starting pin number of the bank.
|
||||
* @nr_pins: number of pins included in this bank.
|
||||
* @func_width: width of the function selector bit field.
|
||||
* @pud_width: width of the pin pull up/down selector bit field.
|
||||
* @drv_width: width of the pin driver strength selector bit field.
|
||||
* @conpdn_width: width of the sleep mode function selector bin field.
|
||||
* @pudpdn_width: width of the sleep mode pull up/down selector bit field.
|
||||
* @eint_func: function to set in CON register to configure pin as EINT.
|
||||
* @eint_type: type of the external interrupt supported by the bank.
|
||||
* @eint_mask: bit mask of pins which support EINT function.
|
||||
* @name: name to be prefixed for each pin in this pin bank.
|
||||
* @of_node: OF node of the bank.
|
||||
* @drvdata: link to controller driver data
|
||||
* @irq_domain: IRQ domain of the bank.
|
||||
* @gpio_chip: GPIO chip of the bank.
|
||||
* @grange: linux gpio pin range supported by this bank.
|
||||
* @slock: spinlock protecting bank registers
|
||||
*/
|
||||
struct samsung_pin_bank {
|
||||
struct samsung_pin_bank_type *type;
|
||||
u32 pctl_offset;
|
||||
u32 pin_base;
|
||||
u8 nr_pins;
|
||||
u8 func_width;
|
||||
u8 pud_width;
|
||||
u8 drv_width;
|
||||
u8 conpdn_width;
|
||||
u8 pudpdn_width;
|
||||
u8 eint_func;
|
||||
enum eint_type eint_type;
|
||||
u32 eint_mask;
|
||||
u32 eint_offset;
|
||||
char *name;
|
||||
struct device_node *of_node;
|
||||
@ -137,6 +143,7 @@ struct samsung_pin_bank {
|
||||
struct irq_domain *irq_domain;
|
||||
struct gpio_chip gpio_chip;
|
||||
struct pinctrl_gpio_range grange;
|
||||
spinlock_t slock;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -237,5 +244,6 @@ struct samsung_pmx_func {
|
||||
/* list of all exported SoC specific data */
|
||||
extern struct samsung_pin_ctrl exynos4210_pin_ctrl[];
|
||||
extern struct samsung_pin_ctrl exynos4x12_pin_ctrl[];
|
||||
extern struct samsung_pin_ctrl s3c64xx_pin_ctrl[];
|
||||
|
||||
#endif /* __PINCTRL_SAMSUNG_H */
|
||||
|
@ -22,8 +22,10 @@
|
||||
|
||||
#include <linux/pinctrl/pinctrl.h>
|
||||
#include <linux/pinctrl/pinmux.h>
|
||||
#include <linux/pinctrl/pinconf-generic.h>
|
||||
|
||||
#include "core.h"
|
||||
#include "pinconf.h"
|
||||
|
||||
#define DRIVER_NAME "pinctrl-single"
|
||||
#define PCS_MUX_PINS_NAME "pinctrl-single,pins"
|
||||
@ -58,6 +60,33 @@ struct pcs_func_vals {
|
||||
unsigned mask;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct pcs_conf_vals - pinconf parameter, pinconf register offset
|
||||
* and value, enable, disable, mask
|
||||
* @param: config parameter
|
||||
* @val: user input bits in the pinconf register
|
||||
* @enable: enable bits in the pinconf register
|
||||
* @disable: disable bits in the pinconf register
|
||||
* @mask: mask bits in the register value
|
||||
*/
|
||||
struct pcs_conf_vals {
|
||||
enum pin_config_param param;
|
||||
unsigned val;
|
||||
unsigned enable;
|
||||
unsigned disable;
|
||||
unsigned mask;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct pcs_conf_type - pinconf property name, pinconf param pair
|
||||
* @name: property name in DTS file
|
||||
* @param: config parameter
|
||||
*/
|
||||
struct pcs_conf_type {
|
||||
const char *name;
|
||||
enum pin_config_param param;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct pcs_function - pinctrl function
|
||||
* @name: pinctrl function name
|
||||
@ -73,6 +102,22 @@ struct pcs_function {
|
||||
unsigned nvals;
|
||||
const char **pgnames;
|
||||
int npgnames;
|
||||
struct pcs_conf_vals *conf;
|
||||
int nconfs;
|
||||
struct list_head node;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct pcs_gpiofunc_range - pin ranges with same mux value of gpio function
|
||||
* @offset: offset base of pins
|
||||
* @npins: number pins with the same mux value of gpio function
|
||||
* @gpiofunc: mux value of gpio function
|
||||
* @node: list node
|
||||
*/
|
||||
struct pcs_gpiofunc_range {
|
||||
unsigned offset;
|
||||
unsigned npins;
|
||||
unsigned gpiofunc;
|
||||
struct list_head node;
|
||||
};
|
||||
|
||||
@ -117,12 +162,14 @@ struct pcs_name {
|
||||
* @fshift: function register shift
|
||||
* @foff: value to turn mux off
|
||||
* @fmax: max number of functions in fmask
|
||||
* @is_pinconf: whether supports pinconf
|
||||
* @names: array of register names for pins
|
||||
* @pins: physical pins on the SoC
|
||||
* @pgtree: pingroup index radix tree
|
||||
* @ftree: function index radix tree
|
||||
* @pingroups: list of pingroups
|
||||
* @functions: list of functions
|
||||
* @gpiofuncs: list of gpio functions
|
||||
* @ngroups: number of pingroups
|
||||
* @nfuncs: number of functions
|
||||
* @desc: pin controller descriptor
|
||||
@ -142,12 +189,14 @@ struct pcs_device {
|
||||
unsigned foff;
|
||||
unsigned fmax;
|
||||
bool bits_per_mux;
|
||||
bool is_pinconf;
|
||||
struct pcs_name *names;
|
||||
struct pcs_data pins;
|
||||
struct radix_tree_root pgtree;
|
||||
struct radix_tree_root ftree;
|
||||
struct list_head pingroups;
|
||||
struct list_head functions;
|
||||
struct list_head gpiofuncs;
|
||||
unsigned ngroups;
|
||||
unsigned nfuncs;
|
||||
struct pinctrl_desc desc;
|
||||
@ -155,6 +204,16 @@ struct pcs_device {
|
||||
void (*write)(unsigned val, void __iomem *reg);
|
||||
};
|
||||
|
||||
static int pcs_pinconf_get(struct pinctrl_dev *pctldev, unsigned pin,
|
||||
unsigned long *config);
|
||||
static int pcs_pinconf_set(struct pinctrl_dev *pctldev, unsigned pin,
|
||||
unsigned long config);
|
||||
|
||||
static enum pin_config_param pcs_bias[] = {
|
||||
PIN_CONFIG_BIAS_PULL_DOWN,
|
||||
PIN_CONFIG_BIAS_PULL_UP,
|
||||
};
|
||||
|
||||
/*
|
||||
* REVISIT: Reads and writes could eventually use regmap or something
|
||||
* generic. But at least on omaps, some mux registers are performance
|
||||
@ -270,7 +329,7 @@ static int pcs_dt_node_to_map(struct pinctrl_dev *pctldev,
|
||||
struct device_node *np_config,
|
||||
struct pinctrl_map **map, unsigned *num_maps);
|
||||
|
||||
static struct pinctrl_ops pcs_pinctrl_ops = {
|
||||
static const struct pinctrl_ops pcs_pinctrl_ops = {
|
||||
.get_groups_count = pcs_get_groups_count,
|
||||
.get_group_name = pcs_get_group_name,
|
||||
.get_group_pins = pcs_get_group_pins,
|
||||
@ -326,6 +385,28 @@ static int pcs_get_function_groups(struct pinctrl_dev *pctldev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pcs_get_function(struct pinctrl_dev *pctldev, unsigned pin,
|
||||
struct pcs_function **func)
|
||||
{
|
||||
struct pcs_device *pcs = pinctrl_dev_get_drvdata(pctldev);
|
||||
struct pin_desc *pdesc = pin_desc_get(pctldev, pin);
|
||||
const struct pinctrl_setting_mux *setting;
|
||||
unsigned fselector;
|
||||
|
||||
/* If pin is not described in DTS & enabled, mux_setting is NULL. */
|
||||
setting = pdesc->mux_setting;
|
||||
if (!setting)
|
||||
return -ENOTSUPP;
|
||||
fselector = setting->func;
|
||||
*func = radix_tree_lookup(&pcs->ftree, fselector);
|
||||
if (!(*func)) {
|
||||
dev_err(pcs->dev, "%s could not find function%i\n",
|
||||
__func__, fselector);
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pcs_enable(struct pinctrl_dev *pctldev, unsigned fselector,
|
||||
unsigned group)
|
||||
{
|
||||
@ -334,6 +415,9 @@ static int pcs_enable(struct pinctrl_dev *pctldev, unsigned fselector,
|
||||
int i;
|
||||
|
||||
pcs = pinctrl_dev_get_drvdata(pctldev);
|
||||
/* If function mask is null, needn't enable it. */
|
||||
if (!pcs->fmask)
|
||||
return 0;
|
||||
func = radix_tree_lookup(&pcs->ftree, fselector);
|
||||
if (!func)
|
||||
return -EINVAL;
|
||||
@ -368,6 +452,10 @@ static void pcs_disable(struct pinctrl_dev *pctldev, unsigned fselector,
|
||||
int i;
|
||||
|
||||
pcs = pinctrl_dev_get_drvdata(pctldev);
|
||||
/* If function mask is null, needn't disable it. */
|
||||
if (!pcs->fmask)
|
||||
return;
|
||||
|
||||
func = radix_tree_lookup(&pcs->ftree, fselector);
|
||||
if (!func) {
|
||||
dev_err(pcs->dev, "%s could not find function%i\n",
|
||||
@ -403,12 +491,33 @@ static void pcs_disable(struct pinctrl_dev *pctldev, unsigned fselector,
|
||||
}
|
||||
|
||||
static int pcs_request_gpio(struct pinctrl_dev *pctldev,
|
||||
struct pinctrl_gpio_range *range, unsigned offset)
|
||||
struct pinctrl_gpio_range *range, unsigned pin)
|
||||
{
|
||||
return -ENOTSUPP;
|
||||
struct pcs_device *pcs = pinctrl_dev_get_drvdata(pctldev);
|
||||
struct pcs_gpiofunc_range *frange = NULL;
|
||||
struct list_head *pos, *tmp;
|
||||
int mux_bytes = 0;
|
||||
unsigned data;
|
||||
|
||||
/* If function mask is null, return directly. */
|
||||
if (!pcs->fmask)
|
||||
return -ENOTSUPP;
|
||||
|
||||
list_for_each_safe(pos, tmp, &pcs->gpiofuncs) {
|
||||
frange = list_entry(pos, struct pcs_gpiofunc_range, node);
|
||||
if (pin >= frange->offset + frange->npins
|
||||
|| pin < frange->offset)
|
||||
continue;
|
||||
mux_bytes = pcs->width / BITS_PER_BYTE;
|
||||
data = pcs->read(pcs->base + pin * mux_bytes) & ~pcs->fmask;
|
||||
data |= frange->gpiofunc;
|
||||
pcs->write(data, pcs->base + pin * mux_bytes);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct pinmux_ops pcs_pinmux_ops = {
|
||||
static const struct pinmux_ops pcs_pinmux_ops = {
|
||||
.get_functions_count = pcs_get_functions_count,
|
||||
.get_function_name = pcs_get_function_name,
|
||||
.get_function_groups = pcs_get_function_groups,
|
||||
@ -417,32 +526,190 @@ static struct pinmux_ops pcs_pinmux_ops = {
|
||||
.gpio_request_enable = pcs_request_gpio,
|
||||
};
|
||||
|
||||
/* Clear BIAS value */
|
||||
static void pcs_pinconf_clear_bias(struct pinctrl_dev *pctldev, unsigned pin)
|
||||
{
|
||||
unsigned long config;
|
||||
int i;
|
||||
for (i = 0; i < ARRAY_SIZE(pcs_bias); i++) {
|
||||
config = pinconf_to_config_packed(pcs_bias[i], 0);
|
||||
pcs_pinconf_set(pctldev, pin, config);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Check whether PIN_CONFIG_BIAS_DISABLE is valid.
|
||||
* It's depend on that PULL_DOWN & PULL_UP configs are all invalid.
|
||||
*/
|
||||
static bool pcs_pinconf_bias_disable(struct pinctrl_dev *pctldev, unsigned pin)
|
||||
{
|
||||
unsigned long config;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(pcs_bias); i++) {
|
||||
config = pinconf_to_config_packed(pcs_bias[i], 0);
|
||||
if (!pcs_pinconf_get(pctldev, pin, &config))
|
||||
goto out;
|
||||
}
|
||||
return true;
|
||||
out:
|
||||
return false;
|
||||
}
|
||||
|
||||
static int pcs_pinconf_get(struct pinctrl_dev *pctldev,
|
||||
unsigned pin, unsigned long *config)
|
||||
{
|
||||
struct pcs_device *pcs = pinctrl_dev_get_drvdata(pctldev);
|
||||
struct pcs_function *func;
|
||||
enum pin_config_param param;
|
||||
unsigned offset = 0, data = 0, i, j, ret;
|
||||
|
||||
ret = pcs_get_function(pctldev, pin, &func);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
for (i = 0; i < func->nconfs; i++) {
|
||||
param = pinconf_to_config_param(*config);
|
||||
if (param == PIN_CONFIG_BIAS_DISABLE) {
|
||||
if (pcs_pinconf_bias_disable(pctldev, pin)) {
|
||||
*config = 0;
|
||||
return 0;
|
||||
} else {
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
} else if (param != func->conf[i].param) {
|
||||
continue;
|
||||
}
|
||||
|
||||
offset = pin * (pcs->width / BITS_PER_BYTE);
|
||||
data = pcs->read(pcs->base + offset) & func->conf[i].mask;
|
||||
switch (func->conf[i].param) {
|
||||
/* 4 parameters */
|
||||
case PIN_CONFIG_BIAS_PULL_DOWN:
|
||||
case PIN_CONFIG_BIAS_PULL_UP:
|
||||
case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
|
||||
if ((data != func->conf[i].enable) ||
|
||||
(data == func->conf[i].disable))
|
||||
return -ENOTSUPP;
|
||||
*config = 0;
|
||||
break;
|
||||
/* 2 parameters */
|
||||
case PIN_CONFIG_INPUT_SCHMITT:
|
||||
for (j = 0; j < func->nconfs; j++) {
|
||||
switch (func->conf[j].param) {
|
||||
case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
|
||||
if (data != func->conf[j].enable)
|
||||
return -ENOTSUPP;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
*config = data;
|
||||
break;
|
||||
case PIN_CONFIG_DRIVE_STRENGTH:
|
||||
case PIN_CONFIG_SLEW_RATE:
|
||||
default:
|
||||
*config = data;
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
static int pcs_pinconf_set(struct pinctrl_dev *pctldev,
|
||||
unsigned pin, unsigned long config)
|
||||
{
|
||||
struct pcs_device *pcs = pinctrl_dev_get_drvdata(pctldev);
|
||||
struct pcs_function *func;
|
||||
unsigned offset = 0, shift = 0, i, data, ret;
|
||||
u16 arg;
|
||||
|
||||
ret = pcs_get_function(pctldev, pin, &func);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
for (i = 0; i < func->nconfs; i++) {
|
||||
if (pinconf_to_config_param(config) == func->conf[i].param) {
|
||||
offset = pin * (pcs->width / BITS_PER_BYTE);
|
||||
data = pcs->read(pcs->base + offset);
|
||||
arg = pinconf_to_config_argument(config);
|
||||
switch (func->conf[i].param) {
|
||||
/* 2 parameters */
|
||||
case PIN_CONFIG_INPUT_SCHMITT:
|
||||
case PIN_CONFIG_DRIVE_STRENGTH:
|
||||
case PIN_CONFIG_SLEW_RATE:
|
||||
shift = ffs(func->conf[i].mask) - 1;
|
||||
data &= ~func->conf[i].mask;
|
||||
data |= (arg << shift) & func->conf[i].mask;
|
||||
break;
|
||||
/* 4 parameters */
|
||||
case PIN_CONFIG_BIAS_DISABLE:
|
||||
pcs_pinconf_clear_bias(pctldev, pin);
|
||||
break;
|
||||
case PIN_CONFIG_BIAS_PULL_DOWN:
|
||||
case PIN_CONFIG_BIAS_PULL_UP:
|
||||
if (arg)
|
||||
pcs_pinconf_clear_bias(pctldev, pin);
|
||||
/* fall through */
|
||||
case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
|
||||
data &= ~func->conf[i].mask;
|
||||
if (arg)
|
||||
data |= func->conf[i].enable;
|
||||
else
|
||||
data |= func->conf[i].disable;
|
||||
break;
|
||||
default:
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
pcs->write(data, pcs->base + offset);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
static int pcs_pinconf_group_get(struct pinctrl_dev *pctldev,
|
||||
unsigned group, unsigned long *config)
|
||||
{
|
||||
return -ENOTSUPP;
|
||||
const unsigned *pins;
|
||||
unsigned npins, old = 0;
|
||||
int i, ret;
|
||||
|
||||
ret = pcs_get_group_pins(pctldev, group, &pins, &npins);
|
||||
if (ret)
|
||||
return ret;
|
||||
for (i = 0; i < npins; i++) {
|
||||
if (pcs_pinconf_get(pctldev, pins[i], config))
|
||||
return -ENOTSUPP;
|
||||
/* configs do not match between two pins */
|
||||
if (i && (old != *config))
|
||||
return -ENOTSUPP;
|
||||
old = *config;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pcs_pinconf_group_set(struct pinctrl_dev *pctldev,
|
||||
unsigned group, unsigned long config)
|
||||
{
|
||||
return -ENOTSUPP;
|
||||
const unsigned *pins;
|
||||
unsigned npins;
|
||||
int i, ret;
|
||||
|
||||
ret = pcs_get_group_pins(pctldev, group, &pins, &npins);
|
||||
if (ret)
|
||||
return ret;
|
||||
for (i = 0; i < npins; i++) {
|
||||
if (pcs_pinconf_set(pctldev, pins[i], config))
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void pcs_pinconf_dbg_show(struct pinctrl_dev *pctldev,
|
||||
struct seq_file *s, unsigned offset)
|
||||
struct seq_file *s, unsigned pin)
|
||||
{
|
||||
}
|
||||
|
||||
@ -451,13 +718,22 @@ static void pcs_pinconf_group_dbg_show(struct pinctrl_dev *pctldev,
|
||||
{
|
||||
}
|
||||
|
||||
static struct pinconf_ops pcs_pinconf_ops = {
|
||||
static void pcs_pinconf_config_dbg_show(struct pinctrl_dev *pctldev,
|
||||
struct seq_file *s,
|
||||
unsigned long config)
|
||||
{
|
||||
pinconf_generic_dump_config(pctldev, s, config);
|
||||
}
|
||||
|
||||
static const struct pinconf_ops pcs_pinconf_ops = {
|
||||
.pin_config_get = pcs_pinconf_get,
|
||||
.pin_config_set = pcs_pinconf_set,
|
||||
.pin_config_group_get = pcs_pinconf_group_get,
|
||||
.pin_config_group_set = pcs_pinconf_group_set,
|
||||
.pin_config_dbg_show = pcs_pinconf_dbg_show,
|
||||
.pin_config_group_dbg_show = pcs_pinconf_group_dbg_show,
|
||||
.pin_config_config_dbg_show = pcs_pinconf_config_dbg_show,
|
||||
.is_generic = true,
|
||||
};
|
||||
|
||||
/**
|
||||
@ -648,11 +924,158 @@ static int pcs_get_pin_by_offset(struct pcs_device *pcs, unsigned offset)
|
||||
return index;
|
||||
}
|
||||
|
||||
/*
|
||||
* check whether data matches enable bits or disable bits
|
||||
* Return value: 1 for matching enable bits, 0 for matching disable bits,
|
||||
* and negative value for matching failure.
|
||||
*/
|
||||
static int pcs_config_match(unsigned data, unsigned enable, unsigned disable)
|
||||
{
|
||||
int ret = -EINVAL;
|
||||
|
||||
if (data == enable)
|
||||
ret = 1;
|
||||
else if (data == disable)
|
||||
ret = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void add_config(struct pcs_conf_vals **conf, enum pin_config_param param,
|
||||
unsigned value, unsigned enable, unsigned disable,
|
||||
unsigned mask)
|
||||
{
|
||||
(*conf)->param = param;
|
||||
(*conf)->val = value;
|
||||
(*conf)->enable = enable;
|
||||
(*conf)->disable = disable;
|
||||
(*conf)->mask = mask;
|
||||
(*conf)++;
|
||||
}
|
||||
|
||||
static void add_setting(unsigned long **setting, enum pin_config_param param,
|
||||
unsigned arg)
|
||||
{
|
||||
**setting = pinconf_to_config_packed(param, arg);
|
||||
(*setting)++;
|
||||
}
|
||||
|
||||
/* add pinconf setting with 2 parameters */
|
||||
static void pcs_add_conf2(struct pcs_device *pcs, struct device_node *np,
|
||||
const char *name, enum pin_config_param param,
|
||||
struct pcs_conf_vals **conf, unsigned long **settings)
|
||||
{
|
||||
unsigned value[2], shift;
|
||||
int ret;
|
||||
|
||||
ret = of_property_read_u32_array(np, name, value, 2);
|
||||
if (ret)
|
||||
return;
|
||||
/* set value & mask */
|
||||
value[0] &= value[1];
|
||||
shift = ffs(value[1]) - 1;
|
||||
/* skip enable & disable */
|
||||
add_config(conf, param, value[0], 0, 0, value[1]);
|
||||
add_setting(settings, param, value[0] >> shift);
|
||||
}
|
||||
|
||||
/* add pinconf setting with 4 parameters */
|
||||
static void pcs_add_conf4(struct pcs_device *pcs, struct device_node *np,
|
||||
const char *name, enum pin_config_param param,
|
||||
struct pcs_conf_vals **conf, unsigned long **settings)
|
||||
{
|
||||
unsigned value[4];
|
||||
int ret;
|
||||
|
||||
/* value to set, enable, disable, mask */
|
||||
ret = of_property_read_u32_array(np, name, value, 4);
|
||||
if (ret)
|
||||
return;
|
||||
if (!value[3]) {
|
||||
dev_err(pcs->dev, "mask field of the property can't be 0\n");
|
||||
return;
|
||||
}
|
||||
value[0] &= value[3];
|
||||
value[1] &= value[3];
|
||||
value[2] &= value[3];
|
||||
ret = pcs_config_match(value[0], value[1], value[2]);
|
||||
if (ret < 0)
|
||||
dev_dbg(pcs->dev, "failed to match enable or disable bits\n");
|
||||
add_config(conf, param, value[0], value[1], value[2], value[3]);
|
||||
add_setting(settings, param, ret);
|
||||
}
|
||||
|
||||
static int pcs_parse_pinconf(struct pcs_device *pcs, struct device_node *np,
|
||||
struct pcs_function *func,
|
||||
struct pinctrl_map **map)
|
||||
|
||||
{
|
||||
struct pinctrl_map *m = *map;
|
||||
int i = 0, nconfs = 0;
|
||||
unsigned long *settings = NULL, *s = NULL;
|
||||
struct pcs_conf_vals *conf = NULL;
|
||||
struct pcs_conf_type prop2[] = {
|
||||
{ "pinctrl-single,drive-strength", PIN_CONFIG_DRIVE_STRENGTH, },
|
||||
{ "pinctrl-single,slew-rate", PIN_CONFIG_SLEW_RATE, },
|
||||
{ "pinctrl-single,input-schmitt", PIN_CONFIG_INPUT_SCHMITT, },
|
||||
};
|
||||
struct pcs_conf_type prop4[] = {
|
||||
{ "pinctrl-single,bias-pullup", PIN_CONFIG_BIAS_PULL_UP, },
|
||||
{ "pinctrl-single,bias-pulldown", PIN_CONFIG_BIAS_PULL_DOWN, },
|
||||
{ "pinctrl-single,input-schmitt-enable",
|
||||
PIN_CONFIG_INPUT_SCHMITT_ENABLE, },
|
||||
};
|
||||
|
||||
/* If pinconf isn't supported, don't parse properties in below. */
|
||||
if (!pcs->is_pinconf)
|
||||
return 0;
|
||||
|
||||
/* cacluate how much properties are supported in current node */
|
||||
for (i = 0; i < ARRAY_SIZE(prop2); i++) {
|
||||
if (of_find_property(np, prop2[i].name, NULL))
|
||||
nconfs++;
|
||||
}
|
||||
for (i = 0; i < ARRAY_SIZE(prop4); i++) {
|
||||
if (of_find_property(np, prop4[i].name, NULL))
|
||||
nconfs++;
|
||||
}
|
||||
if (!nconfs)
|
||||
return 0;
|
||||
|
||||
func->conf = devm_kzalloc(pcs->dev,
|
||||
sizeof(struct pcs_conf_vals) * nconfs,
|
||||
GFP_KERNEL);
|
||||
if (!func->conf)
|
||||
return -ENOMEM;
|
||||
func->nconfs = nconfs;
|
||||
conf = &(func->conf[0]);
|
||||
m++;
|
||||
settings = devm_kzalloc(pcs->dev, sizeof(unsigned long) * nconfs,
|
||||
GFP_KERNEL);
|
||||
if (!settings)
|
||||
return -ENOMEM;
|
||||
s = &settings[0];
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(prop2); i++)
|
||||
pcs_add_conf2(pcs, np, prop2[i].name, prop2[i].param,
|
||||
&conf, &s);
|
||||
for (i = 0; i < ARRAY_SIZE(prop4); i++)
|
||||
pcs_add_conf4(pcs, np, prop4[i].name, prop4[i].param,
|
||||
&conf, &s);
|
||||
m->type = PIN_MAP_TYPE_CONFIGS_GROUP;
|
||||
m->data.configs.group_or_pin = np->name;
|
||||
m->data.configs.configs = settings;
|
||||
m->data.configs.num_configs = nconfs;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void pcs_free_pingroups(struct pcs_device *pcs);
|
||||
|
||||
/**
|
||||
* smux_parse_one_pinctrl_entry() - parses a device tree mux entry
|
||||
* @pcs: pinctrl driver instance
|
||||
* @np: device node of the mux entry
|
||||
* @map: map entry
|
||||
* @num_maps: number of map
|
||||
* @pgnames: pingroup names
|
||||
*
|
||||
* Note that this binding currently supports only sets of one register + value.
|
||||
@ -669,6 +1092,7 @@ static int pcs_get_pin_by_offset(struct pcs_device *pcs, unsigned offset)
|
||||
static int pcs_parse_one_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;
|
||||
@ -741,8 +1165,18 @@ static int pcs_parse_one_pinctrl_entry(struct pcs_device *pcs,
|
||||
(*map)->data.mux.group = np->name;
|
||||
(*map)->data.mux.function = np->name;
|
||||
|
||||
if (pcs->is_pinconf) {
|
||||
if (pcs_parse_pinconf(pcs, np, function, map))
|
||||
goto free_pingroups;
|
||||
*num_maps = 2;
|
||||
} else {
|
||||
*num_maps = 1;
|
||||
}
|
||||
return 0;
|
||||
|
||||
free_pingroups:
|
||||
pcs_free_pingroups(pcs);
|
||||
*num_maps = 1;
|
||||
free_function:
|
||||
pcs_remove_function(pcs, function);
|
||||
|
||||
@ -771,7 +1205,8 @@ static int pcs_dt_node_to_map(struct pinctrl_dev *pctldev,
|
||||
|
||||
pcs = pinctrl_dev_get_drvdata(pctldev);
|
||||
|
||||
*map = devm_kzalloc(pcs->dev, sizeof(**map), GFP_KERNEL);
|
||||
/* create 2 maps. One is for pinmux, and the other is for pinconf. */
|
||||
*map = devm_kzalloc(pcs->dev, sizeof(**map) * 2, GFP_KERNEL);
|
||||
if (!*map)
|
||||
return -ENOMEM;
|
||||
|
||||
@ -783,13 +1218,13 @@ static int pcs_dt_node_to_map(struct pinctrl_dev *pctldev,
|
||||
goto free_map;
|
||||
}
|
||||
|
||||
ret = pcs_parse_one_pinctrl_entry(pcs, np_config, map, pgnames);
|
||||
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;
|
||||
}
|
||||
*num_maps = 1;
|
||||
|
||||
return 0;
|
||||
|
||||
@ -879,6 +1314,37 @@ static void pcs_free_resources(struct pcs_device *pcs)
|
||||
|
||||
static struct of_device_id pcs_of_match[];
|
||||
|
||||
static int pcs_add_gpio_func(struct device_node *node, struct pcs_device *pcs)
|
||||
{
|
||||
const char *propname = "pinctrl-single,gpio-range";
|
||||
const char *cellname = "#pinctrl-single,gpio-range-cells";
|
||||
struct of_phandle_args gpiospec;
|
||||
struct pcs_gpiofunc_range *range;
|
||||
int ret, i;
|
||||
|
||||
for (i = 0; ; i++) {
|
||||
ret = of_parse_phandle_with_args(node, propname, cellname,
|
||||
i, &gpiospec);
|
||||
/* Do not treat it as error. Only treat it as end condition. */
|
||||
if (ret) {
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
range = devm_kzalloc(pcs->dev, sizeof(*range), GFP_KERNEL);
|
||||
if (!range) {
|
||||
ret = -ENOMEM;
|
||||
break;
|
||||
}
|
||||
range->offset = gpiospec.args[0];
|
||||
range->npins = gpiospec.args[1];
|
||||
range->gpiofunc = gpiospec.args[2];
|
||||
mutex_lock(&pcs->mutex);
|
||||
list_add_tail(&range->node, &pcs->gpiofuncs);
|
||||
mutex_unlock(&pcs->mutex);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int pcs_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
@ -900,14 +1366,23 @@ static int pcs_probe(struct platform_device *pdev)
|
||||
mutex_init(&pcs->mutex);
|
||||
INIT_LIST_HEAD(&pcs->pingroups);
|
||||
INIT_LIST_HEAD(&pcs->functions);
|
||||
INIT_LIST_HEAD(&pcs->gpiofuncs);
|
||||
pcs->is_pinconf = match->data;
|
||||
|
||||
PCS_GET_PROP_U32("pinctrl-single,register-width", &pcs->width,
|
||||
"register width not specified\n");
|
||||
|
||||
PCS_GET_PROP_U32("pinctrl-single,function-mask", &pcs->fmask,
|
||||
"function register mask not specified\n");
|
||||
pcs->fshift = ffs(pcs->fmask) - 1;
|
||||
pcs->fmax = pcs->fmask >> pcs->fshift;
|
||||
ret = of_property_read_u32(np, "pinctrl-single,function-mask",
|
||||
&pcs->fmask);
|
||||
if (!ret) {
|
||||
pcs->fshift = ffs(pcs->fmask) - 1;
|
||||
pcs->fmax = pcs->fmask >> pcs->fshift;
|
||||
} else {
|
||||
/* If mask property doesn't exist, function mux is invalid. */
|
||||
pcs->fmask = 0;
|
||||
pcs->fshift = 0;
|
||||
pcs->fmax = 0;
|
||||
}
|
||||
|
||||
ret = of_property_read_u32(np, "pinctrl-single,function-off",
|
||||
&pcs->foff);
|
||||
@ -961,7 +1436,8 @@ static int pcs_probe(struct platform_device *pdev)
|
||||
pcs->desc.name = DRIVER_NAME;
|
||||
pcs->desc.pctlops = &pcs_pinctrl_ops;
|
||||
pcs->desc.pmxops = &pcs_pinmux_ops;
|
||||
pcs->desc.confops = &pcs_pinconf_ops;
|
||||
if (pcs->is_pinconf)
|
||||
pcs->desc.confops = &pcs_pinconf_ops;
|
||||
pcs->desc.owner = THIS_MODULE;
|
||||
|
||||
ret = pcs_allocate_pin_table(pcs);
|
||||
@ -975,6 +1451,10 @@ static int pcs_probe(struct platform_device *pdev)
|
||||
goto free;
|
||||
}
|
||||
|
||||
ret = pcs_add_gpio_func(np, pcs);
|
||||
if (ret < 0)
|
||||
goto free;
|
||||
|
||||
dev_info(pcs->dev, "%i pins at pa %p size %u\n",
|
||||
pcs->desc.npins, pcs->base, pcs->size);
|
||||
|
||||
@ -999,7 +1479,8 @@ static int pcs_remove(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
static struct of_device_id pcs_of_match[] = {
|
||||
{ .compatible = DRIVER_NAME, },
|
||||
{ .compatible = "pinctrl-single", .data = (void *)false },
|
||||
{ .compatible = "pinconf-single", .data = (void *)true },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, pcs_of_match);
|
||||
|
@ -979,7 +979,7 @@ static void sirfsoc_dt_free_map(struct pinctrl_dev *pctldev,
|
||||
kfree(map);
|
||||
}
|
||||
|
||||
static struct pinctrl_ops sirfsoc_pctrl_ops = {
|
||||
static const 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,
|
||||
@ -1181,7 +1181,7 @@ static int sirfsoc_pinmux_request_gpio(struct pinctrl_dev *pmxdev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct pinmux_ops sirfsoc_pinmux_ops = {
|
||||
static const struct pinmux_ops sirfsoc_pinmux_ops = {
|
||||
.enable = sirfsoc_pinmux_enable,
|
||||
.disable = sirfsoc_pinmux_disable,
|
||||
.get_functions_count = sirfsoc_pinmux_get_funcs_count,
|
||||
@ -1685,15 +1685,12 @@ static void sirfsoc_gpio_set_pullup(const u32 *pullups)
|
||||
const unsigned long *p = (const unsigned long *)pullups;
|
||||
|
||||
for (i = 0; i < SIRFSOC_GPIO_NO_OF_BANKS; i++) {
|
||||
n = find_first_bit(p + i, BITS_PER_LONG);
|
||||
while (n < BITS_PER_LONG) {
|
||||
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);
|
||||
|
||||
n = find_next_bit(p + i, BITS_PER_LONG, n + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1704,15 +1701,12 @@ static void sirfsoc_gpio_set_pulldown(const u32 *pulldowns)
|
||||
const unsigned long *p = (const unsigned long *)pulldowns;
|
||||
|
||||
for (i = 0; i < SIRFSOC_GPIO_NO_OF_BANKS; i++) {
|
||||
n = find_first_bit(p + i, BITS_PER_LONG);
|
||||
while (n < BITS_PER_LONG) {
|
||||
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);
|
||||
|
||||
n = find_next_bit(p + i, BITS_PER_LONG, n + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -316,7 +316,7 @@ static int tegra_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct pinctrl_ops tegra_pinctrl_ops = {
|
||||
static const struct pinctrl_ops tegra_pinctrl_ops = {
|
||||
.get_groups_count = tegra_pinctrl_get_groups_count,
|
||||
.get_group_name = tegra_pinctrl_get_group_name,
|
||||
.get_group_pins = tegra_pinctrl_get_group_pins,
|
||||
@ -401,7 +401,7 @@ static void tegra_pinctrl_disable(struct pinctrl_dev *pctldev,
|
||||
pmx_writel(pmx, val, g->mux_bank, g->mux_reg);
|
||||
}
|
||||
|
||||
static struct pinmux_ops tegra_pinmux_ops = {
|
||||
static const struct pinmux_ops tegra_pinmux_ops = {
|
||||
.get_functions_count = tegra_pinctrl_get_funcs_count,
|
||||
.get_function_name = tegra_pinctrl_get_func_name,
|
||||
.get_function_groups = tegra_pinctrl_get_func_groups,
|
||||
@ -676,7 +676,7 @@ static void tegra_pinconf_config_dbg_show(struct pinctrl_dev *pctldev,
|
||||
}
|
||||
#endif
|
||||
|
||||
static struct pinconf_ops tegra_pinconf_ops = {
|
||||
static const struct pinconf_ops tegra_pinconf_ops = {
|
||||
.pin_config_get = tegra_pinconf_get,
|
||||
.pin_config_set = tegra_pinconf_set,
|
||||
.pin_config_group_get = tegra_pinconf_group_get,
|
||||
|
@ -860,7 +860,7 @@ static void u300_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
|
||||
seq_printf(s, " " DRIVER_NAME);
|
||||
}
|
||||
|
||||
static struct pinctrl_ops u300_pctrl_ops = {
|
||||
static const struct pinctrl_ops u300_pctrl_ops = {
|
||||
.get_groups_count = u300_get_groups_count,
|
||||
.get_group_name = u300_get_group_name,
|
||||
.get_group_pins = u300_get_group_pins,
|
||||
@ -1003,7 +1003,7 @@ static int u300_pmx_get_groups(struct pinctrl_dev *pctldev, unsigned selector,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct pinmux_ops u300_pmx_ops = {
|
||||
static const struct pinmux_ops u300_pmx_ops = {
|
||||
.get_functions_count = u300_pmx_get_funcs_count,
|
||||
.get_function_name = u300_pmx_get_func_name,
|
||||
.get_function_groups = u300_pmx_get_groups,
|
||||
@ -1046,7 +1046,7 @@ static int u300_pin_config_set(struct pinctrl_dev *pctldev, unsigned pin,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct pinconf_ops u300_pconf_ops = {
|
||||
static const struct pinconf_ops u300_pconf_ops = {
|
||||
.is_generic = true,
|
||||
.pin_config_get = u300_pin_config_get,
|
||||
.pin_config_set = u300_pin_config_set,
|
||||
|
@ -553,7 +553,7 @@ int xway_pinconf_group_set(struct pinctrl_dev *pctldev,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct pinconf_ops xway_pinconf_ops = {
|
||||
static const struct pinconf_ops xway_pinconf_ops = {
|
||||
.pin_config_get = xway_pinconf_get,
|
||||
.pin_config_set = xway_pinconf_set,
|
||||
.pin_config_group_set = xway_pinconf_group_set,
|
||||
|
@ -506,7 +506,7 @@ static int pinmux_functions_show(struct seq_file *s, void *what)
|
||||
if (!pmxops)
|
||||
return 0;
|
||||
|
||||
mutex_lock(&pinctrl_mutex);
|
||||
mutex_lock(&pctldev->mutex);
|
||||
nfuncs = pmxops->get_functions_count(pctldev);
|
||||
while (func_selector < nfuncs) {
|
||||
const char *func = pmxops->get_function_name(pctldev,
|
||||
@ -530,7 +530,7 @@ static int pinmux_functions_show(struct seq_file *s, void *what)
|
||||
func_selector++;
|
||||
}
|
||||
|
||||
mutex_unlock(&pinctrl_mutex);
|
||||
mutex_unlock(&pctldev->mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -548,7 +548,7 @@ static int pinmux_pins_show(struct seq_file *s, void *what)
|
||||
seq_puts(s, "Pinmux settings per pin\n");
|
||||
seq_puts(s, "Format: pin (name): mux_owner gpio_owner hog?\n");
|
||||
|
||||
mutex_lock(&pinctrl_mutex);
|
||||
mutex_lock(&pctldev->mutex);
|
||||
|
||||
/* The pin number can be retrived from the pin controller descriptor */
|
||||
for (i = 0; i < pctldev->desc->npins; i++) {
|
||||
@ -583,7 +583,7 @@ static int pinmux_pins_show(struct seq_file *s, void *what)
|
||||
seq_printf(s, "\n");
|
||||
}
|
||||
|
||||
mutex_unlock(&pinctrl_mutex);
|
||||
mutex_unlock(&pctldev->mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -198,7 +198,7 @@ static void spear_pinctrl_dt_free_map(struct pinctrl_dev *pctldev,
|
||||
kfree(map);
|
||||
}
|
||||
|
||||
static struct pinctrl_ops spear_pinctrl_ops = {
|
||||
static const struct pinctrl_ops spear_pinctrl_ops = {
|
||||
.get_groups_count = spear_pinctrl_get_groups_cnt,
|
||||
.get_group_name = spear_pinctrl_get_group_name,
|
||||
.get_group_pins = spear_pinctrl_get_group_pins,
|
||||
@ -340,7 +340,7 @@ static void gpio_disable_free(struct pinctrl_dev *pctldev,
|
||||
gpio_request_endisable(pctldev, range, offset, false);
|
||||
}
|
||||
|
||||
static struct pinmux_ops spear_pinmux_ops = {
|
||||
static const struct pinmux_ops spear_pinmux_ops = {
|
||||
.get_functions_count = spear_pinctrl_get_funcs_count,
|
||||
.get_function_name = spear_pinctrl_get_func_name,
|
||||
.get_function_groups = spear_pinctrl_get_func_groups,
|
||||
|
@ -14,6 +14,8 @@
|
||||
|
||||
#ifdef CONFIG_PINCONF
|
||||
|
||||
#include <linux/pinctrl/machine.h>
|
||||
|
||||
struct pinctrl_dev;
|
||||
struct seq_file;
|
||||
|
||||
@ -28,6 +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_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
|
||||
@ -51,6 +54,9 @@ struct pinconf_ops {
|
||||
int (*pin_config_group_set) (struct pinctrl_dev *pctldev,
|
||||
unsigned selector,
|
||||
unsigned long config);
|
||||
int (*pin_config_dbg_parse_modify) (struct pinctrl_dev *pctldev,
|
||||
const char *arg,
|
||||
unsigned long *config);
|
||||
void (*pin_config_dbg_show) (struct pinctrl_dev *pctldev,
|
||||
struct seq_file *s,
|
||||
unsigned offset);
|
||||
|
@ -118,9 +118,9 @@ struct pinctrl_desc {
|
||||
const char *name;
|
||||
struct pinctrl_pin_desc const *pins;
|
||||
unsigned int npins;
|
||||
struct pinctrl_ops *pctlops;
|
||||
struct pinmux_ops *pmxops;
|
||||
struct pinconf_ops *confops;
|
||||
const struct pinctrl_ops *pctlops;
|
||||
const struct pinmux_ops *pmxops;
|
||||
const struct pinconf_ops *confops;
|
||||
struct module *owner;
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user