mirror of https://gitee.com/openkylin/linux.git
GPIO changes for v3.6:
- New driver for AMD-8111 southbridge GPIOs - New driver for Wolfson Micro Arizona devices - Propagate device tree parse errors - Probe deferral finalizations - all expected calls to GPIO will now hopefully request deferral where apropriate - Misc updates to TCA6424, WM8994, LPC32xx, PCF857x, Samsung MXC, OMAP and PCA953X drivers. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.12 (GNU/Linux) iQIcBAABAgAGBQJQEHMDAAoJEEEQszewGV1zwPYP/jkxBzvEl+iEO0RFwT4PtmCi Y8JOJNT1bw/3MHPcRT12E+gzj01S9GldbuaUObcudmnnynpjeC0S8JNhSKGD9uHa TTcCcMbZiKzJyZr/OL8EId7W1FGUO+51uB4hqEKCHMWRY/PBIjKxhvtj+BKEWyvn OVhWCxo2O7lv7rzeKiPc8WJMiodLS1urbZEyz7IADZtT3m8vu146rEQRvbNSSXa0 AJfl494XX1sbv0tzYzvE66+vjvvkgsjHq3O7On5b2svdnZGpAL/6CjEUVrpBXr4K NPKuq9TsLfVMH3w3xvQ70PoA7M0L+KvKcdjTvgZpf2KLIU7dwoL91PzAupcjSTr1 SkcTPtNFxuaRy0cFD+ZAwL2eIOGaNxk6N4tj1da35QjCUkNROHG5K6ByIL1e1ewO NuxAyn7QLrYdmXzBc5/DhZiBA0ShqoYg4oEgBDZklOKqjT3mqmjQbDq8i0Qy197W lb3Barg+WWm+NW1kmPYnrOJUZXa1ApVHuz8db7OrcUy5kTcUhVTY3DcQzFgG1CZT H284c9Zm8WaP814jE8SzLMGeFaCuI63xFMNkpnba11Bt+8Cr1I+LjWSd+ttCFdVm W9t/fMEX1bVpVrbTKMvcwm7AwnoeOUEwJCqAICLe5OE/1mEvanyjNXX4wfFP58jv OlQ/a9REqoOLAvvbV2qp =tujx -----END PGP SIGNATURE----- Merge tag 'gpio-for-v3.6' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio Pull GPIO changes from Linus Walleij: - New driver for AMD-8111 southbridge GPIOs - New driver for Wolfson Micro Arizona devices - Propagate device tree parse errors - Probe deferral finalizations - all expected calls to GPIO will now hopefully request deferral where apropriate - Misc updates to TCA6424, WM8994, LPC32xx, PCF857x, Samsung MXC, OMAP and PCA953X drivers. Fix up gpio_idx conflicts in drivers/gpio/gpio-mxc.c * tag 'gpio-for-v3.6' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio: gpio: of_get_named_gpio_flags() return -EPROBE_DEFER if GPIO not yet available gpiolib: Defer failed gpio requests by default MAINTAINERS: add entry OMAP GPIO driver gpio/pca953x: increase variables size to support 24 bit of data GPIO: PCA953X: Increase size of invert variable to support 24 bit gpio/omap: move bank->dbck initialization to omap_gpio_mod_init() gpio/mxc: use the edge_sel feature if available gpio: propagate of_parse_phandle_with_args errors gpio: samsung: add flags specifier to device-tree binding gpiolib: Add support for Wolfson Microelectronics Arizona class devices gpio: gpio-lpc32xx: Add gpio_to_irq mapping gpio: pcf857x: share 8/16 bit access functions gpio: LPC32xx: Driver cleanup MAINTAINERS: Add Wolfson gpiolib drivers to the Wolfson entry gpiolib: wm8994: Convert to devm_kzalloc() gpiolib: wm8994: Use irq_domain mappings for gpios gpio: add a driver for GPIO pins found on AMD-8111 south bridge chips gpio/tca6424: merge I2C transactions, remove cast gpio/of: fix a typo of comment message
This commit is contained in:
commit
f948ad0787
|
@ -22,7 +22,7 @@ Required properties:
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
gpio0: gpio@73f84000 {
|
gpio0: gpio@73f84000 {
|
||||||
compatible = "fsl,imx51-gpio", "fsl,imx31-gpio";
|
compatible = "fsl,imx51-gpio", "fsl,imx35-gpio";
|
||||||
reg = <0x73f84000 0x4000>;
|
reg = <0x73f84000 0x4000>;
|
||||||
interrupts = <50 51>;
|
interrupts = <50 51>;
|
||||||
gpio-controller;
|
gpio-controller;
|
||||||
|
|
|
@ -11,14 +11,15 @@ Required properties:
|
||||||
<[phandle of the gpio controller node]
|
<[phandle of the gpio controller node]
|
||||||
[pin number within the gpio controller]
|
[pin number within the gpio controller]
|
||||||
[mux function]
|
[mux function]
|
||||||
[pull up/down]
|
[flags and pull up/down]
|
||||||
[drive strength]>
|
[drive strength]>
|
||||||
|
|
||||||
Values for gpio specifier:
|
Values for gpio specifier:
|
||||||
- Pin number: is a value between 0 to 7.
|
- Pin number: is a value between 0 to 7.
|
||||||
- Pull Up/Down: 0 - Pull Up/Down Disabled.
|
- Flags and Pull Up/Down: 0 - Pull Up/Down Disabled.
|
||||||
1 - Pull Down Enabled.
|
1 - Pull Down Enabled.
|
||||||
3 - Pull Up Enabled.
|
3 - Pull Up Enabled.
|
||||||
|
Bit 16 (0x00010000) - Input is active low.
|
||||||
- Drive Strength: 0 - 1x,
|
- Drive Strength: 0 - 1x,
|
||||||
1 - 3x,
|
1 - 3x,
|
||||||
2 - 2x,
|
2 - 2x,
|
||||||
|
|
|
@ -4961,6 +4961,13 @@ S: Maintained
|
||||||
F: drivers/usb/*/*omap*
|
F: drivers/usb/*/*omap*
|
||||||
F: arch/arm/*omap*/usb*
|
F: arch/arm/*omap*/usb*
|
||||||
|
|
||||||
|
OMAP GPIO DRIVER
|
||||||
|
M: Santosh Shilimkar <santosh.shilimkar@ti.com>
|
||||||
|
M: Kevin Hilman <khilman@ti.com>
|
||||||
|
L: linux-omap@vger.kernel.org
|
||||||
|
S: Maintained
|
||||||
|
F: drivers/gpio/gpio-omap.c
|
||||||
|
|
||||||
OMFS FILESYSTEM
|
OMFS FILESYSTEM
|
||||||
M: Bob Copeland <me@bobcopeland.com>
|
M: Bob Copeland <me@bobcopeland.com>
|
||||||
L: linux-karma-devel@lists.sourceforge.net
|
L: linux-karma-devel@lists.sourceforge.net
|
||||||
|
@ -7615,6 +7622,7 @@ F: Documentation/hwmon/wm83??
|
||||||
F: arch/arm/mach-s3c64xx/mach-crag6410*
|
F: arch/arm/mach-s3c64xx/mach-crag6410*
|
||||||
F: drivers/clk/clk-wm83*.c
|
F: drivers/clk/clk-wm83*.c
|
||||||
F: drivers/leds/leds-wm83*.c
|
F: drivers/leds/leds-wm83*.c
|
||||||
|
F: drivers/gpio/gpio-*wm*.c
|
||||||
F: drivers/hwmon/wm83??-hwmon.c
|
F: drivers/hwmon/wm83??-hwmon.c
|
||||||
F: drivers/input/misc/wm831x-on.c
|
F: drivers/input/misc/wm831x-on.c
|
||||||
F: drivers/input/touchscreen/wm831x-ts.c
|
F: drivers/input/touchscreen/wm831x-ts.c
|
||||||
|
|
|
@ -127,7 +127,7 @@ esdhc@70024000 { /* ESDHC4 */
|
||||||
};
|
};
|
||||||
|
|
||||||
gpio1: gpio@73f84000 {
|
gpio1: gpio@73f84000 {
|
||||||
compatible = "fsl,imx51-gpio", "fsl,imx31-gpio";
|
compatible = "fsl,imx51-gpio", "fsl,imx35-gpio";
|
||||||
reg = <0x73f84000 0x4000>;
|
reg = <0x73f84000 0x4000>;
|
||||||
interrupts = <50 51>;
|
interrupts = <50 51>;
|
||||||
gpio-controller;
|
gpio-controller;
|
||||||
|
@ -137,7 +137,7 @@ gpio1: gpio@73f84000 {
|
||||||
};
|
};
|
||||||
|
|
||||||
gpio2: gpio@73f88000 {
|
gpio2: gpio@73f88000 {
|
||||||
compatible = "fsl,imx51-gpio", "fsl,imx31-gpio";
|
compatible = "fsl,imx51-gpio", "fsl,imx35-gpio";
|
||||||
reg = <0x73f88000 0x4000>;
|
reg = <0x73f88000 0x4000>;
|
||||||
interrupts = <52 53>;
|
interrupts = <52 53>;
|
||||||
gpio-controller;
|
gpio-controller;
|
||||||
|
@ -147,7 +147,7 @@ gpio2: gpio@73f88000 {
|
||||||
};
|
};
|
||||||
|
|
||||||
gpio3: gpio@73f8c000 {
|
gpio3: gpio@73f8c000 {
|
||||||
compatible = "fsl,imx51-gpio", "fsl,imx31-gpio";
|
compatible = "fsl,imx51-gpio", "fsl,imx35-gpio";
|
||||||
reg = <0x73f8c000 0x4000>;
|
reg = <0x73f8c000 0x4000>;
|
||||||
interrupts = <54 55>;
|
interrupts = <54 55>;
|
||||||
gpio-controller;
|
gpio-controller;
|
||||||
|
@ -157,7 +157,7 @@ gpio3: gpio@73f8c000 {
|
||||||
};
|
};
|
||||||
|
|
||||||
gpio4: gpio@73f90000 {
|
gpio4: gpio@73f90000 {
|
||||||
compatible = "fsl,imx51-gpio", "fsl,imx31-gpio";
|
compatible = "fsl,imx51-gpio", "fsl,imx35-gpio";
|
||||||
reg = <0x73f90000 0x4000>;
|
reg = <0x73f90000 0x4000>;
|
||||||
interrupts = <56 57>;
|
interrupts = <56 57>;
|
||||||
gpio-controller;
|
gpio-controller;
|
||||||
|
|
|
@ -129,7 +129,7 @@ esdhc@50024000 { /* ESDHC4 */
|
||||||
};
|
};
|
||||||
|
|
||||||
gpio1: gpio@53f84000 {
|
gpio1: gpio@53f84000 {
|
||||||
compatible = "fsl,imx53-gpio", "fsl,imx31-gpio";
|
compatible = "fsl,imx53-gpio", "fsl,imx35-gpio";
|
||||||
reg = <0x53f84000 0x4000>;
|
reg = <0x53f84000 0x4000>;
|
||||||
interrupts = <50 51>;
|
interrupts = <50 51>;
|
||||||
gpio-controller;
|
gpio-controller;
|
||||||
|
@ -139,7 +139,7 @@ gpio1: gpio@53f84000 {
|
||||||
};
|
};
|
||||||
|
|
||||||
gpio2: gpio@53f88000 {
|
gpio2: gpio@53f88000 {
|
||||||
compatible = "fsl,imx53-gpio", "fsl,imx31-gpio";
|
compatible = "fsl,imx53-gpio", "fsl,imx35-gpio";
|
||||||
reg = <0x53f88000 0x4000>;
|
reg = <0x53f88000 0x4000>;
|
||||||
interrupts = <52 53>;
|
interrupts = <52 53>;
|
||||||
gpio-controller;
|
gpio-controller;
|
||||||
|
@ -149,7 +149,7 @@ gpio2: gpio@53f88000 {
|
||||||
};
|
};
|
||||||
|
|
||||||
gpio3: gpio@53f8c000 {
|
gpio3: gpio@53f8c000 {
|
||||||
compatible = "fsl,imx53-gpio", "fsl,imx31-gpio";
|
compatible = "fsl,imx53-gpio", "fsl,imx35-gpio";
|
||||||
reg = <0x53f8c000 0x4000>;
|
reg = <0x53f8c000 0x4000>;
|
||||||
interrupts = <54 55>;
|
interrupts = <54 55>;
|
||||||
gpio-controller;
|
gpio-controller;
|
||||||
|
@ -159,7 +159,7 @@ gpio3: gpio@53f8c000 {
|
||||||
};
|
};
|
||||||
|
|
||||||
gpio4: gpio@53f90000 {
|
gpio4: gpio@53f90000 {
|
||||||
compatible = "fsl,imx53-gpio", "fsl,imx31-gpio";
|
compatible = "fsl,imx53-gpio", "fsl,imx35-gpio";
|
||||||
reg = <0x53f90000 0x4000>;
|
reg = <0x53f90000 0x4000>;
|
||||||
interrupts = <56 57>;
|
interrupts = <56 57>;
|
||||||
gpio-controller;
|
gpio-controller;
|
||||||
|
@ -197,7 +197,7 @@ uart2: serial@53fc0000 {
|
||||||
};
|
};
|
||||||
|
|
||||||
gpio5: gpio@53fdc000 {
|
gpio5: gpio@53fdc000 {
|
||||||
compatible = "fsl,imx53-gpio", "fsl,imx31-gpio";
|
compatible = "fsl,imx53-gpio", "fsl,imx35-gpio";
|
||||||
reg = <0x53fdc000 0x4000>;
|
reg = <0x53fdc000 0x4000>;
|
||||||
interrupts = <103 104>;
|
interrupts = <103 104>;
|
||||||
gpio-controller;
|
gpio-controller;
|
||||||
|
@ -207,7 +207,7 @@ gpio5: gpio@53fdc000 {
|
||||||
};
|
};
|
||||||
|
|
||||||
gpio6: gpio@53fe0000 {
|
gpio6: gpio@53fe0000 {
|
||||||
compatible = "fsl,imx53-gpio", "fsl,imx31-gpio";
|
compatible = "fsl,imx53-gpio", "fsl,imx35-gpio";
|
||||||
reg = <0x53fe0000 0x4000>;
|
reg = <0x53fe0000 0x4000>;
|
||||||
interrupts = <105 106>;
|
interrupts = <105 106>;
|
||||||
gpio-controller;
|
gpio-controller;
|
||||||
|
@ -217,7 +217,7 @@ gpio6: gpio@53fe0000 {
|
||||||
};
|
};
|
||||||
|
|
||||||
gpio7: gpio@53fe4000 {
|
gpio7: gpio@53fe4000 {
|
||||||
compatible = "fsl,imx53-gpio", "fsl,imx31-gpio";
|
compatible = "fsl,imx53-gpio", "fsl,imx35-gpio";
|
||||||
reg = <0x53fe4000 0x4000>;
|
reg = <0x53fe4000 0x4000>;
|
||||||
interrupts = <107 108>;
|
interrupts = <107 108>;
|
||||||
gpio-controller;
|
gpio-controller;
|
||||||
|
|
|
@ -277,7 +277,7 @@ gpt@02098000 {
|
||||||
};
|
};
|
||||||
|
|
||||||
gpio1: gpio@0209c000 {
|
gpio1: gpio@0209c000 {
|
||||||
compatible = "fsl,imx6q-gpio", "fsl,imx31-gpio";
|
compatible = "fsl,imx6q-gpio", "fsl,imx35-gpio";
|
||||||
reg = <0x0209c000 0x4000>;
|
reg = <0x0209c000 0x4000>;
|
||||||
interrupts = <0 66 0x04 0 67 0x04>;
|
interrupts = <0 66 0x04 0 67 0x04>;
|
||||||
gpio-controller;
|
gpio-controller;
|
||||||
|
@ -287,7 +287,7 @@ gpio1: gpio@0209c000 {
|
||||||
};
|
};
|
||||||
|
|
||||||
gpio2: gpio@020a0000 {
|
gpio2: gpio@020a0000 {
|
||||||
compatible = "fsl,imx6q-gpio", "fsl,imx31-gpio";
|
compatible = "fsl,imx6q-gpio", "fsl,imx35-gpio";
|
||||||
reg = <0x020a0000 0x4000>;
|
reg = <0x020a0000 0x4000>;
|
||||||
interrupts = <0 68 0x04 0 69 0x04>;
|
interrupts = <0 68 0x04 0 69 0x04>;
|
||||||
gpio-controller;
|
gpio-controller;
|
||||||
|
@ -297,7 +297,7 @@ gpio2: gpio@020a0000 {
|
||||||
};
|
};
|
||||||
|
|
||||||
gpio3: gpio@020a4000 {
|
gpio3: gpio@020a4000 {
|
||||||
compatible = "fsl,imx6q-gpio", "fsl,imx31-gpio";
|
compatible = "fsl,imx6q-gpio", "fsl,imx35-gpio";
|
||||||
reg = <0x020a4000 0x4000>;
|
reg = <0x020a4000 0x4000>;
|
||||||
interrupts = <0 70 0x04 0 71 0x04>;
|
interrupts = <0 70 0x04 0 71 0x04>;
|
||||||
gpio-controller;
|
gpio-controller;
|
||||||
|
@ -307,7 +307,7 @@ gpio3: gpio@020a4000 {
|
||||||
};
|
};
|
||||||
|
|
||||||
gpio4: gpio@020a8000 {
|
gpio4: gpio@020a8000 {
|
||||||
compatible = "fsl,imx6q-gpio", "fsl,imx31-gpio";
|
compatible = "fsl,imx6q-gpio", "fsl,imx35-gpio";
|
||||||
reg = <0x020a8000 0x4000>;
|
reg = <0x020a8000 0x4000>;
|
||||||
interrupts = <0 72 0x04 0 73 0x04>;
|
interrupts = <0 72 0x04 0 73 0x04>;
|
||||||
gpio-controller;
|
gpio-controller;
|
||||||
|
@ -317,7 +317,7 @@ gpio4: gpio@020a8000 {
|
||||||
};
|
};
|
||||||
|
|
||||||
gpio5: gpio@020ac000 {
|
gpio5: gpio@020ac000 {
|
||||||
compatible = "fsl,imx6q-gpio", "fsl,imx31-gpio";
|
compatible = "fsl,imx6q-gpio", "fsl,imx35-gpio";
|
||||||
reg = <0x020ac000 0x4000>;
|
reg = <0x020ac000 0x4000>;
|
||||||
interrupts = <0 74 0x04 0 75 0x04>;
|
interrupts = <0 74 0x04 0 75 0x04>;
|
||||||
gpio-controller;
|
gpio-controller;
|
||||||
|
@ -327,7 +327,7 @@ gpio5: gpio@020ac000 {
|
||||||
};
|
};
|
||||||
|
|
||||||
gpio6: gpio@020b0000 {
|
gpio6: gpio@020b0000 {
|
||||||
compatible = "fsl,imx6q-gpio", "fsl,imx31-gpio";
|
compatible = "fsl,imx6q-gpio", "fsl,imx35-gpio";
|
||||||
reg = <0x020b0000 0x4000>;
|
reg = <0x020b0000 0x4000>;
|
||||||
interrupts = <0 76 0x04 0 77 0x04>;
|
interrupts = <0 76 0x04 0 77 0x04>;
|
||||||
gpio-controller;
|
gpio-controller;
|
||||||
|
@ -337,7 +337,7 @@ gpio6: gpio@020b0000 {
|
||||||
};
|
};
|
||||||
|
|
||||||
gpio7: gpio@020b4000 {
|
gpio7: gpio@020b4000 {
|
||||||
compatible = "fsl,imx6q-gpio", "fsl,imx31-gpio";
|
compatible = "fsl,imx6q-gpio", "fsl,imx35-gpio";
|
||||||
reg = <0x020b4000 0x4000>;
|
reg = <0x020b4000 0x4000>;
|
||||||
interrupts = <0 78 0x04 0 79 0x04>;
|
interrupts = <0 78 0x04 0 79 0x04>;
|
||||||
gpio-controller;
|
gpio-controller;
|
||||||
|
|
|
@ -89,11 +89,11 @@ static const struct resource imx25_audmux_res[] __initconst = {
|
||||||
|
|
||||||
void __init imx25_soc_init(void)
|
void __init imx25_soc_init(void)
|
||||||
{
|
{
|
||||||
/* i.mx25 has the i.mx31 type gpio */
|
/* i.mx25 has the i.mx35 type gpio */
|
||||||
mxc_register_gpio("imx31-gpio", 0, MX25_GPIO1_BASE_ADDR, SZ_16K, MX25_INT_GPIO1, 0);
|
mxc_register_gpio("imx35-gpio", 0, MX25_GPIO1_BASE_ADDR, SZ_16K, MX25_INT_GPIO1, 0);
|
||||||
mxc_register_gpio("imx31-gpio", 1, MX25_GPIO2_BASE_ADDR, SZ_16K, MX25_INT_GPIO2, 0);
|
mxc_register_gpio("imx35-gpio", 1, MX25_GPIO2_BASE_ADDR, SZ_16K, MX25_INT_GPIO2, 0);
|
||||||
mxc_register_gpio("imx31-gpio", 2, MX25_GPIO3_BASE_ADDR, SZ_16K, MX25_INT_GPIO3, 0);
|
mxc_register_gpio("imx35-gpio", 2, MX25_GPIO3_BASE_ADDR, SZ_16K, MX25_INT_GPIO3, 0);
|
||||||
mxc_register_gpio("imx31-gpio", 3, MX25_GPIO4_BASE_ADDR, SZ_16K, MX25_INT_GPIO4, 0);
|
mxc_register_gpio("imx35-gpio", 3, MX25_GPIO4_BASE_ADDR, SZ_16K, MX25_INT_GPIO4, 0);
|
||||||
|
|
||||||
pinctrl_provide_dummies();
|
pinctrl_provide_dummies();
|
||||||
/* i.mx25 has the i.mx35 type sdma */
|
/* i.mx25 has the i.mx35 type sdma */
|
||||||
|
|
|
@ -272,10 +272,9 @@ void __init imx35_soc_init(void)
|
||||||
|
|
||||||
imx3_init_l2x0();
|
imx3_init_l2x0();
|
||||||
|
|
||||||
/* i.mx35 has the i.mx31 type gpio */
|
mxc_register_gpio("imx35-gpio", 0, MX35_GPIO1_BASE_ADDR, SZ_16K, MX35_INT_GPIO1, 0);
|
||||||
mxc_register_gpio("imx31-gpio", 0, MX35_GPIO1_BASE_ADDR, SZ_16K, MX35_INT_GPIO1, 0);
|
mxc_register_gpio("imx35-gpio", 1, MX35_GPIO2_BASE_ADDR, SZ_16K, MX35_INT_GPIO2, 0);
|
||||||
mxc_register_gpio("imx31-gpio", 1, MX35_GPIO2_BASE_ADDR, SZ_16K, MX35_INT_GPIO2, 0);
|
mxc_register_gpio("imx35-gpio", 2, MX35_GPIO3_BASE_ADDR, SZ_16K, MX35_INT_GPIO3, 0);
|
||||||
mxc_register_gpio("imx31-gpio", 2, MX35_GPIO3_BASE_ADDR, SZ_16K, MX35_INT_GPIO3, 0);
|
|
||||||
|
|
||||||
pinctrl_provide_dummies();
|
pinctrl_provide_dummies();
|
||||||
if (to_version == 1) {
|
if (to_version == 1) {
|
||||||
|
|
|
@ -161,13 +161,13 @@ static const struct resource imx53_audmux_res[] __initconst = {
|
||||||
|
|
||||||
void __init imx50_soc_init(void)
|
void __init imx50_soc_init(void)
|
||||||
{
|
{
|
||||||
/* i.mx50 has the i.mx31 type gpio */
|
/* i.mx50 has the i.mx35 type gpio */
|
||||||
mxc_register_gpio("imx31-gpio", 0, MX50_GPIO1_BASE_ADDR, SZ_16K, MX50_INT_GPIO1_LOW, MX50_INT_GPIO1_HIGH);
|
mxc_register_gpio("imx35-gpio", 0, MX50_GPIO1_BASE_ADDR, SZ_16K, MX50_INT_GPIO1_LOW, MX50_INT_GPIO1_HIGH);
|
||||||
mxc_register_gpio("imx31-gpio", 1, MX50_GPIO2_BASE_ADDR, SZ_16K, MX50_INT_GPIO2_LOW, MX50_INT_GPIO2_HIGH);
|
mxc_register_gpio("imx35-gpio", 1, MX50_GPIO2_BASE_ADDR, SZ_16K, MX50_INT_GPIO2_LOW, MX50_INT_GPIO2_HIGH);
|
||||||
mxc_register_gpio("imx31-gpio", 2, MX50_GPIO3_BASE_ADDR, SZ_16K, MX50_INT_GPIO3_LOW, MX50_INT_GPIO3_HIGH);
|
mxc_register_gpio("imx35-gpio", 2, MX50_GPIO3_BASE_ADDR, SZ_16K, MX50_INT_GPIO3_LOW, MX50_INT_GPIO3_HIGH);
|
||||||
mxc_register_gpio("imx31-gpio", 3, MX50_GPIO4_BASE_ADDR, SZ_16K, MX50_INT_GPIO4_LOW, MX50_INT_GPIO4_HIGH);
|
mxc_register_gpio("imx35-gpio", 3, MX50_GPIO4_BASE_ADDR, SZ_16K, MX50_INT_GPIO4_LOW, MX50_INT_GPIO4_HIGH);
|
||||||
mxc_register_gpio("imx31-gpio", 4, MX50_GPIO5_BASE_ADDR, SZ_16K, MX50_INT_GPIO5_LOW, MX50_INT_GPIO5_HIGH);
|
mxc_register_gpio("imx35-gpio", 4, MX50_GPIO5_BASE_ADDR, SZ_16K, MX50_INT_GPIO5_LOW, MX50_INT_GPIO5_HIGH);
|
||||||
mxc_register_gpio("imx31-gpio", 5, MX50_GPIO6_BASE_ADDR, SZ_16K, MX50_INT_GPIO6_LOW, MX50_INT_GPIO6_HIGH);
|
mxc_register_gpio("imx35-gpio", 5, MX50_GPIO6_BASE_ADDR, SZ_16K, MX50_INT_GPIO6_LOW, MX50_INT_GPIO6_HIGH);
|
||||||
|
|
||||||
/* i.mx50 has the i.mx31 type audmux */
|
/* i.mx50 has the i.mx31 type audmux */
|
||||||
platform_device_register_simple("imx31-audmux", 0, imx50_audmux_res,
|
platform_device_register_simple("imx31-audmux", 0, imx50_audmux_res,
|
||||||
|
@ -176,11 +176,11 @@ void __init imx50_soc_init(void)
|
||||||
|
|
||||||
void __init imx51_soc_init(void)
|
void __init imx51_soc_init(void)
|
||||||
{
|
{
|
||||||
/* i.mx51 has the i.mx31 type gpio */
|
/* i.mx51 has the i.mx35 type gpio */
|
||||||
mxc_register_gpio("imx31-gpio", 0, MX51_GPIO1_BASE_ADDR, SZ_16K, MX51_INT_GPIO1_LOW, MX51_INT_GPIO1_HIGH);
|
mxc_register_gpio("imx35-gpio", 0, MX51_GPIO1_BASE_ADDR, SZ_16K, MX51_INT_GPIO1_LOW, MX51_INT_GPIO1_HIGH);
|
||||||
mxc_register_gpio("imx31-gpio", 1, MX51_GPIO2_BASE_ADDR, SZ_16K, MX51_INT_GPIO2_LOW, MX51_INT_GPIO2_HIGH);
|
mxc_register_gpio("imx35-gpio", 1, MX51_GPIO2_BASE_ADDR, SZ_16K, MX51_INT_GPIO2_LOW, MX51_INT_GPIO2_HIGH);
|
||||||
mxc_register_gpio("imx31-gpio", 2, MX51_GPIO3_BASE_ADDR, SZ_16K, MX51_INT_GPIO3_LOW, MX51_INT_GPIO3_HIGH);
|
mxc_register_gpio("imx35-gpio", 2, MX51_GPIO3_BASE_ADDR, SZ_16K, MX51_INT_GPIO3_LOW, MX51_INT_GPIO3_HIGH);
|
||||||
mxc_register_gpio("imx31-gpio", 3, MX51_GPIO4_BASE_ADDR, SZ_16K, MX51_INT_GPIO4_LOW, MX51_INT_GPIO4_HIGH);
|
mxc_register_gpio("imx35-gpio", 3, MX51_GPIO4_BASE_ADDR, SZ_16K, MX51_INT_GPIO4_LOW, MX51_INT_GPIO4_HIGH);
|
||||||
|
|
||||||
pinctrl_provide_dummies();
|
pinctrl_provide_dummies();
|
||||||
|
|
||||||
|
@ -198,14 +198,14 @@ void __init imx51_soc_init(void)
|
||||||
|
|
||||||
void __init imx53_soc_init(void)
|
void __init imx53_soc_init(void)
|
||||||
{
|
{
|
||||||
/* i.mx53 has the i.mx31 type gpio */
|
/* i.mx53 has the i.mx35 type gpio */
|
||||||
mxc_register_gpio("imx31-gpio", 0, MX53_GPIO1_BASE_ADDR, SZ_16K, MX53_INT_GPIO1_LOW, MX53_INT_GPIO1_HIGH);
|
mxc_register_gpio("imx35-gpio", 0, MX53_GPIO1_BASE_ADDR, SZ_16K, MX53_INT_GPIO1_LOW, MX53_INT_GPIO1_HIGH);
|
||||||
mxc_register_gpio("imx31-gpio", 1, MX53_GPIO2_BASE_ADDR, SZ_16K, MX53_INT_GPIO2_LOW, MX53_INT_GPIO2_HIGH);
|
mxc_register_gpio("imx35-gpio", 1, MX53_GPIO2_BASE_ADDR, SZ_16K, MX53_INT_GPIO2_LOW, MX53_INT_GPIO2_HIGH);
|
||||||
mxc_register_gpio("imx31-gpio", 2, MX53_GPIO3_BASE_ADDR, SZ_16K, MX53_INT_GPIO3_LOW, MX53_INT_GPIO3_HIGH);
|
mxc_register_gpio("imx35-gpio", 2, MX53_GPIO3_BASE_ADDR, SZ_16K, MX53_INT_GPIO3_LOW, MX53_INT_GPIO3_HIGH);
|
||||||
mxc_register_gpio("imx31-gpio", 3, MX53_GPIO4_BASE_ADDR, SZ_16K, MX53_INT_GPIO4_LOW, MX53_INT_GPIO4_HIGH);
|
mxc_register_gpio("imx35-gpio", 3, MX53_GPIO4_BASE_ADDR, SZ_16K, MX53_INT_GPIO4_LOW, MX53_INT_GPIO4_HIGH);
|
||||||
mxc_register_gpio("imx31-gpio", 4, MX53_GPIO5_BASE_ADDR, SZ_16K, MX53_INT_GPIO5_LOW, MX53_INT_GPIO5_HIGH);
|
mxc_register_gpio("imx35-gpio", 4, MX53_GPIO5_BASE_ADDR, SZ_16K, MX53_INT_GPIO5_LOW, MX53_INT_GPIO5_HIGH);
|
||||||
mxc_register_gpio("imx31-gpio", 5, MX53_GPIO6_BASE_ADDR, SZ_16K, MX53_INT_GPIO6_LOW, MX53_INT_GPIO6_HIGH);
|
mxc_register_gpio("imx35-gpio", 5, MX53_GPIO6_BASE_ADDR, SZ_16K, MX53_INT_GPIO6_LOW, MX53_INT_GPIO6_HIGH);
|
||||||
mxc_register_gpio("imx31-gpio", 6, MX53_GPIO7_BASE_ADDR, SZ_16K, MX53_INT_GPIO7_LOW, MX53_INT_GPIO7_HIGH);
|
mxc_register_gpio("imx35-gpio", 6, MX53_GPIO7_BASE_ADDR, SZ_16K, MX53_INT_GPIO7_LOW, MX53_INT_GPIO7_HIGH);
|
||||||
|
|
||||||
pinctrl_provide_dummies();
|
pinctrl_provide_dummies();
|
||||||
/* i.mx53 has the i.mx35 type sdma */
|
/* i.mx53 has the i.mx35 type sdma */
|
||||||
|
|
|
@ -253,6 +253,12 @@ config GPIO_GE_FPGA
|
||||||
|
|
||||||
comment "I2C GPIO expanders:"
|
comment "I2C GPIO expanders:"
|
||||||
|
|
||||||
|
config GPIO_ARIZONA
|
||||||
|
tristate "Wolfson Microelectronics Arizona class devices"
|
||||||
|
depends on MFD_ARIZONA
|
||||||
|
help
|
||||||
|
Support for GPIOs on Wolfson Arizona class devices.
|
||||||
|
|
||||||
config GPIO_MAX7300
|
config GPIO_MAX7300
|
||||||
tristate "Maxim MAX7300 GPIO expander"
|
tristate "Maxim MAX7300 GPIO expander"
|
||||||
depends on I2C
|
depends on I2C
|
||||||
|
@ -466,6 +472,18 @@ config GPIO_BT8XX
|
||||||
|
|
||||||
If unsure, say N.
|
If unsure, say N.
|
||||||
|
|
||||||
|
config GPIO_AMD8111
|
||||||
|
tristate "AMD 8111 GPIO driver"
|
||||||
|
depends on PCI
|
||||||
|
help
|
||||||
|
The AMD 8111 south bridge contains 32 GPIO pins which can be used.
|
||||||
|
|
||||||
|
Note, that usually system firmware/ACPI handles GPIO pins on their
|
||||||
|
own and users might easily break their systems with uncarefull usage
|
||||||
|
of this driver!
|
||||||
|
|
||||||
|
If unsure, say N
|
||||||
|
|
||||||
config GPIO_LANGWELL
|
config GPIO_LANGWELL
|
||||||
bool "Intel Langwell/Penwell GPIO support"
|
bool "Intel Langwell/Penwell GPIO support"
|
||||||
depends on PCI && X86
|
depends on PCI && X86
|
||||||
|
|
|
@ -12,6 +12,8 @@ obj-$(CONFIG_GPIO_74X164) += gpio-74x164.o
|
||||||
obj-$(CONFIG_GPIO_AB8500) += gpio-ab8500.o
|
obj-$(CONFIG_GPIO_AB8500) += gpio-ab8500.o
|
||||||
obj-$(CONFIG_GPIO_ADP5520) += gpio-adp5520.o
|
obj-$(CONFIG_GPIO_ADP5520) += gpio-adp5520.o
|
||||||
obj-$(CONFIG_GPIO_ADP5588) += gpio-adp5588.o
|
obj-$(CONFIG_GPIO_ADP5588) += gpio-adp5588.o
|
||||||
|
obj-$(CONFIG_GPIO_AMD8111) += gpio-amd8111.o
|
||||||
|
obj-$(CONFIG_GPIO_ARIZONA) += gpio-arizona.o
|
||||||
obj-$(CONFIG_GPIO_BT8XX) += gpio-bt8xx.o
|
obj-$(CONFIG_GPIO_BT8XX) += gpio-bt8xx.o
|
||||||
obj-$(CONFIG_GPIO_CS5535) += gpio-cs5535.o
|
obj-$(CONFIG_GPIO_CS5535) += gpio-cs5535.o
|
||||||
obj-$(CONFIG_GPIO_DA9052) += gpio-da9052.o
|
obj-$(CONFIG_GPIO_DA9052) += gpio-da9052.o
|
||||||
|
|
|
@ -0,0 +1,246 @@
|
||||||
|
/*
|
||||||
|
* GPIO driver for AMD 8111 south bridges
|
||||||
|
*
|
||||||
|
* Copyright (c) 2012 Dmitry Eremin-Solenikov
|
||||||
|
*
|
||||||
|
* Based on the AMD RNG driver:
|
||||||
|
* Copyright 2005 (c) MontaVista Software, Inc.
|
||||||
|
* with the majority of the code coming from:
|
||||||
|
*
|
||||||
|
* Hardware driver for the Intel/AMD/VIA Random Number Generators (RNG)
|
||||||
|
* (c) Copyright 2003 Red Hat Inc <jgarzik@redhat.com>
|
||||||
|
*
|
||||||
|
* derived from
|
||||||
|
*
|
||||||
|
* Hardware driver for the AMD 768 Random Number Generator (RNG)
|
||||||
|
* (c) Copyright 2001 Red Hat Inc
|
||||||
|
*
|
||||||
|
* derived from
|
||||||
|
*
|
||||||
|
* Hardware driver for Intel i810 Random Number Generator (RNG)
|
||||||
|
* Copyright 2000,2001 Jeff Garzik <jgarzik@pobox.com>
|
||||||
|
* Copyright 2000,2001 Philipp Rumpf <prumpf@mandrakesoft.com>
|
||||||
|
*
|
||||||
|
* This file is licensed under the terms of the GNU General Public
|
||||||
|
* License version 2. This program is licensed "as is" without any
|
||||||
|
* warranty of any kind, whether express or implied.
|
||||||
|
*/
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/gpio.h>
|
||||||
|
#include <linux/pci.h>
|
||||||
|
#include <linux/spinlock.h>
|
||||||
|
|
||||||
|
#define PMBASE_OFFSET 0xb0
|
||||||
|
#define PMBASE_SIZE 0x30
|
||||||
|
|
||||||
|
#define AMD_REG_GPIO(i) (0x10 + (i))
|
||||||
|
|
||||||
|
#define AMD_GPIO_LTCH_STS 0x40 /* Latch status, w1 */
|
||||||
|
#define AMD_GPIO_RTIN 0x20 /* Real Time in, ro */
|
||||||
|
#define AMD_GPIO_DEBOUNCE 0x10 /* Debounce, rw */
|
||||||
|
#define AMD_GPIO_MODE_MASK 0x0c /* Pin Mode Select, rw */
|
||||||
|
#define AMD_GPIO_MODE_IN 0x00
|
||||||
|
#define AMD_GPIO_MODE_OUT 0x04
|
||||||
|
/* Enable alternative (e.g. clkout, IRQ, etc) function of the pin */
|
||||||
|
#define AMD_GPIO_MODE_ALTFN 0x08 /* Or 0x09 */
|
||||||
|
#define AMD_GPIO_X_MASK 0x03 /* In/Out specific, rw */
|
||||||
|
#define AMD_GPIO_X_IN_ACTIVEHI 0x01 /* Active High */
|
||||||
|
#define AMD_GPIO_X_IN_LATCH 0x02 /* Latched version is selected */
|
||||||
|
#define AMD_GPIO_X_OUT_LOW 0x00
|
||||||
|
#define AMD_GPIO_X_OUT_HI 0x01
|
||||||
|
#define AMD_GPIO_X_OUT_CLK0 0x02
|
||||||
|
#define AMD_GPIO_X_OUT_CLK1 0x03
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Data for PCI driver interface
|
||||||
|
*
|
||||||
|
* This data only exists for exporting the supported
|
||||||
|
* PCI ids via MODULE_DEVICE_TABLE. We do not actually
|
||||||
|
* register a pci_driver, because someone else might one day
|
||||||
|
* want to register another driver on the same PCI id.
|
||||||
|
*/
|
||||||
|
static DEFINE_PCI_DEVICE_TABLE(pci_tbl) = {
|
||||||
|
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_SMBUS), 0 },
|
||||||
|
{ 0, }, /* terminate list */
|
||||||
|
};
|
||||||
|
MODULE_DEVICE_TABLE(pci, pci_tbl);
|
||||||
|
|
||||||
|
struct amd_gpio {
|
||||||
|
struct gpio_chip chip;
|
||||||
|
u32 pmbase;
|
||||||
|
void __iomem *pm;
|
||||||
|
struct pci_dev *pdev;
|
||||||
|
spinlock_t lock; /* guards hw registers and orig table */
|
||||||
|
u8 orig[32];
|
||||||
|
};
|
||||||
|
|
||||||
|
#define to_agp(chip) container_of(chip, struct amd_gpio, chip)
|
||||||
|
|
||||||
|
static int amd_gpio_request(struct gpio_chip *chip, unsigned offset)
|
||||||
|
{
|
||||||
|
struct amd_gpio *agp = to_agp(chip);
|
||||||
|
|
||||||
|
agp->orig[offset] = ioread8(agp->pm + AMD_REG_GPIO(offset)) &
|
||||||
|
(AMD_GPIO_DEBOUNCE | AMD_GPIO_MODE_MASK | AMD_GPIO_X_MASK);
|
||||||
|
|
||||||
|
dev_dbg(&agp->pdev->dev, "Requested gpio %d, data %x\n", offset, agp->orig[offset]);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void amd_gpio_free(struct gpio_chip *chip, unsigned offset)
|
||||||
|
{
|
||||||
|
struct amd_gpio *agp = to_agp(chip);
|
||||||
|
|
||||||
|
dev_dbg(&agp->pdev->dev, "Freed gpio %d, data %x\n", offset, agp->orig[offset]);
|
||||||
|
|
||||||
|
iowrite8(agp->orig[offset], agp->pm + AMD_REG_GPIO(offset));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void amd_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
|
||||||
|
{
|
||||||
|
struct amd_gpio *agp = to_agp(chip);
|
||||||
|
u8 temp;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&agp->lock, flags);
|
||||||
|
temp = ioread8(agp->pm + AMD_REG_GPIO(offset));
|
||||||
|
temp = (temp & AMD_GPIO_DEBOUNCE) | AMD_GPIO_MODE_OUT | (value ? AMD_GPIO_X_OUT_HI : AMD_GPIO_X_OUT_LOW);
|
||||||
|
iowrite8(temp, agp->pm + AMD_REG_GPIO(offset));
|
||||||
|
spin_unlock_irqrestore(&agp->lock, flags);
|
||||||
|
|
||||||
|
dev_dbg(&agp->pdev->dev, "Setting gpio %d, value %d, reg=%02x\n", offset, !!value, temp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int amd_gpio_get(struct gpio_chip *chip, unsigned offset)
|
||||||
|
{
|
||||||
|
struct amd_gpio *agp = to_agp(chip);
|
||||||
|
u8 temp;
|
||||||
|
|
||||||
|
temp = ioread8(agp->pm + AMD_REG_GPIO(offset));
|
||||||
|
|
||||||
|
dev_dbg(&agp->pdev->dev, "Getting gpio %d, reg=%02x\n", offset, temp);
|
||||||
|
|
||||||
|
return (temp & AMD_GPIO_RTIN) ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int amd_gpio_dirout(struct gpio_chip *chip, unsigned offset, int value)
|
||||||
|
{
|
||||||
|
struct amd_gpio *agp = to_agp(chip);
|
||||||
|
u8 temp;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&agp->lock, flags);
|
||||||
|
temp = ioread8(agp->pm + AMD_REG_GPIO(offset));
|
||||||
|
temp = (temp & AMD_GPIO_DEBOUNCE) | AMD_GPIO_MODE_OUT | (value ? AMD_GPIO_X_OUT_HI : AMD_GPIO_X_OUT_LOW);
|
||||||
|
iowrite8(temp, agp->pm + AMD_REG_GPIO(offset));
|
||||||
|
spin_unlock_irqrestore(&agp->lock, flags);
|
||||||
|
|
||||||
|
dev_dbg(&agp->pdev->dev, "Dirout gpio %d, value %d, reg=%02x\n", offset, !!value, temp);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int amd_gpio_dirin(struct gpio_chip *chip, unsigned offset)
|
||||||
|
{
|
||||||
|
struct amd_gpio *agp = to_agp(chip);
|
||||||
|
u8 temp;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&agp->lock, flags);
|
||||||
|
temp = ioread8(agp->pm + AMD_REG_GPIO(offset));
|
||||||
|
temp = (temp & AMD_GPIO_DEBOUNCE) | AMD_GPIO_MODE_IN;
|
||||||
|
iowrite8(temp, agp->pm + AMD_REG_GPIO(offset));
|
||||||
|
spin_unlock_irqrestore(&agp->lock, flags);
|
||||||
|
|
||||||
|
dev_dbg(&agp->pdev->dev, "Dirin gpio %d, reg=%02x\n", offset, temp);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct amd_gpio gp = {
|
||||||
|
.chip = {
|
||||||
|
.label = "AMD GPIO",
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
.base = -1,
|
||||||
|
.ngpio = 32,
|
||||||
|
.request = amd_gpio_request,
|
||||||
|
.free = amd_gpio_free,
|
||||||
|
.set = amd_gpio_set,
|
||||||
|
.get = amd_gpio_get,
|
||||||
|
.direction_output = amd_gpio_dirout,
|
||||||
|
.direction_input = amd_gpio_dirin,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static int __init amd_gpio_init(void)
|
||||||
|
{
|
||||||
|
int err = -ENODEV;
|
||||||
|
struct pci_dev *pdev = NULL;
|
||||||
|
const struct pci_device_id *ent;
|
||||||
|
|
||||||
|
|
||||||
|
/* We look for our device - AMD South Bridge
|
||||||
|
* I don't know about a system with two such bridges,
|
||||||
|
* so we can assume that there is max. one device.
|
||||||
|
*
|
||||||
|
* We can't use plain pci_driver mechanism,
|
||||||
|
* as the device is really a multiple function device,
|
||||||
|
* main driver that binds to the pci_device is an smbus
|
||||||
|
* driver and have to find & bind to the device this way.
|
||||||
|
*/
|
||||||
|
for_each_pci_dev(pdev) {
|
||||||
|
ent = pci_match_id(pci_tbl, pdev);
|
||||||
|
if (ent)
|
||||||
|
goto found;
|
||||||
|
}
|
||||||
|
/* Device not found. */
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
found:
|
||||||
|
err = pci_read_config_dword(pdev, 0x58, &gp.pmbase);
|
||||||
|
if (err)
|
||||||
|
goto out;
|
||||||
|
err = -EIO;
|
||||||
|
gp.pmbase &= 0x0000FF00;
|
||||||
|
if (gp.pmbase == 0)
|
||||||
|
goto out;
|
||||||
|
if (!request_region(gp.pmbase + PMBASE_OFFSET, PMBASE_SIZE, "AMD GPIO")) {
|
||||||
|
dev_err(&pdev->dev, "AMD GPIO region 0x%x already in use!\n",
|
||||||
|
gp.pmbase + PMBASE_OFFSET);
|
||||||
|
err = -EBUSY;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
gp.pm = ioport_map(gp.pmbase + PMBASE_OFFSET, PMBASE_SIZE);
|
||||||
|
gp.pdev = pdev;
|
||||||
|
gp.chip.dev = &pdev->dev;
|
||||||
|
|
||||||
|
spin_lock_init(&gp.lock);
|
||||||
|
|
||||||
|
printk(KERN_INFO "AMD-8111 GPIO detected\n");
|
||||||
|
err = gpiochip_add(&gp.chip);
|
||||||
|
if (err) {
|
||||||
|
printk(KERN_ERR "GPIO registering failed (%d)\n",
|
||||||
|
err);
|
||||||
|
release_region(gp.pmbase + PMBASE_OFFSET, PMBASE_SIZE);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
out:
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __exit amd_gpio_exit(void)
|
||||||
|
{
|
||||||
|
int err = gpiochip_remove(&gp.chip);
|
||||||
|
WARN_ON(err);
|
||||||
|
ioport_unmap(gp.pm);
|
||||||
|
release_region(gp.pmbase + PMBASE_OFFSET, PMBASE_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
module_init(amd_gpio_init);
|
||||||
|
module_exit(amd_gpio_exit);
|
||||||
|
|
||||||
|
MODULE_AUTHOR("The Linux Kernel team");
|
||||||
|
MODULE_DESCRIPTION("GPIO driver for AMD chipsets");
|
||||||
|
MODULE_LICENSE("GPL");
|
|
@ -0,0 +1,163 @@
|
||||||
|
/*
|
||||||
|
* gpiolib support for Wolfson Arizona class devices
|
||||||
|
*
|
||||||
|
* Copyright 2012 Wolfson Microelectronics PLC.
|
||||||
|
*
|
||||||
|
* Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the
|
||||||
|
* Free Software Foundation; either version 2 of the License, or (at your
|
||||||
|
* option) any later version.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/gpio.h>
|
||||||
|
#include <linux/platform_device.h>
|
||||||
|
#include <linux/seq_file.h>
|
||||||
|
|
||||||
|
#include <linux/mfd/arizona/core.h>
|
||||||
|
#include <linux/mfd/arizona/pdata.h>
|
||||||
|
#include <linux/mfd/arizona/registers.h>
|
||||||
|
|
||||||
|
struct arizona_gpio {
|
||||||
|
struct arizona *arizona;
|
||||||
|
struct gpio_chip gpio_chip;
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline struct arizona_gpio *to_arizona_gpio(struct gpio_chip *chip)
|
||||||
|
{
|
||||||
|
return container_of(chip, struct arizona_gpio, gpio_chip);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int arizona_gpio_direction_in(struct gpio_chip *chip, unsigned offset)
|
||||||
|
{
|
||||||
|
struct arizona_gpio *arizona_gpio = to_arizona_gpio(chip);
|
||||||
|
struct arizona *arizona = arizona_gpio->arizona;
|
||||||
|
|
||||||
|
return regmap_update_bits(arizona->regmap, ARIZONA_GPIO1_CTRL + offset,
|
||||||
|
ARIZONA_GPN_DIR, ARIZONA_GPN_DIR);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int arizona_gpio_get(struct gpio_chip *chip, unsigned offset)
|
||||||
|
{
|
||||||
|
struct arizona_gpio *arizona_gpio = to_arizona_gpio(chip);
|
||||||
|
struct arizona *arizona = arizona_gpio->arizona;
|
||||||
|
unsigned int val;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = regmap_read(arizona->regmap, ARIZONA_GPIO1_CTRL + offset, &val);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
if (val & ARIZONA_GPN_LVL)
|
||||||
|
return 1;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int arizona_gpio_direction_out(struct gpio_chip *chip,
|
||||||
|
unsigned offset, int value)
|
||||||
|
{
|
||||||
|
struct arizona_gpio *arizona_gpio = to_arizona_gpio(chip);
|
||||||
|
struct arizona *arizona = arizona_gpio->arizona;
|
||||||
|
|
||||||
|
if (value)
|
||||||
|
value = ARIZONA_GPN_LVL;
|
||||||
|
|
||||||
|
return regmap_update_bits(arizona->regmap, ARIZONA_GPIO1_CTRL + offset,
|
||||||
|
ARIZONA_GPN_DIR | ARIZONA_GPN_LVL, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void arizona_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
|
||||||
|
{
|
||||||
|
struct arizona_gpio *arizona_gpio = to_arizona_gpio(chip);
|
||||||
|
struct arizona *arizona = arizona_gpio->arizona;
|
||||||
|
|
||||||
|
if (value)
|
||||||
|
value = ARIZONA_GPN_LVL;
|
||||||
|
|
||||||
|
regmap_update_bits(arizona->regmap, ARIZONA_GPIO1_CTRL + offset,
|
||||||
|
ARIZONA_GPN_LVL, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct gpio_chip template_chip = {
|
||||||
|
.label = "arizona",
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
.direction_input = arizona_gpio_direction_in,
|
||||||
|
.get = arizona_gpio_get,
|
||||||
|
.direction_output = arizona_gpio_direction_out,
|
||||||
|
.set = arizona_gpio_set,
|
||||||
|
.can_sleep = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int __devinit arizona_gpio_probe(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
struct arizona *arizona = dev_get_drvdata(pdev->dev.parent);
|
||||||
|
struct arizona_pdata *pdata = arizona->dev->platform_data;
|
||||||
|
struct arizona_gpio *arizona_gpio;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
arizona_gpio = devm_kzalloc(&pdev->dev, sizeof(*arizona_gpio),
|
||||||
|
GFP_KERNEL);
|
||||||
|
if (arizona_gpio == NULL)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
arizona_gpio->arizona = arizona;
|
||||||
|
arizona_gpio->gpio_chip = template_chip;
|
||||||
|
arizona_gpio->gpio_chip.dev = &pdev->dev;
|
||||||
|
|
||||||
|
switch (arizona->type) {
|
||||||
|
case WM5102:
|
||||||
|
case WM5110:
|
||||||
|
arizona_gpio->gpio_chip.ngpio = 5;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
dev_err(&pdev->dev, "Unknown chip variant %d\n",
|
||||||
|
arizona->type);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pdata && pdata->gpio_base)
|
||||||
|
arizona_gpio->gpio_chip.base = pdata->gpio_base;
|
||||||
|
else
|
||||||
|
arizona_gpio->gpio_chip.base = -1;
|
||||||
|
|
||||||
|
ret = gpiochip_add(&arizona_gpio->gpio_chip);
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(&pdev->dev, "Could not register gpiochip, %d\n",
|
||||||
|
ret);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
platform_set_drvdata(pdev, arizona_gpio);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
err:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int __devexit arizona_gpio_remove(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
struct arizona_gpio *arizona_gpio = platform_get_drvdata(pdev);
|
||||||
|
|
||||||
|
return gpiochip_remove(&arizona_gpio->gpio_chip);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct platform_driver arizona_gpio_driver = {
|
||||||
|
.driver.name = "arizona-gpio",
|
||||||
|
.driver.owner = THIS_MODULE,
|
||||||
|
.probe = arizona_gpio_probe,
|
||||||
|
.remove = __devexit_p(arizona_gpio_remove),
|
||||||
|
};
|
||||||
|
|
||||||
|
module_platform_driver(arizona_gpio_driver);
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
|
||||||
|
MODULE_DESCRIPTION("GPIO interface for Arizona devices");
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
|
MODULE_ALIAS("platform:arizona-gpio");
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* arch/arm/mach-lpc32xx/gpiolib.c
|
* GPIO driver for LPC32xx SoC
|
||||||
*
|
*
|
||||||
* Author: Kevin Wells <kevin.wells@nxp.com>
|
* Author: Kevin Wells <kevin.wells@nxp.com>
|
||||||
*
|
*
|
||||||
|
@ -28,6 +28,7 @@
|
||||||
#include <mach/hardware.h>
|
#include <mach/hardware.h>
|
||||||
#include <mach/platform.h>
|
#include <mach/platform.h>
|
||||||
#include <mach/gpio-lpc32xx.h>
|
#include <mach/gpio-lpc32xx.h>
|
||||||
|
#include <mach/irqs.h>
|
||||||
|
|
||||||
#define LPC32XX_GPIO_P3_INP_STATE _GPREG(0x000)
|
#define LPC32XX_GPIO_P3_INP_STATE _GPREG(0x000)
|
||||||
#define LPC32XX_GPIO_P3_OUTP_SET _GPREG(0x004)
|
#define LPC32XX_GPIO_P3_OUTP_SET _GPREG(0x004)
|
||||||
|
@ -367,6 +368,66 @@ static int lpc32xx_gpio_request(struct gpio_chip *chip, unsigned pin)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int lpc32xx_gpio_to_irq_p01(struct gpio_chip *chip, unsigned offset)
|
||||||
|
{
|
||||||
|
return IRQ_LPC32XX_P0_P1_IRQ;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char lpc32xx_gpio_to_irq_gpio_p3_table[] = {
|
||||||
|
IRQ_LPC32XX_GPIO_00,
|
||||||
|
IRQ_LPC32XX_GPIO_01,
|
||||||
|
IRQ_LPC32XX_GPIO_02,
|
||||||
|
IRQ_LPC32XX_GPIO_03,
|
||||||
|
IRQ_LPC32XX_GPIO_04,
|
||||||
|
IRQ_LPC32XX_GPIO_05,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int lpc32xx_gpio_to_irq_gpio_p3(struct gpio_chip *chip, unsigned offset)
|
||||||
|
{
|
||||||
|
if (offset < ARRAY_SIZE(lpc32xx_gpio_to_irq_gpio_p3_table))
|
||||||
|
return lpc32xx_gpio_to_irq_gpio_p3_table[offset];
|
||||||
|
return -ENXIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char lpc32xx_gpio_to_irq_gpi_p3_table[] = {
|
||||||
|
IRQ_LPC32XX_GPI_00,
|
||||||
|
IRQ_LPC32XX_GPI_01,
|
||||||
|
IRQ_LPC32XX_GPI_02,
|
||||||
|
IRQ_LPC32XX_GPI_03,
|
||||||
|
IRQ_LPC32XX_GPI_04,
|
||||||
|
IRQ_LPC32XX_GPI_05,
|
||||||
|
IRQ_LPC32XX_GPI_06,
|
||||||
|
IRQ_LPC32XX_GPI_07,
|
||||||
|
IRQ_LPC32XX_GPI_08,
|
||||||
|
IRQ_LPC32XX_GPI_09,
|
||||||
|
-ENXIO, /* 10 */
|
||||||
|
-ENXIO, /* 11 */
|
||||||
|
-ENXIO, /* 12 */
|
||||||
|
-ENXIO, /* 13 */
|
||||||
|
-ENXIO, /* 14 */
|
||||||
|
-ENXIO, /* 15 */
|
||||||
|
-ENXIO, /* 16 */
|
||||||
|
-ENXIO, /* 17 */
|
||||||
|
-ENXIO, /* 18 */
|
||||||
|
IRQ_LPC32XX_GPI_19,
|
||||||
|
-ENXIO, /* 20 */
|
||||||
|
-ENXIO, /* 21 */
|
||||||
|
-ENXIO, /* 22 */
|
||||||
|
-ENXIO, /* 23 */
|
||||||
|
-ENXIO, /* 24 */
|
||||||
|
-ENXIO, /* 25 */
|
||||||
|
-ENXIO, /* 26 */
|
||||||
|
-ENXIO, /* 27 */
|
||||||
|
IRQ_LPC32XX_GPI_28,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int lpc32xx_gpio_to_irq_gpi_p3(struct gpio_chip *chip, unsigned offset)
|
||||||
|
{
|
||||||
|
if (offset < ARRAY_SIZE(lpc32xx_gpio_to_irq_gpi_p3_table))
|
||||||
|
return lpc32xx_gpio_to_irq_gpi_p3_table[offset];
|
||||||
|
return -ENXIO;
|
||||||
|
}
|
||||||
|
|
||||||
static struct lpc32xx_gpio_chip lpc32xx_gpiochip[] = {
|
static struct lpc32xx_gpio_chip lpc32xx_gpiochip[] = {
|
||||||
{
|
{
|
||||||
.chip = {
|
.chip = {
|
||||||
|
@ -376,6 +437,7 @@ static struct lpc32xx_gpio_chip lpc32xx_gpiochip[] = {
|
||||||
.direction_output = lpc32xx_gpio_dir_output_p012,
|
.direction_output = lpc32xx_gpio_dir_output_p012,
|
||||||
.set = lpc32xx_gpio_set_value_p012,
|
.set = lpc32xx_gpio_set_value_p012,
|
||||||
.request = lpc32xx_gpio_request,
|
.request = lpc32xx_gpio_request,
|
||||||
|
.to_irq = lpc32xx_gpio_to_irq_p01,
|
||||||
.base = LPC32XX_GPIO_P0_GRP,
|
.base = LPC32XX_GPIO_P0_GRP,
|
||||||
.ngpio = LPC32XX_GPIO_P0_MAX,
|
.ngpio = LPC32XX_GPIO_P0_MAX,
|
||||||
.names = gpio_p0_names,
|
.names = gpio_p0_names,
|
||||||
|
@ -391,6 +453,7 @@ static struct lpc32xx_gpio_chip lpc32xx_gpiochip[] = {
|
||||||
.direction_output = lpc32xx_gpio_dir_output_p012,
|
.direction_output = lpc32xx_gpio_dir_output_p012,
|
||||||
.set = lpc32xx_gpio_set_value_p012,
|
.set = lpc32xx_gpio_set_value_p012,
|
||||||
.request = lpc32xx_gpio_request,
|
.request = lpc32xx_gpio_request,
|
||||||
|
.to_irq = lpc32xx_gpio_to_irq_p01,
|
||||||
.base = LPC32XX_GPIO_P1_GRP,
|
.base = LPC32XX_GPIO_P1_GRP,
|
||||||
.ngpio = LPC32XX_GPIO_P1_MAX,
|
.ngpio = LPC32XX_GPIO_P1_MAX,
|
||||||
.names = gpio_p1_names,
|
.names = gpio_p1_names,
|
||||||
|
@ -421,6 +484,7 @@ static struct lpc32xx_gpio_chip lpc32xx_gpiochip[] = {
|
||||||
.direction_output = lpc32xx_gpio_dir_output_p3,
|
.direction_output = lpc32xx_gpio_dir_output_p3,
|
||||||
.set = lpc32xx_gpio_set_value_p3,
|
.set = lpc32xx_gpio_set_value_p3,
|
||||||
.request = lpc32xx_gpio_request,
|
.request = lpc32xx_gpio_request,
|
||||||
|
.to_irq = lpc32xx_gpio_to_irq_gpio_p3,
|
||||||
.base = LPC32XX_GPIO_P3_GRP,
|
.base = LPC32XX_GPIO_P3_GRP,
|
||||||
.ngpio = LPC32XX_GPIO_P3_MAX,
|
.ngpio = LPC32XX_GPIO_P3_MAX,
|
||||||
.names = gpio_p3_names,
|
.names = gpio_p3_names,
|
||||||
|
@ -434,6 +498,7 @@ static struct lpc32xx_gpio_chip lpc32xx_gpiochip[] = {
|
||||||
.direction_input = lpc32xx_gpio_dir_in_always,
|
.direction_input = lpc32xx_gpio_dir_in_always,
|
||||||
.get = lpc32xx_gpi_get_value,
|
.get = lpc32xx_gpi_get_value,
|
||||||
.request = lpc32xx_gpio_request,
|
.request = lpc32xx_gpio_request,
|
||||||
|
.to_irq = lpc32xx_gpio_to_irq_gpi_p3,
|
||||||
.base = LPC32XX_GPI_P3_GRP,
|
.base = LPC32XX_GPI_P3_GRP,
|
||||||
.ngpio = LPC32XX_GPI_P3_MAX,
|
.ngpio = LPC32XX_GPI_P3_MAX,
|
||||||
.names = gpi_p3_names,
|
.names = gpi_p3_names,
|
||||||
|
@ -457,13 +522,6 @@ static struct lpc32xx_gpio_chip lpc32xx_gpiochip[] = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Empty now, can be removed later when mach-lpc32xx is finally switched over
|
|
||||||
* to DT support
|
|
||||||
*/
|
|
||||||
void __init lpc32xx_gpio_init(void)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static int lpc32xx_of_xlate(struct gpio_chip *gc,
|
static int lpc32xx_of_xlate(struct gpio_chip *gc,
|
||||||
const struct of_phandle_args *gpiospec, u32 *flags)
|
const struct of_phandle_args *gpiospec, u32 *flags)
|
||||||
{
|
{
|
||||||
|
|
|
@ -37,7 +37,8 @@
|
||||||
enum mxc_gpio_hwtype {
|
enum mxc_gpio_hwtype {
|
||||||
IMX1_GPIO, /* runs on i.mx1 */
|
IMX1_GPIO, /* runs on i.mx1 */
|
||||||
IMX21_GPIO, /* runs on i.mx21 and i.mx27 */
|
IMX21_GPIO, /* runs on i.mx21 and i.mx27 */
|
||||||
IMX31_GPIO, /* runs on all other i.mx */
|
IMX31_GPIO, /* runs on i.mx31 */
|
||||||
|
IMX35_GPIO, /* runs on all other i.mx */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* device type dependent stuff */
|
/* device type dependent stuff */
|
||||||
|
@ -49,6 +50,7 @@ struct mxc_gpio_hwdata {
|
||||||
unsigned icr2_reg;
|
unsigned icr2_reg;
|
||||||
unsigned imr_reg;
|
unsigned imr_reg;
|
||||||
unsigned isr_reg;
|
unsigned isr_reg;
|
||||||
|
int edge_sel_reg;
|
||||||
unsigned low_level;
|
unsigned low_level;
|
||||||
unsigned high_level;
|
unsigned high_level;
|
||||||
unsigned rise_edge;
|
unsigned rise_edge;
|
||||||
|
@ -73,6 +75,7 @@ static struct mxc_gpio_hwdata imx1_imx21_gpio_hwdata = {
|
||||||
.icr2_reg = 0x2c,
|
.icr2_reg = 0x2c,
|
||||||
.imr_reg = 0x30,
|
.imr_reg = 0x30,
|
||||||
.isr_reg = 0x34,
|
.isr_reg = 0x34,
|
||||||
|
.edge_sel_reg = -EINVAL,
|
||||||
.low_level = 0x03,
|
.low_level = 0x03,
|
||||||
.high_level = 0x02,
|
.high_level = 0x02,
|
||||||
.rise_edge = 0x00,
|
.rise_edge = 0x00,
|
||||||
|
@ -87,6 +90,22 @@ static struct mxc_gpio_hwdata imx31_gpio_hwdata = {
|
||||||
.icr2_reg = 0x10,
|
.icr2_reg = 0x10,
|
||||||
.imr_reg = 0x14,
|
.imr_reg = 0x14,
|
||||||
.isr_reg = 0x18,
|
.isr_reg = 0x18,
|
||||||
|
.edge_sel_reg = -EINVAL,
|
||||||
|
.low_level = 0x00,
|
||||||
|
.high_level = 0x01,
|
||||||
|
.rise_edge = 0x02,
|
||||||
|
.fall_edge = 0x03,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct mxc_gpio_hwdata imx35_gpio_hwdata = {
|
||||||
|
.dr_reg = 0x00,
|
||||||
|
.gdir_reg = 0x04,
|
||||||
|
.psr_reg = 0x08,
|
||||||
|
.icr1_reg = 0x0c,
|
||||||
|
.icr2_reg = 0x10,
|
||||||
|
.imr_reg = 0x14,
|
||||||
|
.isr_reg = 0x18,
|
||||||
|
.edge_sel_reg = 0x1c,
|
||||||
.low_level = 0x00,
|
.low_level = 0x00,
|
||||||
.high_level = 0x01,
|
.high_level = 0x01,
|
||||||
.rise_edge = 0x02,
|
.rise_edge = 0x02,
|
||||||
|
@ -103,12 +122,13 @@ static struct mxc_gpio_hwdata *mxc_gpio_hwdata;
|
||||||
#define GPIO_ICR2 (mxc_gpio_hwdata->icr2_reg)
|
#define GPIO_ICR2 (mxc_gpio_hwdata->icr2_reg)
|
||||||
#define GPIO_IMR (mxc_gpio_hwdata->imr_reg)
|
#define GPIO_IMR (mxc_gpio_hwdata->imr_reg)
|
||||||
#define GPIO_ISR (mxc_gpio_hwdata->isr_reg)
|
#define GPIO_ISR (mxc_gpio_hwdata->isr_reg)
|
||||||
|
#define GPIO_EDGE_SEL (mxc_gpio_hwdata->edge_sel_reg)
|
||||||
|
|
||||||
#define GPIO_INT_LOW_LEV (mxc_gpio_hwdata->low_level)
|
#define GPIO_INT_LOW_LEV (mxc_gpio_hwdata->low_level)
|
||||||
#define GPIO_INT_HIGH_LEV (mxc_gpio_hwdata->high_level)
|
#define GPIO_INT_HIGH_LEV (mxc_gpio_hwdata->high_level)
|
||||||
#define GPIO_INT_RISE_EDGE (mxc_gpio_hwdata->rise_edge)
|
#define GPIO_INT_RISE_EDGE (mxc_gpio_hwdata->rise_edge)
|
||||||
#define GPIO_INT_FALL_EDGE (mxc_gpio_hwdata->fall_edge)
|
#define GPIO_INT_FALL_EDGE (mxc_gpio_hwdata->fall_edge)
|
||||||
#define GPIO_INT_NONE 0x4
|
#define GPIO_INT_BOTH_EDGES 0x4
|
||||||
|
|
||||||
static struct platform_device_id mxc_gpio_devtype[] = {
|
static struct platform_device_id mxc_gpio_devtype[] = {
|
||||||
{
|
{
|
||||||
|
@ -120,6 +140,9 @@ static struct platform_device_id mxc_gpio_devtype[] = {
|
||||||
}, {
|
}, {
|
||||||
.name = "imx31-gpio",
|
.name = "imx31-gpio",
|
||||||
.driver_data = IMX31_GPIO,
|
.driver_data = IMX31_GPIO,
|
||||||
|
}, {
|
||||||
|
.name = "imx35-gpio",
|
||||||
|
.driver_data = IMX35_GPIO,
|
||||||
}, {
|
}, {
|
||||||
/* sentinel */
|
/* sentinel */
|
||||||
}
|
}
|
||||||
|
@ -129,6 +152,7 @@ static const struct of_device_id mxc_gpio_dt_ids[] = {
|
||||||
{ .compatible = "fsl,imx1-gpio", .data = &mxc_gpio_devtype[IMX1_GPIO], },
|
{ .compatible = "fsl,imx1-gpio", .data = &mxc_gpio_devtype[IMX1_GPIO], },
|
||||||
{ .compatible = "fsl,imx21-gpio", .data = &mxc_gpio_devtype[IMX21_GPIO], },
|
{ .compatible = "fsl,imx21-gpio", .data = &mxc_gpio_devtype[IMX21_GPIO], },
|
||||||
{ .compatible = "fsl,imx31-gpio", .data = &mxc_gpio_devtype[IMX31_GPIO], },
|
{ .compatible = "fsl,imx31-gpio", .data = &mxc_gpio_devtype[IMX31_GPIO], },
|
||||||
|
{ .compatible = "fsl,imx35-gpio", .data = &mxc_gpio_devtype[IMX35_GPIO], },
|
||||||
{ /* sentinel */ }
|
{ /* sentinel */ }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -160,15 +184,19 @@ static int gpio_set_irq_type(struct irq_data *d, u32 type)
|
||||||
edge = GPIO_INT_FALL_EDGE;
|
edge = GPIO_INT_FALL_EDGE;
|
||||||
break;
|
break;
|
||||||
case IRQ_TYPE_EDGE_BOTH:
|
case IRQ_TYPE_EDGE_BOTH:
|
||||||
val = gpio_get_value(gpio);
|
if (GPIO_EDGE_SEL >= 0) {
|
||||||
if (val) {
|
edge = GPIO_INT_BOTH_EDGES;
|
||||||
edge = GPIO_INT_LOW_LEV;
|
|
||||||
pr_debug("mxc: set GPIO %d to low trigger\n", gpio);
|
|
||||||
} else {
|
} else {
|
||||||
edge = GPIO_INT_HIGH_LEV;
|
val = gpio_get_value(gpio);
|
||||||
pr_debug("mxc: set GPIO %d to high trigger\n", gpio);
|
if (val) {
|
||||||
|
edge = GPIO_INT_LOW_LEV;
|
||||||
|
pr_debug("mxc: set GPIO %d to low trigger\n", gpio);
|
||||||
|
} else {
|
||||||
|
edge = GPIO_INT_HIGH_LEV;
|
||||||
|
pr_debug("mxc: set GPIO %d to high trigger\n", gpio);
|
||||||
|
}
|
||||||
|
port->both_edges |= 1 << gpio_idx;
|
||||||
}
|
}
|
||||||
port->both_edges |= 1 << gpio_idx;
|
|
||||||
break;
|
break;
|
||||||
case IRQ_TYPE_LEVEL_LOW:
|
case IRQ_TYPE_LEVEL_LOW:
|
||||||
edge = GPIO_INT_LOW_LEV;
|
edge = GPIO_INT_LOW_LEV;
|
||||||
|
@ -180,10 +208,23 @@ static int gpio_set_irq_type(struct irq_data *d, u32 type)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
reg += GPIO_ICR1 + ((gpio_idx & 0x10) >> 2); /* ICR1 or ICR2 */
|
if (GPIO_EDGE_SEL >= 0) {
|
||||||
bit = gpio_idx & 0xf;
|
val = readl(port->base + GPIO_EDGE_SEL);
|
||||||
val = readl(reg) & ~(0x3 << (bit << 1));
|
if (edge == GPIO_INT_BOTH_EDGES)
|
||||||
writel(val | (edge << (bit << 1)), reg);
|
writel(val | (1 << gpio_idx),
|
||||||
|
port->base + GPIO_EDGE_SEL);
|
||||||
|
else
|
||||||
|
writel(val & ~(1 << gpio_idx),
|
||||||
|
port->base + GPIO_EDGE_SEL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (edge != GPIO_INT_BOTH_EDGES) {
|
||||||
|
reg += GPIO_ICR1 + ((gpio_idx & 0x10) >> 2); /* lower or upper register */
|
||||||
|
bit = gpio_idx & 0xf;
|
||||||
|
val = readl(reg) & ~(0x3 << (bit << 1));
|
||||||
|
writel(val | (edge << (bit << 1)), reg);
|
||||||
|
}
|
||||||
|
|
||||||
writel(1 << gpio_idx, port->base + GPIO_ISR);
|
writel(1 << gpio_idx, port->base + GPIO_ISR);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -335,7 +376,9 @@ static void __devinit mxc_gpio_get_hw(struct platform_device *pdev)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hwtype == IMX31_GPIO)
|
if (hwtype == IMX35_GPIO)
|
||||||
|
mxc_gpio_hwdata = &imx35_gpio_hwdata;
|
||||||
|
else if (hwtype == IMX31_GPIO)
|
||||||
mxc_gpio_hwdata = &imx31_gpio_hwdata;
|
mxc_gpio_hwdata = &imx31_gpio_hwdata;
|
||||||
else
|
else
|
||||||
mxc_gpio_hwdata = &imx1_imx21_gpio_hwdata;
|
mxc_gpio_hwdata = &imx1_imx21_gpio_hwdata;
|
||||||
|
|
|
@ -899,12 +899,6 @@ static int gpio_debounce(struct gpio_chip *chip, unsigned offset,
|
||||||
|
|
||||||
bank = container_of(chip, struct gpio_bank, chip);
|
bank = container_of(chip, struct gpio_bank, chip);
|
||||||
|
|
||||||
if (!bank->dbck) {
|
|
||||||
bank->dbck = clk_get(bank->dev, "dbclk");
|
|
||||||
if (IS_ERR(bank->dbck))
|
|
||||||
dev_err(bank->dev, "Could not get gpio dbck\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
spin_lock_irqsave(&bank->lock, flags);
|
spin_lock_irqsave(&bank->lock, flags);
|
||||||
_set_gpio_debounce(bank, offset, debounce);
|
_set_gpio_debounce(bank, offset, debounce);
|
||||||
spin_unlock_irqrestore(&bank->lock, flags);
|
spin_unlock_irqrestore(&bank->lock, flags);
|
||||||
|
@ -976,6 +970,10 @@ static void omap_gpio_mod_init(struct gpio_bank *bank)
|
||||||
/* Initialize interface clk ungated, module enabled */
|
/* Initialize interface clk ungated, module enabled */
|
||||||
if (bank->regs->ctrl)
|
if (bank->regs->ctrl)
|
||||||
__raw_writel(0, base + bank->regs->ctrl);
|
__raw_writel(0, base + bank->regs->ctrl);
|
||||||
|
|
||||||
|
bank->dbck = clk_get(bank->dev, "dbclk");
|
||||||
|
if (IS_ERR(bank->dbck))
|
||||||
|
dev_err(bank->dev, "Could not get gpio dbck\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static __devinit void
|
static __devinit void
|
||||||
|
|
|
@ -78,10 +78,10 @@ struct pca953x_chip {
|
||||||
|
|
||||||
#ifdef CONFIG_GPIO_PCA953X_IRQ
|
#ifdef CONFIG_GPIO_PCA953X_IRQ
|
||||||
struct mutex irq_lock;
|
struct mutex irq_lock;
|
||||||
uint16_t irq_mask;
|
u32 irq_mask;
|
||||||
uint16_t irq_stat;
|
u32 irq_stat;
|
||||||
uint16_t irq_trig_raise;
|
u32 irq_trig_raise;
|
||||||
uint16_t irq_trig_fall;
|
u32 irq_trig_fall;
|
||||||
int irq_base;
|
int irq_base;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -98,12 +98,11 @@ static int pca953x_write_reg(struct pca953x_chip *chip, int reg, u32 val)
|
||||||
if (chip->gpio_chip.ngpio <= 8)
|
if (chip->gpio_chip.ngpio <= 8)
|
||||||
ret = i2c_smbus_write_byte_data(chip->client, reg, val);
|
ret = i2c_smbus_write_byte_data(chip->client, reg, val);
|
||||||
else if (chip->gpio_chip.ngpio == 24) {
|
else if (chip->gpio_chip.ngpio == 24) {
|
||||||
ret = i2c_smbus_write_word_data(chip->client,
|
cpu_to_le32s(&val);
|
||||||
|
ret = i2c_smbus_write_i2c_block_data(chip->client,
|
||||||
(reg << 2) | REG_ADDR_AI,
|
(reg << 2) | REG_ADDR_AI,
|
||||||
val & 0xffff);
|
3,
|
||||||
ret = i2c_smbus_write_byte_data(chip->client,
|
(u8 *) &val);
|
||||||
(reg << 2) + 2,
|
|
||||||
(val & 0xff0000) >> 16);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
switch (chip->chip_type) {
|
switch (chip->chip_type) {
|
||||||
|
@ -135,22 +134,27 @@ static int pca953x_read_reg(struct pca953x_chip *chip, int reg, u32 *val)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (chip->gpio_chip.ngpio <= 8)
|
if (chip->gpio_chip.ngpio <= 8) {
|
||||||
ret = i2c_smbus_read_byte_data(chip->client, reg);
|
ret = i2c_smbus_read_byte_data(chip->client, reg);
|
||||||
else if (chip->gpio_chip.ngpio == 24) {
|
*val = ret;
|
||||||
ret = i2c_smbus_read_word_data(chip->client, reg << 2);
|
|
||||||
ret |= (i2c_smbus_read_byte_data(chip->client,
|
|
||||||
(reg << 2) + 2)<<16);
|
|
||||||
}
|
}
|
||||||
else
|
else if (chip->gpio_chip.ngpio == 24) {
|
||||||
|
*val = 0;
|
||||||
|
ret = i2c_smbus_read_i2c_block_data(chip->client,
|
||||||
|
(reg << 2) | REG_ADDR_AI,
|
||||||
|
3,
|
||||||
|
(u8 *) val);
|
||||||
|
le32_to_cpus(val);
|
||||||
|
} else {
|
||||||
ret = i2c_smbus_read_word_data(chip->client, reg << 1);
|
ret = i2c_smbus_read_word_data(chip->client, reg << 1);
|
||||||
|
*val = ret;
|
||||||
|
}
|
||||||
|
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
dev_err(&chip->client->dev, "failed reading register\n");
|
dev_err(&chip->client->dev, "failed reading register\n");
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
*val = (u32)ret;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -349,8 +353,8 @@ static void pca953x_irq_bus_lock(struct irq_data *d)
|
||||||
static void pca953x_irq_bus_sync_unlock(struct irq_data *d)
|
static void pca953x_irq_bus_sync_unlock(struct irq_data *d)
|
||||||
{
|
{
|
||||||
struct pca953x_chip *chip = irq_data_get_irq_chip_data(d);
|
struct pca953x_chip *chip = irq_data_get_irq_chip_data(d);
|
||||||
uint16_t new_irqs;
|
u32 new_irqs;
|
||||||
uint16_t level;
|
u32 level;
|
||||||
|
|
||||||
/* Look for any newly setup interrupt */
|
/* Look for any newly setup interrupt */
|
||||||
new_irqs = chip->irq_trig_fall | chip->irq_trig_raise;
|
new_irqs = chip->irq_trig_fall | chip->irq_trig_raise;
|
||||||
|
@ -368,8 +372,8 @@ static void pca953x_irq_bus_sync_unlock(struct irq_data *d)
|
||||||
static int pca953x_irq_set_type(struct irq_data *d, unsigned int type)
|
static int pca953x_irq_set_type(struct irq_data *d, unsigned int type)
|
||||||
{
|
{
|
||||||
struct pca953x_chip *chip = irq_data_get_irq_chip_data(d);
|
struct pca953x_chip *chip = irq_data_get_irq_chip_data(d);
|
||||||
uint16_t level = d->irq - chip->irq_base;
|
u32 level = d->irq - chip->irq_base;
|
||||||
uint16_t mask = 1 << level;
|
u32 mask = 1 << level;
|
||||||
|
|
||||||
if (!(type & IRQ_TYPE_EDGE_BOTH)) {
|
if (!(type & IRQ_TYPE_EDGE_BOTH)) {
|
||||||
dev_err(&chip->client->dev, "irq %d: unsupported type %d\n",
|
dev_err(&chip->client->dev, "irq %d: unsupported type %d\n",
|
||||||
|
@ -399,12 +403,12 @@ static struct irq_chip pca953x_irq_chip = {
|
||||||
.irq_set_type = pca953x_irq_set_type,
|
.irq_set_type = pca953x_irq_set_type,
|
||||||
};
|
};
|
||||||
|
|
||||||
static uint16_t pca953x_irq_pending(struct pca953x_chip *chip)
|
static u32 pca953x_irq_pending(struct pca953x_chip *chip)
|
||||||
{
|
{
|
||||||
u32 cur_stat;
|
u32 cur_stat;
|
||||||
uint16_t old_stat;
|
u32 old_stat;
|
||||||
uint16_t pending;
|
u32 pending;
|
||||||
uint16_t trigger;
|
u32 trigger;
|
||||||
int ret, offset = 0;
|
int ret, offset = 0;
|
||||||
|
|
||||||
switch (chip->chip_type) {
|
switch (chip->chip_type) {
|
||||||
|
@ -440,8 +444,8 @@ static uint16_t pca953x_irq_pending(struct pca953x_chip *chip)
|
||||||
static irqreturn_t pca953x_irq_handler(int irq, void *devid)
|
static irqreturn_t pca953x_irq_handler(int irq, void *devid)
|
||||||
{
|
{
|
||||||
struct pca953x_chip *chip = devid;
|
struct pca953x_chip *chip = devid;
|
||||||
uint16_t pending;
|
u32 pending;
|
||||||
uint16_t level;
|
u32 level;
|
||||||
|
|
||||||
pending = pca953x_irq_pending(chip);
|
pending = pca953x_irq_pending(chip);
|
||||||
|
|
||||||
|
@ -564,7 +568,7 @@ static void pca953x_irq_teardown(struct pca953x_chip *chip)
|
||||||
* WARNING: This is DEPRECATED and will be removed eventually!
|
* WARNING: This is DEPRECATED and will be removed eventually!
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
pca953x_get_alt_pdata(struct i2c_client *client, int *gpio_base, int *invert)
|
pca953x_get_alt_pdata(struct i2c_client *client, int *gpio_base, u32 *invert)
|
||||||
{
|
{
|
||||||
struct device_node *node;
|
struct device_node *node;
|
||||||
const __be32 *val;
|
const __be32 *val;
|
||||||
|
@ -592,13 +596,13 @@ pca953x_get_alt_pdata(struct i2c_client *client, int *gpio_base, int *invert)
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
static void
|
static void
|
||||||
pca953x_get_alt_pdata(struct i2c_client *client, int *gpio_base, int *invert)
|
pca953x_get_alt_pdata(struct i2c_client *client, int *gpio_base, u32 *invert)
|
||||||
{
|
{
|
||||||
*gpio_base = -1;
|
*gpio_base = -1;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int __devinit device_pca953x_init(struct pca953x_chip *chip, int invert)
|
static int __devinit device_pca953x_init(struct pca953x_chip *chip, u32 invert)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
@ -617,7 +621,7 @@ static int __devinit device_pca953x_init(struct pca953x_chip *chip, int invert)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __devinit device_pca957x_init(struct pca953x_chip *chip, int invert)
|
static int __devinit device_pca957x_init(struct pca953x_chip *chip, u32 invert)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
u32 val = 0;
|
u32 val = 0;
|
||||||
|
@ -653,8 +657,9 @@ static int __devinit pca953x_probe(struct i2c_client *client,
|
||||||
{
|
{
|
||||||
struct pca953x_platform_data *pdata;
|
struct pca953x_platform_data *pdata;
|
||||||
struct pca953x_chip *chip;
|
struct pca953x_chip *chip;
|
||||||
int irq_base=0, invert=0;
|
int irq_base = 0;
|
||||||
int ret;
|
int ret;
|
||||||
|
u32 invert = 0;
|
||||||
|
|
||||||
chip = kzalloc(sizeof(struct pca953x_chip), GFP_KERNEL);
|
chip = kzalloc(sizeof(struct pca953x_chip), GFP_KERNEL);
|
||||||
if (chip == NULL)
|
if (chip == NULL)
|
||||||
|
|
|
@ -61,61 +61,28 @@ struct pcf857x {
|
||||||
struct i2c_client *client;
|
struct i2c_client *client;
|
||||||
struct mutex lock; /* protect 'out' */
|
struct mutex lock; /* protect 'out' */
|
||||||
unsigned out; /* software latch */
|
unsigned out; /* software latch */
|
||||||
|
|
||||||
|
int (*write)(struct i2c_client *client, unsigned data);
|
||||||
|
int (*read)(struct i2c_client *client);
|
||||||
};
|
};
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------*/
|
||||||
|
|
||||||
/* Talk to 8-bit I/O expander */
|
/* Talk to 8-bit I/O expander */
|
||||||
|
|
||||||
static int pcf857x_input8(struct gpio_chip *chip, unsigned offset)
|
static int i2c_write_le8(struct i2c_client *client, unsigned data)
|
||||||
{
|
{
|
||||||
struct pcf857x *gpio = container_of(chip, struct pcf857x, chip);
|
return i2c_smbus_write_byte(client, data);
|
||||||
int status;
|
|
||||||
|
|
||||||
mutex_lock(&gpio->lock);
|
|
||||||
gpio->out |= (1 << offset);
|
|
||||||
status = i2c_smbus_write_byte(gpio->client, gpio->out);
|
|
||||||
mutex_unlock(&gpio->lock);
|
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pcf857x_get8(struct gpio_chip *chip, unsigned offset)
|
static int i2c_read_le8(struct i2c_client *client)
|
||||||
{
|
{
|
||||||
struct pcf857x *gpio = container_of(chip, struct pcf857x, chip);
|
return (int)i2c_smbus_read_byte(client);
|
||||||
s32 value;
|
|
||||||
|
|
||||||
value = i2c_smbus_read_byte(gpio->client);
|
|
||||||
return (value < 0) ? 0 : (value & (1 << offset));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pcf857x_output8(struct gpio_chip *chip, unsigned offset, int value)
|
|
||||||
{
|
|
||||||
struct pcf857x *gpio = container_of(chip, struct pcf857x, chip);
|
|
||||||
unsigned bit = 1 << offset;
|
|
||||||
int status;
|
|
||||||
|
|
||||||
mutex_lock(&gpio->lock);
|
|
||||||
if (value)
|
|
||||||
gpio->out |= bit;
|
|
||||||
else
|
|
||||||
gpio->out &= ~bit;
|
|
||||||
status = i2c_smbus_write_byte(gpio->client, gpio->out);
|
|
||||||
mutex_unlock(&gpio->lock);
|
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void pcf857x_set8(struct gpio_chip *chip, unsigned offset, int value)
|
|
||||||
{
|
|
||||||
pcf857x_output8(chip, offset, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
/* Talk to 16-bit I/O expander */
|
/* Talk to 16-bit I/O expander */
|
||||||
|
|
||||||
static int i2c_write_le16(struct i2c_client *client, u16 word)
|
static int i2c_write_le16(struct i2c_client *client, unsigned word)
|
||||||
{
|
{
|
||||||
u8 buf[2] = { word & 0xff, word >> 8, };
|
u8 buf[2] = { word & 0xff, word >> 8, };
|
||||||
int status;
|
int status;
|
||||||
|
@ -135,29 +102,31 @@ static int i2c_read_le16(struct i2c_client *client)
|
||||||
return (buf[1] << 8) | buf[0];
|
return (buf[1] << 8) | buf[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pcf857x_input16(struct gpio_chip *chip, unsigned offset)
|
/*-------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
static int pcf857x_input(struct gpio_chip *chip, unsigned offset)
|
||||||
{
|
{
|
||||||
struct pcf857x *gpio = container_of(chip, struct pcf857x, chip);
|
struct pcf857x *gpio = container_of(chip, struct pcf857x, chip);
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
mutex_lock(&gpio->lock);
|
mutex_lock(&gpio->lock);
|
||||||
gpio->out |= (1 << offset);
|
gpio->out |= (1 << offset);
|
||||||
status = i2c_write_le16(gpio->client, gpio->out);
|
status = gpio->write(gpio->client, gpio->out);
|
||||||
mutex_unlock(&gpio->lock);
|
mutex_unlock(&gpio->lock);
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pcf857x_get16(struct gpio_chip *chip, unsigned offset)
|
static int pcf857x_get(struct gpio_chip *chip, unsigned offset)
|
||||||
{
|
{
|
||||||
struct pcf857x *gpio = container_of(chip, struct pcf857x, chip);
|
struct pcf857x *gpio = container_of(chip, struct pcf857x, chip);
|
||||||
int value;
|
int value;
|
||||||
|
|
||||||
value = i2c_read_le16(gpio->client);
|
value = gpio->read(gpio->client);
|
||||||
return (value < 0) ? 0 : (value & (1 << offset));
|
return (value < 0) ? 0 : (value & (1 << offset));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pcf857x_output16(struct gpio_chip *chip, unsigned offset, int value)
|
static int pcf857x_output(struct gpio_chip *chip, unsigned offset, int value)
|
||||||
{
|
{
|
||||||
struct pcf857x *gpio = container_of(chip, struct pcf857x, chip);
|
struct pcf857x *gpio = container_of(chip, struct pcf857x, chip);
|
||||||
unsigned bit = 1 << offset;
|
unsigned bit = 1 << offset;
|
||||||
|
@ -168,15 +137,15 @@ static int pcf857x_output16(struct gpio_chip *chip, unsigned offset, int value)
|
||||||
gpio->out |= bit;
|
gpio->out |= bit;
|
||||||
else
|
else
|
||||||
gpio->out &= ~bit;
|
gpio->out &= ~bit;
|
||||||
status = i2c_write_le16(gpio->client, gpio->out);
|
status = gpio->write(gpio->client, gpio->out);
|
||||||
mutex_unlock(&gpio->lock);
|
mutex_unlock(&gpio->lock);
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pcf857x_set16(struct gpio_chip *chip, unsigned offset, int value)
|
static void pcf857x_set(struct gpio_chip *chip, unsigned offset, int value)
|
||||||
{
|
{
|
||||||
pcf857x_output16(chip, offset, value);
|
pcf857x_output(chip, offset, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------*/
|
||||||
|
@ -200,10 +169,15 @@ static int pcf857x_probe(struct i2c_client *client,
|
||||||
|
|
||||||
mutex_init(&gpio->lock);
|
mutex_init(&gpio->lock);
|
||||||
|
|
||||||
gpio->chip.base = pdata ? pdata->gpio_base : -1;
|
gpio->chip.base = pdata ? pdata->gpio_base : -1;
|
||||||
gpio->chip.can_sleep = 1;
|
gpio->chip.can_sleep = 1;
|
||||||
gpio->chip.dev = &client->dev;
|
gpio->chip.dev = &client->dev;
|
||||||
gpio->chip.owner = THIS_MODULE;
|
gpio->chip.owner = THIS_MODULE;
|
||||||
|
gpio->chip.get = pcf857x_get;
|
||||||
|
gpio->chip.set = pcf857x_set;
|
||||||
|
gpio->chip.direction_input = pcf857x_input;
|
||||||
|
gpio->chip.direction_output = pcf857x_output;
|
||||||
|
gpio->chip.ngpio = id->driver_data;
|
||||||
|
|
||||||
/* NOTE: the OnSemi jlc1562b is also largely compatible with
|
/* NOTE: the OnSemi jlc1562b is also largely compatible with
|
||||||
* these parts, notably for output. It has a low-resolution
|
* these parts, notably for output. It has a low-resolution
|
||||||
|
@ -216,12 +190,9 @@ static int pcf857x_probe(struct i2c_client *client,
|
||||||
*
|
*
|
||||||
* NOTE: we don't distinguish here between *4 and *4a parts.
|
* NOTE: we don't distinguish here between *4 and *4a parts.
|
||||||
*/
|
*/
|
||||||
gpio->chip.ngpio = id->driver_data;
|
|
||||||
if (gpio->chip.ngpio == 8) {
|
if (gpio->chip.ngpio == 8) {
|
||||||
gpio->chip.direction_input = pcf857x_input8;
|
gpio->write = i2c_write_le8;
|
||||||
gpio->chip.get = pcf857x_get8;
|
gpio->read = i2c_read_le8;
|
||||||
gpio->chip.direction_output = pcf857x_output8;
|
|
||||||
gpio->chip.set = pcf857x_set8;
|
|
||||||
|
|
||||||
if (!i2c_check_functionality(client->adapter,
|
if (!i2c_check_functionality(client->adapter,
|
||||||
I2C_FUNC_SMBUS_BYTE))
|
I2C_FUNC_SMBUS_BYTE))
|
||||||
|
@ -238,10 +209,8 @@ static int pcf857x_probe(struct i2c_client *client,
|
||||||
* NOTE: we don't distinguish here between '75 and '75c parts.
|
* NOTE: we don't distinguish here between '75 and '75c parts.
|
||||||
*/
|
*/
|
||||||
} else if (gpio->chip.ngpio == 16) {
|
} else if (gpio->chip.ngpio == 16) {
|
||||||
gpio->chip.direction_input = pcf857x_input16;
|
gpio->write = i2c_write_le16;
|
||||||
gpio->chip.get = pcf857x_get16;
|
gpio->read = i2c_read_le16;
|
||||||
gpio->chip.direction_output = pcf857x_output16;
|
|
||||||
gpio->chip.set = pcf857x_set16;
|
|
||||||
|
|
||||||
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
|
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
|
||||||
status = -EIO;
|
status = -EIO;
|
||||||
|
|
|
@ -2681,11 +2681,14 @@ static int exynos_gpio_xlate(struct gpio_chip *gc,
|
||||||
|
|
||||||
if (s3c_gpio_cfgpin(pin, S3C_GPIO_SFN(gpiospec->args[1])))
|
if (s3c_gpio_cfgpin(pin, S3C_GPIO_SFN(gpiospec->args[1])))
|
||||||
pr_warn("gpio_xlate: failed to set pin function\n");
|
pr_warn("gpio_xlate: failed to set pin function\n");
|
||||||
if (s3c_gpio_setpull(pin, gpiospec->args[2]))
|
if (s3c_gpio_setpull(pin, gpiospec->args[2] & 0xffff))
|
||||||
pr_warn("gpio_xlate: failed to set pin pull up/down\n");
|
pr_warn("gpio_xlate: failed to set pin pull up/down\n");
|
||||||
if (s5p_gpio_set_drvstr(pin, gpiospec->args[3]))
|
if (s5p_gpio_set_drvstr(pin, gpiospec->args[3]))
|
||||||
pr_warn("gpio_xlate: failed to set pin drive strength\n");
|
pr_warn("gpio_xlate: failed to set pin drive strength\n");
|
||||||
|
|
||||||
|
if (flags)
|
||||||
|
*flags = gpiospec->args[2] >> 16;
|
||||||
|
|
||||||
return gpiospec->args[0];
|
return gpiospec->args[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include <linux/mfd/core.h>
|
#include <linux/mfd/core.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
#include <linux/seq_file.h>
|
#include <linux/seq_file.h>
|
||||||
|
#include <linux/regmap.h>
|
||||||
|
|
||||||
#include <linux/mfd/wm8994/core.h>
|
#include <linux/mfd/wm8994/core.h>
|
||||||
#include <linux/mfd/wm8994/pdata.h>
|
#include <linux/mfd/wm8994/pdata.h>
|
||||||
|
@ -112,10 +113,7 @@ static int wm8994_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
|
||||||
struct wm8994_gpio *wm8994_gpio = to_wm8994_gpio(chip);
|
struct wm8994_gpio *wm8994_gpio = to_wm8994_gpio(chip);
|
||||||
struct wm8994 *wm8994 = wm8994_gpio->wm8994;
|
struct wm8994 *wm8994 = wm8994_gpio->wm8994;
|
||||||
|
|
||||||
if (!wm8994->irq_base)
|
return regmap_irq_get_virq(wm8994->irq_data, offset);
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
return wm8994->irq_base + offset;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -254,7 +252,8 @@ static int __devinit wm8994_gpio_probe(struct platform_device *pdev)
|
||||||
struct wm8994_gpio *wm8994_gpio;
|
struct wm8994_gpio *wm8994_gpio;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
wm8994_gpio = kzalloc(sizeof(*wm8994_gpio), GFP_KERNEL);
|
wm8994_gpio = devm_kzalloc(&pdev->dev, sizeof(*wm8994_gpio),
|
||||||
|
GFP_KERNEL);
|
||||||
if (wm8994_gpio == NULL)
|
if (wm8994_gpio == NULL)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
@ -279,20 +278,14 @@ static int __devinit wm8994_gpio_probe(struct platform_device *pdev)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
kfree(wm8994_gpio);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __devexit wm8994_gpio_remove(struct platform_device *pdev)
|
static int __devexit wm8994_gpio_remove(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct wm8994_gpio *wm8994_gpio = platform_get_drvdata(pdev);
|
struct wm8994_gpio *wm8994_gpio = platform_get_drvdata(pdev);
|
||||||
int ret;
|
|
||||||
|
|
||||||
ret = gpiochip_remove(&wm8994_gpio->gpio_chip);
|
return gpiochip_remove(&wm8994_gpio->gpio_chip);
|
||||||
if (ret == 0)
|
|
||||||
kfree(wm8994_gpio);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct platform_driver wm8994_gpio_driver = {
|
static struct platform_driver wm8994_gpio_driver = {
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
#include <linux/of_gpio.h>
|
#include <linux/of_gpio.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
|
|
||||||
/* Private data structure for of_gpiochip_is_match */
|
/* Private data structure for of_gpiochip_find_and_xlate */
|
||||||
struct gg_data {
|
struct gg_data {
|
||||||
enum of_gpio_flags *flags;
|
enum of_gpio_flags *flags;
|
||||||
struct of_phandle_args gpiospec;
|
struct of_phandle_args gpiospec;
|
||||||
|
@ -62,7 +62,10 @@ static int of_gpiochip_find_and_xlate(struct gpio_chip *gc, void *data)
|
||||||
int of_get_named_gpio_flags(struct device_node *np, const char *propname,
|
int of_get_named_gpio_flags(struct device_node *np, const char *propname,
|
||||||
int index, enum of_gpio_flags *flags)
|
int index, enum of_gpio_flags *flags)
|
||||||
{
|
{
|
||||||
struct gg_data gg_data = { .flags = flags, .out_gpio = -ENODEV };
|
/* Return -EPROBE_DEFER to support probe() functions to be called
|
||||||
|
* later when the GPIO actually becomes available
|
||||||
|
*/
|
||||||
|
struct gg_data gg_data = { .flags = flags, .out_gpio = -EPROBE_DEFER };
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/* .of_xlate might decide to not fill in the flags, so clear it. */
|
/* .of_xlate might decide to not fill in the flags, so clear it. */
|
||||||
|
@ -73,7 +76,7 @@ int of_get_named_gpio_flags(struct device_node *np, const char *propname,
|
||||||
&gg_data.gpiospec);
|
&gg_data.gpiospec);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
pr_debug("%s: can't parse gpios property\n", __func__);
|
pr_debug("%s: can't parse gpios property\n", __func__);
|
||||||
return -EINVAL;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
gpiochip_find(&gg_data, of_gpiochip_find_and_xlate);
|
gpiochip_find(&gg_data, of_gpiochip_find_and_xlate);
|
||||||
|
|
|
@ -1186,7 +1186,7 @@ int gpio_request(unsigned gpio, const char *label)
|
||||||
{
|
{
|
||||||
struct gpio_desc *desc;
|
struct gpio_desc *desc;
|
||||||
struct gpio_chip *chip;
|
struct gpio_chip *chip;
|
||||||
int status = -EINVAL;
|
int status = -EPROBE_DEFER;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
spin_lock_irqsave(&gpio_lock, flags);
|
spin_lock_irqsave(&gpio_lock, flags);
|
||||||
|
|
|
@ -11,7 +11,7 @@ struct pca953x_platform_data {
|
||||||
unsigned gpio_base;
|
unsigned gpio_base;
|
||||||
|
|
||||||
/* initial polarity inversion setting */
|
/* initial polarity inversion setting */
|
||||||
uint16_t invert;
|
u32 invert;
|
||||||
|
|
||||||
/* interrupt base */
|
/* interrupt base */
|
||||||
int irq_base;
|
int irq_base;
|
||||||
|
|
Loading…
Reference in New Issue