aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOlof Johansson <olof@lixom.net>2012-11-21 10:18:54 -0800
committerOlof Johansson <olof@lixom.net>2012-11-21 10:18:54 -0800
commit41739b60b3c00e0591d1a413276ddfa0d0b1ea89 (patch)
tree9d94865a3ace7e1f2d6f892c0fe03ffc896cafd1
parent24e93941f26e28b2f884d30dc8bfb4c7c5d905d1 (diff)
parent4a991b410cd7940c48f261e854e8698923e23fd2 (diff)
Merge branch 'samsung/pinctrl' into next/soc
From Kukjin Kim: Here is Samsung DT for v3.8 and this is including DT for EXYNOS4X12 SoC, SMDK4412 board, pinctrl for exynos4x12, TMU, MFC, SATA and SATA PHY. As I commented on [4/7], this branch merged pinctrl/samsung to support pinctrl for exynos4x12 without useless merge conflicts. * samsung/pinctrl: pinctrl: samsung: Update error check for unsigned variables pinctrl: samsung: Add support for EXYNOS4X12 Documentation: Update samsung-pinctrl device tree bindings documentation pinctrl: samsung: Add GPIO to IRQ translation pinctrl: exynos: Set pin function to EINT in irq_set_type of wake-up EINT pinctrl: samsung: Use per-bank IRQ domain for wake-up interrupts pinctrl: samsung: Use one GPIO chip per pin bank pinctrl: exynos: Use one IRQ domain per pin bank pinctrl: samsung: Include bank-specific eint offset in bank struct pinctrl: samsung: Hold pointer to driver data in bank struct pinctrl: samsung: Match pin banks with their device nodes ARM: dts: exynos4210-pinctrl: Add nodes for pin banks pinctrl: samsung: Distinguish between pin group and bank nodes pinctrl: samsung: Remove static pin enumerations pinctrl: samsung: Assing pin numbers dynamically pinctrl: samsung: Do not pass gpio_chip to pin_to_reg_bank pinctrl: samsung: Detect and handle unsupported configuration types
-rw-r--r--Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt119
-rw-r--r--arch/arm/boot/dts/exynos4210-pinctrl.dtsi278
-rw-r--r--arch/arm/boot/dts/exynos4210.dtsi241
-rw-r--r--drivers/pinctrl/pinctrl-exynos.c477
-rw-r--r--drivers/pinctrl/pinctrl-exynos.h170
-rw-r--r--drivers/pinctrl/pinctrl-samsung.c207
-rw-r--r--drivers/pinctrl/pinctrl-samsung.h30
7 files changed, 856 insertions, 666 deletions
diff --git a/Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt
index 03dee50532f5..e97a27856b21 100644
--- a/Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt
+++ b/Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt
@@ -8,13 +8,20 @@ on-chip controllers onto these pads.
Required Properties:
- compatible: should be one of the following.
- "samsung,pinctrl-exynos4210": for Exynos4210 compatible pin-controller.
+ - "samsung,pinctrl-exynos4x12": for Exynos4x12 compatible pin-controller.
- "samsung,pinctrl-exynos5250": for Exynos5250 compatible pin-controller.
- reg: Base address of the pin controller hardware module and length of
the address space it occupies.
-- interrupts: interrupt specifier for the controller. The format and value of
- the interrupt specifier depends on the interrupt parent for the controller.
+- Pin banks as child nodes: Pin banks of the controller are represented by child
+ nodes of the controller node. Bank name is taken from name of the node. Each
+ bank node must contain following properties:
+
+ - gpio-controller: identifies the node as a gpio controller and pin bank.
+ - #gpio-cells: number of cells in GPIO specifier. Since the generic GPIO
+ binding is used, the amount of cells must be specified as 2. See generic
+ GPIO binding documentation for description of particular cells.
- Pin mux/config groups as child nodes: The pin mux (selecting pin function
mode) and pin config (pull up/down, driver strength) settings are represented
@@ -72,16 +79,24 @@ used as system wakeup events.
A. External GPIO Interrupts: For supporting external gpio interrupts, the
following properties should be specified in the pin-controller device node.
-- interrupt-controller: identifies the controller node as interrupt-parent.
-- #interrupt-cells: the value of this property should be 2.
- - First Cell: represents the external gpio interrupt number local to the
- external gpio interrupt space of the controller.
- - Second Cell: flags to identify the type of the interrupt
- - 1 = rising edge triggered
- - 2 = falling edge triggered
- - 3 = rising and falling edge triggered
- - 4 = high level triggered
- - 8 = low level triggered
+ - interrupt-parent: phandle of the interrupt parent to which the external
+ GPIO interrupts are forwarded to.
+ - interrupts: interrupt specifier for the controller. The format and value of
+ the interrupt specifier depends on the interrupt parent for the controller.
+
+ In addition, following properties must be present in node of every bank
+ of pins supporting GPIO interrupts:
+
+ - interrupt-controller: identifies the controller node as interrupt-parent.
+ - #interrupt-cells: the value of this property should be 2.
+ - First Cell: represents the external gpio interrupt number local to the
+ external gpio interrupt space of the controller.
+ - Second Cell: flags to identify the type of the interrupt
+ - 1 = rising edge triggered
+ - 2 = falling edge triggered
+ - 3 = rising and falling edge triggered
+ - 4 = high level triggered
+ - 8 = low level triggered
B. External Wakeup Interrupts: For supporting external wakeup interrupts, a
child node representing the external wakeup interrupt controller should be
@@ -94,6 +109,11 @@ B. External Wakeup Interrupts: For supporting external wakeup interrupts, a
found on Samsung Exynos4210 SoC.
- interrupt-parent: phandle of the interrupt parent to which the external
wakeup interrupts are forwarded to.
+ - interrupts: interrupt used by multiplexed wakeup interrupts.
+
+ In addition, following properties must be present in node of every bank
+ of pins supporting wake-up interrupts:
+
- interrupt-controller: identifies the node as interrupt-parent.
- #interrupt-cells: the value of this property should be 2
- First Cell: represents the external wakeup interrupt number local to
@@ -105,11 +125,63 @@ B. External Wakeup Interrupts: For supporting external wakeup interrupts, a
- 4 = high level triggered
- 8 = low level triggered
+ Node of every bank of pins supporting direct wake-up interrupts (without
+ multiplexing) must contain following properties:
+
+ - interrupt-parent: phandle of the interrupt parent to which the external
+ wakeup interrupts are forwarded to.
+ - interrupts: interrupts of the interrupt parent which are used for external
+ wakeup interrupts from pins of the bank, must contain interrupts for all
+ pins of the bank.
+
Aliases:
All the pin controller nodes should be represented in the aliases node using
the following format 'pinctrl{n}' where n is a unique number for the alias.
+Example: A pin-controller node with pin banks:
+
+ pinctrl_0: pinctrl@11400000 {
+ compatible = "samsung,pinctrl-exynos4210";
+ reg = <0x11400000 0x1000>;
+ interrupts = <0 47 0>;
+
+ /* ... */
+
+ /* Pin bank without external interrupts */
+ gpy0: gpy0 {
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ /* ... */
+
+ /* Pin bank with external GPIO or muxed wake-up interrupts */
+ gpj0: gpj0 {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ /* ... */
+
+ /* Pin bank with external direct wake-up interrupts */
+ gpx0: gpx0 {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ interrupt-parent = <&gic>;
+ interrupts = <0 16 0>, <0 17 0>, <0 18 0>, <0 19 0>,
+ <0 20 0>, <0 21 0>, <0 22 0>, <0 23 0>;
+ #interrupt-cells = <2>;
+ };
+
+ /* ... */
+ };
+
Example 1: A pin-controller node with pin groups.
pinctrl_0: pinctrl@11400000 {
@@ -117,6 +189,8 @@ Example 1: A pin-controller node with pin groups.
reg = <0x11400000 0x1000>;
interrupts = <0 47 0>;
+ /* ... */
+
uart0_data: uart0-data {
samsung,pins = "gpa0-0", "gpa0-1";
samsung,pin-function = <2>;
@@ -158,20 +232,14 @@ Example 2: A pin-controller node with external wakeup interrupt controller node.
pinctrl_1: pinctrl@11000000 {
compatible = "samsung,pinctrl-exynos4210";
reg = <0x11000000 0x1000>;
- interrupts = <0 46 0>;
- interrupt-controller;
- #interrupt-cells = <2>;
+ interrupts = <0 46 0>
- wakup_eint: wakeup-interrupt-controller {
+ /* ... */
+
+ wakeup-interrupt-controller {
compatible = "samsung,exynos4210-wakeup-eint";
interrupt-parent = <&gic>;
- interrupt-controller;
- #interrupt-cells = <2>;
- interrupts = <0 16 0>, <0 17 0>, <0 18 0>, <0 19 0>,
- <0 20 0>, <0 21 0>, <0 22 0>, <0 23 0>,
- <0 24 0>, <0 25 0>, <0 26 0>, <0 27 0>,
- <0 28 0>, <0 29 0>, <0 30 0>, <0 31 0>,
- <0 32 0>;
+ interrupts = <0 32 0>;
};
};
@@ -190,7 +258,8 @@ Example 4: Set up the default pin state for uart controller.
static int s3c24xx_serial_probe(struct platform_device *pdev) {
struct pinctrl *pinctrl;
- ...
- ...
+
+ /* ... */
+
pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
}
diff --git a/arch/arm/boot/dts/exynos4210-pinctrl.dtsi b/arch/arm/boot/dts/exynos4210-pinctrl.dtsi
index b12cf272ad0d..6a4a1a04221c 100644
--- a/arch/arm/boot/dts/exynos4210-pinctrl.dtsi
+++ b/arch/arm/boot/dts/exynos4210-pinctrl.dtsi
@@ -16,6 +16,134 @@
/ {
pinctrl@11400000 {
+ gpa0: gpa0 {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpa1: gpa1 {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpb: gpb {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpc0: gpc0 {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpc1: gpc1 {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpd0: gpd0 {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpd1: gpd1 {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpe0: gpe0 {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpe1: gpe1 {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpe2: gpe2 {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpe3: gpe3 {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpe4: gpe4 {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpf0: gpf0 {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpf1: gpf1 {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpf2: gpf2 {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpf3: gpf3 {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
uart0_data: uart0-data {
samsung,pins = "gpa0-0", "gpa0-1";
samsung,pin-function = <0x2>;
@@ -205,6 +333,151 @@
};
pinctrl@11000000 {
+ gpj0: gpj0 {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpj1: gpj1 {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpk0: gpk0 {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpk1: gpk1 {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpk2: gpk2 {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpk3: gpk3 {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpl0: gpl0 {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpl1: gpl1 {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpl2: gpl2 {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpy0: gpy0 {
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ gpy1: gpy1 {
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ gpy2: gpy2 {
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ gpy3: gpy3 {
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ gpy4: gpy4 {
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ gpy5: gpy5 {
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ gpy6: gpy6 {
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ gpx0: gpx0 {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ interrupt-parent = <&gic>;
+ interrupts = <0 16 0>, <0 17 0>, <0 18 0>, <0 19 0>,
+ <0 20 0>, <0 21 0>, <0 22 0>, <0 23 0>;
+ #interrupt-cells = <2>;
+ };
+
+ gpx1: gpx1 {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ interrupt-parent = <&gic>;
+ interrupts = <0 24 0>, <0 25 0>, <0 26 0>, <0 27 0>,
+ <0 28 0>, <0 29 0>, <0 30 0>, <0 31 0>;
+ #interrupt-cells = <2>;
+ };
+
+ gpx2: gpx2 {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpx3: gpx3 {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
sd0_clk: sd0-clk {
samsung,pins = "gpk0-0";
samsung,pin-function = <2>;
@@ -438,6 +711,11 @@
};
pinctrl@03860000 {
+ gpz: gpz {
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
i2s0_bus: i2s0-bus {
samsung,pins = "gpz-0", "gpz-1", "gpz-2", "gpz-3",
"gpz-4", "gpz-5", "gpz-6";
diff --git a/arch/arm/boot/dts/exynos4210.dtsi b/arch/arm/boot/dts/exynos4210.dtsi
index 214c557eda7f..d877dbe7ac0e 100644
--- a/arch/arm/boot/dts/exynos4210.dtsi
+++ b/arch/arm/boot/dts/exynos4210.dtsi
@@ -46,27 +46,17 @@
compatible = "samsung,pinctrl-exynos4210";
reg = <0x11400000 0x1000>;
interrupts = <0 47 0>;
- interrupt-controller;
- #interrupt-cells = <2>;
};
pinctrl_1: pinctrl@11000000 {
compatible = "samsung,pinctrl-exynos4210";
reg = <0x11000000 0x1000>;
interrupts = <0 46 0>;
- interrupt-controller;
- #interrupt-cells = <2>;
wakup_eint: wakeup-interrupt-controller {
compatible = "samsung,exynos4210-wakeup-eint";
interrupt-parent = <&gic>;
- interrupt-controller;
- #interrupt-cells = <2>;
- interrupts = <0 16 0>, <0 17 0>, <0 18 0>, <0 19 0>,
- <0 20 0>, <0 21 0>, <0 22 0>, <0 23 0>,
- <0 24 0>, <0 25 0>, <0 26 0>, <0 27 0>,
- <0 28 0>, <0 29 0>, <0 30 0>, <0 31 0>,
- <0 32 0>;
+ interrupts = <0 32 0>;
};
};
@@ -74,233 +64,4 @@
compatible = "samsung,pinctrl-exynos4210";
reg = <0x03860000 0x1000>;
};
-
- gpio-controllers {
- #address-cells = <1>;
- #size-cells = <1>;
- gpio-controller;
- ranges;
-
- gpa0: gpio-controller@11400000 {
- compatible = "samsung,exynos4-gpio";
- reg = <0x11400000 0x20>;
- #gpio-cells = <4>;
- };
-
- gpa1: gpio-controller@11400020 {
- compatible = "samsung,exynos4-gpio";
- reg = <0x11400020 0x20>;
- #gpio-cells = <4>;
- };
-
- gpb: gpio-controller@11400040 {
- compatible = "samsung,exynos4-gpio";
- reg = <0x11400040 0x20>;
- #gpio-cells = <4>;
- };
-
- gpc0: gpio-controller@11400060 {
- compatible = "samsung,exynos4-gpio";
- reg = <0x11400060 0x20>;
- #gpio-cells = <4>;
- };
-
- gpc1: gpio-controller@11400080 {
- compatible = "samsung,exynos4-gpio";
- reg = <0x11400080 0x20>;
- #gpio-cells = <4>;
- };
-
- gpd0: gpio-controller@114000A0 {
- compatible = "samsung,exynos4-gpio";
- reg = <0x114000A0 0x20>;
- #gpio-cells = <4>;
- };
-
- gpd1: gpio-controller@114000C0 {
- compatible = "samsung,exynos4-gpio";
- reg = <0x114000C0 0x20>;
- #gpio-cells = <4>;
- };
-
- gpe0: gpio-controller@114000E0 {
- compatible = "samsung,exynos4-gpio";
- reg = <0x114000E0 0x20>;
- #gpio-cells = <4>;
- };
-
- gpe1: gpio-controller@11400100 {
- compatible = "samsung,exynos4-gpio";
- reg = <0x11400100 0x20>;
- #gpio-cells = <4>;
- };
-
- gpe2: gpio-controller@11400120 {
- compatible = "samsung,exynos4-gpio";
- reg = <0x11400120 0x20>;
- #gpio-cells = <4>;
- };
-
- gpe3: gpio-controller@11400140 {
- compatible = "samsung,exynos4-gpio";
- reg = <0x11400140 0x20>;
- #gpio-cells = <4>;
- };
-
- gpe4: gpio-controller@11400160 {
- compatible = "samsung,exynos4-gpio";
- reg = <0x11400160 0x20>;
- #gpio-cells = <4>;
- };
-
- gpf0: gpio-controller@11400180 {
- compatible = "samsung,exynos4-gpio";
- reg = <0x11400180 0x20>;
- #gpio-cells = <4>;
- };
-
- gpf1: gpio-controller@114001A0 {
- compatible = "samsung,exynos4-gpio";
- reg = <0x114001A0 0x20>;
- #gpio-cells = <4>;
- };
-
- gpf2: gpio-controller@114001C0 {
- compatible = "samsung,exynos4-gpio";
- reg = <0x114001C0 0x20>;
- #gpio-cells = <4>;
- };
-
- gpf3: gpio-controller@114001E0 {
- compatible = "samsung,exynos4-gpio";
- reg = <0x114001E0 0x20>;
- #gpio-cells = <4>;
- };
-
- gpj0: gpio-controller@11000000 {
- compatible = "samsung,exynos4-gpio";
- reg = <0x11000000 0x20>;
- #gpio-cells = <4>;
- };
-
- gpj1: gpio-controller@11000020 {
- compatible = "samsung,exynos4-gpio";
- reg = <0x11000020 0x20>;
- #gpio-cells = <4>;
- };
-
- gpk0: gpio-controller@11000040 {
- compatible = "samsung,exynos4-gpio";
- reg = <0x11000040 0x20>;
- #gpio-cells = <4>;
- };
-
- gpk1: gpio-controller@11000060 {
- compatible = "samsung,exynos4-gpio";
- reg = <0x11000060 0x20>;
- #gpio-cells = <4>;
- };
-
- gpk2: gpio-controller@11000080 {
- compatible = "samsung,exynos4-gpio";
- reg = <0x11000080 0x20>;
- #gpio-cells = <4>;
- };
-
- gpk3: gpio-controller@110000A0 {
- compatible = "samsung,exynos4-gpio";
- reg = <0x110000A0 0x20>;
- #gpio-cells = <4>;
- };
-
- gpl0: gpio-controller@110000C0 {
- compatible = "samsung,exynos4-gpio";
- reg = <0x110000C0 0x20>;
- #gpio-cells = <4>;
- };
-
- gpl1: gpio-controller@110000E0 {
- compatible = "samsung,exynos4-gpio";
- reg = <0x110000E0 0x20>;
- #gpio-cells = <4>;
- };
-
- gpl2: gpio-controller@11000100 {
- compatible = "samsung,exynos4-gpio";
- reg = <0x11000100 0x20>;
- #gpio-cells = <4>;
- };
-
- gpy0: gpio-controller@11000120 {
- compatible = "samsung,exynos4-gpio";
- reg = <0x11000120 0x20>;
- #gpio-cells = <4>;
- };
-
- gpy1: gpio-controller@11000140 {
- compatible = "samsung,exynos4-gpio";
- reg = <0x11000140 0x20>;
- #gpio-cells = <4>;
- };
-
- gpy2: gpio-controller@11000160 {
- compatible = "samsung,exynos4-gpio";
- reg = <0x11000160 0x20>;
- #gpio-cells = <4>;
- };
-
- gpy3: gpio-controller@11000180 {
- compatible = "samsung,exynos4-gpio";
- reg = <0x11000180 0x20>;
- #gpio-cells = <4>;
- };
-
- gpy4: gpio-controller@110001A0 {
- compatible = "samsung,exynos4-gpio";
- reg = <0x110001A0 0x20>;
- #gpio-cells = <4>;
- };
-
- gpy5: gpio-controller@110001C0 {
- compatible = "samsung,exynos4-gpio";
- reg = <0x110001C0 0x20>;
- #gpio-cells = <4>;
- };
-
- gpy6: gpio-controller@110001E0 {
- compatible = "samsung,exynos4-gpio";
- reg = <0x110001E0 0x20>;
- #gpio-cells = <4>;
- };
-
- gpx0: gpio-controller@11000C00 {
- compatible = "samsung,exynos4-gpio";
- reg = <0x11000C00 0x20>;
- #gpio-cells = <4>;
- };
-
- gpx1: gpio-controller@11000C20 {
- compatible = "samsung,exynos4-gpio";
- reg = <0x11000C20 0x20>;
- #gpio-cells = <4>;
- };
-
- gpx2: gpio-controller@11000C40 {
- compatible = "samsung,exynos4-gpio";
- reg = <0x11000C40 0x20>;
- #gpio-cells = <4>;
- };
-
- gpx3: gpio-controller@11000C60 {
- compatible = "samsung,exynos4-gpio";
- reg = <0x11000C60 0x20>;
- #gpio-cells = <4>;
- };
-
- gpz: gpio-controller@03860000 {
- compatible = "samsung,exynos4-gpio";
- reg = <0x03860000 0x20>;
- #gpio-cells = <4>;
- };
- };
};
diff --git a/drivers/pinctrl/pinctrl-exynos.c b/drivers/pinctrl/pinctrl-exynos.c
index 21362f48d370..19fab68a9fbf 100644
--- a/drivers/pinctrl/pinctrl-exynos.c
+++ b/drivers/pinctrl/pinctrl-exynos.c
@@ -40,46 +40,46 @@ static const struct of_device_id exynos_wkup_irq_ids[] = {
static void exynos_gpio_irq_unmask(struct irq_data *irqd)
{
- struct samsung_pinctrl_drv_data *d = irqd->domain->host_data;
- struct exynos_geint_data *edata = irq_data_get_irq_handler_data(irqd);
- unsigned long reg_mask = d->ctrl->geint_mask + edata->eint_offset;
+ struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
+ struct samsung_pinctrl_drv_data *d = bank->drvdata;
+ unsigned long reg_mask = d->ctrl->geint_mask + bank->eint_offset;
unsigned long mask;
mask = readl(d->virt_base + reg_mask);
- mask &= ~(1 << edata->pin);
+ mask &= ~(1 << irqd->hwirq);
writel(mask, d->virt_base + reg_mask);
}
static void exynos_gpio_irq_mask(struct irq_data *irqd)
{
- struct samsung_pinctrl_drv_data *d = irqd->domain->host_data;
- struct exynos_geint_data *edata = irq_data_get_irq_handler_data(irqd);
- unsigned long reg_mask = d->ctrl->geint_mask + edata->eint_offset;
+ struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
+ struct samsung_pinctrl_drv_data *d = bank->drvdata;
+ unsigned long reg_mask = d->ctrl->geint_mask + bank->eint_offset;
unsigned long mask;
mask = readl(d->virt_base + reg_mask);
- mask |= 1 << edata->pin;
+ mask |= 1 << irqd->hwirq;
writel(mask, d->virt_base + reg_mask);
}
static void exynos_gpio_irq_ack(struct irq_data *irqd)
{
- struct samsung_pinctrl_drv_data *d = irqd->domain->host_data;
- struct exynos_geint_data *edata = irq_data_get_irq_handler_data(irqd);
- unsigned long reg_pend = d->ctrl->geint_pend + edata->eint_offset;
+ struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
+ struct samsung_pinctrl_drv_data *d = bank->drvdata;
+ unsigned long reg_pend = d->ctrl->geint_pend + bank->eint_offset;
- writel(1 << edata->pin, d->virt_base + reg_pend);
+ writel(1 << irqd->hwirq, d->virt_base + reg_pend);
}
static int exynos_gpio_irq_set_type(struct irq_data *irqd, unsigned int type)
{
- struct samsung_pinctrl_drv_data *d = irqd->domain->host_data;
+ struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
+ struct samsung_pinctrl_drv_data *d = bank->drvdata;
struct samsung_pin_ctrl *ctrl = d->ctrl;
- struct exynos_geint_data *edata = irq_data_get_irq_handler_data(irqd);
- struct samsung_pin_bank *bank = edata->bank;
- unsigned int shift = EXYNOS_EINT_CON_LEN * edata->pin;
+ 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 + edata->eint_offset;
+ unsigned long reg_con = ctrl->geint_con + bank->eint_offset;
unsigned int mask;
switch (type) {
@@ -114,7 +114,7 @@ static int exynos_gpio_irq_set_type(struct irq_data *irqd, unsigned int type)
writel(con, d->virt_base + reg_con);
reg_con = bank->pctl_offset;
- shift = edata->pin * bank->func_width;
+ shift = pin * bank->func_width;
mask = (1 << bank->func_width) - 1;
con = readl(d->virt_base + reg_con);
@@ -136,82 +136,23 @@ static struct irq_chip exynos_gpio_irq_chip = {
.irq_set_type = exynos_gpio_irq_set_type,
};
-/*
- * given a controller-local external gpio interrupt number, prepare the handler
- * data for it.
- */
-static struct exynos_geint_data *exynos_get_eint_data(irq_hw_number_t hw,
- struct samsung_pinctrl_drv_data *d)
-{
- struct samsung_pin_bank *bank = d->ctrl->pin_banks;
- struct exynos_geint_data *eint_data;
- unsigned int nr_banks = d->ctrl->nr_banks, idx;
- unsigned int irq_base = 0, eint_offset = 0;
-
- if (hw >= d->ctrl->nr_gint) {
- dev_err(d->dev, "unsupported ext-gpio interrupt\n");
- return NULL;
- }
-
- for (idx = 0; idx < nr_banks; idx++, bank++) {
- if (bank->eint_type != EINT_TYPE_GPIO)
- continue;
- if ((hw >= irq_base) && (hw < (irq_base + bank->nr_pins)))
- break;
- irq_base += bank->nr_pins;
- eint_offset += 4;
- }
-
- if (idx == nr_banks) {
- dev_err(d->dev, "pin bank not found for ext-gpio interrupt\n");
- return NULL;
- }
-
- eint_data = devm_kzalloc(d->dev, sizeof(*eint_data), GFP_KERNEL);
- if (!eint_data) {
- dev_err(d->dev, "no memory for eint-gpio data\n");
- return NULL;
- }
-
- eint_data->bank = bank;
- eint_data->pin = hw - irq_base;
- eint_data->eint_offset = eint_offset;
- return eint_data;
-}
-
static int exynos_gpio_irq_map(struct irq_domain *h, unsigned int virq,
irq_hw_number_t hw)
{
- struct samsung_pinctrl_drv_data *d = h->host_data;
- struct exynos_geint_data *eint_data;
-
- eint_data = exynos_get_eint_data(hw, d);
- if (!eint_data)
- return -EINVAL;
+ struct samsung_pin_bank *b = h->host_data;
- irq_set_handler_data(virq, eint_data);
- irq_set_chip_data(virq, h->host_data);
+ irq_set_chip_data(virq, b);
irq_set_chip_and_handler(virq, &exynos_gpio_irq_chip,
handle_level_irq);
set_irq_flags(virq, IRQF_VALID);
return 0;
}
-static void exynos_gpio_irq_unmap(struct irq_domain *h, unsigned int virq)
-{
- struct samsung_pinctrl_drv_data *d = h->host_data;
- struct exynos_geint_data *eint_data;
-
- eint_data = irq_get_handler_data(virq);
- devm_kfree(d->dev, eint_data);
-}
-
/*
* irq domain callbacks for external gpio interrupt controller.
*/
static const struct irq_domain_ops exynos_gpio_irqd_ops = {
.map = exynos_gpio_irq_map,
- .unmap = exynos_gpio_irq_unmap,
.xlate = irq_domain_xlate_twocell,
};
@@ -230,7 +171,7 @@ static irqreturn_t exynos_eint_gpio_irq(int irq, void *data)
return IRQ_HANDLED;
bank += (group - 1);
- virq = irq_linear_revmap(d->gpio_irqd, bank->irq_base + pin);
+ virq = irq_linear_revmap(bank->irq_domain, pin);
if (!virq)
return IRQ_NONE;
generic_handle_irq(virq);
@@ -243,8 +184,10 @@ static irqreturn_t exynos_eint_gpio_irq(int irq, void *data)
*/
static int exynos_eint_gpio_init(struct samsung_pinctrl_drv_data *d)
{
+ struct samsung_pin_bank *bank;
struct device *dev = d->dev;
unsigned int ret;
+ unsigned int i;
if (!d->irq) {
dev_err(dev, "irq number not available\n");
@@ -258,11 +201,16 @@ static int exynos_eint_gpio_init(struct samsung_pinctrl_drv_data *d)
return -ENXIO;
}
- d->gpio_irqd = irq_domain_add_linear(dev->of_node, d->ctrl->nr_gint,
- &exynos_gpio_irqd_ops, d);
- if (!d->gpio_irqd) {
- dev_err(dev, "gpio irq domain allocation failed\n");
- return -ENXIO;
+ bank = d->ctrl->pin_banks;
+ for (i = 0; i < d->ctrl->nr_banks; ++i, ++bank) {
+ if (bank->eint_type != EINT_TYPE_GPIO)
+ continue;
+ bank->irq_domain = irq_domain_add_linear(bank->of_node,
+ bank->nr_pins, &exynos_gpio_irqd_ops, bank);
+ if (!bank->irq_domain) {
+ dev_err(dev, "gpio irq domain add failed\n");
+ return -ENXIO;
+ }
}
return 0;
@@ -270,48 +218,46 @@ static int exynos_eint_gpio_init(struct samsung_pinctrl_drv_data *d)
static void exynos_wkup_irq_unmask(struct irq_data *irqd)
{
- struct samsung_pinctrl_drv_data *d = irq_data_get_irq_chip_data(irqd);
- unsigned int bank = irqd->hwirq / EXYNOS_EINT_MAX_PER_BANK;
- unsigned int pin = irqd->hwirq & (EXYNOS_EINT_MAX_PER_BANK - 1);
- unsigned long reg_mask = d->ctrl->weint_mask + (bank << 2);
+ struct samsung_pin_bank *b = irq_data_get_irq_chip_data(irqd);
+ struct samsung_pinctrl_drv_data *d = b->drvdata;
+ unsigned long reg_mask = d->ctrl->weint_mask + b->eint_offset;
unsigned long mask;
mask = readl(d->virt_base + reg_mask);
- mask &= ~(1 << pin);
+ mask &= ~(1 << irqd->hwirq);
writel(mask, d->virt_base + reg_mask);
}
static void exynos_wkup_irq_mask(struct irq_data *irqd)
{
- struct samsung_pinctrl_drv_data *d = irq_data_get_irq_chip_data(irqd);
- unsigned int bank = irqd->hwirq / EXYNOS_EINT_MAX_PER_BANK;
- unsigned int pin = irqd->hwirq & (EXYNOS_EINT_MAX_PER_BANK - 1);
- unsigned long reg_mask = d->ctrl->weint_mask + (bank << 2);
+ struct samsung_pin_bank *b = irq_data_get_irq_chip_data(irqd);
+ struct samsung_pinctrl_drv_data *d = b->drvdata;
+ unsigned long reg_mask = d->ctrl->weint_mask + b->eint_offset;
unsigned long mask;
mask = readl(d->virt_base + reg_mask);
- mask |= 1 << pin;
+ mask |= 1 << irqd->hwirq;
writel(mask, d->virt_base + reg_mask);
}
static void exynos_wkup_irq_ack(struct irq_data *irqd)
{
- struct samsung_pinctrl_drv_data *d = irq_data_get_irq_chip_data(irqd);
- unsigned int bank = irqd->hwirq / EXYNOS_EINT_MAX_PER_BANK;
- unsigned int pin = irqd->hwirq & (EXYNOS_EINT_MAX_PER_BANK - 1);
- unsigned long pend = d->ctrl->weint_pend + (bank << 2);
+ struct samsung_pin_bank *b = irq_data_get_irq_chip_data(irqd);
+ struct samsung_pinctrl_drv_data *d = b->drvdata;
+ unsigned long pend = d->ctrl->weint_pend + b->eint_offset;
- writel(1 << pin, d->virt_base + pend);
+ writel(1 << irqd->hwirq, d->virt_base + pend);
}
static int exynos_wkup_irq_set_type(struct irq_data *irqd, unsigned int type)
{
- struct samsung_pinctrl_drv_data *d = irq_data_get_irq_chip_data(irqd);
- unsigned int bank = irqd->hwirq / EXYNOS_EINT_MAX_PER_BANK;
- unsigned int pin = irqd->hwirq & (EXYNOS_EINT_MAX_PER_BANK - 1);
- unsigned long reg_con = d->ctrl->weint_con + (bank << 2);
+ struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
+ 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 int mask;
switch (type) {
case IRQ_TYPE_EDGE_RISING:
@@ -343,6 +289,16 @@ static int exynos_wkup_irq_set_type(struct irq_data *irqd, unsigned int type)
con &= ~(EXYNOS_EINT_CON_MASK << shift);
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;
+
+ con = readl(d->virt_base + reg_con);
+ con &= ~(mask << shift);
+ con |= EXYNOS_EINT_FUNC << shift;
+ writel(con, d->virt_base + reg_con);