Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
cloud-kernel
提交
bdd45eaa
cloud-kernel
项目概览
openanolis
/
cloud-kernel
1 年多 前同步成功
通知
161
Star
36
Fork
7
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
10
列表
看板
标记
里程碑
合并请求
2
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
cloud-kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
10
Issue
10
列表
看板
标记
里程碑
合并请求
2
合并请求
2
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
bdd45eaa
编写于
11月 19, 2012
作者:
K
Kukjin Kim
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'next/pinctrl-samsung' into next/dt-exynos4x12
上级
ba51bdd3
6edc794a
变更
7
展开全部
隐藏空白更改
内联
并排
Showing
7 changed file
with
855 addition
and
665 deletion
+855
-665
Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt
...mentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt
+94
-25
arch/arm/boot/dts/exynos4210-pinctrl.dtsi
arch/arm/boot/dts/exynos4210-pinctrl.dtsi
+278
-0
arch/arm/boot/dts/exynos4210.dtsi
arch/arm/boot/dts/exynos4210.dtsi
+1
-240
drivers/pinctrl/pinctrl-exynos.c
drivers/pinctrl/pinctrl-exynos.c
+288
-189
drivers/pinctrl/pinctrl-exynos.h
drivers/pinctrl/pinctrl-exynos.h
+30
-140
drivers/pinctrl/pinctrl-samsung.c
drivers/pinctrl/pinctrl-samsung.c
+148
-57
drivers/pinctrl/pinctrl-samsung.h
drivers/pinctrl/pinctrl-samsung.h
+16
-14
未找到文件。
Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt
浏览文件 @
bdd45eaa
...
@@ -8,13 +8,20 @@ on-chip controllers onto these pads.
...
@@ -8,13 +8,20 @@ on-chip controllers onto these pads.
Required Properties:
Required Properties:
- compatible: should be one of the following.
- compatible: should be one of the following.
- "samsung,pinctrl-exynos4210": for Exynos4210 compatible pin-controller.
- "samsung,pinctrl-exynos4210": for Exynos4210 compatible pin-controller.
- "samsung,pinctrl-exynos4x12": for Exynos4x12 compatible pin-controller.
- "samsung,pinctrl-exynos5250": for Exynos5250 compatible pin-controller.
- "samsung,pinctrl-exynos5250": for Exynos5250 compatible pin-controller.
- reg: Base address of the pin controller hardware module and length of
- reg: Base address of the pin controller hardware module and length of
the address space it occupies.
the address space it occupies.
- interrupts: interrupt specifier for the controller. The format and value of
- Pin banks as child nodes: Pin banks of the controller are represented by child
the interrupt specifier depends on the interrupt parent for the controller.
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
- 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
mode) and pin config (pull up/down, driver strength) settings are represented
...
@@ -72,16 +79,24 @@ used as system wakeup events.
...
@@ -72,16 +79,24 @@ used as system wakeup events.
A. External GPIO Interrupts: For supporting external gpio interrupts, the
A. External GPIO Interrupts: For supporting external gpio interrupts, the
following properties should be specified in the pin-controller device node.
following properties should be specified in the pin-controller device node.
- interrupt-controller: identifies the controller node as interrupt-parent.
- interrupt-parent: phandle of the interrupt parent to which the external
- #interrupt-cells: the value of this property should be 2.
GPIO interrupts are forwarded to.
- First Cell: represents the external gpio interrupt number local to the
- interrupts: interrupt specifier for the controller. The format and value of
external gpio interrupt space of the controller.
the interrupt specifier depends on the interrupt parent for the controller.
- Second Cell: flags to identify the type of the interrupt
- 1 = rising edge triggered
In addition, following properties must be present in node of every bank
- 2 = falling edge triggered
of pins supporting GPIO interrupts:
- 3 = rising and falling edge triggered
- 4 = high level triggered
- interrupt-controller: identifies the controller node as interrupt-parent.
- 8 = low level triggered
- #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
B. External Wakeup Interrupts: For supporting external wakeup interrupts, a
child node representing the external wakeup interrupt controller should be
child node representing the external wakeup interrupt controller should be
...
@@ -94,6 +109,11 @@ B. External Wakeup Interrupts: For supporting external wakeup interrupts, a
...
@@ -94,6 +109,11 @@ B. External Wakeup Interrupts: For supporting external wakeup interrupts, a
found on Samsung Exynos4210 SoC.
found on Samsung Exynos4210 SoC.
- interrupt-parent: phandle of the interrupt parent to which the external
- interrupt-parent: phandle of the interrupt parent to which the external
wakeup interrupts are forwarded to.
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-controller: identifies the node as interrupt-parent.
- #interrupt-cells: the value of this property should be 2
- #interrupt-cells: the value of this property should be 2
- First Cell: represents the external wakeup interrupt number local to
- First Cell: represents the external wakeup interrupt number local to
...
@@ -105,11 +125,63 @@ B. External Wakeup Interrupts: For supporting external wakeup interrupts, a
...
@@ -105,11 +125,63 @@ B. External Wakeup Interrupts: For supporting external wakeup interrupts, a
- 4 = high level triggered
- 4 = high level triggered
- 8 = low 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:
Aliases:
All the pin controller nodes should be represented in the aliases node using
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.
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.
Example 1: A pin-controller node with pin groups.
pinctrl_0: pinctrl@11400000 {
pinctrl_0: pinctrl@11400000 {
...
@@ -117,6 +189,8 @@ Example 1: A pin-controller node with pin groups.
...
@@ -117,6 +189,8 @@ Example 1: A pin-controller node with pin groups.
reg = <0x11400000 0x1000>;
reg = <0x11400000 0x1000>;
interrupts = <0 47 0>;
interrupts = <0 47 0>;
/* ... */
uart0_data: uart0-data {
uart0_data: uart0-data {
samsung,pins = "gpa0-0", "gpa0-1";
samsung,pins = "gpa0-0", "gpa0-1";
samsung,pin-function = <2>;
samsung,pin-function = <2>;
...
@@ -158,20 +232,14 @@ Example 2: A pin-controller node with external wakeup interrupt controller node.
...
@@ -158,20 +232,14 @@ Example 2: A pin-controller node with external wakeup interrupt controller node.
pinctrl_1: pinctrl@11000000 {
pinctrl_1: pinctrl@11000000 {
compatible = "samsung,pinctrl-exynos4210";
compatible = "samsung,pinctrl-exynos4210";
reg = <0x11000000 0x1000>;
reg = <0x11000000 0x1000>;
interrupts = <0 46 0>;
interrupts = <0 46 0>
interrupt-controller;
#interrupt-cells = <2>;
wakup_eint: wakeup-interrupt-controller {
/* ... */
wakeup-interrupt-controller {
compatible = "samsung,exynos4210-wakeup-eint";
compatible = "samsung,exynos4210-wakeup-eint";
interrupt-parent = <&gic>;
interrupt-parent = <&gic>;
interrupt-controller;
interrupts = <0 32 0>;
#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>;
};
};
};
};
...
@@ -190,7 +258,8 @@ Example 4: Set up the default pin state for uart controller.
...
@@ -190,7 +258,8 @@ Example 4: Set up the default pin state for uart controller.
static int s3c24xx_serial_probe(struct platform_device *pdev) {
static int s3c24xx_serial_probe(struct platform_device *pdev) {
struct pinctrl *pinctrl;
struct pinctrl *pinctrl;
...
...
/* ... */
pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
}
}
arch/arm/boot/dts/exynos4210-pinctrl.dtsi
浏览文件 @
bdd45eaa
...
@@ -16,6 +16,134 @@
...
@@ -16,6 +16,134 @@
/ {
/ {
pinctrl@11400000 {
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 {
uart0_data: uart0-data {
samsung,pins = "gpa0-0", "gpa0-1";
samsung,pins = "gpa0-0", "gpa0-1";
samsung,pin-function = <0x2>;
samsung,pin-function = <0x2>;
...
@@ -205,6 +333,151 @@
...
@@ -205,6 +333,151 @@
};
};
pinctrl@11000000 {
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 {
sd0_clk: sd0-clk {
samsung,pins = "gpk0-0";
samsung,pins = "gpk0-0";
samsung,pin-function = <2>;
samsung,pin-function = <2>;
...
@@ -438,6 +711,11 @@
...
@@ -438,6 +711,11 @@
};
};
pinctrl@03860000 {
pinctrl@03860000 {
gpz: gpz {
gpio-controller;
#gpio-cells = <2>;
};
i2s0_bus: i2s0-bus {
i2s0_bus: i2s0-bus {
samsung,pins = "gpz-0", "gpz-1", "gpz-2", "gpz-3",
samsung,pins = "gpz-0", "gpz-1", "gpz-2", "gpz-3",
"gpz-4", "gpz-5", "gpz-6";
"gpz-4", "gpz-5", "gpz-6";
...
...
arch/arm/boot/dts/exynos4210.dtsi
浏览文件 @
bdd45eaa
...
@@ -46,27 +46,17 @@
...
@@ -46,27 +46,17 @@
compatible = "samsung,pinctrl-exynos4210";
compatible = "samsung,pinctrl-exynos4210";
reg = <0x11400000 0x1000>;
reg = <0x11400000 0x1000>;
interrupts = <0 47 0>;
interrupts = <0 47 0>;
interrupt-controller;
#interrupt-cells = <2>;
};
};
pinctrl_1: pinctrl@11000000 {
pinctrl_1: pinctrl@11000000 {
compatible = "samsung,pinctrl-exynos4210";
compatible = "samsung,pinctrl-exynos4210";
reg = <0x11000000 0x1000>;
reg = <0x11000000 0x1000>;
interrupts = <0 46 0>;
interrupts = <0 46 0>;
interrupt-controller;
#interrupt-cells = <2>;
wakup_eint: wakeup-interrupt-controller {
wakup_eint: wakeup-interrupt-controller {
compatible = "samsung,exynos4210-wakeup-eint";
compatible = "samsung,exynos4210-wakeup-eint";
interrupt-parent = <&gic>;
interrupt-parent = <&gic>;
interrupt-controller;
interrupts = <0 32 0>;
#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>;
};
};
};
};
...
@@ -74,233 +64,4 @@
...
@@ -74,233 +64,4 @@
compatible = "samsung,pinctrl-exynos4210";
compatible = "samsung,pinctrl-exynos4210";
reg = <0x03860000 0x1000>;
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>;
};
};
};
};
drivers/pinctrl/pinctrl-exynos.c
浏览文件 @
bdd45eaa
此差异已折叠。
点击以展开。
drivers/pinctrl/pinctrl-exynos.h
浏览文件 @
bdd45eaa
...
@@ -17,125 +17,6 @@
...
@@ -17,125 +17,6 @@
* (at your option) any later version.
* (at your option) any later version.
*/
*/
#define EXYNOS_GPIO_START(__gpio) ((__gpio##_START) + (__gpio##_NR))
#define EXYNOS4210_GPIO_A0_NR (8)
#define EXYNOS4210_GPIO_A1_NR (6)
#define EXYNOS4210_GPIO_B_NR (8)
#define EXYNOS4210_GPIO_C0_NR (5)
#define EXYNOS4210_GPIO_C1_NR (5)
#define EXYNOS4210_GPIO_D0_NR (4)
#define EXYNOS4210_GPIO_D1_NR (4)
#define EXYNOS4210_GPIO_E0_NR (5)
#define EXYNOS4210_GPIO_E1_NR (8)
#define EXYNOS4210_GPIO_E2_NR (6)
#define EXYNOS4210_GPIO_E3_NR (8)
#define EXYNOS4210_GPIO_E4_NR (8)
#define EXYNOS4210_GPIO_F0_NR (8)
#define EXYNOS4210_GPIO_F1_NR (8)
#define EXYNOS4210_GPIO_F2_NR (8)
#define EXYNOS4210_GPIO_F3_NR (6)
#define EXYNOS4210_GPIO_J0_NR (8)
#define EXYNOS4210_GPIO_J1_NR (5)
#define EXYNOS4210_GPIO_K0_NR (7)
#define EXYNOS4210_GPIO_K1_NR (7)
#define EXYNOS4210_GPIO_K2_NR (7)
#define EXYNOS4210_GPIO_K3_NR (7)
#define EXYNOS4210_GPIO_L0_NR (8)
#define EXYNOS4210_GPIO_L1_NR (3)
#define EXYNOS4210_GPIO_L2_NR (8)
#define EXYNOS4210_GPIO_Y0_NR (6)
#define EXYNOS4210_GPIO_Y1_NR (4)
#define EXYNOS4210_GPIO_Y2_NR (6)
#define EXYNOS4210_GPIO_Y3_NR (8)
#define EXYNOS4210_GPIO_Y4_NR (8)
#define EXYNOS4210_GPIO_Y5_NR (8)
#define EXYNOS4210_GPIO_Y6_NR (8)
#define EXYNOS4210_GPIO_X0_NR (8)
#define EXYNOS4210_GPIO_X1_NR (8)
#define EXYNOS4210_GPIO_X2_NR (8)
#define EXYNOS4210_GPIO_X3_NR (8)
#define EXYNOS4210_GPIO_Z_NR (7)
enum
exynos4210_gpio_xa_start
{
EXYNOS4210_GPIO_A0_START
=
0
,
EXYNOS4210_GPIO_A1_START
=
EXYNOS_GPIO_START
(
EXYNOS4210_GPIO_A0
),
EXYNOS4210_GPIO_B_START
=
EXYNOS_GPIO_START
(
EXYNOS4210_GPIO_A1
),
EXYNOS4210_GPIO_C0_START
=
EXYNOS_GPIO_START
(
EXYNOS4210_GPIO_B
),
EXYNOS4210_GPIO_C1_START
=
EXYNOS_GPIO_START
(
EXYNOS4210_GPIO_C0
),
EXYNOS4210_GPIO_D0_START
=
EXYNOS_GPIO_START
(
EXYNOS4210_GPIO_C1
),
EXYNOS4210_GPIO_D1_START
=
EXYNOS_GPIO_START
(
EXYNOS4210_GPIO_D0
),
EXYNOS4210_GPIO_E0_START
=
EXYNOS_GPIO_START
(
EXYNOS4210_GPIO_D1
),
EXYNOS4210_GPIO_E1_START
=
EXYNOS_GPIO_START
(
EXYNOS4210_GPIO_E0
),
EXYNOS4210_GPIO_E2_START
=
EXYNOS_GPIO_START
(
EXYNOS4210_GPIO_E1
),
EXYNOS4210_GPIO_E3_START
=
EXYNOS_GPIO_START
(
EXYNOS4210_GPIO_E2
),
EXYNOS4210_GPIO_E4_START
=
EXYNOS_GPIO_START
(
EXYNOS4210_GPIO_E3
),
EXYNOS4210_GPIO_F0_START
=
EXYNOS_GPIO_START
(
EXYNOS4210_GPIO_E4
),
EXYNOS4210_GPIO_F1_START
=
EXYNOS_GPIO_START
(
EXYNOS4210_GPIO_F0
),
EXYNOS4210_GPIO_F2_START
=
EXYNOS_GPIO_START
(
EXYNOS4210_GPIO_F1
),
EXYNOS4210_GPIO_F3_START
=
EXYNOS_GPIO_START
(
EXYNOS4210_GPIO_F2
),
};
enum
exynos4210_gpio_xb_start
{
EXYNOS4210_GPIO_J0_START
=
0
,
EXYNOS4210_GPIO_J1_START
=
EXYNOS_GPIO_START
(
EXYNOS4210_GPIO_J0
),
EXYNOS4210_GPIO_K0_START
=
EXYNOS_GPIO_START
(
EXYNOS4210_GPIO_J1
),
EXYNOS4210_GPIO_K1_START
=
EXYNOS_GPIO_START
(
EXYNOS4210_GPIO_K0
),
EXYNOS4210_GPIO_K2_START
=
EXYNOS_GPIO_START
(
EXYNOS4210_GPIO_K1
),
EXYNOS4210_GPIO_K3_START
=
EXYNOS_GPIO_START
(
EXYNOS4210_GPIO_K2
),
EXYNOS4210_GPIO_L0_START
=
EXYNOS_GPIO_START
(
EXYNOS4210_GPIO_K3
),
EXYNOS4210_GPIO_L1_START
=
EXYNOS_GPIO_START
(
EXYNOS4210_GPIO_L0
),
EXYNOS4210_GPIO_L2_START
=
EXYNOS_GPIO_START
(
EXYNOS4210_GPIO_L1
),
EXYNOS4210_GPIO_Y0_START
=
EXYNOS_GPIO_START
(
EXYNOS4210_GPIO_L2
),
EXYNOS4210_GPIO_Y1_START
=
EXYNOS_GPIO_START
(
EXYNOS4210_GPIO_Y0
),
EXYNOS4210_GPIO_Y2_START
=
EXYNOS_GPIO_START
(
EXYNOS4210_GPIO_Y1
),
EXYNOS4210_GPIO_Y3_START
=
EXYNOS_GPIO_START
(
EXYNOS4210_GPIO_Y2
),
EXYNOS4210_GPIO_Y4_START
=
EXYNOS_GPIO_START
(
EXYNOS4210_GPIO_Y3
),
EXYNOS4210_GPIO_Y5_START
=
EXYNOS_GPIO_START
(
EXYNOS4210_GPIO_Y4
),
EXYNOS4210_GPIO_Y6_START
=
EXYNOS_GPIO_START
(
EXYNOS4210_GPIO_Y5
),
EXYNOS4210_GPIO_X0_START
=
EXYNOS_GPIO_START
(
EXYNOS4210_GPIO_Y6
),
EXYNOS4210_GPIO_X1_START
=
EXYNOS_GPIO_START
(
EXYNOS4210_GPIO_X0
),
EXYNOS4210_GPIO_X2_START
=
EXYNOS_GPIO_START
(
EXYNOS4210_GPIO_X1
),
EXYNOS4210_GPIO_X3_START
=
EXYNOS_GPIO_START
(
EXYNOS4210_GPIO_X2
),
};
enum
exynos4210_gpio_xc_start
{
EXYNOS4210_GPIO_Z_START
=
0
,
};
#define EXYNOS4210_GPIO_A0_IRQ EXYNOS4210_GPIO_A0_START
#define EXYNOS4210_GPIO_A1_IRQ EXYNOS4210_GPIO_A1_START
#define EXYNOS4210_GPIO_B_IRQ EXYNOS4210_GPIO_B_START
#define EXYNOS4210_GPIO_C0_IRQ EXYNOS4210_GPIO_C0_START
#define EXYNOS4210_GPIO_C1_IRQ EXYNOS4210_GPIO_C1_START
#define EXYNOS4210_GPIO_D0_IRQ EXYNOS4210_GPIO_D0_START
#define EXYNOS4210_GPIO_D1_IRQ EXYNOS4210_GPIO_D1_START
#define EXYNOS4210_GPIO_E0_IRQ EXYNOS4210_GPIO_E0_START
#define EXYNOS4210_GPIO_E1_IRQ EXYNOS4210_GPIO_E1_START
#define EXYNOS4210_GPIO_E2_IRQ EXYNOS4210_GPIO_E2_START
#define EXYNOS4210_GPIO_E3_IRQ EXYNOS4210_GPIO_E3_START
#define EXYNOS4210_GPIO_E4_IRQ EXYNOS4210_GPIO_E4_START
#define EXYNOS4210_GPIO_F0_IRQ EXYNOS4210_GPIO_F0_START
#define EXYNOS4210_GPIO_F1_IRQ EXYNOS4210_GPIO_F1_START
#define EXYNOS4210_GPIO_F2_IRQ EXYNOS4210_GPIO_F2_START
#define EXYNOS4210_GPIO_F3_IRQ EXYNOS4210_GPIO_F3_START
#define EXYNOS4210_GPIO_J0_IRQ EXYNOS4210_GPIO_J0_START
#define EXYNOS4210_GPIO_J1_IRQ EXYNOS4210_GPIO_J1_START
#define EXYNOS4210_GPIO_K0_IRQ EXYNOS4210_GPIO_K0_START
#define EXYNOS4210_GPIO_K1_IRQ EXYNOS4210_GPIO_K1_START
#define EXYNOS4210_GPIO_K2_IRQ EXYNOS4210_GPIO_K2_START
#define EXYNOS4210_GPIO_K3_IRQ EXYNOS4210_GPIO_K3_START
#define EXYNOS4210_GPIO_L0_IRQ EXYNOS4210_GPIO_L0_START
#define EXYNOS4210_GPIO_L1_IRQ EXYNOS4210_GPIO_L1_START
#define EXYNOS4210_GPIO_L2_IRQ EXYNOS4210_GPIO_L2_START
#define EXYNOS4210_GPIO_Z_IRQ EXYNOS4210_GPIO_Z_START
#define EXYNOS4210_GPIOA_NR_PINS EXYNOS_GPIO_START(EXYNOS4210_GPIO_F3)
#define EXYNOS4210_GPIOA_NR_GINT EXYNOS_GPIO_START(EXYNOS4210_GPIO_F3)
#define EXYNOS4210_GPIOB_NR_PINS EXYNOS_GPIO_START(EXYNOS4210_GPIO_X3)
#define EXYNOS4210_GPIOB_NR_GINT EXYNOS_GPIO_START(EXYNOS4210_GPIO_L2)
#define EXYNOS4210_GPIOC_NR_PINS EXYNOS_GPIO_START(EXYNOS4210_GPIO_Z)
/* External GPIO and wakeup interrupt related definitions */
/* External GPIO and wakeup interrupt related definitions */
#define EXYNOS_GPIO_ECON_OFFSET 0x700
#define EXYNOS_GPIO_ECON_OFFSET 0x700
#define EXYNOS_GPIO_EMASK_OFFSET 0x900
#define EXYNOS_GPIO_EMASK_OFFSET 0x900
...
@@ -165,11 +46,10 @@ enum exynos4210_gpio_xc_start {
...
@@ -165,11 +46,10 @@ enum exynos4210_gpio_xc_start {
#define EXYNOS_EINT_MAX_PER_BANK 8
#define EXYNOS_EINT_MAX_PER_BANK 8
#define EXYNOS_EINT_NR_WKUP_EINT
#define EXYNOS_EINT_NR_WKUP_EINT
#define EXYNOS_PIN_BANK_EINTN(
reg, __gpio
, id) \
#define EXYNOS_PIN_BANK_EINTN(
pins, reg
, id) \
{ \
{ \
.pctl_offset = reg, \
.pctl_offset = reg, \
.pin_base = (__gpio##_START), \
.nr_pins = pins, \
.nr_pins = (__gpio##_NR), \
.func_width = 4, \
.func_width = 4, \
.pud_width = 2, \
.pud_width = 2, \
.drv_width = 2, \
.drv_width = 2, \
...
@@ -179,40 +59,50 @@ enum exynos4210_gpio_xc_start {
...
@@ -179,40 +59,50 @@ enum exynos4210_gpio_xc_start {
.name = id \
.name = id \
}
}
#define EXYNOS_PIN_BANK_EINTG(
reg, __gpio, id)
\
#define EXYNOS_PIN_BANK_EINTG(
pins, reg, id, offs)
\
{ \
{ \
.pctl_offset = reg, \
.pctl_offset = reg, \
.pin_base = (__gpio##_START), \
.nr_pins = pins, \
.nr_pins = (__gpio##_NR), \
.func_width = 4, \
.func_width = 4, \
.pud_width = 2, \
.pud_width = 2, \
.drv_width = 2, \
.drv_width = 2, \
.conpdn_width = 2, \
.conpdn_width = 2, \
.pudpdn_width = 2, \
.pudpdn_width = 2, \
.eint_type = EINT_TYPE_GPIO, \
.eint_type = EINT_TYPE_GPIO, \
.
irq_base = (__gpio##_IRQ),
\
.
eint_offset = offs,
\
.name = id \
.name = id \
}
}
/**
#define EXYNOS_PIN_BANK_EINTW(pins, reg, id, offs) \
* struct exynos_geint_data: gpio eint specific data for irq_chip callbacks.
{ \
* @bank: pin bank from which this gpio interrupt originates.
.pctl_offset = reg, \
* @pin: pin number within the bank.
.nr_pins = pins, \
* @eint_offset: offset to be added to the con/pend/mask register bank base.
.func_width = 4, \
*/
.pud_width = 2, \
struct
exynos_geint_data
{
.drv_width = 2, \
struct
samsung_pin_bank
*
bank
;
.eint_type = EINT_TYPE_WKUP, \
u32
pin
;
.eint_offset = offs, \
u32
eint_offset
;
.name = id \
};
}
/**
/**
* struct exynos_weint_data: irq specific data for all the wakeup interrupts
* struct exynos_weint_data: irq specific data for all the wakeup interrupts
* generated by the external wakeup interrupt controller.
* generated by the external wakeup interrupt controller.
* @domain: irq domain representing the external wakeup interrupts
* @irq: interrupt number within the domain.
* @irq: interrupt number within the domain.
* @bank: bank responsible for this interrupt
*/
*/
struct
exynos_weint_data
{
struct
exynos_weint_data
{
struct
irq_domain
*
domain
;
unsigned
int
irq
;
u32
irq
;
struct
samsung_pin_bank
*
bank
;
};
/**
* struct exynos_muxed_weint_data: irq specific data for muxed wakeup interrupts
* generated by the external wakeup interrupt controller.
* @nr_banks: count of banks being part of the mux
* @banks: array of banks being part of the mux
*/
struct
exynos_muxed_weint_data
{
unsigned
int
nr_banks
;
struct
samsung_pin_bank
*
banks
[];
};
};
drivers/pinctrl/pinctrl-samsung.c
浏览文件 @
bdd45eaa
...
@@ -26,6 +26,7 @@
...
@@ -26,6 +26,7 @@
#include <linux/slab.h>
#include <linux/slab.h>
#include <linux/err.h>
#include <linux/err.h>
#include <linux/gpio.h>
#include <linux/gpio.h>
#include <linux/irqdomain.h>
#include "core.h"
#include "core.h"
#include "pinctrl-samsung.h"
#include "pinctrl-samsung.h"
...
@@ -46,6 +47,13 @@ struct pin_config {
...
@@ -46,6 +47,13 @@ struct pin_config {
{
"samsung,pin-pud-pdn"
,
PINCFG_TYPE_PUD_PDN
},
{
"samsung,pin-pud-pdn"
,
PINCFG_TYPE_PUD_PDN
},
};
};
static
unsigned
int
pin_base
=
0
;
static
inline
struct
samsung_pin_bank
*
gc_to_pin_bank
(
struct
gpio_chip
*
gc
)
{
return
container_of
(
gc
,
struct
samsung_pin_bank
,
gpio_chip
);
}
/* check if the selector is a valid pin group selector */
/* check if the selector is a valid pin group selector */
static
int
samsung_get_group_count
(
struct
pinctrl_dev
*
pctldev
)
static
int
samsung_get_group_count
(
struct
pinctrl_dev
*
pctldev
)
{
{
...
@@ -250,14 +258,12 @@ static int samsung_pinmux_get_groups(struct pinctrl_dev *pctldev,
...
@@ -250,14 +258,12 @@ static int samsung_pinmux_get_groups(struct pinctrl_dev *pctldev,
* given a pin number that is local to a pin controller, find out the pin bank
* given a pin number that is local to a pin controller, find out the pin bank
* and the register base of the pin bank.
* and the register base of the pin bank.
*/
*/
static
void
pin_to_reg_bank
(
struct
gpio_chip
*
gc
,
unsigned
pin
,
static
void
pin_to_reg_bank
(
struct
samsung_pinctrl_drv_data
*
drvdata
,
void
__iomem
**
reg
,
u32
*
offset
,
unsigned
pin
,
void
__iomem
**
reg
,
u32
*
offset
,
struct
samsung_pin_bank
**
bank
)
struct
samsung_pin_bank
**
bank
)
{
{
struct
samsung_pinctrl_drv_data
*
drvdata
;
struct
samsung_pin_bank
*
b
;
struct
samsung_pin_bank
*
b
;
drvdata
=
dev_get_drvdata
(
gc
->
dev
);
b
=
drvdata
->
ctrl
->
pin_banks
;
b
=
drvdata
->
ctrl
->
pin_banks
;
while
((
pin
>=
b
->
pin_base
)
&&
while
((
pin
>=
b
->
pin_base
)
&&
...
@@ -292,7 +298,7 @@ static void samsung_pinmux_setup(struct pinctrl_dev *pctldev, unsigned selector,
...
@@ -292,7 +298,7 @@ static void samsung_pinmux_setup(struct pinctrl_dev *pctldev, unsigned selector,
* pin function number in the config register.
* pin function number in the config register.
*/
*/
for
(
cnt
=
0
;
cnt
<
drvdata
->
pin_groups
[
group
].
num_pins
;
cnt
++
)
{
for
(
cnt
=
0
;
cnt
<
drvdata
->
pin_groups
[
group
].
num_pins
;
cnt
++
)
{
pin_to_reg_bank
(
drvdata
->
gc
,
pins
[
cnt
]
-
drvdata
->
ctrl
->
base
,
pin_to_reg_bank
(
drvdata
,
pins
[
cnt
]
-
drvdata
->
ctrl
->
base
,
&
reg
,
&
pin_offset
,
&
bank
);
&
reg
,
&
pin_offset
,
&
bank
);
mask
=
(
1
<<
bank
->
func_width
)
-
1
;
mask
=
(
1
<<
bank
->
func_width
)
-
1
;
shift
=
pin_offset
*
bank
->
func_width
;
shift
=
pin_offset
*
bank
->
func_width
;
...
@@ -329,10 +335,16 @@ static int samsung_pinmux_gpio_set_direction(struct pinctrl_dev *pctldev,
...
@@ -329,10 +335,16 @@ static int samsung_pinmux_gpio_set_direction(struct pinctrl_dev *pctldev,
struct
pinctrl_gpio_range
*
range
,
unsigned
offset
,
bool
input
)
struct
pinctrl_gpio_range
*
range
,
unsigned
offset
,
bool
input
)
{
{
struct
samsung_pin_bank
*
bank
;
struct
samsung_pin_bank
*
bank
;
struct
samsung_pinctrl_drv_data
*
drvdata
;
void
__iomem
*
reg
;
void
__iomem
*
reg
;
u32
data
,
pin_offset
,
mask
,
shift
;
u32
data
,
pin_offset
,
mask
,
shift
;
pin_to_reg_bank
(
range
->
gc
,
offset
,
&
reg
,
&
pin_offset
,
&
bank
);
bank
=
gc_to_pin_bank
(
range
->
gc
);
drvdata
=
pinctrl_dev_get_drvdata
(
pctldev
);
pin_offset
=
offset
-
bank
->
pin_base
;
reg
=
drvdata
->
virt_base
+
bank
->
pctl_offset
;
mask
=
(
1
<<
bank
->
func_width
)
-
1
;
mask
=
(
1
<<
bank
->
func_width
)
-
1
;
shift
=
pin_offset
*
bank
->
func_width
;
shift
=
pin_offset
*
bank
->
func_width
;
...
@@ -366,7 +378,7 @@ static int samsung_pinconf_rw(struct pinctrl_dev *pctldev, unsigned int pin,
...
@@ -366,7 +378,7 @@ static int samsung_pinconf_rw(struct pinctrl_dev *pctldev, unsigned int pin,
u32
cfg_value
,
cfg_reg
;
u32
cfg_value
,
cfg_reg
;
drvdata
=
pinctrl_dev_get_drvdata
(
pctldev
);
drvdata
=
pinctrl_dev_get_drvdata
(
pctldev
);
pin_to_reg_bank
(
drvdata
->
gc
,
pin
-
drvdata
->
ctrl
->
base
,
&
reg_base
,
pin_to_reg_bank
(
drvdata
,
pin
-
drvdata
->
ctrl
->
base
,
&
reg_base
,
&
pin_offset
,
&
bank
);
&
pin_offset
,
&
bank
);
switch
(
cfg_type
)
{
switch
(
cfg_type
)
{
...
@@ -391,6 +403,9 @@ static int samsung_pinconf_rw(struct pinctrl_dev *pctldev, unsigned int pin,
...
@@ -391,6 +403,9 @@ static int samsung_pinconf_rw(struct pinctrl_dev *pctldev, unsigned int pin,
return
-
EINVAL
;
return
-
EINVAL
;
}
}
if
(
!
width
)
return
-
EINVAL
;
mask
=
(
1
<<
width
)
-
1
;
mask
=
(
1
<<
width
)
-
1
;
shift
=
pin_offset
*
width
;
shift
=
pin_offset
*
width
;
data
=
readl
(
reg_base
+
cfg_reg
);
data
=
readl
(
reg_base
+
cfg_reg
);
...
@@ -463,14 +478,16 @@ static struct pinconf_ops samsung_pinconf_ops = {
...
@@ -463,14 +478,16 @@ static struct pinconf_ops samsung_pinconf_ops = {
/* gpiolib gpio_set callback function */
/* gpiolib gpio_set callback function */
static
void
samsung_gpio_set
(
struct
gpio_chip
*
gc
,
unsigned
offset
,
int
value
)
static
void
samsung_gpio_set
(
struct
gpio_chip
*
gc
,
unsigned
offset
,
int
value
)
{
{
struct
samsung_pin_bank
*
bank
=
gc_to_pin_bank
(
gc
);
void
__iomem
*
reg
;
void
__iomem
*
reg
;
u32
pin_offset
,
data
;
u32
data
;
reg
=
bank
->
drvdata
->
virt_base
+
bank
->
pctl_offset
;
pin_to_reg_bank
(
gc
,
offset
,
&
reg
,
&
pin_offset
,
NULL
);
data
=
readl
(
reg
+
DAT_REG
);
data
=
readl
(
reg
+
DAT_REG
);
data
&=
~
(
1
<<
pin_
offset
);
data
&=
~
(
1
<<
offset
);
if
(
value
)
if
(
value
)
data
|=
1
<<
pin_
offset
;
data
|=
1
<<
offset
;
writel
(
data
,
reg
+
DAT_REG
);
writel
(
data
,
reg
+
DAT_REG
);
}
}
...
@@ -478,11 +495,13 @@ static void samsung_gpio_set(struct gpio_chip *gc, unsigned offset, int value)
...
@@ -478,11 +495,13 @@ static void samsung_gpio_set(struct gpio_chip *gc, unsigned offset, int value)
static
int
samsung_gpio_get
(
struct
gpio_chip
*
gc
,
unsigned
offset
)
static
int
samsung_gpio_get
(
struct
gpio_chip
*
gc
,
unsigned
offset
)
{
{
void
__iomem
*
reg
;
void
__iomem
*
reg
;
u32
pin_offset
,
data
;
u32
data
;
struct
samsung_pin_bank
*
bank
=
gc_to_pin_bank
(
gc
);
reg
=
bank
->
drvdata
->
virt_base
+
bank
->
pctl_offset
;
pin_to_reg_bank
(
gc
,
offset
,
&
reg
,
&
pin_offset
,
NULL
);
data
=
readl
(
reg
+
DAT_REG
);
data
=
readl
(
reg
+
DAT_REG
);
data
>>=
pin_
offset
;
data
>>=
offset
;
data
&=
1
;
data
&=
1
;
return
data
;
return
data
;
}
}
...
@@ -509,6 +528,23 @@ static int samsung_gpio_direction_output(struct gpio_chip *gc, unsigned offset,
...
@@ -509,6 +528,23 @@ static int samsung_gpio_direction_output(struct gpio_chip *gc, unsigned offset,
return
pinctrl_gpio_direction_output
(
gc
->
base
+
offset
);
return
pinctrl_gpio_direction_output
(
gc
->
base
+
offset
);
}
}
/*
* gpiolib gpio_to_irq callback function. Creates a mapping between a GPIO pin
* and a virtual IRQ, if not already present.
*/
static
int
samsung_gpio_to_irq
(
struct
gpio_chip
*
gc
,
unsigned
offset
)
{
struct
samsung_pin_bank
*
bank
=
gc_to_pin_bank
(
gc
);
unsigned
int
virq
;
if
(
!
bank
->
irq_domain
)
return
-
ENXIO
;
virq
=
irq_create_mapping
(
bank
->
irq_domain
,
offset
);
return
(
virq
)
?
:
-
ENXIO
;
}
/*
/*
* Parse the pin names listed in the 'samsung,pins' property and convert it
* Parse the pin names listed in the 'samsung,pins' property and convert it
* into a list of gpio numbers are create a pin group from it.
* into a list of gpio numbers are create a pin group from it.
...
@@ -597,7 +633,7 @@ static int __devinit samsung_pinctrl_parse_dt(struct platform_device *pdev,
...
@@ -597,7 +633,7 @@ static int __devinit samsung_pinctrl_parse_dt(struct platform_device *pdev,
*/
*/
for_each_child_of_node
(
dev_np
,
cfg_np
)
{
for_each_child_of_node
(
dev_np
,
cfg_np
)
{
u32
function
;
u32
function
;
if
(
of_find_property
(
cfg_np
,
"interrupt-controller
"
,
NULL
))
if
(
!
of_find_property
(
cfg_np
,
"samsung,pins
"
,
NULL
))
continue
;
continue
;
ret
=
samsung_pinctrl_parse_dt_pins
(
pdev
,
cfg_np
,
ret
=
samsung_pinctrl_parse_dt_pins
(
pdev
,
cfg_np
,
...
@@ -712,12 +748,16 @@ static int __devinit samsung_pinctrl_register(struct platform_device *pdev,
...
@@ -712,12 +748,16 @@ static int __devinit samsung_pinctrl_register(struct platform_device *pdev,
return
-
EINVAL
;
return
-
EINVAL
;
}
}
drvdata
->
grange
.
name
=
"samsung-pctrl-gpio-range"
;
for
(
bank
=
0
;
bank
<
drvdata
->
ctrl
->
nr_banks
;
++
bank
)
{
drvdata
->
grange
.
id
=
0
;
pin_bank
=
&
drvdata
->
ctrl
->
pin_banks
[
bank
];
drvdata
->
grange
.
base
=
drvdata
->
ctrl
->
base
;
pin_bank
->
grange
.
name
=
pin_bank
->
name
;
drvdata
->
grange
.
npins
=
drvdata
->
ctrl
->
nr_pins
;
pin_bank
->
grange
.
id
=
bank
;
drvdata
->
grange
.
gc
=
drvdata
->
gc
;
pin_bank
->
grange
.
pin_base
=
pin_bank
->
pin_base
;
pinctrl_add_gpio_range
(
drvdata
->
pctl_dev
,
&
drvdata
->
grange
);
pin_bank
->
grange
.
base
=
pin_bank
->
gpio_chip
.
base
;
pin_bank
->
grange
.
npins
=
pin_bank
->
gpio_chip
.
ngpio
;
pin_bank
->
grange
.
gc
=
&
pin_bank
->
gpio_chip
;
pinctrl_add_gpio_range
(
drvdata
->
pctl_dev
,
&
pin_bank
->
grange
);
}
ret
=
samsung_pinctrl_parse_dt
(
pdev
,
drvdata
);
ret
=
samsung_pinctrl_parse_dt
(
pdev
,
drvdata
);
if
(
ret
)
{
if
(
ret
)
{
...
@@ -728,68 +768,117 @@ static int __devinit samsung_pinctrl_register(struct platform_device *pdev,
...
@@ -728,68 +768,117 @@ static int __devinit samsung_pinctrl_register(struct platform_device *pdev,
return
0
;
return
0
;
}
}
static
const
struct
gpio_chip
samsung_gpiolib_chip
=
{
.
set
=
samsung_gpio_set
,
.
get
=
samsung_gpio_get
,
.
direction_input
=
samsung_gpio_direction_input
,
.
direction_output
=
samsung_gpio_direction_output
,
.
to_irq
=
samsung_gpio_to_irq
,
.
owner
=
THIS_MODULE
,
};
/* register the gpiolib interface with the gpiolib subsystem */
/* register the gpiolib interface with the gpiolib subsystem */
static
int
__devinit
samsung_gpiolib_register
(
struct
platform_device
*
pdev
,
static
int
__devinit
samsung_gpiolib_register
(
struct
platform_device
*
pdev
,
struct
samsung_pinctrl_drv_data
*
drvdata
)
struct
samsung_pinctrl_drv_data
*
drvdata
)
{
{
struct
samsung_pin_ctrl
*
ctrl
=
drvdata
->
ctrl
;
struct
samsung_pin_bank
*
bank
=
ctrl
->
pin_banks
;
struct
gpio_chip
*
gc
;
struct
gpio_chip
*
gc
;
int
ret
;
int
ret
;
int
i
;
gc
=
devm_kzalloc
(
&
pdev
->
dev
,
sizeof
(
*
gc
),
GFP_KERNEL
);
if
(
!
gc
)
{
for
(
i
=
0
;
i
<
ctrl
->
nr_banks
;
++
i
,
++
bank
)
{
dev_err
(
&
pdev
->
dev
,
"mem alloc for gpio_chip failed
\n
"
);
bank
->
gpio_chip
=
samsung_gpiolib_chip
;
return
-
ENOMEM
;
}
gc
=
&
bank
->
gpio_chip
;
gc
->
base
=
ctrl
->
base
+
bank
->
pin_base
;
drvdata
->
gc
=
gc
;
gc
->
ngpio
=
bank
->
nr_pins
;
gc
->
base
=
drvdata
->
ctrl
->
base
;
gc
->
dev
=
&
pdev
->
dev
;
gc
->
ngpio
=
drvdata
->
ctrl
->
nr_pins
;
gc
->
of_node
=
bank
->
of_node
;
gc
->
dev
=
&
pdev
->
dev
;
gc
->
label
=
bank
->
name
;
gc
->
set
=
samsung_gpio_set
;
gc
->
get
=
samsung_gpio_get
;
ret
=
gpiochip_add
(
gc
);
gc
->
direction_input
=
samsung_gpio_direction_input
;
if
(
ret
)
{
gc
->
direction_output
=
samsung_gpio_direction_output
;
dev_err
(
&
pdev
->
dev
,
"failed to register gpio_chip %s, error code: %d
\n
"
,
gc
->
label
=
drvdata
->
ctrl
->
label
;
gc
->
label
,
ret
);
gc
->
owner
=
THIS_MODULE
;
goto
fail
;
ret
=
gpiochip_add
(
gc
);
}
if
(
ret
)
{
dev_err
(
&
pdev
->
dev
,
"failed to register gpio_chip %s, error "
"code: %d
\n
"
,
gc
->
label
,
ret
);
return
ret
;
}
}
return
0
;
return
0
;
fail:
for
(
--
i
,
--
bank
;
i
>=
0
;
--
i
,
--
bank
)
if
(
gpiochip_remove
(
&
bank
->
gpio_chip
))
dev_err
(
&
pdev
->
dev
,
"gpio chip %s remove failed
\n
"
,
bank
->
gpio_chip
.
label
);
return
ret
;
}
}
/* unregister the gpiolib interface with the gpiolib subsystem */
/* unregister the gpiolib interface with the gpiolib subsystem */
static
int
__devinit
samsung_gpiolib_unregister
(
struct
platform_device
*
pdev
,
static
int
__devinit
samsung_gpiolib_unregister
(
struct
platform_device
*
pdev
,
struct
samsung_pinctrl_drv_data
*
drvdata
)
struct
samsung_pinctrl_drv_data
*
drvdata
)
{
{
int
ret
=
gpiochip_remove
(
drvdata
->
gc
);
struct
samsung_pin_ctrl
*
ctrl
=
drvdata
->
ctrl
;
if
(
ret
)
{
struct
samsung_pin_bank
*
bank
=
ctrl
->
pin_banks
;
int
ret
=
0
;
int
i
;
for
(
i
=
0
;
!
ret
&&
i
<
ctrl
->
nr_banks
;
++
i
,
++
bank
)
ret
=
gpiochip_remove
(
&
bank
->
gpio_chip
);
if
(
ret
)
dev_err
(
&
pdev
->
dev
,
"gpio chip remove failed
\n
"
);
dev_err
(
&
pdev
->
dev
,
"gpio chip remove failed
\n
"
);
return
ret
;
}
return
ret
;
return
0
;
}
}
static
const
struct
of_device_id
samsung_pinctrl_dt_match
[];
static
const
struct
of_device_id
samsung_pinctrl_dt_match
[];
/* retrieve the soc specific data */
/* retrieve the soc specific data */
static
struct
samsung_pin_ctrl
*
samsung_pinctrl_get_soc_data
(
static
struct
samsung_pin_ctrl
*
samsung_pinctrl_get_soc_data
(
struct
samsung_pinctrl_drv_data
*
d
,
struct
platform_device
*
pdev
)
struct
platform_device
*
pdev
)
{
{
int
id
;
int
id
;
const
struct
of_device_id
*
match
;
const
struct
of_device_id
*
match
;
const
struct
device_node
*
node
=
pdev
->
dev
.
of_node
;
struct
device_node
*
node
=
pdev
->
dev
.
of_node
;
struct
device_node
*
np
;
struct
samsung_pin_ctrl
*
ctrl
;
struct
samsung_pin_bank
*
bank
;
int
i
;
id
=
of_alias_get_id
(
pdev
->
dev
.
of_
node
,
"pinctrl"
);
id
=
of_alias_get_id
(
node
,
"pinctrl"
);
if
(
id
<
0
)
{
if
(
id
<
0
)
{
dev_err
(
&
pdev
->
dev
,
"failed to get alias id
\n
"
);
dev_err
(
&
pdev
->
dev
,
"failed to get alias id
\n
"
);
return
NULL
;
return
NULL
;
}
}
match
=
of_match_node
(
samsung_pinctrl_dt_match
,
node
);
match
=
of_match_node
(
samsung_pinctrl_dt_match
,
node
);
return
(
struct
samsung_pin_ctrl
*
)
match
->
data
+
id
;
ctrl
=
(
struct
samsung_pin_ctrl
*
)
match
->
data
+
id
;
bank
=
ctrl
->
pin_banks
;
for
(
i
=
0
;
i
<
ctrl
->
nr_banks
;
++
i
,
++
bank
)
{
bank
->
drvdata
=
d
;
bank
->
pin_base
=
ctrl
->
nr_pins
;
ctrl
->
nr_pins
+=
bank
->
nr_pins
;
}
for_each_child_of_node
(
node
,
np
)
{
if
(
!
of_find_property
(
np
,
"gpio-controller"
,
NULL
))
continue
;
bank
=
ctrl
->
pin_banks
;
for
(
i
=
0
;
i
<
ctrl
->
nr_banks
;
++
i
,
++
bank
)
{
if
(
!
strcmp
(
bank
->
name
,
np
->
name
))
{
bank
->
of_node
=
np
;
break
;
}
}
}
ctrl
->
base
=
pin_base
;
pin_base
+=
ctrl
->
nr_pins
;
return
ctrl
;
}
}
static
int
__devinit
samsung_pinctrl_probe
(
struct
platform_device
*
pdev
)
static
int
__devinit
samsung_pinctrl_probe
(
struct
platform_device
*
pdev
)
...
@@ -805,18 +894,18 @@ static int __devinit samsung_pinctrl_probe(struct platform_device *pdev)
...
@@ -805,18 +894,18 @@ static int __devinit samsung_pinctrl_probe(struct platform_device *pdev)
return
-
ENODEV
;
return
-
ENODEV
;
}
}
ctrl
=
samsung_pinctrl_get_soc_data
(
pdev
);
if
(
!
ctrl
)
{
dev_err
(
&
pdev
->
dev
,
"driver data not available
\n
"
);
return
-
EINVAL
;
}
drvdata
=
devm_kzalloc
(
dev
,
sizeof
(
*
drvdata
),
GFP_KERNEL
);
drvdata
=
devm_kzalloc
(
dev
,
sizeof
(
*
drvdata
),
GFP_KERNEL
);
if
(
!
drvdata
)
{
if
(
!
drvdata
)
{
dev_err
(
dev
,
"failed to allocate memory for driver's "
dev_err
(
dev
,
"failed to allocate memory for driver's "
"private data
\n
"
);
"private data
\n
"
);
return
-
ENOMEM
;
return
-
ENOMEM
;
}
}
ctrl
=
samsung_pinctrl_get_soc_data
(
drvdata
,
pdev
);
if
(
!
ctrl
)
{
dev_err
(
&
pdev
->
dev
,
"driver data not available
\n
"
);
return
-
EINVAL
;
}
drvdata
->
ctrl
=
ctrl
;
drvdata
->
ctrl
=
ctrl
;
drvdata
->
dev
=
dev
;
drvdata
->
dev
=
dev
;
...
@@ -858,6 +947,8 @@ static int __devinit samsung_pinctrl_probe(struct platform_device *pdev)
...
@@ -858,6 +947,8 @@ static int __devinit samsung_pinctrl_probe(struct platform_device *pdev)
static
const
struct
of_device_id
samsung_pinctrl_dt_match
[]
=
{
static
const
struct
of_device_id
samsung_pinctrl_dt_match
[]
=
{
{
.
compatible
=
"samsung,pinctrl-exynos4210"
,
{
.
compatible
=
"samsung,pinctrl-exynos4210"
,
.
data
=
(
void
*
)
exynos4210_pin_ctrl
},
.
data
=
(
void
*
)
exynos4210_pin_ctrl
},
{
.
compatible
=
"samsung,pinctrl-exynos4x12"
,
.
data
=
(
void
*
)
exynos4x12_pin_ctrl
},
{},
{},
};
};
MODULE_DEVICE_TABLE
(
of
,
samsung_pinctrl_dt_match
);
MODULE_DEVICE_TABLE
(
of
,
samsung_pinctrl_dt_match
);
...
...
drivers/pinctrl/pinctrl-samsung.h
浏览文件 @
bdd45eaa
...
@@ -23,6 +23,8 @@
...
@@ -23,6 +23,8 @@
#include <linux/pinctrl/consumer.h>
#include <linux/pinctrl/consumer.h>
#include <linux/pinctrl/machine.h>
#include <linux/pinctrl/machine.h>
#include <linux/gpio.h>
/* register offsets within a pin bank */
/* register offsets within a pin bank */
#define DAT_REG 0x4
#define DAT_REG 0x4
#define PUD_REG 0x8
#define PUD_REG 0x8
...
@@ -64,6 +66,7 @@ enum pincfg_type {
...
@@ -64,6 +66,7 @@ enum pincfg_type {
* @EINT_TYPE_NONE: bank does not support external interrupts
* @EINT_TYPE_NONE: bank does not support external interrupts
* @EINT_TYPE_GPIO: bank supportes external gpio interrupts
* @EINT_TYPE_GPIO: bank supportes external gpio interrupts
* @EINT_TYPE_WKUP: bank supportes external wakeup interrupts
* @EINT_TYPE_WKUP: bank supportes external wakeup interrupts
* @EINT_TYPE_WKUP_MUX: bank supports multiplexed external wakeup interrupts
*
*
* Samsung GPIO controller groups all the available pins into banks. The pins
* Samsung GPIO controller groups all the available pins into banks. The pins
* in a pin bank can support external gpio interrupts or external wakeup
* in a pin bank can support external gpio interrupts or external wakeup
...
@@ -76,6 +79,7 @@ enum eint_type {
...
@@ -76,6 +79,7 @@ enum eint_type {
EINT_TYPE_NONE
,
EINT_TYPE_NONE
,
EINT_TYPE_GPIO
,
EINT_TYPE_GPIO
,
EINT_TYPE_WKUP
,
EINT_TYPE_WKUP
,
EINT_TYPE_WKUP_MUX
,
};
};
/* maximum length of a pin in pin descriptor (example: "gpa0-0") */
/* maximum length of a pin in pin descriptor (example: "gpa0-0") */
...
@@ -109,8 +113,12 @@ struct samsung_pinctrl_drv_data;
...
@@ -109,8 +113,12 @@ struct samsung_pinctrl_drv_data;
* @conpdn_width: width of the sleep mode function selector bin field.
* @conpdn_width: width of the sleep mode function selector bin field.
* @pudpdn_width: width of the sleep mode pull up/down selector bit field.
* @pudpdn_width: width of the sleep mode pull up/down selector bit field.
* @eint_type: type of the external interrupt supported by the bank.
* @eint_type: type of the external interrupt supported by the bank.
* @irq_base: starting controller local irq number of the bank.
* @name: name to be prefixed for each pin in this pin bank.
* @name: name to be prefixed for each pin in this pin bank.
* @of_node: OF node of the bank.
* @drvdata: link to controller driver data
* @irq_domain: IRQ domain of the bank.
* @gpio_chip: GPIO chip of the bank.
* @grange: linux gpio pin range supported by this bank.
*/
*/
struct
samsung_pin_bank
{
struct
samsung_pin_bank
{
u32
pctl_offset
;
u32
pctl_offset
;
...
@@ -122,8 +130,13 @@ struct samsung_pin_bank {
...
@@ -122,8 +130,13 @@ struct samsung_pin_bank {
u8
conpdn_width
;
u8
conpdn_width
;
u8
pudpdn_width
;
u8
pudpdn_width
;
enum
eint_type
eint_type
;
enum
eint_type
eint_type
;
u32
irq_base
;
u32
eint_offset
;
char
*
name
;
char
*
name
;
struct
device_node
*
of_node
;
struct
samsung_pinctrl_drv_data
*
drvdata
;
struct
irq_domain
*
irq_domain
;
struct
gpio_chip
gpio_chip
;
struct
pinctrl_gpio_range
grange
;
};
};
/**
/**
...
@@ -132,8 +145,6 @@ struct samsung_pin_bank {
...
@@ -132,8 +145,6 @@ struct samsung_pin_bank {
* @nr_banks: number of pin banks.
* @nr_banks: number of pin banks.
* @base: starting system wide pin number.
* @base: starting system wide pin number.
* @nr_pins: number of pins supported by the controller.
* @nr_pins: number of pins supported by the controller.
* @nr_gint: number of external gpio interrupts supported.
* @nr_wint: number of external wakeup interrupts supported.
* @geint_con: offset of the ext-gpio controller registers.
* @geint_con: offset of the ext-gpio controller registers.
* @geint_mask: offset of the ext-gpio interrupt mask registers.
* @geint_mask: offset of the ext-gpio interrupt mask registers.
* @geint_pend: offset of the ext-gpio interrupt pending registers.
* @geint_pend: offset of the ext-gpio interrupt pending registers.
...
@@ -153,8 +164,6 @@ struct samsung_pin_ctrl {
...
@@ -153,8 +164,6 @@ struct samsung_pin_ctrl {
u32
base
;
u32
base
;
u32
nr_pins
;
u32
nr_pins
;
u32
nr_gint
;
u32
nr_wint
;
u32
geint_con
;
u32
geint_con
;
u32
geint_mask
;
u32
geint_mask
;
...
@@ -183,8 +192,6 @@ struct samsung_pin_ctrl {
...
@@ -183,8 +192,6 @@ struct samsung_pin_ctrl {
* @nr_groups: number of such pin groups.
* @nr_groups: number of such pin groups.
* @pmx_functions: list of pin functions available to the driver.
* @pmx_functions: list of pin functions available to the driver.
* @nr_function: number of such pin functions.
* @nr_function: number of such pin functions.
* @gc: gpio_chip instance registered with gpiolib.
* @grange: linux gpio pin range supported by this controller.
*/
*/
struct
samsung_pinctrl_drv_data
{
struct
samsung_pinctrl_drv_data
{
void
__iomem
*
virt_base
;
void
__iomem
*
virt_base
;
...
@@ -199,12 +206,6 @@ struct samsung_pinctrl_drv_data {
...
@@ -199,12 +206,6 @@ struct samsung_pinctrl_drv_data {
unsigned
int
nr_groups
;
unsigned
int
nr_groups
;
const
struct
samsung_pmx_func
*
pmx_functions
;
const
struct
samsung_pmx_func
*
pmx_functions
;
unsigned
int
nr_functions
;
unsigned
int
nr_functions
;
struct
irq_domain
*
gpio_irqd
;
struct
irq_domain
*
wkup_irqd
;
struct
gpio_chip
*
gc
;
struct
pinctrl_gpio_range
grange
;
};
};
/**
/**
...
@@ -235,5 +236,6 @@ struct samsung_pmx_func {
...
@@ -235,5 +236,6 @@ struct samsung_pmx_func {
/* list of all exported SoC specific data */
/* list of all exported SoC specific data */
extern
struct
samsung_pin_ctrl
exynos4210_pin_ctrl
[];
extern
struct
samsung_pin_ctrl
exynos4210_pin_ctrl
[];
extern
struct
samsung_pin_ctrl
exynos4x12_pin_ctrl
[];
#endif
/* __PINCTRL_SAMSUNG_H */
#endif
/* __PINCTRL_SAMSUNG_H */
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录