aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOlof Johansson <olof@lixom.net>2012-09-20 19:41:32 -0400
committerOlof Johansson <olof@lixom.net>2012-09-20 19:41:32 -0400
commit827cbe71886bc82125212630a52c5fe94b284330 (patch)
treea1f81706789fd8bbc5ace65e0bec4df7a603f272
parent1ef3f756b069469621a47ded867e71c97e1b483f (diff)
parent011527b45f8e3092e1f3192e5aea94187a6ca269 (diff)
Merge branch 'next/pinctrl-samsung' of git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung into next/drivers
From Kukjin Kim: This branch is for supporting pinctrl for Samsung EXYNOS. Now this can support EXYNOS4210 and other EXYNOS SoCs such as EXYNOS4X12 will be supported next time. * 'next/pinctrl-samsung' of git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung: ARM: EXYNOS: Enable pinctrl driver support for EXYNOS4 device tree enabled platform ARM: dts: Add pinctrl node entries for SAMSUNG EXYNOS4210 SoC ARM: EXYNOS: skip wakeup interrupt setup if pinctrl driver is used gpio: exynos4: skip gpiolib registration if pinctrl driver is used pinctrl: add exynos4210 specific extensions for samsung pinctrl driver pinctrl: add samsung pinctrl and gpiolib driver
-rw-r--r--Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt196
-rw-r--r--arch/arm/boot/dts/exynos4210-pinctrl.dtsi457
-rw-r--r--arch/arm/boot/dts/exynos4210.dtsi37
-rw-r--r--arch/arm/mach-exynos/Kconfig2
-rw-r--r--arch/arm/mach-exynos/common.c26
-rw-r--r--drivers/gpio/gpio-samsung.c21
-rw-r--r--drivers/pinctrl/Kconfig9
-rw-r--r--drivers/pinctrl/Makefile2
-rw-r--r--drivers/pinctrl/pinctrl-exynos.c560
-rw-r--r--drivers/pinctrl/pinctrl-exynos.h217
-rw-r--r--drivers/pinctrl/pinctrl-samsung.c888
-rw-r--r--drivers/pinctrl/pinctrl-samsung.h239
12 files changed, 2654 insertions, 0 deletions
diff --git a/Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt
new file mode 100644
index 000000000000..03dee50532f5
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt
@@ -0,0 +1,196 @@
1Samsung GPIO and Pin Mux/Config controller
2
3Samsung's ARM based SoC's integrates a GPIO and Pin mux/config hardware
4controller. It controls the input/output settings on the available pads/pins
5and also provides ability to multiplex and configure the output of various
6on-chip controllers onto these pads.
7
8Required Properties:
9- compatible: should be one of the following.
10 - "samsung,pinctrl-exynos4210": for Exynos4210 compatible pin-controller.
11 - "samsung,pinctrl-exynos5250": for Exynos5250 compatible pin-controller.
12
13- reg: Base address of the pin controller hardware module and length of
14 the address space it occupies.
15
16- interrupts: interrupt specifier for the controller. The format and value of
17 the interrupt specifier depends on the interrupt parent for the controller.
18
19- Pin mux/config groups as child nodes: The pin mux (selecting pin function
20 mode) and pin config (pull up/down, driver strength) settings are represented
21 as child nodes of the pin-controller node. There should be atleast one
22 child node and there is no limit on the count of these child nodes.
23
24 The child node should contain a list of pin(s) on which a particular pin
25 function selection or pin configuration (or both) have to applied. This
26 list of pins is specified using the property name "samsung,pins". There
27 should be atleast one pin specfied for this property and there is no upper
28 limit on the count of pins that can be specified. The pins are specified
29 using pin names which are derived from the hardware manual of the SoC. As
30 an example, the pins in GPA0 bank of the pin controller can be represented
31 as "gpa0-0", "gpa0-1", "gpa0-2" and so on. The names should be in lower case.
32 The format of the pin names should be (as per the hardware manual)
33 "[pin bank name]-[pin number within the bank]".
34
35 The pin function selection that should be applied on the pins listed in the
36 child node is specified using the "samsung,pin-function" property. The value
37 of this property that should be applied to each of the pins listed in the
38 "samsung,pins" property should be picked from the hardware manual of the SoC
39 for the specified pin group. This property is optional in the child node if
40 no specific function selection is desired for the pins listed in the child
41 node. The value of this property is used as-is to program the pin-controller
42 function selector register of the pin-bank.
43
44 The child node can also optionally specify one or more of the pin
45 configuration that should be applied on all the pins listed in the
46 "samsung,pins" property of the child node. The following pin configuration
47 properties are supported.
48
49 - samsung,pin-pud: Pull up/down configuration.
50 - samsung,pin-drv: Drive strength configuration.
51 - samsung,pin-pud-pdn: Pull up/down configuration in power down mode.
52 - samsung,pin-drv-pdn: Drive strength configuration in power down mode.
53
54 The values specified by these config properties should be derived from the
55 hardware manual and these values are programmed as-is into the pin
56 pull up/down and driver strength register of the pin-controller.
57
58 Note: A child should include atleast a pin function selection property or
59 pin configuration property (one or more) or both.
60
61 The client nodes that require a particular pin function selection and/or
62 pin configuration should use the bindings listed in the "pinctrl-bindings.txt"
63 file.
64
65External GPIO and Wakeup Interrupts:
66
67The controller supports two types of external interrupts over gpio. The first
68is the external gpio interrupt and second is the external wakeup interrupts.
69The difference between the two is that the external wakeup interrupts can be
70used as system wakeup events.
71
72A. External GPIO Interrupts: For supporting external gpio interrupts, the
73 following properties should be specified in the pin-controller device node.
74
75- interrupt-controller: identifies the controller node as interrupt-parent.
76- #interrupt-cells: the value of this property should be 2.
77 - First Cell: represents the external gpio interrupt number local to the
78 external gpio interrupt space of the controller.
79 - Second Cell: flags to identify the type of the interrupt
80 - 1 = rising edge triggered
81 - 2 = falling edge triggered
82 - 3 = rising and falling edge triggered
83 - 4 = high level triggered
84 - 8 = low level triggered
85
86B. External Wakeup Interrupts: For supporting external wakeup interrupts, a
87 child node representing the external wakeup interrupt controller should be
88 included in the pin-controller device node. This child node should include
89 the following properties.
90
91 - compatible: identifies the type of the external wakeup interrupt controller
92 The possible values are:
93 - samsung,exynos4210-wakeup-eint: represents wakeup interrupt controller
94 found on Samsung Exynos4210 SoC.
95 - interrupt-parent: phandle of the interrupt parent to which the external
96 wakeup interrupts are forwarded to.
97 - interrupt-controller: identifies the node as interrupt-parent.
98 - #interrupt-cells: the value of this property should be 2
99 - First Cell: represents the external wakeup interrupt number local to
100 the external wakeup interrupt space of the controller.
101 - Second Cell: flags to identify the type of the interrupt
102 - 1 = rising edge triggered
103 - 2 = falling edge triggered
104 - 3 = rising and falling edge triggered
105 - 4 = high level triggered
106 - 8 = low level triggered
107
108Aliases:
109
110All the pin controller nodes should be represented in the aliases node using
111the following format 'pinctrl{n}' where n is a unique number for the alias.
112
113Example 1: A pin-controller node with pin groups.
114
115 pinctrl_0: pinctrl@11400000 {
116 compatible = "samsung,pinctrl-exynos4210";
117 reg = <0x11400000 0x1000>;
118 interrupts = <0 47 0>;
119
120 uart0_data: uart0-data {
121 samsung,pins = "gpa0-0", "gpa0-1";
122 samsung,pin-function = <2>;
123 samsung,pin-pud = <0>;
124 samsung,pin-drv = <0>;
125 };
126
127 uart0_fctl: uart0-fctl {
128 samsung,pins = "gpa0-2", "gpa0-3";
129 samsung,pin-function = <2>;
130 samsung,pin-pud = <0>;
131 samsung,pin-drv = <0>;
132 };
133
134 uart1_data: uart1-data {
135 samsung,pins = "gpa0-4", "gpa0-5";
136 samsung,pin-function = <2>;
137 samsung,pin-pud = <0>;
138 samsung,pin-drv = <0>;
139 };
140
141 uart1_fctl: uart1-fctl {
142 samsung,pins = "gpa0-6", "gpa0-7";
143 samsung,pin-function = <2>;
144 samsung,pin-pud = <0>;
145 samsung,pin-drv = <0>;
146 };
147
148 i2c2_bus: i2c2-bus {
149 samsung,pins = "gpa0-6", "gpa0-7";
150 samsung,pin-function = <3>;
151 samsung,pin-pud = <3>;
152 samsung,pin-drv = <0>;
153 };
154 };
155
156Example 2: A pin-controller node with external wakeup interrupt controller node.
157
158 pinctrl_1: pinctrl@11000000 {
159 compatible = "samsung,pinctrl-exynos4210";
160 reg = <0x11000000 0x1000>;
161 interrupts = <0 46 0>;
162 interrupt-controller;
163 #interrupt-cells = <2>;
164
165 wakup_eint: wakeup-interrupt-controller {
166 compatible = "samsung,exynos4210-wakeup-eint";
167 interrupt-parent = <&gic>;
168 interrupt-controller;
169 #interrupt-cells = <2>;
170 interrupts = <0 16 0>, <0 17 0>, <0 18 0>, <0 19 0>,
171 <0 20 0>, <0 21 0>, <0 22 0>, <0 23 0>,
172 <0 24 0>, <0 25 0>, <0 26 0>, <0 27 0>,
173 <0 28 0>, <0 29 0>, <0 30 0>, <0 31 0>,
174 <0 32 0>;
175 };
176 };
177
178Example 3: A uart client node that supports 'default' and 'flow-control' states.
179
180 uart@13800000 {
181 compatible = "samsung,exynos4210-uart";
182 reg = <0x13800000 0x100>;
183 interrupts = <0 52 0>;
184 pinctrl-names = "default", "flow-control;
185 pinctrl-0 = <&uart0_data>;
186 pinctrl-1 = <&uart0_data &uart0_fctl>;
187 };
188
189Example 4: Set up the default pin state for uart controller.
190
191 static int s3c24xx_serial_probe(struct platform_device *pdev) {
192 struct pinctrl *pinctrl;
193 ...
194 ...
195 pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
196 }
diff --git a/arch/arm/boot/dts/exynos4210-pinctrl.dtsi b/arch/arm/boot/dts/exynos4210-pinctrl.dtsi
new file mode 100644
index 000000000000..b12cf272ad0d
--- /dev/null
+++ b/arch/arm/boot/dts/exynos4210-pinctrl.dtsi
@@ -0,0 +1,457 @@
1/*
2 * Samsung's Exynos4210 SoC pin-mux and pin-config device tree source
3 *
4 * Copyright (c) 2011-2012 Samsung Electronics Co., Ltd.
5 * http://www.samsung.com
6 * Copyright (c) 2011-2012 Linaro Ltd.
7 * www.linaro.org
8 *
9 * Samsung's Exynos4210 SoC pin-mux and pin-config optiosn are listed as device
10 * tree nodes are listed in this file.
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License version 2 as
14 * published by the Free Software Foundation.
15*/
16
17/ {
18 pinctrl@11400000 {
19 uart0_data: uart0-data {
20 samsung,pins = "gpa0-0", "gpa0-1";
21 samsung,pin-function = <0x2>;
22 samsung,pin-pud = <0>;
23 samsung,pin-drv = <0>;
24 };
25
26 uart0_fctl: uart0-fctl {
27 samsung,pins = "gpa0-2", "gpa0-3";
28 samsung,pin-function = <2>;
29 samsung,pin-pud = <0>;
30 samsung,pin-drv = <0>;
31 };
32
33 uart1_data: uart1-data {
34 samsung,pins = "gpa0-4", "gpa0-5";
35 samsung,pin-function = <2>;
36 samsung,pin-pud = <0>;
37 samsung,pin-drv = <0>;
38 };
39
40 uart1_fctl: uart1-fctl {
41 samsung,pins = "gpa0-6", "gpa0-7";
42 samsung,pin-function = <2>;
43 samsung,pin-pud = <0>;
44 samsung,pin-drv = <0>;
45 };
46
47 i2c2_bus: i2c2-bus {
48 samsung,pins = "gpa0-6", "gpa0-7";
49 samsung,pin-function = <3>;
50 samsung,pin-pud = <3>;
51 samsung,pin-drv = <0>;
52 };
53
54 uart2_data: uart2-data {
55 samsung,pins = "gpa1-0", "gpa1-1";
56 samsung,pin-function = <2>;
57 samsung,pin-pud = <0>;
58 samsung,pin-drv = <0>;
59 };
60
61 uart2_fctl: uart2-fctl {
62 samsung,pins = "gpa1-2", "gpa1-3";
63 samsung,pin-function = <2>;
64 samsung,pin-pud = <0>;
65 samsung,pin-drv = <0>;
66 };
67
68 uart_audio_a: uart-audio-a {
69 samsung,pins = "gpa1-0", "gpa1-1";
70 samsung,pin-function = <4>;
71 samsung,pin-pud = <0>;
72 samsung,pin-drv = <0>;
73 };
74
75 i2c3_bus: i2c3-bus {
76 samsung,pins = "gpa1-2", "gpa1-3";
77 samsung,pin-function = <3>;
78 samsung,pin-pud = <3>;
79 samsung,pin-drv = <0>;
80 };
81
82 uart3_data: uart3-data {
83 samsung,pins = "gpa1-4", "gpa1-5";
84 samsung,pin-function = <2>;
85 samsung,pin-pud = <0>;
86 samsung,pin-drv = <0>;
87 };
88
89 uart_audio_b: uart-audio-b {
90 samsung,pins = "gpa1-4", "gpa1-5";
91 samsung,pin-function = <4>;
92 samsung,pin-pud = <0>;
93 samsung,pin-drv = <0>;
94 };
95
96 spi0_bus: spi0-bus {
97 samsung,pins = "gpb-0", "gpb-2", "gpb-3";
98 samsung,pin-function = <2>;
99 samsung,pin-pud = <3>;
100 samsung,pin-drv = <0>;
101 };
102
103 i2c4_bus: i2c4-bus {
104 samsung,pins = "gpb-2", "gpb-3";
105 samsung,pin-function = <3>;
106 samsung,pin-pud = <3>;
107 samsung,pin-drv = <0>;
108 };
109
110 spi1_bus: spi1-bus {
111 samsung,pins = "gpb-4", "gpb-6", "gpb-7";
112 samsung,pin-function = <2>;
113 samsung,pin-pud = <3>;
114 samsung,pin-drv = <0>;
115 };
116
117 i2c5_bus: i2c5-bus {
118 samsung,pins = "gpb-6", "gpb-7";
119 samsung,pin-function = <3>;
120 samsung,pin-pud = <3>;
121 samsung,pin-drv = <0>;
122 };
123
124 i2s1_bus: i2s1-bus {
125 samsung,pins = "gpc0-0", "gpc0-1", "gpc0-2", "gpc0-3",
126 "gpc0-4";
127 samsung,pin-function = <2>;
128 samsung,pin-pud = <0>;
129 samsung,pin-drv = <0>;
130 };
131
132 pcm1_bus: pcm1-bus {
133 samsung,pins = "gpc0-0", "gpc0-1", "gpc0-2", "gpc0-3",
134 "gpc0-4";
135 samsung,pin-function = <3>;
136 samsung,pin-pud = <0>;
137 samsung,pin-drv = <0>;
138 };
139
140 ac97_bus: ac97-bus {
141 samsung,pins = "gpc0-0", "gpc0-1", "gpc0-2", "gpc0-3",
142 "gpc0-4";
143 samsung,pin-function = <4>;
144 samsung,pin-pud = <0>;
145 samsung,pin-drv = <0>;
146 };
147
148 i2s2_bus: i2s2-bus {
149 samsung,pins = "gpc1-0", "gpc1-1", "gpc1-2", "gpc1-3",
150 "gpc1-4";
151 samsung,pin-function = <2>;
152 samsung,pin-pud = <0>;
153 samsung,pin-drv = <0>;
154 };
155
156 pcm2_bus: pcm2-bus {
157 samsung,pins = "gpc1-0", "gpc1-1", "gpc1-2", "gpc1-3",
158 "gpc1-4";
159 samsung,pin-function = <3>;
160 samsung,pin-pud = <0>;
161 samsung,pin-drv = <0>;
162 };
163
164 spdif_bus: spdif-bus {
165 samsung,pins = "gpc1-0", "gpc1-1";
166 samsung,pin-function = <4>;
167 samsung,pin-pud = <0>;
168 samsung,pin-drv = <0>;
169 };
170
171 i2c6_bus: i2c6-bus {
172 samsung,pins = "gpc1-3", "gpc1-4";
173 samsung,pin-function = <4>;
174 samsung,pin-pud = <3>;
175 samsung,pin-drv = <0>;
176 };
177
178 spi2_bus: spi2-bus {
179 samsung,pins = "gpc1-1", "gpc1-2", "gpc1-3", "gpc1-4";
180 samsung,pin-function = <5>;
181 samsung,pin-pud = <3>;
182 samsung,pin-drv = <0>;
183 };
184
185 i2c7_bus: i2c7-bus {
186 samsung,pins = "gpd0-2", "gpd0-3";
187 samsung,pin-function = <3>;
188 samsung,pin-pud = <3>;
189 samsung,pin-drv = <0>;
190 };
191
192 i2c0_bus: i2c0-bus {
193 samsung,pins = "gpd1-0", "gpd1-1";
194 samsung,pin-function = <2>;
195 samsung,pin-pud = <3>;
196 samsung,pin-drv = <0>;
197 };
198
199 i2c1_bus: i2c1-bus {
200 samsung,pins = "gpd1-2", "gpd1-3";
201 samsung,pin-function = <2>;
202 samsung,pin-pud = <3>;
203 samsung,pin-drv = <0>;
204 };
205 };
206
207 pinctrl@11000000 {
208 sd0_clk: sd0-clk {
209 samsung,pins = "gpk0-0";
210 samsung,pin-function = <2>;
211 samsung,pin-pud = <0>;
212 samsung,pin-drv = <0>;
213 };
214
215 sd0_cmd: sd0-cmd {
216 samsung,pins = "gpk0-1";
217 samsung,pin-function = <2>;
218 samsung,pin-pud = <0>;
219 samsung,pin-drv = <0>;
220 };
221
222 sd0_cd: sd0-cd {
223 samsung,pins = "gpk0-2";
224 samsung,pin-function = <2>;
225 samsung,pin-pud = <3>;
226 samsung,pin-drv = <0>;
227 };
228
229 sd0_bus1: sd0-bus-width1 {
230 samsung,pins = "gpk0-3";
231 samsung,pin-function = <2>;
232 samsung,pin-pud = <3>;
233 samsung,pin-drv = <0>;
234 };
235
236 sd0_bus4: sd0-bus-width4 {
237 samsung,pins = "gpk0-3", "gpk0-4", "gpk0-5", "gpk0-6";
238 samsung,pin-function = <2>;
239 samsung,pin-pud = <3>;
240 samsung,pin-drv = <0>;
241 };
242
243 sd0_bus8: sd0-bus-width8 {
244 samsung,pins = "gpk1-3", "gpk1-4", "gpk1-5", "gpk1-6";
245 samsung,pin-function = <3>;
246 samsung,pin-pud = <3>;
247 samsung,pin-drv = <0>;
248 };
249
250 sd4_clk: sd4-clk {
251 samsung,pins = "gpk0-0";
252 samsung,pin-function = <3>;
253 samsung,pin-pud = <0>;
254 samsung,pin-drv = <0>;
255 };
256
257 sd4_cmd: sd4-cmd {
258 samsung,pins = "gpk0-1";
259 samsung,pin-function = <3>;
260 samsung,pin-pud = <0>;
261 samsung,pin-drv = <0>;
262 };
263
264 sd4_cd: sd4-cd {
265 samsung,pins = "gpk0-2";
266 samsung,pin-function = <3>;
267 samsung,pin-pud = <3>;
268 samsung,pin-drv = <0>;
269 };
270
271 sd4_bus1: sd4-bus-width1 {
272 samsung,pins = "gpk0-3";
273 samsung,pin-function = <3>;
274 samsung,pin-pud = <3>;
275 samsung,pin-drv = <0>;
276 };
277
278 sd4_bus4: sd4-bus-width4 {
279 samsung,pins = "gpk0-3", "gpk0-4", "gpk0-5", "gpk0-6";
280 samsung,pin-function = <3>;
281 samsung,pin-pud = <3>;
282 samsung,pin-drv = <0>;
283 };
284
285 sd4_bus8: sd4-bus-width8 {
286 samsung,pins = "gpk1-3", "gpk1-4", "gpk1-5", "gpk1-6";
287 samsung,pin-function = <3>;
288 samsung,pin-pud = <4>;
289 samsung,pin-drv = <0>;
290 };
291
292 sd1_clk: sd1-clk {
293 samsung,pins = "gpk1-0";
294 samsung,pin-function = <2>;
295 samsung,pin-pud = <0>;
296 samsung,pin-drv = <0>;
297 };
298
299 sd1_cmd: sd1-cmd {
300 samsung,pins = "gpk1-1";
301 samsung,pin-function = <2>;
302 samsung,pin-pud = <0>;
303 samsung,pin-drv = <0>;
304 };
305
306 sd1_cd: sd1-cd {
307 samsung,pins = "gpk1-2";
308 samsung,pin-function = <2>;
309 samsung,pin-pud = <3>;
310 samsung,pin-drv = <0>;
311 };
312
313 sd1_bus1: sd1-bus-width1 {
314 samsung,pins = "gpk1-3";
315 samsung,pin-function = <2>;
316 samsung,pin-pud = <3>;
317 samsung,pin-drv = <0>;
318 };
319
320 sd1_bus4: sd1-bus-width4 {
321 samsung,pins = "gpk1-3", "gpk1-4", "gpk1-5", "gpk1-6";
322 samsung,pin-function = <2>;
323 samsung,pin-pud = <3>;
324 samsung,pin-drv = <0>;
325 };
326
327 sd2_clk: sd2-clk {
328 samsung,pins = "gpk2-0";
329 samsung,pin-function = <2>;
330 samsung,pin-pud = <0>;
331 samsung,pin-drv = <0>;
332 };
333
334 sd2_cmd: sd2-cmd {
335 samsung,pins = "gpk2-1";
336 samsung,pin-function = <2>;
337 samsung,pin-pud = <0>;
338 samsung,pin-drv = <0>;
339 };
340
341 sd2_cd: sd2-cd {
342 samsung,pins = "gpk2-2";
343 samsung,pin-function = <2>;
344 samsung,pin-pud = <3>;
345 samsung,pin-drv = <0>;
346 };
347
348 sd2_bus1: sd2-bus-width1 {
349 samsung,pins = "gpk2-3";
350 samsung,pin-function = <2>;
351 samsung,pin-pud = <3>;
352 samsung,pin-drv = <0>;
353 };
354
355 sd2_bus4: sd2-bus-width4 {
356 samsung,pins = "gpk2-3", "gpk2-4", "gpk2-5", "gpk2-6";
357 samsung,pin-function = <2>;
358 samsung,pin-pud = <3>;
359 samsung,pin-drv = <0>;
360 };
361
362 sd2_bus8: sd2-bus-width8 {
363 samsung,pins = "gpk3-3", "gpk3-4", "gpk3-5", "gpk3-6";
364 samsung,pin-function = <3>;
365 samsung,pin-pud = <3>;
366 samsung,pin-drv = <0>;
367 };
368
369 sd3_clk: sd3-clk {
370 samsung,pins = "gpk3-0";
371 samsung,pin-function = <2>;
372 samsung,pin-pud = <0>;
373 samsung,pin-drv = <0>;
374 };
375
376 sd3_cmd: sd3-cmd {
377 samsung,pins = "gpk3-1";
378 samsung,pin-function = <2>;
379 samsung,pin-pud = <0>;
380 samsung,pin-drv = <0>;
381 };
382
383 sd3_cd: sd3-cd {
384 samsung,pins = "gpk3-2";
385 samsung,pin-function = <2>;
386 samsung,pin-pud = <3>;
387 samsung,pin-drv = <0>;
388 };
389
390 sd3_bus1: sd3-bus-width1 {
391 samsung,pins = "gpk3-3";
392 samsung,pin-function = <2>;
393 samsung,pin-pud = <3>;
394 samsung,pin-drv = <0>;
395 };
396
397 sd3_bus4: sd3-bus-width4 {
398 samsung,pins = "gpk3-3", "gpk3-4", "gpk3-5", "gpk3-6";
399 samsung,pin-function = <2>;
400 samsung,pin-pud = <3>;
401 samsung,pin-drv = <0>;
402 };
403
404 eint0: ext-int0 {
405 samsung,pins = "gpx0-0";
406 samsung,pin-function = <0xf>;
407 samsung,pin-pud = <0>;
408 samsung,pin-drv = <0>;
409 };
410
411 eint8: ext-int8 {
412 samsung,pins = "gpx1-0";
413 samsung,pin-function = <0xf>;
414 samsung,pin-pud = <0>;
415 samsung,pin-drv = <0>;
416 };
417
418 eint15: ext-int15 {
419 samsung,pins = "gpx1-7";
420 samsung,pin-function = <0xf>;
421 samsung,pin-pud = <0>;
422 samsung,pin-drv = <0>;
423 };
424
425 eint16: ext-int16 {
426 samsung,pins = "gpx2-0";
427 samsung,pin-function = <0xf>;
428 samsung,pin-pud = <0>;
429 samsung,pin-drv = <0>;
430 };
431
432 eint31: ext-int31 {
433 samsung,pins = "gpx3-7";
434 samsung,pin-function = <0xf>;
435 samsung,pin-pud = <0>;
436 samsung,pin-drv = <0>;
437 };
438 };
439
440 pinctrl@03860000 {
441 i2s0_bus: i2s0-bus {
442 samsung,pins = "gpz-0", "gpz-1", "gpz-2", "gpz-3",
443 "gpz-4", "gpz-5", "gpz-6";
444 samsung,pin-function = <0x2>;
445 samsung,pin-pud = <0>;
446 samsung,pin-drv = <0>;
447 };
448
449 pcm0_bus: pcm0-bus {
450 samsung,pins = "gpz-0", "gpz-1", "gpz-2", "gpz-3",
451 "gpz-4";
452 samsung,pin-function = <0x3>;
453 samsung,pin-pud = <0>;
454 samsung,pin-drv = <0>;
455 };
456 };
457};
diff --git a/arch/arm/boot/dts/exynos4210.dtsi b/arch/arm/boot/dts/exynos4210.dtsi
index 02891fe876e4..a4bd0c9a206e 100644
--- a/arch/arm/boot/dts/exynos4210.dtsi
+++ b/arch/arm/boot/dts/exynos4210.dtsi
@@ -20,6 +20,7 @@
20*/ 20*/
21 21
22/include/ "skeleton.dtsi" 22/include/ "skeleton.dtsi"
23/include/ "exynos4210-pinctrl.dtsi"
23 24
24/ { 25/ {
25 compatible = "samsung,exynos4210"; 26 compatible = "samsung,exynos4210";
@@ -29,6 +30,9 @@
29 spi0 = &spi_0; 30 spi0 = &spi_0;
30 spi1 = &spi_1; 31 spi1 = &spi_1;
31 spi2 = &spi_2; 32 spi2 = &spi_2;
33 pinctrl0 = &pinctrl_0;
34 pinctrl1 = &pinctrl_1;
35 pinctrl2 = &pinctrl_2;
32 }; 36 };
33 37
34 gic:interrupt-controller@10490000 { 38 gic:interrupt-controller@10490000 {
@@ -50,6 +54,39 @@
50 <0 12 0>, <0 13 0>, <0 14 0>, <0 15 0>; 54 <0 12 0>, <0 13 0>, <0 14 0>, <0 15 0>;
51 }; 55 };
52 56
57 pinctrl_0: pinctrl@11400000 {
58 compatible = "samsung,pinctrl-exynos4210";
59 reg = <0x11400000 0x1000>;
60 interrupts = <0 47 0>;
61 interrupt-controller;
62 #interrupt-cells = <2>;
63 };
64
65 pinctrl_1: pinctrl@11000000 {
66 compatible = "samsung,pinctrl-exynos4210";
67 reg = <0x11000000 0x1000>;
68 interrupts = <0 46 0>;
69 interrupt-controller;
70 #interrupt-cells = <2>;
71
72 wakup_eint: wakeup-interrupt-controller {
73 compatible = "samsung,exynos4210-wakeup-eint";
74 interrupt-parent = <&gic>;
75 interrupt-controller;
76 #interrupt-cells = <2>;
77 interrupts = <0 16 0>, <0 17 0>, <0 18 0>, <0 19 0>,
78 <0 20 0>, <0 21 0>, <0 22 0>, <0 23 0>,
79 <0 24 0>, <0 25 0>, <0 26 0>, <0 27 0>,
80 <0 28 0>, <0 29 0>, <0 30 0>, <0 31 0>,
81 <0 32 0>;
82 };
83 };
84
85 pinctrl_2: pinctrl@03860000 {
86 compatible = "samsung,pinctrl-exynos4210";
87 reg = <0x03860000 0x1000>;
88 };
89
53 watchdog@10060000 { 90 watchdog@10060000 {
54 compatible = "samsung,s3c2410-wdt"; 91 compatible = "samsung,s3c2410-wdt";
55 reg = <0x10060000 0x100>; 92 reg = <0x10060000 0x100>;
diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig
index b5b4c8c9db11..195b50eb1e57 100644
--- a/arch/arm/mach-exynos/Kconfig
+++ b/arch/arm/mach-exynos/Kconfig
@@ -405,6 +405,8 @@ config MACH_EXYNOS4_DT
405 select USE_OF 405 select USE_OF
406 select ARM_AMBA 406 select ARM_AMBA
407 select HAVE_SAMSUNG_KEYPAD if INPUT_KEYBOARD 407 select HAVE_SAMSUNG_KEYPAD if INPUT_KEYBOARD
408 select PINCTRL
409 select PINCTRL_EXYNOS4
408 help 410 help
409 Machine support for Samsung Exynos4 machine with device tree enabled. 411 Machine support for Samsung Exynos4 machine with device tree enabled.
410 Select this if a fdt blob is available for the Exynos4 SoC based board. 412 Select this if a fdt blob is available for the Exynos4 SoC based board.
diff --git a/arch/arm/mach-exynos/common.c b/arch/arm/mach-exynos/common.c
index 4eb39cdf75ea..715b690e5009 100644
--- a/arch/arm/mach-exynos/common.c
+++ b/arch/arm/mach-exynos/common.c
@@ -980,6 +980,32 @@ static int __init exynos_init_irq_eint(void)
980{ 980{
981 int irq; 981 int irq;
982 982
983#ifdef CONFIG_PINCTRL_SAMSUNG
984 /*
985 * The Samsung pinctrl driver provides an integrated gpio/pinmux/pinconf
986 * functionality along with support for external gpio and wakeup
987 * interrupts. If the samsung pinctrl driver is enabled and includes
988 * the wakeup interrupt support, then the setting up external wakeup
989 * interrupts here can be skipped. This check here is temporary to
990 * allow exynos4 platforms that do not use Samsung pinctrl driver to
991 * co-exist with platforms that do. When all of the Samsung Exynos4
992 * platforms switch over to using the pinctrl driver, the wakeup
993 * interrupt support code here can be completely removed.
994 */
995 struct device_node *pctrl_np, *wkup_np;
996 const char *pctrl_compat = "samsung,pinctrl-exynos4210";
997 const char *wkup_compat = "samsung,exynos4210-wakeup-eint";
998
999 for_each_compatible_node(pctrl_np, NULL, pctrl_compat) {
1000 if (of_device_is_available(pctrl_np)) {
1001 wkup_np = of_find_compatible_node(pctrl_np, NULL,
1002 wkup_compat);
1003 if (wkup_np)
1004 return -ENODEV;
1005 }
1006 }
1007#endif
1008
983 if (soc_is_exynos5250()) 1009 if (soc_is_exynos5250())
984 exynos_eint_base = ioremap(EXYNOS5_PA_GPIO1, SZ_4K); 1010 exynos_eint_base = ioremap(EXYNOS5_PA_GPIO1, SZ_4K);
985 else 1011 else
diff --git a/drivers/gpio/gpio-samsung.c b/drivers/gpio/gpio-samsung.c
index ba126cc04073..41ab7f66cdf9 100644
--- a/drivers/gpio/gpio-samsung.c
+++ b/drivers/gpio/gpio-samsung.c
@@ -2734,6 +2734,27 @@ static __init void exynos4_gpiolib_init(void)
2734 int group = 0; 2734 int group = 0;
2735 void __iomem *gpx_base; 2735 void __iomem *gpx_base;
2736 2736
2737#ifdef CONFIG_PINCTRL_SAMSUNG
2738 /*
2739 * This gpio driver includes support for device tree support and
2740 * there are platforms using it. In order to maintain
2741 * compatibility with those platforms, and to allow non-dt
2742 * Exynos4210 platforms to use this gpiolib support, a check
2743 * is added to find out if there is a active pin-controller
2744 * driver support available. If it is available, this gpiolib
2745 * support is ignored and the gpiolib support available in
2746 * pin-controller driver is used. This is a temporary check and
2747 * will go away when all of the Exynos4210 platforms have
2748 * switched to using device tree and the pin-ctrl driver.
2749 */
2750 struct device_node *pctrl_np;
2751 const char *pctrl_compat = "samsung,pinctrl-exynos4210";
2752 pctrl_np = of_find_compatible_node(NULL, NULL, pctrl_compat);
2753 if (pctrl_np)
2754 if (of_device_is_available(pctrl_np))
2755 return;
2756#endif
2757
2737 /* gpio part1 */ 2758 /* gpio part1 */
2738 gpio_base1 = ioremap(EXYNOS4_PA_GPIO1, SZ_4K); 2759 gpio_base1 = ioremap(EXYNOS4_PA_GPIO1, SZ_4K);
2739 if (gpio_base1 == NULL) { 2760 if (gpio_base1 == NULL) {
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index 54e3588bef62..34e94c7f68ca 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -145,6 +145,15 @@ config PINCTRL_COH901
145 COH 901 335 and COH 901 571/3. They contain 3, 5 or 7 145 COH 901 335 and COH 901 571/3. They contain 3, 5 or 7
146 ports of 8 GPIO pins each. 146 ports of 8 GPIO pins each.
147 147
148config PINCTRL_SAMSUNG
149 bool "Samsung pinctrl driver"
150 select PINMUX
151 select PINCONF
152
153config PINCTRL_EXYNOS4
154 bool "Pinctrl driver data for Exynos4 SoC"
155 select PINCTRL_SAMSUNG
156
148source "drivers/pinctrl/spear/Kconfig" 157source "drivers/pinctrl/spear/Kconfig"
149 158
150endmenu 159endmenu
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index f40b1f81ff2c..6a88113e11d9 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -29,5 +29,7 @@ obj-$(CONFIG_PINCTRL_TEGRA20) += pinctrl-tegra20.o
29obj-$(CONFIG_PINCTRL_TEGRA30) += pinctrl-tegra30.o 29obj-$(CONFIG_PINCTRL_TEGRA30) += pinctrl-tegra30.o
30obj-$(CONFIG_PINCTRL_U300) += pinctrl-u300.o 30obj-$(CONFIG_PINCTRL_U300) += pinctrl-u300.o
31obj-$(CONFIG_PINCTRL_COH901) += pinctrl-coh901.o 31obj-$(CONFIG_PINCTRL_COH901) += pinctrl-coh901.o
32obj-$(CONFIG_PINCTRL_SAMSUNG) += pinctrl-samsung.o
33obj-$(CONFIG_PINCTRL_EXYNOS4) += pinctrl-exynos.o
32 34
33obj-$(CONFIG_PLAT_SPEAR) += spear/ 35obj-$(CONFIG_PLAT_SPEAR) += spear/
diff --git a/drivers/pinctrl/pinctrl-exynos.c b/drivers/pinctrl/pinctrl-exynos.c
new file mode 100644
index 000000000000..447818d9851b
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-exynos.c
@@ -0,0 +1,560 @@
1/*
2 * Exynos specific support for Samsung pinctrl/gpiolib driver with eint support.
3 *
4 * Copyright (c) 2012 Samsung Electronics Co., Ltd.
5 * http://www.samsung.com
6 * Copyright (c) 2012 Linaro Ltd
7 * http://www.linaro.org
8 *
9 * Author: Thomas Abraham <thomas.ab@samsung.com>
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This file contains the Samsung Exynos specific information required by the
17 * the Samsung pinctrl/gpiolib driver. It also includes the implementation of
18 * external gpio and wakeup interrupt support.
19 */
20
21#include <linux/module.h>
22#include <linux/device.h>
23#include <linux/interrupt.h>
24#include <linux/irqdomain.h>
25#include <linux/irq.h>
26#include <linux/of_irq.h>
27#include <linux/io.h>
28#include <linux/slab.h>
29#include <linux/err.h>
30
31#include <asm/mach/irq.h>
32
33#include "pinctrl-samsung.h"
34#include "pinctrl-exynos.h"
35
36/* list of external wakeup controllers supported */
37static const struct of_device_id exynos_wkup_irq_ids[] = {
38 { .compatible = "samsung,exynos4210-wakeup-eint", },
39};
40
41static void exynos_gpio_irq_unmask(struct irq_data *irqd)
42{
43 struct samsung_pinctrl_drv_data *d = irqd->domain->host_data;
44 struct exynos_geint_data *edata = irq_data_get_irq_handler_data(irqd);
45 unsigned long reg_mask = d->ctrl->geint_mask + edata->eint_offset;
46 unsigned long mask;
47
48 mask = readl(d->virt_base + reg_mask);
49 mask &= ~(1 << edata->pin);
50 writel(mask, d->virt_base + reg_mask);
51}
52
53static void exynos_gpio_irq_mask(struct irq_data *irqd)
54{
55 struct samsung_pinctrl_drv_data *d = irqd->domain->host_data;
56 struct exynos_geint_data *edata = irq_data_get_irq_handler_data(irqd);
57 unsigned long reg_mask = d->ctrl->geint_mask + edata->eint_offset;
58 unsigned long mask;
59
60 mask = readl(d->virt_base + reg_mask);
61 mask |= ~(1 << edata->pin);
62 writel(mask, d->virt_base + reg_mask);
63}
64
65static void exynos_gpio_irq_ack(struct irq_data *irqd)
66{
67 struct samsung_pinctrl_drv_data *d = irqd->domain->host_data;
68 struct exynos_geint_data *edata = irq_data_get_irq_handler_data(irqd);
69 unsigned long reg_pend = d->ctrl->geint_pend + edata->eint_offset;
70
71 writel(1 << edata->pin, d->virt_base + reg_pend);
72}
73
74static int exynos_gpio_irq_set_type(struct irq_data *irqd, unsigned int type)
75{
76 struct samsung_pinctrl_drv_data *d = irqd->domain->host_data;
77 struct samsung_pin_ctrl *ctrl = d->ctrl;
78 struct exynos_geint_data *edata = irq_data_get_irq_handler_data(irqd);
79 unsigned int shift = EXYNOS_EINT_CON_LEN * edata->pin;
80 unsigned int con, trig_type;
81 unsigned long reg_con = ctrl->geint_con + edata->eint_offset;
82
83 switch (type) {
84 case IRQ_TYPE_EDGE_RISING:
85 trig_type = EXYNOS_EINT_EDGE_RISING;
86 break;
87 case IRQ_TYPE_EDGE_FALLING:
88 trig_type = EXYNOS_EINT_EDGE_FALLING;
89 break;
90 case IRQ_TYPE_EDGE_BOTH:
91 trig_type = EXYNOS_EINT_EDGE_BOTH;
92 break;
93 case IRQ_TYPE_LEVEL_HIGH:
94 trig_type = EXYNOS_EINT_LEVEL_HIGH;
95 break;
96 case IRQ_TYPE_LEVEL_LOW:
97 trig_type = EXYNOS_EINT_LEVEL_LOW;
98 break;
99 default:
100 pr_err("unsupported external interrupt type\n");
101 return -EINVAL;
102 }
103
104 if (type & IRQ_TYPE_EDGE_BOTH)
105 __irq_set_handler_locked(irqd->irq, handle_edge_irq);
106 else
107 __irq_set_handler_locked(irqd->irq, handle_level_irq);
108
109 con = readl(d->virt_base + reg_con);
110 con &= ~(EXYNOS_EINT_CON_MASK << shift);
111 con |= trig_type << shift;
112 writel(con, d->virt_base + reg_con);
113 return 0;
114}
115
116/*
117 * irq_chip for gpio interrupts.
118 */
119static struct irq_chip exynos_gpio_irq_chip = {
120 .name = "exynos_gpio_irq_chip",
121 .irq_unmask = exynos_gpio_irq_unmask,
122 .irq_mask = exynos_gpio_irq_mask,
123 .irq_ack = exynos_gpio_irq_ack,
124 .irq_set_type = exynos_gpio_irq_set_type,
125};
126
127/*
128 * given a controller-local external gpio interrupt number, prepare the handler
129 * data for it.
130 */
131static struct exynos_geint_data *exynos_get_eint_data(irq_hw_number_t hw,
132 struct samsung_pinctrl_drv_data *d)
133{
134 struct samsung_pin_bank *bank = d->ctrl->pin_banks;
135 struct exynos_geint_data *eint_data;
136 unsigned int nr_banks = d->ctrl->nr_banks, idx;
137 unsigned int irq_base = 0, eint_offset = 0;
138
139 if (hw >= d->ctrl->nr_gint) {
140 dev_err(d->dev, "unsupported ext-gpio interrupt\n");
141 return NULL;
142 }
143
144 for (idx = 0; idx < nr_banks; idx++, bank++) {
145 if (bank->eint_type != EINT_TYPE_GPIO)
146 continue;
147 if ((hw >= irq_base) && (hw < (irq_base + bank->nr_pins)))
148 break;
149 irq_base += bank->nr_pins;
150 eint_offset += 4;
151 }
152
153 if (idx == nr_banks) {
154 dev_err(d->dev, "pin bank not found for ext-gpio interrupt\n");
155 return NULL;
156 }
157
158 eint_data = devm_kzalloc(d->dev, sizeof(*eint_data), GFP_KERNEL);
159 if (!eint_data) {
160 dev_err(d->dev, "no memory for eint-gpio data\n");
161 return NULL;
162 }
163
164 eint_data->bank = bank;
165 eint_data->pin = hw - irq_base;
166 eint_data->eint_offset = eint_offset;
167 return eint_data;
168}
169
170static int exynos_gpio_irq_map(struct irq_domain *h, unsigned int virq,
171 irq_hw_number_t hw)
172{
173 struct samsung_pinctrl_drv_data *d = h->host_data;
174 struct exynos_geint_data *eint_data;
175
176 eint_data = exynos_get_eint_data(hw, d);
177 if (!eint_data)
178 return -EINVAL;
179
180 irq_set_handler_data(virq, eint_data);
181 irq_set_chip_data(virq, h->host_data);
182 irq_set_chip_and_handler(virq, &exynos_gpio_irq_chip,
183 handle_level_irq);
184 set_irq_flags(virq, IRQF_VALID);
185 return 0;
186}
187
188static void exynos_gpio_irq_unmap(struct irq_domain *h, unsigned int virq)
189{
190 struct samsung_pinctrl_drv_data *d = h->host_data;
191 struct exynos_geint_data *eint_data;
192
193 eint_data = irq_get_handler_data(virq);
194 devm_kfree(d->dev, eint_data);
195}
196
197/*
198 * irq domain callbacks for external gpio interrupt controller.
199 */
200static const struct irq_domain_ops exynos_gpio_irqd_ops = {
201 .map = exynos_gpio_irq_map,
202 .unmap = exynos_gpio_irq_unmap,
203 .xlate = irq_domain_xlate_twocell,
204};
205
206static irqreturn_t exynos_eint_gpio_irq(int irq, void *data)
207{
208 struct samsung_pinctrl_drv_data *d = data;
209 struct samsung_pin_ctrl *ctrl = d->ctrl;
210 struct samsung_pin_bank *bank = ctrl->pin_banks;
211 unsigned int svc, group, pin, virq;
212
213 svc = readl(d->virt_base + ctrl->svc);
214 group = EXYNOS_SVC_GROUP(svc);
215 pin = svc & EXYNOS_SVC_NUM_MASK;
216
217 if (!group)
218 return IRQ_HANDLED;
219 bank += (group - 1);
220
221 virq = irq_linear_revmap(d->gpio_irqd, bank->irq_base + pin);
222 if (!virq)
223 return IRQ_NONE;
224 generic_handle_irq(virq);
225 return IRQ_HANDLED;
226}
227
228/*
229 * exynos_eint_gpio_init() - setup handling of external gpio interrupts.
230 * @d: driver data of samsung pinctrl driver.
231 */
232static int exynos_eint_gpio_init(struct samsung_pinctrl_drv_data *d)
233{
234 struct device *dev = d->dev;
235 unsigned int ret;
236
237 if (!d->irq) {
238 dev_err(dev, "irq number not available\n");
239 return -EINVAL;
240 }
241
242 ret = devm_request_irq(dev, d->irq, exynos_eint_gpio_irq,
243 0, dev_name(dev), d);
244 if (ret) {
245 dev_err(dev, "irq request failed\n");
246 return -ENXIO;
247 }
248
249 d->gpio_irqd = irq_domain_add_linear(dev->of_node, d->ctrl->nr_gint,
250 &exynos_gpio_irqd_ops, d);
251 if (!d->gpio_irqd) {
252 dev_err(dev, "gpio irq domain allocation failed\n");
253 return -ENXIO;
254 }
255
256 return 0;
257}
258
259static void exynos_wkup_irq_unmask(struct irq_data *irqd)
260{
261 struct samsung_pinctrl_drv_data *d = irq_data_get_irq_chip_data(irqd);
262 unsigned int bank = irqd->hwirq / EXYNOS_EINT_MAX_PER_BANK;
263 unsigned int pin = irqd->hwirq & (EXYNOS_EINT_MAX_PER_BANK - 1);
264 unsigned long reg_mask = d->ctrl->weint_mask + (bank << 2);
265 unsigned long mask;
266
267 mask = readl(d->virt_base + reg_mask);
268 mask &= ~(1 << pin);
269 writel(mask, d->virt_base + reg_mask);
270}
271
272static void exynos_wkup_irq_mask(struct irq_data *irqd)
273{
274 struct samsung_pinctrl_drv_data *d = irq_data_get_irq_chip_data(irqd);
275 unsigned int bank = irqd->hwirq / EXYNOS_EINT_MAX_PER_BANK;
276 unsigned int pin = irqd->hwirq & (EXYNOS_EINT_MAX_PER_BANK - 1);
277 unsigned long reg_mask = d->ctrl->weint_mask + (bank << 2);
278 unsigned long mask;
279
280 mask = readl(d->virt_base + reg_mask);
281 mask &= ~(1 << pin);
282 writel(mask, d->virt_base + reg_mask);
283}
284
285static void exynos_wkup_irq_ack(struct irq_data *irqd)
286{
287 struct samsung_pinctrl_drv_data *d = irq_data_get_irq_chip_data(irqd);
288 unsigned int bank = irqd->hwirq / EXYNOS_EINT_MAX_PER_BANK;
289 unsigned int pin = irqd->hwirq & (EXYNOS_EINT_MAX_PER_BANK - 1);
290 unsigned long pend = d->ctrl->weint_pend + (bank << 2);
291
292 writel(1 << pin, d->virt_base + pend);
293}
294
295static int exynos_wkup_irq_set_type(struct irq_data *irqd, unsigned int type)
296{
297 struct samsung_pinctrl_drv_data *d = irq_data_get_irq_chip_data(irqd);
298 unsigned int bank = irqd->hwirq / EXYNOS_EINT_MAX_PER_BANK;
299 unsigned int pin = irqd->hwirq & (EXYNOS_EINT_MAX_PER_BANK - 1);
300 unsigned long reg_con = d->ctrl->weint_con + (bank << 2);
301 unsigned long shift = EXYNOS_EINT_CON_LEN * pin;
302 unsigned long con, trig_type;
303
304 switch (type) {
305 case IRQ_TYPE_EDGE_RISING:
306 trig_type = EXYNOS_EINT_EDGE_RISING;
307 break;
308 case IRQ_TYPE_EDGE_FALLING:
309 trig_type = EXYNOS_EINT_EDGE_FALLING;
310 break;
311 case IRQ_TYPE_EDGE_BOTH:
312 trig_type = EXYNOS_EINT_EDGE_BOTH;
313 break;
314 case IRQ_TYPE_LEVEL_HIGH:
315 trig_type = EXYNOS_EINT_LEVEL_HIGH;
316 break;
317 case IRQ_TYPE_LEVEL_LOW:
318 trig_type = EXYNOS_EINT_LEVEL_LOW;
319 break;
320 default:
321 pr_err("unsupported external interrupt type\n");
322 return -EINVAL;
323 }
324
325 if (type & IRQ_TYPE_EDGE_BOTH)
326 __irq_set_handler_locked(irqd->irq, handle_edge_irq);
327 else
328 __irq_set_handler_locked(irqd->irq, handle_level_irq);
329
330 con = readl(d->virt_base + reg_con);
331 con &= ~(EXYNOS_EINT_CON_MASK << shift);
332 con |= trig_type << shift;
333 writel(con, d->virt_base + reg_con);
334 return 0;
335}
336
337/*
338 * irq_chip for wakeup interrupts
339 */
340static struct irq_chip exynos_wkup_irq_chip = {
341 .name = "exynos_wkup_irq_chip",
342 .irq_unmask = exynos_wkup_irq_unmask,
343 .irq_mask = exynos_wkup_irq_mask,
344 .irq_ack = exynos_wkup_irq_ack,
345 .irq_set_type = exynos_wkup_irq_set_type,
346};
347
348/* interrupt handler for wakeup interrupts 0..15 */
349static void exynos_irq_eint0_15(unsigned int irq, struct irq_desc *desc)
350{
351 struct exynos_weint_data *eintd = irq_get_handler_data(irq);
352 struct irq_chip *chip = irq_get_chip(irq);
353 int eint_irq;
354
355 chained_irq_enter(chip, desc);
356 chip->irq_mask(&desc->irq_data);
357
358 if (chip->irq_ack)
359 chip->irq_ack(&desc->irq_data);
360
361 eint_irq = irq_linear_revmap(eintd->domain, eintd->irq);
362 generic_handle_irq(eint_irq);
363 chip->irq_unmask(&desc->irq_data);
364 chained_irq_exit(chip, desc);
365}
366
367static void exynos_irq_demux_eint(int irq_base, unsigned long pend,
368 struct irq_domain *domain)
369{
370 unsigned int irq;
371
372 while (pend) {
373 irq = fls(pend) - 1;
374 generic_handle_irq(irq_find_mapping(domain, irq_base + irq));
375 pend &= ~(1 << irq);
376 }
377}
378
379/* interrupt handler for wakeup interrupt 16 */
380static void exynos_irq_demux_eint16_31(unsigned int irq, struct irq_desc *desc)
381{
382 struct irq_chip *chip = irq_get_chip(irq);
383 struct exynos_weint_data *eintd = irq_get_handler_data(irq);
384 struct samsung_pinctrl_drv_data *d = eintd->domain->host_data;
385 unsigned long pend;
386
387 chained_irq_enter(chip, desc);
388 pend = readl(d->virt_base + d->ctrl->weint_pend + 0x8);
389 exynos_irq_demux_eint(16, pend, eintd->domain);
390 pend = readl(d->virt_base + d->ctrl->weint_pend + 0xC);
391 exynos_irq_demux_eint(24, pend, eintd->domain);
392 chained_irq_exit(chip, desc);
393}
394
395static int exynos_wkup_irq_map(struct irq_domain *h, unsigned int virq,
396 irq_hw_number_t hw)
397{
398 irq_set_chip_and_handler(virq, &exynos_wkup_irq_chip, handle_level_irq);
399 irq_set_chip_data(virq, h->host_data);
400 set_irq_flags(virq, IRQF_VALID);
401 return 0;
402}
403
404/*
405 * irq domain callbacks for external wakeup interrupt controller.
406 */
407static const struct irq_domain_ops exynos_wkup_irqd_ops = {
408 .map = exynos_wkup_irq_map,
409 .xlate = irq_domain_xlate_twocell,
410};
411
412/*
413 * exynos_eint_wkup_init() - setup handling of external wakeup interrupts.
414 * @d: driver data of samsung pinctrl driver.
415 */
416static int exynos_eint_wkup_init(struct samsung_pinctrl_drv_data *d)
417{
418 struct device *dev = d->dev;
419 struct device_node *wkup_np;
420 struct exynos_weint_data *weint_data;
421 int idx, irq;
422
423 wkup_np = of_find_matching_node(dev->of_node, exynos_wkup_irq_ids);
424 if (!wkup_np) {
425 dev_err(dev, "wakeup controller node not found\n");
426 return -ENODEV;
427 }
428
429 d->wkup_irqd = irq_domain_add_linear(wkup_np, d->ctrl->nr_wint,
430 &exynos_wkup_irqd_ops, d);
431 if (!d->gpio_irqd) {
432 dev_err(dev, "wakeup irq domain allocation failed\n");
433 return -ENXIO;
434 }
435
436 weint_data = devm_kzalloc(dev, sizeof(*weint_data) * 17, GFP_KERNEL);
437 if (!weint_data) {
438 dev_err(dev, "could not allocate memory for weint_data\n");
439 return -ENOMEM;
440 }
441
442 irq = irq_of_parse_and_map(wkup_np, 16);
443 if (irq) {
444 weint_data[16].domain = d->wkup_irqd;
445 irq_set_chained_handler(irq, exynos_irq_demux_eint16_31);
446 irq_set_handler_data(irq, &weint_data[16]);
447 } else {
448 dev_err(dev, "irq number for EINT16-32 not found\n");
449 }
450
451 for (idx = 0; idx < 16; idx++) {
452 weint_data[idx].domain = d->wkup_irqd;
453 weint_data[idx].irq = idx;
454
455 irq = irq_of_parse_and_map(wkup_np, idx);
456 if (irq) {
457 irq_set_handler_data(irq, &weint_data[idx]);
458 irq_set_chained_handler(irq, exynos_irq_eint0_15);
459 } else {
460 dev_err(dev, "irq number for eint-%x not found\n", idx);
461 }
462 }
463 return 0;
464}
465
466/* pin banks of exynos4210 pin-controller 0 */
467static struct samsung_pin_bank exynos4210_pin_banks0[] = {
468 EXYNOS_PIN_BANK_EINTG(0x000, EXYNOS4210_GPIO_A0, "gpa0"),
469 EXYNOS_PIN_BANK_EINTG(0x020, EXYNOS4210_GPIO_A1, "gpa1"),
470 EXYNOS_PIN_BANK_EINTG(0x040, EXYNOS4210_GPIO_B, "gpb"),
471 EXYNOS_PIN_BANK_EINTG(0x060, EXYNOS4210_GPIO_C0, "gpc0"),
472 EXYNOS_PIN_BANK_EINTG(0x080, EXYNOS4210_GPIO_C1, "gpc1"),
473 EXYNOS_PIN_BANK_EINTG(0x0A0, EXYNOS4210_GPIO_D0, "gpd0"),
474 EXYNOS_PIN_BANK_EINTG(0x0C0, EXYNOS4210_GPIO_D1, "gpd1"),
475 EXYNOS_PIN_BANK_EINTG(0x0E0, EXYNOS4210_GPIO_E0, "gpe0"),
476 EXYNOS_PIN_BANK_EINTG(0x100, EXYNOS4210_GPIO_E1, "gpe1"),
477 EXYNOS_PIN_BANK_EINTG(0x120, EXYNOS4210_GPIO_E2, "gpe2"),
478 EXYNOS_PIN_BANK_EINTG(0x140, EXYNOS4210_GPIO_E3, "gpe3"),
479 EXYNOS_PIN_BANK_EINTG(0x160, EXYNOS4210_GPIO_E4, "gpe4"),
480 EXYNOS_PIN_BANK_EINTG(0x180, EXYNOS4210_GPIO_F0, "gpf0"),
481 EXYNOS_PIN_BANK_EINTG(0x1A0, EXYNOS4210_GPIO_F1, "gpf1"),
482 EXYNOS_PIN_BANK_EINTG(0x1C0, EXYNOS4210_GPIO_F2, "gpf2"),
483 EXYNOS_PIN_BANK_EINTG(0x1E0, EXYNOS4210_GPIO_F3, "gpf3"),
484};
485
486/* pin banks of exynos4210 pin-controller 1 */
487static struct samsung_pin_bank exynos4210_pin_banks1[] = {
488 EXYNOS_PIN_BANK_EINTG(0x000, EXYNOS4210_GPIO_J0, "gpj0"),
489 EXYNOS_PIN_BANK_EINTG(0x020, EXYNOS4210_GPIO_J1, "gpj1"),
490 EXYNOS_PIN_BANK_EINTG(0x040, EXYNOS4210_GPIO_K0, "gpk0"),
491 EXYNOS_PIN_BANK_EINTG(0x060, EXYNOS4210_GPIO_K1, "gpk1"),
492 EXYNOS_PIN_BANK_EINTG(0x080, EXYNOS4210_GPIO_K2, "gpk2"),
493 EXYNOS_PIN_BANK_EINTG(0x0A0, EXYNOS4210_GPIO_K3, "gpk3"),
494 EXYNOS_PIN_BANK_EINTG(0x0C0, EXYNOS4210_GPIO_L0, "gpl0"),
495 EXYNOS_PIN_BANK_EINTG(0x0E0, EXYNOS4210_GPIO_L1, "gpl1"),
496 EXYNOS_PIN_BANK_EINTG(0x100, EXYNOS4210_GPIO_L2, "gpl2"),
497 EXYNOS_PIN_BANK_EINTN(0x120, EXYNOS4210_GPIO_Y0, "gpy0"),
498 EXYNOS_PIN_BANK_EINTN(0x140, EXYNOS4210_GPIO_Y1, "gpy1"),
499 EXYNOS_PIN_BANK_EINTN(0x160, EXYNOS4210_GPIO_Y2, "gpy2"),
500 EXYNOS_PIN_BANK_EINTN(0x180, EXYNOS4210_GPIO_Y3, "gpy3"),
501 EXYNOS_PIN_BANK_EINTN(0x1A0, EXYNOS4210_GPIO_Y4, "gpy4"),
502 EXYNOS_PIN_BANK_EINTN(0x1C0, EXYNOS4210_GPIO_Y5, "gpy5"),
503 EXYNOS_PIN_BANK_EINTN(0x1E0, EXYNOS4210_GPIO_Y6, "gpy6"),
504 EXYNOS_PIN_BANK_EINTN(0xC00, EXYNOS4210_GPIO_X0, "gpx0"),
505 EXYNOS_PIN_BANK_EINTN(0xC20, EXYNOS4210_GPIO_X1, "gpx1"),
506 EXYNOS_PIN_BANK_EINTN(0xC40, EXYNOS4210_GPIO_X2, "gpx2"),
507 EXYNOS_PIN_BANK_EINTN(0xC60, EXYNOS4210_GPIO_X3, "gpx3"),
508};
509
510/* pin banks of exynos4210 pin-controller 2 */
511static struct samsung_pin_bank exynos4210_pin_banks2[] = {
512 EXYNOS_PIN_BANK_EINTN(0x000, EXYNOS4210_GPIO_Z, "gpz"),
513};
514
515/*
516 * Samsung pinctrl driver data for Exynos4210 SoC. Exynos4210 SoC includes
517 * three gpio/pin-mux/pinconfig controllers.
518 */
519struct samsung_pin_ctrl exynos4210_pin_ctrl[] = {
520 {
521 /* pin-controller instance 0 data */
522 .pin_banks = exynos4210_pin_banks0,
523 .nr_banks = ARRAY_SIZE(exynos4210_pin_banks0),
524 .base = EXYNOS4210_GPIO_A0_START,
525 .nr_pins = EXYNOS4210_GPIOA_NR_PINS,
526 .nr_gint = EXYNOS4210_GPIOA_NR_GINT,
527 .geint_con = EXYNOS_GPIO_ECON_OFFSET,
528 .geint_mask = EXYNOS_GPIO_EMASK_OFFSET,
529 .geint_pend = EXYNOS_GPIO_EPEND_OFFSET,
530 .svc = EXYNOS_SVC_OFFSET,
531 .eint_gpio_init = exynos_eint_gpio_init,
532 .label = "exynos4210-gpio-ctrl0",
533 }, {
534 /* pin-controller instance 1 data */
535 .pin_banks = exynos4210_pin_banks1,
536 .nr_banks = ARRAY_SIZE(exynos4210_pin_banks1),
537 .base = EXYNOS4210_GPIOA_NR_PINS,
538 .nr_pins = EXYNOS4210_GPIOB_NR_PINS,
539 .nr_gint = EXYNOS4210_GPIOB_NR_GINT,
540 .nr_wint = 32,
541 .geint_con = EXYNOS_GPIO_ECON_OFFSET,
542 .geint_mask = EXYNOS_GPIO_EMASK_OFFSET,
543 .geint_pend = EXYNOS_GPIO_EPEND_OFFSET,
544 .weint_con = EXYNOS_WKUP_ECON_OFFSET,
545 .weint_mask = EXYNOS_WKUP_EMASK_OFFSET,
546 .weint_pend = EXYNOS_WKUP_EPEND_OFFSET,
547 .svc = EXYNOS_SVC_OFFSET,
548 .eint_gpio_init = exynos_eint_gpio_init,
549 .eint_wkup_init = exynos_eint_wkup_init,
550 .label = "exynos4210-gpio-ctrl1",
551 }, {
552 /* pin-controller instance 2 data */
553 .pin_banks = exynos4210_pin_banks2,
554 .nr_banks = ARRAY_SIZE(exynos4210_pin_banks2),
555 .base = EXYNOS4210_GPIOA_NR_PINS +
556 EXYNOS4210_GPIOB_NR_PINS,
557 .nr_pins = EXYNOS4210_GPIOC_NR_PINS,
558 .label = "exynos4210-gpio-ctrl2",
559 },
560};
diff --git a/drivers/pinctrl/pinctrl-exynos.h b/drivers/pinctrl/pinctrl-exynos.h
new file mode 100644
index 000000000000..5f27ba974a3a
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-exynos.h
@@ -0,0 +1,217 @@
1/*
2 * Exynos specific definitions for Samsung pinctrl and gpiolib driver.
3 *
4 * Copyright (c) 2012 Samsung Electronics Co., Ltd.
5 * http://www.samsung.com
6 * Copyright (c) 2012 Linaro Ltd
7 * http://www.linaro.org
8 *
9 * This file contains the Exynos specific definitions for the Samsung
10 * pinctrl/gpiolib interface drivers.
11 *
12 * Author: Thomas Abraham <thomas.ab@samsung.com>
13 *
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
18 */
19
20#define EXYNOS_GPIO_START(__gpio) ((__gpio##_START) + (__gpio##_NR))
21
22#define EXYNOS4210_GPIO_A0_NR (8)
23#define EXYNOS4210_GPIO_A1_NR (6)
24#define EXYNOS4210_GPIO_B_NR (8)
25#define EXYNOS4210_GPIO_C0_NR (5)
26#define EXYNOS4210_GPIO_C1_NR (5)
27#define EXYNOS4210_GPIO_D0_NR (4)
28#define EXYNOS4210_GPIO_D1_NR (4)
29#define EXYNOS4210_GPIO_E0_NR (5)
30#define EXYNOS4210_GPIO_E1_NR (8)
31#define EXYNOS4210_GPIO_E2_NR (6)
32#define EXYNOS4210_GPIO_E3_NR (8)
33#define EXYNOS4210_GPIO_E4_NR (8)
34#define EXYNOS4210_GPIO_F0_NR (8)
35#define EXYNOS4210_GPIO_F1_NR (8)
36#define EXYNOS4210_GPIO_F2_NR (8)
37#define EXYNOS4210_GPIO_F3_NR (6)
38#define EXYNOS4210_GPIO_J0_NR (8)
39#define EXYNOS4210_GPIO_J1_NR (5)
40#define EXYNOS4210_GPIO_K0_NR (7)
41#define EXYNOS4210_GPIO_K1_NR (7)
42#define EXYNOS4210_GPIO_K2_NR (7)
43#define EXYNOS4210_GPIO_K3_NR (7)
44#define EXYNOS4210_GPIO_L0_NR (8)
45#define EXYNOS4210_GPIO_L1_NR (3)
46#define EXYNOS4210_GPIO_L2_NR (8)
47#define EXYNOS4210_GPIO_Y0_NR (6)
48#define EXYNOS4210_GPIO_Y1_NR (4)
49#define EXYNOS4210_GPIO_Y2_NR (6)
50#define EXYNOS4210_GPIO_Y3_NR (8)
51#define EXYNOS4210_GPIO_Y4_NR (8)
52#define EXYNOS4210_GPIO_Y5_NR (8)
53#define EXYNOS4210_GPIO_Y6_NR (8)
54#define EXYNOS4210_GPIO_X0_NR (8)
55#define EXYNOS4210_GPIO_X1_NR (8)
56#define EXYNOS4210_GPIO_X2_NR (8)
57#define EXYNOS4210_GPIO_X3_NR (8)
58#define EXYNOS4210_GPIO_Z_NR (7)
59
60enum exynos4210_gpio_xa_start {
61 EXYNOS4210_GPIO_A0_START = 0,
62 EXYNOS4210_GPIO_A1_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_A0),
63 EXYNOS4210_GPIO_B_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_A1),
64 EXYNOS4210_GPIO_C0_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_B),
65 EXYNOS4210_GPIO_C1_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_C0),
66 EXYNOS4210_GPIO_D0_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_C1),
67 EXYNOS4210_GPIO_D1_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_D0),
68 EXYNOS4210_GPIO_E0_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_D1),
69 EXYNOS4210_GPIO_E1_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_E0),
70 EXYNOS4210_GPIO_E2_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_E1),
71 EXYNOS4210_GPIO_E3_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_E2),
72 EXYNOS4210_GPIO_E4_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_E3),
73 EXYNOS4210_GPIO_F0_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_E4),
74 EXYNOS4210_GPIO_F1_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_F0),
75 EXYNOS4210_GPIO_F2_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_F1),
76 EXYNOS4210_GPIO_F3_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_F2),
77};
78
79enum exynos4210_gpio_xb_start {
80 EXYNOS4210_GPIO_J0_START = 0,
81 EXYNOS4210_GPIO_J1_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_J0),
82 EXYNOS4210_GPIO_K0_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_J1),
83 EXYNOS4210_GPIO_K1_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_K0),
84 EXYNOS4210_GPIO_K2_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_K1),
85 EXYNOS4210_GPIO_K3_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_K2),
86 EXYNOS4210_GPIO_L0_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_K3),
87 EXYNOS4210_GPIO_L1_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_L0),
88 EXYNOS4210_GPIO_L2_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_L1),
89 EXYNOS4210_GPIO_Y0_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_L2),
90 EXYNOS4210_GPIO_Y1_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_Y0),
91 EXYNOS4210_GPIO_Y2_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_Y1),
92 EXYNOS4210_GPIO_Y3_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_Y2),
93 EXYNOS4210_GPIO_Y4_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_Y3),
94 EXYNOS4210_GPIO_Y5_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_Y4),
95 EXYNOS4210_GPIO_Y6_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_Y5),
96 EXYNOS4210_GPIO_X0_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_Y6),
97 EXYNOS4210_GPIO_X1_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_X0),
98 EXYNOS4210_GPIO_X2_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_X1),
99 EXYNOS4210_GPIO_X3_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_X2),
100};
101
102enum exynos4210_gpio_xc_start {
103 EXYNOS4210_GPIO_Z_START = 0,
104};
105
106#define EXYNOS4210_GPIO_A0_IRQ EXYNOS4210_GPIO_A0_START
107#define EXYNOS4210_GPIO_A1_IRQ EXYNOS4210_GPIO_A1_START
108#define EXYNOS4210_GPIO_B_IRQ EXYNOS4210_GPIO_B_START
109#define EXYNOS4210_GPIO_C0_IRQ EXYNOS4210_GPIO_C0_START
110#define EXYNOS4210_GPIO_C1_IRQ EXYNOS4210_GPIO_C1_START
111#define EXYNOS4210_GPIO_D0_IRQ EXYNOS4210_GPIO_D0_START
112#define EXYNOS4210_GPIO_D1_IRQ EXYNOS4210_GPIO_D1_START
113#define EXYNOS4210_GPIO_E0_IRQ EXYNOS4210_GPIO_E0_START
114#define EXYNOS4210_GPIO_E1_IRQ EXYNOS4210_GPIO_E1_START
115#define EXYNOS4210_GPIO_E2_IRQ EXYNOS4210_GPIO_E2_START
116#define EXYNOS4210_GPIO_E3_IRQ EXYNOS4210_GPIO_E3_START
117#define EXYNOS4210_GPIO_E4_IRQ EXYNOS4210_GPIO_E4_START
118#define EXYNOS4210_GPIO_F0_IRQ EXYNOS4210_GPIO_F0_START
119#define EXYNOS4210_GPIO_F1_IRQ EXYNOS4210_GPIO_F1_START
120#define EXYNOS4210_GPIO_F2_IRQ EXYNOS4210_GPIO_F2_START
121#define EXYNOS4210_GPIO_F3_IRQ EXYNOS4210_GPIO_F3_START
122#define EXYNOS4210_GPIO_J0_IRQ EXYNOS4210_GPIO_J0_START
123#define EXYNOS4210_GPIO_J1_IRQ EXYNOS4210_GPIO_J1_START
124#define EXYNOS4210_GPIO_K0_IRQ EXYNOS4210_GPIO_K0_START
125#define EXYNOS4210_GPIO_K1_IRQ EXYNOS4210_GPIO_K1_START
126#define EXYNOS4210_GPIO_K2_IRQ EXYNOS4210_GPIO_K2_START
127#define EXYNOS4210_GPIO_K3_IRQ EXYNOS4210_GPIO_K3_START
128#define EXYNOS4210_GPIO_L0_IRQ EXYNOS4210_GPIO_L0_START
129#define EXYNOS4210_GPIO_L1_IRQ EXYNOS4210_GPIO_L1_START
130#define EXYNOS4210_GPIO_L2_IRQ EXYNOS4210_GPIO_L2_START
131#define EXYNOS4210_GPIO_Z_IRQ EXYNOS4210_GPIO_Z_START
132
133#define EXYNOS4210_GPIOA_NR_PINS EXYNOS_GPIO_START(EXYNOS4210_GPIO_F3)
134#define EXYNOS4210_GPIOA_NR_GINT EXYNOS_GPIO_START(EXYNOS4210_GPIO_F3)
135#define EXYNOS4210_GPIOB_NR_PINS EXYNOS_GPIO_START(EXYNOS4210_GPIO_X3)
136#define EXYNOS4210_GPIOB_NR_GINT EXYNOS_GPIO_START(EXYNOS4210_GPIO_L2)
137#define EXYNOS4210_GPIOC_NR_PINS EXYNOS_GPIO_START(EXYNOS4210_GPIO_Z)
138
139/* External GPIO and wakeup interrupt related definitions */
140#define EXYNOS_GPIO_ECON_OFFSET 0x700
141#define EXYNOS_GPIO_EMASK_OFFSET 0x900
142#define EXYNOS_GPIO_EPEND_OFFSET 0xA00
143#define EXYNOS_WKUP_ECON_OFFSET 0xE00
144#define EXYNOS_WKUP_EMASK_OFFSET 0xF00
145#define EXYNOS_WKUP_EPEND_OFFSET 0xF40
146#define EXYNOS_SVC_OFFSET 0xB08
147
148/* helpers to access interrupt service register */
149#define EXYNOS_SVC_GROUP_SHIFT 3
150#define EXYNOS_SVC_GROUP_MASK 0x1f
151#define EXYNOS_SVC_NUM_MASK 7
152#define EXYNOS_SVC_GROUP(x) ((x >> EXYNOS_SVC_GROUP_SHIFT) & \
153 EXYNOS_SVC_GROUP_MASK)
154
155/* Exynos specific external interrupt trigger types */
156#define EXYNOS_EINT_LEVEL_LOW 0
157#define EXYNOS_EINT_LEVEL_HIGH 1
158#define EXYNOS_EINT_EDGE_FALLING 2
159#define EXYNOS_EINT_EDGE_RISING 3
160#define EXYNOS_EINT_EDGE_BOTH 4
161#define EXYNOS_EINT_CON_MASK 0xF
162#define EXYNOS_EINT_CON_LEN 4
163
164#define EXYNOS_EINT_MAX_PER_BANK 8
165#define EXYNOS_EINT_NR_WKUP_EINT
166
167#define EXYNOS_PIN_BANK_EINTN(reg, __gpio, id) \
168 { \
169 .pctl_offset = reg, \
170 .pin_base = (__gpio##_START), \
171 .nr_pins = (__gpio##_NR), \
172 .func_width = 4, \
173 .pud_width = 2, \
174 .drv_width = 2, \
175 .conpdn_width = 2, \
176 .pudpdn_width = 2, \
177 .eint_type = EINT_TYPE_NONE, \
178 .name = id \
179 }
180
181#define EXYNOS_PIN_BANK_EINTG(reg, __gpio, id) \
182 { \
183 .pctl_offset = reg, \
184 .pin_base = (__gpio##_START), \
185 .nr_pins = (__gpio##_NR), \
186 .func_width = 4, \
187 .pud_width = 2, \
188 .drv_width = 2, \
189 .conpdn_width = 2, \
190 .pudpdn_width = 2, \
191 .eint_type = EINT_TYPE_GPIO, \
192 .irq_base = (__gpio##_IRQ), \
193 .name = id \
194 }
195
196/**
197 * struct exynos_geint_data: gpio eint specific data for irq_chip callbacks.
198 * @bank: pin bank from which this gpio interrupt originates.
199 * @pin: pin number within the bank.
200 * @eint_offset: offset to be added to the con/pend/mask register bank base.
201 */
202struct exynos_geint_data {
203 struct samsung_pin_bank *bank;
204 u32 pin;
205 u32 eint_offset;
206};
207
208/**
209 * struct exynos_weint_data: irq specific data for all the wakeup interrupts
210 * generated by the external wakeup interrupt controller.
211 * @domain: irq domain representing the external wakeup interrupts
212 * @irq: interrupt number within the domain.
213 */
214struct exynos_weint_data {
215 struct irq_domain *domain;
216 u32 irq;
217};
diff --git a/drivers/pinctrl/pinctrl-samsung.c b/drivers/pinctrl/pinctrl-samsung.c
new file mode 100644
index 000000000000..8a24223d5334
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-samsung.c
@@ -0,0 +1,888 @@
1/*
2 * pin-controller/pin-mux/pin-config/gpio-driver for Samsung's SoC's.
3 *
4 * Copyright (c) 2012 Samsung Electronics Co., Ltd.
5 * http://www.samsung.com
6 * Copyright (c) 2012 Linaro Ltd
7 * http://www.linaro.org
8 *
9 * Author: Thomas Abraham <thomas.ab@samsung.com>
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This driver implements the Samsung pinctrl driver. It supports setting up of
17 * pinmux and pinconf configurations. The gpiolib interface is also included.
18 * External interrupt (gpio and wakeup) support are not included in this driver
19 * but provides extensions to which platform specific implementation of the gpio
20 * and wakeup interrupts can be hooked to.
21 */
22
23#include <linux/module.h>
24#include <linux/platform_device.h>
25#include <linux/io.h>
26#include <linux/slab.h>
27#include <linux/err.h>
28#include <linux/gpio.h>
29
30#include "core.h"
31#include "pinctrl-samsung.h"
32
33#define GROUP_SUFFIX "-grp"
34#define GSUFFIX_LEN sizeof(GROUP_SUFFIX)
35#define FUNCTION_SUFFIX "-mux"
36#define FSUFFIX_LEN sizeof(FUNCTION_SUFFIX)
37
38/* list of all possible config options supported */
39struct pin_config {
40 char *prop_cfg;
41 unsigned int cfg_type;
42} pcfgs[] = {
43 { "samsung,pin-pud", PINCFG_TYPE_PUD },
44 { "samsung,pin-drv", PINCFG_TYPE_DRV },
45 { "samsung,pin-con-pdn", PINCFG_TYPE_CON_PDN },
46 { "samsung,pin-pud-pdn", PINCFG_TYPE_PUD_PDN },
47};
48
49/* check if the selector is a valid pin group selector */
50static int samsung_get_group_count(struct pinctrl_dev *pctldev)
51{
52 struct samsung_pinctrl_drv_data *drvdata;
53
54 drvdata = pinctrl_dev_get_drvdata(pctldev);
55 return drvdata->nr_groups;
56}
57
58/* return the name of the group selected by the group selector */
59static const char *samsung_get_group_name(struct pinctrl_dev *pctldev,
60 unsigned selector)
61{
62 struct samsung_pinctrl_drv_data *drvdata;
63
64 drvdata = pinctrl_dev_get_drvdata(pctldev);
65 return drvdata->pin_groups[selector].name;
66}
67
68/* return the pin numbers associated with the specified group */
69static int samsung_get_group_pins(struct pinctrl_dev *pctldev,
70 unsigned selector, const unsigned **pins, unsigned *num_pins)
71{
72 struct samsung_pinctrl_drv_data *drvdata;
73
74 drvdata = pinctrl_dev_get_drvdata(pctldev);
75 *pins = drvdata->pin_groups[selector].pins;
76 *num_pins = drvdata->pin_groups[selector].num_pins;
77 return 0;
78}
79
80/* create pinctrl_map entries by parsing device tree nodes */
81static int samsung_dt_node_to_map(struct pinctrl_dev *pctldev,
82 struct device_node *np, struct pinctrl_map **maps,
83 unsigned *nmaps)
84{
85 struct device *dev = pctldev->dev;
86 struct pinctrl_map *map;
87 unsigned long *cfg = NULL;
88 char *gname, *fname;
89 int cfg_cnt = 0, map_cnt = 0, idx = 0;
90
91 /* count the number of config options specfied in the node */
92 for (idx = 0; idx < ARRAY_SIZE(pcfgs); idx++) {
93 if (of_find_property(np, pcfgs[idx].prop_cfg, NULL))
94 cfg_cnt++;
95 }
96
97 /*
98 * Find out the number of map entries to create. All the config options
99 * can be accomadated into a single config map entry.
100 */
101 if (cfg_cnt)
102 map_cnt = 1;
103 if (of_find_property(np, "samsung,pin-function", NULL))
104 map_cnt++;
105 if (!map_cnt) {
106 dev_err(dev, "node %s does not have either config or function "
107 "configurations\n", np->name);
108 return -EINVAL;
109 }
110
111 /* Allocate memory for pin-map entries */
112 map = kzalloc(sizeof(*map) * map_cnt, GFP_KERNEL);
113 if (!map) {
114 dev_err(dev, "could not alloc memory for pin-maps\n");
115 return -ENOMEM;
116 }
117 *nmaps = 0;
118
119 /*
120 * Allocate memory for pin group name. The pin group name is derived
121 * from the node name from which these map entries are be created.
122 */
123 gname = kzalloc(strlen(np->name) + GSUFFIX_LEN, GFP_KERNEL);
124 if (!gname) {
125 dev_err(dev, "failed to alloc memory for group name\n");
126 goto free_map;
127 }
128 sprintf(gname, "%s%s", np->name, GROUP_SUFFIX);
129
130 /*
131 * don't have config options? then skip over to creating function
132 * map entries.
133 */
134 if (!cfg_cnt)
135 goto skip_cfgs;
136
137 /* Allocate memory for config entries */
138 cfg = kzalloc(sizeof(*cfg) * cfg_cnt, GFP_KERNEL);
139 if (!cfg) {
140 dev_err(dev, "failed to alloc memory for configs\n");
141 goto free_gname;
142 }
143
144 /* Prepare a list of config settings */
145 for (idx = 0, cfg_cnt = 0; idx < ARRAY_SIZE(pcfgs); idx++) {
146 u32 value;
147 if (!of_property_read_u32(np, pcfgs[idx].prop_cfg, &value))
148 cfg[cfg_cnt++] =
149 PINCFG_PACK(pcfgs[idx].cfg_type, value);
150 }
151
152 /* create the config map entry */
153 map[*nmaps].data.configs.group_or_pin = gname;
154 map[*nmaps].data.configs.configs = cfg;
155 map[*nmaps].data.configs.num_configs = cfg_cnt;
156 map[*nmaps].type = PIN_MAP_TYPE_CONFIGS_GROUP;
157 *nmaps += 1;
158
159skip_cfgs:
160 /* create the function map entry */
161 if (of_find_property(np, "samsung,pin-function", NULL)) {
162 fname = kzalloc(strlen(np->name) + FSUFFIX_LEN, GFP_KERNEL);
163 if (!fname) {
164 dev_err(dev, "failed to alloc memory for func name\n");
165 goto free_cfg;
166 }
167 sprintf(fname, "%s%s", np->name, FUNCTION_SUFFIX);
168
169 map[*nmaps].data.mux.group = gname;
170 map[*nmaps].data.mux.function = fname;
171 map[*nmaps].type = PIN_MAP_TYPE_MUX_GROUP;
172 *nmaps += 1;
173 }
174
175 *maps = map;
176 return 0;
177
178free_cfg:
179 kfree(cfg);
180free_gname:
181 kfree(gname);
182free_map:
183 kfree(map);
184 return -ENOMEM;
185}
186
187/* free the memory allocated to hold the pin-map table */
188static void samsung_dt_free_map(struct pinctrl_dev *pctldev,
189 struct pinctrl_map *map, unsigned num_maps)
190{
191 int idx;
192
193 for (idx = 0; idx < num_maps; idx++) {
194 if (map[idx].type == PIN_MAP_TYPE_MUX_GROUP) {
195 kfree(map[idx].data.mux.function);
196 if (!idx)
197 kfree(map[idx].data.mux.group);
198 } else if (map->type == PIN_MAP_TYPE_CONFIGS_GROUP) {
199 kfree(map[idx].data.configs.configs);
200 if (!idx)
201 kfree(map[idx].data.configs.group_or_pin);
202 }
203 };
204
205 kfree(map);
206}
207
208/* list of pinctrl callbacks for the pinctrl core */
209static struct pinctrl_ops samsung_pctrl_ops = {
210 .get_groups_count = samsung_get_group_count,
211 .get_group_name = samsung_get_group_name,
212 .get_group_pins = samsung_get_group_pins,
213 .dt_node_to_map = samsung_dt_node_to_map,
214 .dt_free_map = samsung_dt_free_map,
215};
216
217/* check if the selector is a valid pin function selector */
218static int samsung_get_functions_count(struct pinctrl_dev *pctldev)
219{
220 struct samsung_pinctrl_drv_data *drvdata;
221
222 drvdata = pinctrl_dev_get_drvdata(pctldev);
223 return drvdata->nr_functions;
224}
225
226/* return the name of the pin function specified */
227static const char *samsung_pinmux_get_fname(struct pinctrl_dev *pctldev,
228 unsigned selector)
229{
230 struct samsung_pinctrl_drv_data *drvdata;
231
232 drvdata = pinctrl_dev_get_drvdata(pctldev);
233 return drvdata->pmx_functions[selector].name;
234}
235
236/* return the groups associated for the specified function selector */
237static int samsung_pinmux_get_groups(struct pinctrl_dev *pctldev,
238 unsigned selector, const char * const **groups,
239 unsigned * const num_groups)
240{
241 struct samsung_pinctrl_drv_data *drvdata;
242
243 drvdata = pinctrl_dev_get_drvdata(pctldev);
244 *groups = drvdata->pmx_functions[selector].groups;
245 *num_groups = drvdata->pmx_functions[selector].num_groups;
246 return 0;
247}
248
249/*
250 * given a pin number that is local to a pin controller, find out the pin bank
251 * and the register base of the pin bank.
252 */
253static void pin_to_reg_bank(struct gpio_chip *gc, unsigned pin,
254 void __iomem **reg, u32 *offset,
255 struct samsung_pin_bank **bank)
256{
257 struct samsung_pinctrl_drv_data *drvdata;
258 struct samsung_pin_bank *b;
259
260 drvdata = dev_get_drvdata(gc->dev);
261 b = drvdata->ctrl->pin_banks;
262
263 while ((pin >= b->pin_base) &&
264 ((b->pin_base + b->nr_pins - 1) < pin))
265 b++;
266
267 *reg = drvdata->virt_base + b->pctl_offset;
268 *offset = pin - b->pin_base;
269 if (bank)
270 *bank = b;
271
272 /* some banks have two config registers in a single bank */
273 if (*offset * b->func_width > BITS_PER_LONG)
274 *reg += 4;
275}
276
277/* enable or disable a pinmux function */
278static void samsung_pinmux_setup(struct pinctrl_dev *pctldev, unsigned selector,
279 unsigned group, bool enable)
280{
281 struct samsung_pinctrl_drv_data *drvdata;
282 const unsigned int *pins;
283 struct samsung_pin_bank *bank;
284 void __iomem *reg;
285 u32 mask, shift, data, pin_offset, cnt;
286
287 drvdata = pinctrl_dev_get_drvdata(pctldev);
288 pins = drvdata->pin_groups[group].pins;
289
290 /*
291 * for each pin in the pin group selected, program the correspoding pin
292 * pin function number in the config register.
293 */
294 for (cnt = 0; cnt < drvdata->pin_groups[group].num_pins; cnt++) {
295 pin_to_reg_bank(drvdata->gc, pins[cnt] - drvdata->ctrl->base,
296 &reg, &pin_offset, &bank);
297 mask = (1 << bank->func_width) - 1;
298 shift = pin_offset * bank->func_width;
299
300 data = readl(reg);
301 data &= ~(mask << shift);
302 if (enable)
303 data |= drvdata->pin_groups[group].func << shift;
304 writel(data, reg);
305 }
306}
307
308/* enable a specified pinmux by writing to registers */
309static int samsung_pinmux_enable(struct pinctrl_dev *pctldev, unsigned selector,
310 unsigned group)
311{
312 samsung_pinmux_setup(pctldev, selector, group, true);
313 return 0;
314}
315
316/* disable a specified pinmux by writing to registers */
317static void samsung_pinmux_disable(struct pinctrl_dev *pctldev,
318 unsigned selector, unsigned group)
319{
320 samsung_pinmux_setup(pctldev, selector, group, false);
321}
322
323/*
324 * The calls to gpio_direction_output() and gpio_direction_input()
325 * leads to this function call (via the pinctrl_gpio_direction_{input|output}()
326 * function called from the gpiolib interface).
327 */
328static int samsung_pinmux_gpio_set_direction(struct pinctrl_dev *pctldev,
329 struct pinctrl_gpio_range *range, unsigned offset, bool input)
330{
331 struct samsung_pin_bank *bank;
332 void __iomem *reg;
333 u32 data, pin_offset, mask, shift;
334
335 pin_to_reg_bank(range->gc, offset, &reg, &pin_offset, &bank);
336 mask = (1 << bank->func_width) - 1;
337 shift = pin_offset * bank->func_width;
338
339 data = readl(reg);
340 data &= ~(mask << shift);
341 if (!input)
342 data |= FUNC_OUTPUT << shift;
343 writel(data, reg);
344 return 0;
345}
346
347/* list of pinmux callbacks for the pinmux vertical in pinctrl core */
348static struct pinmux_ops samsung_pinmux_ops = {
349 .get_functions_count = samsung_get_functions_count,
350 .get_function_name = samsung_pinmux_get_fname,
351 .get_function_groups = samsung_pinmux_get_groups,
352 .enable = samsung_pinmux_enable,
353 .disable = samsung_pinmux_disable,
354 .gpio_set_direction = samsung_pinmux_gpio_set_direction,
355};
356
357/* set or get the pin config settings for a specified pin */
358static int samsung_pinconf_rw(struct pinctrl_dev *pctldev, unsigned int pin,
359 unsigned long *config, bool set)
360{
361 struct samsung_pinctrl_drv_data *drvdata;
362 struct samsung_pin_bank *bank;
363 void __iomem *reg_base;
364 enum pincfg_type cfg_type = PINCFG_UNPACK_TYPE(*config);
365 u32 data, width, pin_offset, mask, shift;
366 u32 cfg_value, cfg_reg;
367
368 drvdata = pinctrl_dev_get_drvdata(pctldev);
369 pin_to_reg_bank(drvdata->gc, pin - drvdata->ctrl->base, &reg_base,
370 &pin_offset, &bank);
371
372 switch (cfg_type) {
373 case PINCFG_TYPE_PUD:
374 width = bank->pud_width;
375 cfg_reg = PUD_REG;
376 break;
377 case PINCFG_TYPE_DRV:
378 width = bank->drv_width;
379 cfg_reg = DRV_REG;
380 break;
381 case PINCFG_TYPE_CON_PDN:
382 width = bank->conpdn_width;
383 cfg_reg = CONPDN_REG;
384 break;
385 case PINCFG_TYPE_PUD_PDN:
386 width = bank->pudpdn_width;
387 cfg_reg = PUDPDN_REG;
388 break;
389 default:
390 WARN_ON(1);
391 return -EINVAL;
392 }
393
394 mask = (1 << width) - 1;
395 shift = pin_offset * width;
396 data = readl(reg_base + cfg_reg);
397
398 if (set) {
399 cfg_value = PINCFG_UNPACK_VALUE(*config);
400 data &= ~(mask << shift);
401 data |= (cfg_value << shift);
402 writel(data, reg_base + cfg_reg);
403 } else {
404 data >>= shift;
405 data &= mask;
406 *config = PINCFG_PACK(cfg_type, data);
407 }
408 return 0;
409}
410
411/* set the pin config settings for a specified pin */
412static int samsung_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
413 unsigned long config)
414{
415 return samsung_pinconf_rw(pctldev, pin, &config, true);
416}
417
418/* get the pin config settings for a specified pin */
419static int samsung_pinconf_get(struct pinctrl_dev *pctldev, unsigned int pin,
420 unsigned long *config)
421{
422 return samsung_pinconf_rw(pctldev, pin, config, false);
423}
424
425/* set the pin config settings for a specified pin group */
426static int samsung_pinconf_group_set(struct pinctrl_dev *pctldev,
427 unsigned group, unsigned long config)
428{
429 struct samsung_pinctrl_drv_data *drvdata;
430 const unsigned int *pins;
431 unsigned int cnt;
432
433 drvdata = pinctrl_dev_get_drvdata(pctldev);
434 pins = drvdata->pin_groups[group].pins;
435
436 for (cnt = 0; cnt < drvdata->pin_groups[group].num_pins; cnt++)
437 samsung_pinconf_set(pctldev, pins[cnt], config);
438
439 return 0;
440}
441
442/* get the pin config settings for a specified pin group */
443static int samsung_pinconf_group_get(struct pinctrl_dev *pctldev,
444 unsigned int group, unsigned long *config)
445{
446 struct samsung_pinctrl_drv_data *drvdata;
447 const unsigned int *pins;
448
449 drvdata = pinctrl_dev_get_drvdata(pctldev);
450 pins = drvdata->pin_groups[group].pins;
451 samsung_pinconf_get(pctldev, pins[0], config);
452 return 0;
453}
454
455/* list of pinconfig callbacks for pinconfig vertical in the pinctrl code */
456static struct pinconf_ops samsung_pinconf_ops = {
457 .pin_config_get = samsung_pinconf_get,
458 .pin_config_set = samsung_pinconf_set,
459 .pin_config_group_get = samsung_pinconf_group_get,
460 .pin_config_group_set = samsung_pinconf_group_set,
461};
462
463/* gpiolib gpio_set callback function */
464static void samsung_gpio_set(struct gpio_chip *gc, unsigned offset, int value)
465{
466 void __iomem *reg;
467 u32 pin_offset, data;
468
469 pin_to_reg_bank(gc, offset, &reg, &pin_offset, NULL);
470 data = readl(reg + DAT_REG);
471 data &= ~(1 << pin_offset);
472 if (value)
473 data |= 1 << pin_offset;
474 writel(data, reg + DAT_REG);
475}
476
477/* gpiolib gpio_get callback function */
478static int samsung_gpio_get(struct gpio_chip *gc, unsigned offset)
479{
480 void __iomem *reg;
481 u32 pin_offset, data;
482
483 pin_to_reg_bank(gc, offset, &reg, &pin_offset, NULL);
484 data = readl(reg + DAT_REG);
485 data >>= pin_offset;
486 data &= 1;
487 return data;
488}
489
490/*
491 * gpiolib gpio_direction_input callback function. The setting of the pin
492 * mux function as 'gpio input' will be handled by the pinctrl susbsystem
493 * interface.
494 */
495static int samsung_gpio_direction_input(struct gpio_chip *gc, unsigned offset)
496{
497 return pinctrl_gpio_direction_input(gc->base + offset);
498}
499
500/*
501 * gpiolib gpio_direction_output callback function. The setting of the pin
502 * mux function as 'gpio output' will be handled by the pinctrl susbsystem
503 * interface.
504 */
505static int samsung_gpio_direction_output(struct gpio_chip *gc, unsigned offset,
506 int value)
507{
508 samsung_gpio_set(gc, offset, value);
509 return pinctrl_gpio_direction_output(gc->base + offset);
510}
511
512/*
513 * Parse the pin names listed in the 'samsung,pins' property and convert it
514 * into a list of gpio numbers are create a pin group from it.
515 */
516static int __init samsung_pinctrl_parse_dt_pins(struct platform_device *pdev,
517 struct device_node *cfg_np, struct pinctrl_desc *pctl,
518 unsigned int **pin_list, unsigned int *npins)
519{
520 struct device *dev = &pdev->dev;
521 struct property *prop;
522 struct pinctrl_pin_desc const *pdesc = pctl->pins;
523 unsigned int idx = 0, cnt;
524 const char *pin_name;
525
526 *npins = of_property_count_strings(cfg_np, "samsung,pins");
527 if (*npins < 0) {
528 dev_err(dev, "invalid pin list in %s node", cfg_np->name);
529 return -EINVAL;
530 }
531
532 *pin_list = devm_kzalloc(dev, *npins * sizeof(**pin_list), GFP_KERNEL);
533 if (!*pin_list) {
534 dev_err(dev, "failed to allocate memory for pin list\n");
535 return -ENOMEM;
536 }
537
538 of_property_for_each_string(cfg_np, "samsung,pins", prop, pin_name) {
539 for (cnt = 0; cnt < pctl->npins; cnt++) {
540 if (pdesc[cnt].name) {
541 if (!strcmp(pin_name, pdesc[cnt].name)) {
542 (*pin_list)[idx++] = pdesc[cnt].number;
543 break;
544 }
545 }
546 }
547 if (cnt == pctl->npins) {
548 dev_err(dev, "pin %s not valid in %s node\n",
549 pin_name, cfg_np->name);
550 devm_kfree(dev, *pin_list);
551 return -EINVAL;
552 }
553 }
554
555 return 0;
556}
557
558/*
559 * Parse the information about all the available pin groups and pin functions
560 * from device node of the pin-controller. A pin group is formed with all
561 * the pins listed in the "samsung,pins" property.
562 */
563static int __init samsung_pinctrl_parse_dt(struct platform_device *pdev,
564 struct samsung_pinctrl_drv_data *drvdata)
565{
566 struct device *dev = &pdev->dev;
567 struct device_node *dev_np = dev->of_node;
568 struct device_node *cfg_np;
569 struct samsung_pin_group *groups, *grp;
570 struct samsung_pmx_func *functions, *func;
571 unsigned *pin_list;
572 unsigned int npins, grp_cnt, func_idx = 0;
573 char *gname, *fname;
574 int ret;
575
576 grp_cnt = of_get_child_count(dev_np);
577 if (!grp_cnt)
578 return -EINVAL;
579
580 groups = devm_kzalloc(dev, grp_cnt * sizeof(*groups), GFP_KERNEL);
581 if (!groups) {
582 dev_err(dev, "failed allocate memory for ping group list\n");
583 return -EINVAL;
584 }
585 grp = groups;
586
587 functions = devm_kzalloc(dev, grp_cnt * sizeof(*functions), GFP_KERNEL);
588 if (!functions) {
589 dev_err(dev, "failed to allocate memory for function list\n");
590 return -EINVAL;
591 }
592 func = functions;
593
594 /*
595 * Iterate over all the child nodes of the pin controller node
596 * and create pin groups and pin function lists.
597 */
598 for_each_child_of_node(dev_np, cfg_np) {
599 u32 function;
600 if (of_find_property(cfg_np, "interrupt-controller", NULL))
601 continue;
602
603 ret = samsung_pinctrl_parse_dt_pins(pdev, cfg_np,
604 &drvdata->pctl, &pin_list, &npins);
605 if (ret)
606 return ret;
607
608 /* derive pin group name from the node name */
609 gname = devm_kzalloc(dev, strlen(cfg_np->name) + GSUFFIX_LEN,
610 GFP_KERNEL);
611 if (!gname) {
612 dev_err(dev, "failed to alloc memory for group name\n");
613 return -ENOMEM;
614 }
615 sprintf(gname, "%s%s", cfg_np->name, GROUP_SUFFIX);
616
617 grp->name = gname;
618 grp->pins = pin_list;
619 grp->num_pins = npins;
620 of_property_read_u32(cfg_np, "samsung,pin-function", &function);
621 grp->func = function;
622 grp++;
623
624 if (!of_find_property(cfg_np, "samsung,pin-function", NULL))
625 continue;
626
627 /* derive function name from the node name */
628 fname = devm_kzalloc(dev, strlen(cfg_np->name) + FSUFFIX_LEN,
629 GFP_KERNEL);
630 if (!fname) {
631 dev_err(dev, "failed to alloc memory for func name\n");
632 return -ENOMEM;
633 }
634 sprintf(fname, "%s%s", cfg_np->name, FUNCTION_SUFFIX);
635
636 func->name = fname;
637 func->groups = devm_kzalloc(dev, sizeof(char *), GFP_KERNEL);
638 if (!func->groups) {
639 dev_err(dev, "failed to alloc memory for group list "
640 "in pin function");
641 return -ENOMEM;
642 }
643 func->groups[0] = gname;
644 func->num_groups = 1;
645 func++;
646 func_idx++;
647 }
648
649 drvdata->pin_groups = groups;
650 drvdata->nr_groups = grp_cnt;
651 drvdata->pmx_functions = functions;
652 drvdata->nr_functions = func_idx;
653
654 return 0;
655}
656
657/* register the pinctrl interface with the pinctrl subsystem */
658static int __init samsung_pinctrl_register(struct platform_device *pdev,
659 struct samsung_pinctrl_drv_data *drvdata)
660{
661 struct pinctrl_desc *ctrldesc = &drvdata->pctl;
662 struct pinctrl_pin_desc *pindesc, *pdesc;
663 struct samsung_pin_bank *pin_bank;
664 char *pin_names;
665 int pin, bank, ret;
666
667 ctrldesc->name = "samsung-pinctrl";
668 ctrldesc->owner = THIS_MODULE;
669 ctrldesc->pctlops = &samsung_pctrl_ops;
670 ctrldesc->pmxops = &samsung_pinmux_ops;
671 ctrldesc->confops = &samsung_pinconf_ops;
672
673 pindesc = devm_kzalloc(&pdev->dev, sizeof(*pindesc) *
674 drvdata->ctrl->nr_pins, GFP_KERNEL);
675 if (!pindesc) {
676 dev_err(&pdev->dev, "mem alloc for pin descriptors failed\n");
677 return -ENOMEM;
678 }
679 ctrldesc->pins = pindesc;
680 ctrldesc->npins = drvdata->ctrl->nr_pins;
681 ctrldesc->npins = drvdata->ctrl->nr_pins;
682
683 /* dynamically populate the pin number and pin name for pindesc */
684 for (pin = 0, pdesc = pindesc; pin < ctrldesc->npins; pin++, pdesc++)
685 pdesc->number = pin + drvdata->ctrl->base;
686
687 /*
688 * allocate space for storing the dynamically generated names for all
689 * the pins which belong to this pin-controller.
690 */
691 pin_names = devm_kzalloc(&pdev->dev, sizeof(char) * PIN_NAME_LENGTH *
692 drvdata->ctrl->nr_pins, GFP_KERNEL);
693 if (!pin_names) {
694 dev_err(&pdev->dev, "mem alloc for pin names failed\n");
695 return -ENOMEM;
696 }
697
698 /* for each pin, the name of the pin is pin-bank name + pin number */
699 for (bank = 0; bank < drvdata->ctrl->nr_banks; bank++) {
700 pin_bank = &drvdata->ctrl->pin_banks[bank];
701 for (pin = 0; pin < pin_bank->nr_pins; pin++) {
702 sprintf(pin_names, "%s-%d", pin_bank->name, pin);
703 pdesc = pindesc + pin_bank->pin_base + pin;
704 pdesc->name = pin_names;
705 pin_names += PIN_NAME_LENGTH;
706 }
707 }
708
709 drvdata->pctl_dev = pinctrl_register(ctrldesc, &pdev->dev, drvdata);
710 if (!drvdata->pctl_dev) {
711 dev_err(&pdev->dev, "could not register pinctrl driver\n");
712 return -EINVAL;
713 }
714
715 drvdata->grange.name = "samsung-pctrl-gpio-range";
716 drvdata->grange.id = 0;
717 drvdata->grange.base = drvdata->ctrl->base;
718 drvdata->grange.npins = drvdata->ctrl->nr_pins;
719 drvdata->grange.gc = drvdata->gc;
720 pinctrl_add_gpio_range(drvdata->pctl_dev, &drvdata->grange);
721
722 ret = samsung_pinctrl_parse_dt(pdev, drvdata);
723 if (ret) {
724 pinctrl_unregister(drvdata->pctl_dev);
725 return ret;
726 }
727
728 return 0;
729}
730
731/* register the gpiolib interface with the gpiolib subsystem */
732static int __init samsung_gpiolib_register(struct platform_device *pdev,
733 struct samsung_pinctrl_drv_data *drvdata)
734{
735 struct gpio_chip *gc;
736 int ret;
737
738 gc = devm_kzalloc(&pdev->dev, sizeof(*gc), GFP_KERNEL);
739 if (!gc) {
740 dev_err(&pdev->dev, "mem alloc for gpio_chip failed\n");
741 return -ENOMEM;
742 }
743
744 drvdata->gc = gc;
745 gc->base = drvdata->ctrl->base;
746 gc->ngpio = drvdata->ctrl->nr_pins;
747 gc->dev = &pdev->dev;
748 gc->set = samsung_gpio_set;
749 gc->get = samsung_gpio_get;
750 gc->direction_input = samsung_gpio_direction_input;
751 gc->direction_output = samsung_gpio_direction_output;
752 gc->label = drvdata->ctrl->label;
753 gc->owner = THIS_MODULE;
754 ret = gpiochip_add(gc);
755 if (ret) {
756 dev_err(&pdev->dev, "failed to register gpio_chip %s, error "
757 "code: %d\n", gc->label, ret);
758 return ret;
759 }
760
761 return 0;
762}
763
764/* unregister the gpiolib interface with the gpiolib subsystem */
765static int __init samsung_gpiolib_unregister(struct platform_device *pdev,
766 struct samsung_pinctrl_drv_data *drvdata)
767{
768 int ret = gpiochip_remove(drvdata->gc);
769 if (ret) {
770 dev_err(&pdev->dev, "gpio chip remove failed\n");
771 return ret;
772 }
773 return 0;
774}
775
776static const struct of_device_id samsung_pinctrl_dt_match[];
777
778/* retrieve the soc specific data */
779static inline struct samsung_pin_ctrl *samsung_pinctrl_get_soc_data(
780 struct platform_device *pdev)
781{
782 int id;
783 const struct of_device_id *match;
784 const struct device_node *node = pdev->dev.of_node;
785
786 id = of_alias_get_id(pdev->dev.of_node, "pinctrl");
787 if (id < 0) {
788 dev_err(&pdev->dev, "failed to get alias id\n");
789 return NULL;
790 }
791 match = of_match_node(samsung_pinctrl_dt_match, node);
792 return (struct samsung_pin_ctrl *)match->data + id;
793}
794
795static int __devinit samsung_pinctrl_probe(struct platform_device *pdev)
796{
797 struct samsung_pinctrl_drv_data *drvdata;
798 struct device *dev = &pdev->dev;
799 struct samsung_pin_ctrl *ctrl;
800 struct resource *res;
801 int ret;
802
803 if (!dev->of_node) {
804 dev_err(dev, "device tree node not found\n");
805 return -ENODEV;
806 }
807
808 ctrl = samsung_pinctrl_get_soc_data(pdev);
809 if (!ctrl) {
810 dev_err(&pdev->dev, "driver data not available\n");
811 return -EINVAL;
812 }
813
814 drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
815 if (!drvdata) {
816 dev_err(dev, "failed to allocate memory for driver's "
817 "private data\n");
818 return -ENOMEM;
819 }
820 drvdata->ctrl = ctrl;
821 drvdata->dev = dev;
822
823 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
824 if (!res) {
825 dev_err(dev, "cannot find IO resource\n");
826 return -ENOENT;
827 }
828
829 drvdata->virt_base = devm_request_and_ioremap(&pdev->dev, res);
830 if (!drvdata->virt_base) {
831 dev_err(dev, "ioremap failed\n");
832 return -ENODEV;
833 }
834
835 res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
836 if (res)
837 drvdata->irq = res->start;
838
839 ret = samsung_gpiolib_register(pdev, drvdata);
840 if (ret)
841 return ret;
842
843 ret = samsung_pinctrl_register(pdev, drvdata);
844 if (ret) {
845 samsung_gpiolib_unregister(pdev, drvdata);
846 return ret;
847 }
848
849 if (ctrl->eint_gpio_init)
850 ctrl->eint_gpio_init(drvdata);
851 if (ctrl->eint_wkup_init)
852 ctrl->eint_wkup_init(drvdata);
853
854 platform_set_drvdata(pdev, drvdata);
855 return 0;
856}
857
858static const struct of_device_id samsung_pinctrl_dt_match[] = {
859 { .compatible = "samsung,pinctrl-exynos4210",
860 .data = (void *)exynos4210_pin_ctrl },
861 {},
862};
863MODULE_DEVICE_TABLE(of, samsung_pinctrl_dt_match);
864
865static struct platform_driver samsung_pinctrl_driver = {
866 .probe = samsung_pinctrl_probe,
867 .driver = {
868 .name = "samsung-pinctrl",
869 .owner = THIS_MODULE,
870 .of_match_table = of_match_ptr(samsung_pinctrl_dt_match),
871 },
872};
873
874static int __init samsung_pinctrl_drv_register(void)
875{
876 return platform_driver_register(&samsung_pinctrl_driver);
877}
878postcore_initcall(samsung_pinctrl_drv_register);
879
880static void __exit samsung_pinctrl_drv_unregister(void)
881{
882 platform_driver_unregister(&samsung_pinctrl_driver);
883}
884module_exit(samsung_pinctrl_drv_unregister);
885
886MODULE_AUTHOR("Thomas Abraham <thomas.ab@samsung.com>");
887MODULE_DESCRIPTION("Samsung pinctrl driver");
888MODULE_LICENSE("GPL v2");
diff --git a/drivers/pinctrl/pinctrl-samsung.h b/drivers/pinctrl/pinctrl-samsung.h
new file mode 100644
index 000000000000..b8956934cda6
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-samsung.h
@@ -0,0 +1,239 @@
1/*
2 * pin-controller/pin-mux/pin-config/gpio-driver for Samsung's SoC's.
3 *
4 * Copyright (c) 2012 Samsung Electronics Co., Ltd.
5 * http://www.samsung.com
6 * Copyright (c) 2012 Linaro Ltd
7 * http://www.linaro.org
8 *
9 * Author: Thomas Abraham <thomas.ab@samsung.com>
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 */
16
17#ifndef __PINCTRL_SAMSUNG_H
18#define __PINCTRL_SAMSUNG_H
19
20#include <linux/pinctrl/pinctrl.h>
21#include <linux/pinctrl/pinmux.h>
22#include <linux/pinctrl/pinconf.h>
23#include <linux/pinctrl/consumer.h>
24#include <linux/pinctrl/machine.h>
25
26/* register offsets within a pin bank */
27#define DAT_REG 0x4
28#define PUD_REG 0x8
29#define DRV_REG 0xC
30#define CONPDN_REG 0x10
31#define PUDPDN_REG 0x14
32
33/* pinmux function number for pin as gpio output line */
34#define FUNC_OUTPUT 0x1
35
36/**
37 * enum pincfg_type - possible pin configuration types supported.
38 * @PINCFG_TYPE_PUD: Pull up/down configuration.
39 * @PINCFG_TYPE_DRV: Drive strength configuration.
40 * @PINCFG_TYPE_CON_PDN: Pin function in power down mode.
41 * @PINCFG_TYPE_PUD_PDN: Pull up/down configuration in power down mode.
42 */
43enum pincfg_type {
44 PINCFG_TYPE_PUD,
45 PINCFG_TYPE_DRV,
46 PINCFG_TYPE_CON_PDN,
47 PINCFG_TYPE_PUD_PDN,
48};
49
50/*
51 * pin configuration (pull up/down and drive strength) type and its value are
52 * packed together into a 16-bits. The upper 8-bits represent the configuration
53 * type and the lower 8-bits hold the value of the configuration type.
54 */
55#define PINCFG_TYPE_MASK 0xFF
56#define PINCFG_VALUE_SHIFT 8
57#define PINCFG_VALUE_MASK (0xFF << PINCFG_VALUE_SHIFT)
58#define PINCFG_PACK(type, value) (((value) << PINCFG_VALUE_SHIFT) | type)
59#define PINCFG_UNPACK_TYPE(cfg) ((cfg) & PINCFG_TYPE_MASK)
60#define PINCFG_UNPACK_VALUE(cfg) (((cfg) & PINCFG_VALUE_MASK) >> \
61 PINCFG_VALUE_SHIFT)
62/**
63 * enum eint_type - possible external interrupt types.
64 * @EINT_TYPE_NONE: bank does not support external interrupts
65 * @EINT_TYPE_GPIO: bank supportes external gpio interrupts
66 * @EINT_TYPE_WKUP: bank supportes external wakeup interrupts
67 *
68 * Samsung GPIO controller groups all the available pins into banks. The pins
69 * in a pin bank can support external gpio interrupts or external wakeup
70 * interrupts or no interrupts at all. From a software perspective, the only
71 * difference between external gpio and external wakeup interrupts is that
72 * the wakeup interrupts can additionally wakeup the system if it is in
73 * suspended state.
74 */
75enum eint_type {
76 EINT_TYPE_NONE,
77 EINT_TYPE_GPIO,
78 EINT_TYPE_WKUP,
79};
80
81/* maximum length of a pin in pin descriptor (example: "gpa0-0") */
82#define PIN_NAME_LENGTH 10
83
84#define PIN_GROUP(n, p, f) \
85 { \
86 .name = n, \
87 .pins = p, \
88 .num_pins = ARRAY_SIZE(p), \
89 .func = f \
90 }
91
92#define PMX_FUNC(n, g) \
93 { \
94 .name = n, \
95 .groups = g, \
96 .num_groups = ARRAY_SIZE(g), \
97 }
98
99struct samsung_pinctrl_drv_data;
100
101/**
102 * struct samsung_pin_bank: represent a controller pin-bank.
103 * @reg_offset: starting offset of the pin-bank registers.
104 * @pin_base: starting pin number of the bank.
105 * @nr_pins: number of pins included in this bank.
106 * @func_width: width of the function selector bit field.
107 * @pud_width: width of the pin pull up/down selector bit field.
108 * @drv_width: width of the pin driver strength selector bit field.
109 * @conpdn_width: width of the sleep mode function selector bin field.
110 * @pudpdn_width: width of the sleep mode pull up/down selector bit field.
111 * @eint_type: type of the external interrupt supported by the bank.
112 * @irq_base: starting controller local irq number of the bank.
113 * @name: name to be prefixed for each pin in this pin bank.
114 */
115struct samsung_pin_bank {
116 u32 pctl_offset;
117 u32 pin_base;
118 u8 nr_pins;
119 u8 func_width;
120 u8 pud_width;
121 u8 drv_width;
122 u8 conpdn_width;
123 u8 pudpdn_width;
124 enum eint_type eint_type;
125 u32 irq_base;
126 char *name;
127};
128
129/**
130 * struct samsung_pin_ctrl: represent a pin controller.
131 * @pin_banks: list of pin banks included in this controller.
132 * @nr_banks: number of pin banks.
133 * @base: starting system wide pin number.
134 * @nr_pins: number of pins supported by the controller.
135 * @nr_gint: number of external gpio interrupts supported.
136 * @nr_wint: number of external wakeup interrupts supported.
137 * @geint_con: offset of the ext-gpio controller registers.
138 * @geint_mask: offset of the ext-gpio interrupt mask registers.
139 * @geint_pend: offset of the ext-gpio interrupt pending registers.
140 * @weint_con: offset of the ext-wakeup controller registers.
141 * @weint_mask: offset of the ext-wakeup interrupt mask registers.
142 * @weint_pend: offset of the ext-wakeup interrupt pending registers.
143 * @svc: offset of the interrupt service register.
144 * @eint_gpio_init: platform specific callback to setup the external gpio
145 * interrupts for the controller.
146 * @eint_wkup_init: platform specific callback to setup the external wakeup
147 * interrupts for the controller.
148 * @label: for debug information.
149 */
150struct samsung_pin_ctrl {
151 struct samsung_pin_bank *pin_banks;
152 u32 nr_banks;
153
154 u32 base;
155 u32 nr_pins;
156 u32 nr_gint;
157 u32 nr_wint;
158
159 u32 geint_con;
160 u32 geint_mask;
161 u32 geint_pend;
162
163 u32 weint_con;
164 u32 weint_mask;
165 u32 weint_pend;
166
167 u32 svc;
168
169 int (*eint_gpio_init)(struct samsung_pinctrl_drv_data *);
170 int (*eint_wkup_init)(struct samsung_pinctrl_drv_data *);
171 char *label;
172};
173
174/**
175 * struct samsung_pinctrl_drv_data: wrapper for holding driver data together.
176 * @virt_base: register base address of the controller.
177 * @dev: device instance representing the controller.
178 * @irq: interrpt number used by the controller to notify gpio interrupts.
179 * @ctrl: pin controller instance managed by the driver.
180 * @pctl: pin controller descriptor registered with the pinctrl subsystem.
181 * @pctl_dev: cookie representing pinctrl device instance.
182 * @pin_groups: list of pin groups available to the driver.
183 * @nr_groups: number of such pin groups.
184 * @pmx_functions: list of pin functions available to the driver.
185 * @nr_function: number of such pin functions.
186 * @gc: gpio_chip instance registered with gpiolib.
187 * @grange: linux gpio pin range supported by this controller.
188 */
189struct samsung_pinctrl_drv_data {
190 void __iomem *virt_base;
191 struct device *dev;
192 int irq;
193
194 struct samsung_pin_ctrl *ctrl;
195 struct pinctrl_desc pctl;
196 struct pinctrl_dev *pctl_dev;
197
198 const struct samsung_pin_group *pin_groups;
199 unsigned int nr_groups;
200 const struct samsung_pmx_func *pmx_functions;
201 unsigned int nr_functions;
202
203 struct irq_domain *gpio_irqd;
204 struct irq_domain *wkup_irqd;
205
206 struct gpio_chip *gc;
207 struct pinctrl_gpio_range grange;
208};
209
210/**
211 * struct samsung_pin_group: represent group of pins of a pinmux function.
212 * @name: name of the pin group, used to lookup the group.
213 * @pins: the pins included in this group.
214 * @num_pins: number of pins included in this group.
215 * @func: the function number to be programmed when selected.
216 */
217struct samsung_pin_group {
218 const char *name;
219 const unsigned int *pins;
220 u8 num_pins;
221 u8 func;
222};
223
224/**
225 * struct samsung_pmx_func: represent a pin function.
226 * @name: name of the pin function, used to lookup the function.
227 * @groups: one or more names of pin groups that provide this function.
228 * @num_groups: number of groups included in @groups.
229 */
230struct samsung_pmx_func {
231 const char *name;
232 const char **groups;
233 u8 num_groups;
234};
235
236/* list of all exported SoC specific data */
237extern struct samsung_pin_ctrl exynos4210_pin_ctrl[];
238
239#endif /* __PINCTRL_SAMSUNG_H */