diff options
| -rw-r--r-- | Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt | 119 | ||||
| -rw-r--r-- | arch/arm/boot/dts/exynos4210-pinctrl.dtsi | 278 | ||||
| -rw-r--r-- | arch/arm/boot/dts/exynos4210.dtsi | 241 | ||||
| -rw-r--r-- | drivers/pinctrl/pinctrl-exynos.c | 477 | ||||
| -rw-r--r-- | drivers/pinctrl/pinctrl-exynos.h | 170 | ||||
| -rw-r--r-- | drivers/pinctrl/pinctrl-samsung.c | 205 | ||||
| -rw-r--r-- | drivers/pinctrl/pinctrl-samsung.h | 30 |
7 files changed, 855 insertions, 665 deletions
diff --git a/Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt index 03dee50532f5..e97a27856b21 100644 --- a/Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt +++ b/Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt | |||
| @@ -8,13 +8,20 @@ on-chip controllers onto these pads. | |||
| 8 | Required Properties: | 8 | Required Properties: |
| 9 | - compatible: should be one of the following. | 9 | - compatible: should be one of the following. |
| 10 | - "samsung,pinctrl-exynos4210": for Exynos4210 compatible pin-controller. | 10 | - "samsung,pinctrl-exynos4210": for Exynos4210 compatible pin-controller. |
| 11 | - "samsung,pinctrl-exynos4x12": for Exynos4x12 compatible pin-controller. | ||
| 11 | - "samsung,pinctrl-exynos5250": for Exynos5250 compatible pin-controller. | 12 | - "samsung,pinctrl-exynos5250": for Exynos5250 compatible pin-controller. |
| 12 | 13 | ||
| 13 | - reg: Base address of the pin controller hardware module and length of | 14 | - reg: Base address of the pin controller hardware module and length of |
| 14 | the address space it occupies. | 15 | the address space it occupies. |
| 15 | 16 | ||
| 16 | - interrupts: interrupt specifier for the controller. The format and value of | 17 | - Pin banks as child nodes: Pin banks of the controller are represented by child |
| 17 | the interrupt specifier depends on the interrupt parent for the controller. | 18 | nodes of the controller node. Bank name is taken from name of the node. Each |
| 19 | bank node must contain following properties: | ||
| 20 | |||
| 21 | - gpio-controller: identifies the node as a gpio controller and pin bank. | ||
| 22 | - #gpio-cells: number of cells in GPIO specifier. Since the generic GPIO | ||
| 23 | binding is used, the amount of cells must be specified as 2. See generic | ||
| 24 | GPIO binding documentation for description of particular cells. | ||
| 18 | 25 | ||
| 19 | - Pin mux/config groups as child nodes: The pin mux (selecting pin function | 26 | - 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 | 27 | mode) and pin config (pull up/down, driver strength) settings are represented |
| @@ -72,16 +79,24 @@ used as system wakeup events. | |||
| 72 | A. External GPIO Interrupts: For supporting external gpio interrupts, the | 79 | A. External GPIO Interrupts: For supporting external gpio interrupts, the |
| 73 | following properties should be specified in the pin-controller device node. | 80 | following properties should be specified in the pin-controller device node. |
| 74 | 81 | ||
| 75 | - interrupt-controller: identifies the controller node as interrupt-parent. | 82 | - interrupt-parent: phandle of the interrupt parent to which the external |
| 76 | - #interrupt-cells: the value of this property should be 2. | 83 | GPIO interrupts are forwarded to. |
| 77 | - First Cell: represents the external gpio interrupt number local to the | 84 | - interrupts: interrupt specifier for the controller. The format and value of |
| 78 | external gpio interrupt space of the controller. | 85 | the interrupt specifier depends on the interrupt parent for the controller. |
| 79 | - Second Cell: flags to identify the type of the interrupt | 86 | |
| 80 | - 1 = rising edge triggered | 87 | In addition, following properties must be present in node of every bank |
| 81 | - 2 = falling edge triggered | 88 | of pins supporting GPIO interrupts: |
| 82 | - 3 = rising and falling edge triggered | 89 | |
| 83 | - 4 = high level triggered | 90 | - interrupt-controller: identifies the controller node as interrupt-parent. |
| 84 | - 8 = low level triggered | 91 | - #interrupt-cells: the value of this property should be 2. |
| 92 | - First Cell: represents the external gpio interrupt number local to the | ||
| 93 | external gpio interrupt space of the controller. | ||
| 94 | - Second Cell: flags to identify the type of the interrupt | ||
| 95 | - 1 = rising edge triggered | ||
| 96 | - 2 = falling edge triggered | ||
| 97 | - 3 = rising and falling edge triggered | ||
| 98 | - 4 = high level triggered | ||
| 99 | - 8 = low level triggered | ||
| 85 | 100 | ||
| 86 | B. External Wakeup Interrupts: For supporting external wakeup interrupts, a | 101 | B. External Wakeup Interrupts: For supporting external wakeup interrupts, a |
| 87 | child node representing the external wakeup interrupt controller should be | 102 | child node representing the external wakeup interrupt controller should be |
| @@ -94,6 +109,11 @@ B. External Wakeup Interrupts: For supporting external wakeup interrupts, a | |||
| 94 | found on Samsung Exynos4210 SoC. | 109 | found on Samsung Exynos4210 SoC. |
| 95 | - interrupt-parent: phandle of the interrupt parent to which the external | 110 | - interrupt-parent: phandle of the interrupt parent to which the external |
| 96 | wakeup interrupts are forwarded to. | 111 | wakeup interrupts are forwarded to. |
| 112 | - interrupts: interrupt used by multiplexed wakeup interrupts. | ||
| 113 | |||
| 114 | In addition, following properties must be present in node of every bank | ||
| 115 | of pins supporting wake-up interrupts: | ||
| 116 | |||
| 97 | - interrupt-controller: identifies the node as interrupt-parent. | 117 | - interrupt-controller: identifies the node as interrupt-parent. |
| 98 | - #interrupt-cells: the value of this property should be 2 | 118 | - #interrupt-cells: the value of this property should be 2 |
| 99 | - First Cell: represents the external wakeup interrupt number local to | 119 | - First Cell: represents the external wakeup interrupt number local to |
| @@ -105,11 +125,63 @@ B. External Wakeup Interrupts: For supporting external wakeup interrupts, a | |||
| 105 | - 4 = high level triggered | 125 | - 4 = high level triggered |
| 106 | - 8 = low level triggered | 126 | - 8 = low level triggered |
| 107 | 127 | ||
| 128 | Node of every bank of pins supporting direct wake-up interrupts (without | ||
| 129 | multiplexing) must contain following properties: | ||
| 130 | |||
| 131 | - interrupt-parent: phandle of the interrupt parent to which the external | ||
| 132 | wakeup interrupts are forwarded to. | ||
| 133 | - interrupts: interrupts of the interrupt parent which are used for external | ||
| 134 | wakeup interrupts from pins of the bank, must contain interrupts for all | ||
| 135 | pins of the bank. | ||
| 136 | |||
| 108 | Aliases: | 137 | Aliases: |
| 109 | 138 | ||
| 110 | All the pin controller nodes should be represented in the aliases node using | 139 | All the pin controller nodes should be represented in the aliases node using |
| 111 | the following format 'pinctrl{n}' where n is a unique number for the alias. | 140 | the following format 'pinctrl{n}' where n is a unique number for the alias. |
| 112 | 141 | ||
| 142 | Example: A pin-controller node with pin banks: | ||
| 143 | |||
| 144 | pinctrl_0: pinctrl@11400000 { | ||
| 145 | compatible = "samsung,pinctrl-exynos4210"; | ||
| 146 | reg = <0x11400000 0x1000>; | ||
| 147 | interrupts = <0 47 0>; | ||
| 148 | |||
| 149 | /* ... */ | ||
| 150 | |||
| 151 | /* Pin bank without external interrupts */ | ||
| 152 | gpy0: gpy0 { | ||
| 153 | gpio-controller; | ||
| 154 | #gpio-cells = <2>; | ||
| 155 | }; | ||
| 156 | |||
| 157 | /* ... */ | ||
| 158 | |||
| 159 | /* Pin bank with external GPIO or muxed wake-up interrupts */ | ||
| 160 | gpj0: gpj0 { | ||
| 161 | gpio-controller; | ||
| 162 | #gpio-cells = <2>; | ||
| 163 | |||
| 164 | interrupt-controller; | ||
| 165 | #interrupt-cells = <2>; | ||
| 166 | }; | ||
| 167 | |||
| 168 | /* ... */ | ||
| 169 | |||
| 170 | /* Pin bank with external direct wake-up interrupts */ | ||
| 171 | gpx0: gpx0 { | ||
| 172 | gpio-controller; | ||
| 173 | #gpio-cells = <2>; | ||
| 174 | |||
| 175 | interrupt-controller; | ||
| 176 | interrupt-parent = <&gic>; | ||
| 177 | interrupts = <0 16 0>, <0 17 0>, <0 18 0>, <0 19 0>, | ||
| 178 | <0 20 0>, <0 21 0>, <0 22 0>, <0 23 0>; | ||
| 179 | #interrupt-cells = <2>; | ||
| 180 | }; | ||
| 181 | |||
| 182 | /* ... */ | ||
| 183 | }; | ||
| 184 | |||
| 113 | Example 1: A pin-controller node with pin groups. | 185 | Example 1: A pin-controller node with pin groups. |
| 114 | 186 | ||
| 115 | pinctrl_0: pinctrl@11400000 { | 187 | pinctrl_0: pinctrl@11400000 { |
| @@ -117,6 +189,8 @@ Example 1: A pin-controller node with pin groups. | |||
| 117 | reg = <0x11400000 0x1000>; | 189 | reg = <0x11400000 0x1000>; |
| 118 | interrupts = <0 47 0>; | 190 | interrupts = <0 47 0>; |
| 119 | 191 | ||
| 192 | /* ... */ | ||
| 193 | |||
| 120 | uart0_data: uart0-data { | 194 | uart0_data: uart0-data { |
| 121 | samsung,pins = "gpa0-0", "gpa0-1"; | 195 | samsung,pins = "gpa0-0", "gpa0-1"; |
| 122 | samsung,pin-function = <2>; | 196 | samsung,pin-function = <2>; |
| @@ -158,20 +232,14 @@ Example 2: A pin-controller node with external wakeup interrupt controller node. | |||
| 158 | pinctrl_1: pinctrl@11000000 { | 232 | pinctrl_1: pinctrl@11000000 { |
| 159 | compatible = "samsung,pinctrl-exynos4210"; | 233 | compatible = "samsung,pinctrl-exynos4210"; |
| 160 | reg = <0x11000000 0x1000>; | 234 | reg = <0x11000000 0x1000>; |
| 161 | interrupts = <0 46 0>; | 235 | interrupts = <0 46 0> |
| 162 | interrupt-controller; | ||
| 163 | #interrupt-cells = <2>; | ||
| 164 | 236 | ||
| 165 | wakup_eint: wakeup-interrupt-controller { | 237 | /* ... */ |
| 238 | |||
| 239 | wakeup-interrupt-controller { | ||
| 166 | compatible = "samsung,exynos4210-wakeup-eint"; | 240 | compatible = "samsung,exynos4210-wakeup-eint"; |
| 167 | interrupt-parent = <&gic>; | 241 | interrupt-parent = <&gic>; |
| 168 | interrupt-controller; | 242 | interrupts = <0 32 0>; |
| 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 | }; | 243 | }; |
| 176 | }; | 244 | }; |
| 177 | 245 | ||
| @@ -190,7 +258,8 @@ Example 4: Set up the default pin state for uart controller. | |||
| 190 | 258 | ||
| 191 | static int s3c24xx_serial_probe(struct platform_device *pdev) { | 259 | static int s3c24xx_serial_probe(struct platform_device *pdev) { |
| 192 | struct pinctrl *pinctrl; | 260 | struct pinctrl *pinctrl; |
| 193 | ... | 261 | |
| 194 | ... | 262 | /* ... */ |
| 263 | |||
| 195 | pinctrl = devm_pinctrl_get_select_default(&pdev->dev); | 264 | pinctrl = devm_pinctrl_get_select_default(&pdev->dev); |
| 196 | } | 265 | } |
diff --git a/arch/arm/boot/dts/exynos4210-pinctrl.dtsi b/arch/arm/boot/dts/exynos4210-pinctrl.dtsi index b12cf272ad0d..6a4a1a04221c 100644 --- a/arch/arm/boot/dts/exynos4210-pinctrl.dtsi +++ b/arch/arm/boot/dts/exynos4210-pinctrl.dtsi | |||
| @@ -16,6 +16,134 @@ | |||
| 16 | 16 | ||
| 17 | / { | 17 | / { |
| 18 | pinctrl@11400000 { | 18 | pinctrl@11400000 { |
| 19 | gpa0: gpa0 { | ||
| 20 | gpio-controller; | ||
| 21 | #gpio-cells = <2>; | ||
| 22 | |||
| 23 | interrupt-controller; | ||
| 24 | #interrupt-cells = <2>; | ||
| 25 | }; | ||
| 26 | |||
| 27 | gpa1: gpa1 { | ||
| 28 | gpio-controller; | ||
| 29 | #gpio-cells = <2>; | ||
| 30 | |||
| 31 | interrupt-controller; | ||
| 32 | #interrupt-cells = <2>; | ||
| 33 | }; | ||
| 34 | |||
| 35 | gpb: gpb { | ||
| 36 | gpio-controller; | ||
| 37 | #gpio-cells = <2>; | ||
| 38 | |||
| 39 | interrupt-controller; | ||
| 40 | #interrupt-cells = <2>; | ||
| 41 | }; | ||
| 42 | |||
| 43 | gpc0: gpc0 { | ||
| 44 | gpio-controller; | ||
| 45 | #gpio-cells = <2>; | ||
| 46 | |||
| 47 | interrupt-controller; | ||
| 48 | #interrupt-cells = <2>; | ||
| 49 | }; | ||
| 50 | |||
| 51 | gpc1: gpc1 { | ||
| 52 | gpio-controller; | ||
| 53 | #gpio-cells = <2>; | ||
| 54 | |||
| 55 | interrupt-controller; | ||
| 56 | #interrupt-cells = <2>; | ||
| 57 | }; | ||
| 58 | |||
| 59 | gpd0: gpd0 { | ||
| 60 | gpio-controller; | ||
| 61 | #gpio-cells = <2>; | ||
| 62 | |||
| 63 | interrupt-controller; | ||
| 64 | #interrupt-cells = <2>; | ||
| 65 | }; | ||
| 66 | |||
| 67 | gpd1: gpd1 { | ||
| 68 | gpio-controller; | ||
| 69 | #gpio-cells = <2>; | ||
| 70 | |||
| 71 | interrupt-controller; | ||
| 72 | #interrupt-cells = <2>; | ||
| 73 | }; | ||
| 74 | |||
| 75 | gpe0: gpe0 { | ||
| 76 | gpio-controller; | ||
| 77 | #gpio-cells = <2>; | ||
| 78 | |||
| 79 | interrupt-controller; | ||
| 80 | #interrupt-cells = <2>; | ||
| 81 | }; | ||
| 82 | |||
| 83 | gpe1: gpe1 { | ||
| 84 | gpio-controller; | ||
| 85 | #gpio-cells = <2>; | ||
| 86 | |||
| 87 | interrupt-controller; | ||
| 88 | #interrupt-cells = <2>; | ||
| 89 | }; | ||
| 90 | |||
| 91 | gpe2: gpe2 { | ||
| 92 | gpio-controller; | ||
| 93 | #gpio-cells = <2>; | ||
| 94 | |||
| 95 | interrupt-controller; | ||
| 96 | #interrupt-cells = <2>; | ||
| 97 | }; | ||
| 98 | |||
| 99 | gpe3: gpe3 { | ||
| 100 | gpio-controller; | ||
| 101 | #gpio-cells = <2>; | ||
| 102 | |||
| 103 | interrupt-controller; | ||
| 104 | #interrupt-cells = <2>; | ||
| 105 | }; | ||
| 106 | |||
| 107 | gpe4: gpe4 { | ||
| 108 | gpio-controller; | ||
| 109 | #gpio-cells = <2>; | ||
| 110 | |||
| 111 | interrupt-controller; | ||
| 112 | #interrupt-cells = <2>; | ||
| 113 | }; | ||
| 114 | |||
| 115 | gpf0: gpf0 { | ||
| 116 | gpio-controller; | ||
| 117 | #gpio-cells = <2>; | ||
| 118 | |||
| 119 | interrupt-controller; | ||
| 120 | #interrupt-cells = <2>; | ||
| 121 | }; | ||
| 122 | |||
| 123 | gpf1: gpf1 { | ||
| 124 | gpio-controller; | ||
| 125 | #gpio-cells = <2>; | ||
| 126 | |||
| 127 | interrupt-controller; | ||
| 128 | #interrupt-cells = <2>; | ||
| 129 | }; | ||
| 130 | |||
| 131 | gpf2: gpf2 { | ||
| 132 | gpio-controller; | ||
| 133 | #gpio-cells = <2>; | ||
| 134 | |||
| 135 | interrupt-controller; | ||
| 136 | #interrupt-cells = <2>; | ||
| 137 | }; | ||
| 138 | |||
| 139 | gpf3: gpf3 { | ||
| 140 | gpio-controller; | ||
| 141 | #gpio-cells = <2>; | ||
| 142 | |||
| 143 | interrupt-controller; | ||
| 144 | #interrupt-cells = <2>; | ||
| 145 | }; | ||
| 146 | |||
| 19 | uart0_data: uart0-data { | 147 | uart0_data: uart0-data { |
| 20 | samsung,pins = "gpa0-0", "gpa0-1"; | 148 | samsung,pins = "gpa0-0", "gpa0-1"; |
| 21 | samsung,pin-function = <0x2>; | 149 | samsung,pin-function = <0x2>; |
| @@ -205,6 +333,151 @@ | |||
| 205 | }; | 333 | }; |
| 206 | 334 | ||
| 207 | pinctrl@11000000 { | 335 | pinctrl@11000000 { |
| 336 | gpj0: gpj0 { | ||
| 337 | gpio-controller; | ||
| 338 | #gpio-cells = <2>; | ||
| 339 | |||
| 340 | interrupt-controller; | ||
| 341 | #interrupt-cells = <2>; | ||
| 342 | }; | ||
| 343 | |||
| 344 | gpj1: gpj1 { | ||
| 345 | gpio-controller; | ||
| 346 | #gpio-cells = <2>; | ||
| 347 | |||
| 348 | interrupt-controller; | ||
| 349 | #interrupt-cells = <2>; | ||
| 350 | }; | ||
| 351 | |||
| 352 | gpk0: gpk0 { | ||
| 353 | gpio-controller; | ||
| 354 | #gpio-cells = <2>; | ||
| 355 | |||
| 356 | interrupt-controller; | ||
| 357 | #interrupt-cells = <2>; | ||
| 358 | }; | ||
| 359 | |||
| 360 | gpk1: gpk1 { | ||
| 361 | gpio-controller; | ||
| 362 | #gpio-cells = <2>; | ||
| 363 | |||
| 364 | interrupt-controller; | ||
| 365 | #interrupt-cells = <2>; | ||
| 366 | }; | ||
| 367 | |||
| 368 | gpk2: gpk2 { | ||
| 369 | gpio-controller; | ||
| 370 | #gpio-cells = <2>; | ||
| 371 | |||
| 372 | interrupt-controller; | ||
| 373 | #interrupt-cells = <2>; | ||
| 374 | }; | ||
| 375 | |||
| 376 | gpk3: gpk3 { | ||
| 377 | gpio-controller; | ||
| 378 | #gpio-cells = <2>; | ||
| 379 | |||
| 380 | interrupt-controller; | ||
| 381 | #interrupt-cells = <2>; | ||
| 382 | }; | ||
| 383 | |||
| 384 | gpl0: gpl0 { | ||
| 385 | gpio-controller; | ||
| 386 | #gpio-cells = <2>; | ||
| 387 | |||
| 388 | interrupt-controller; | ||
| 389 | #interrupt-cells = <2>; | ||
| 390 | }; | ||
| 391 | |||
| 392 | gpl1: gpl1 { | ||
| 393 | gpio-controller; | ||
| 394 | #gpio-cells = <2>; | ||
| 395 | |||
| 396 | interrupt-controller; | ||
| 397 | #interrupt-cells = <2>; | ||
| 398 | }; | ||
| 399 | |||
| 400 | gpl2: gpl2 { | ||
| 401 | gpio-controller; | ||
| 402 | #gpio-cells = <2>; | ||
| 403 | |||
| 404 | interrupt-controller; | ||
| 405 | #interrupt-cells = <2>; | ||
| 406 | }; | ||
| 407 | |||
| 408 | gpy0: gpy0 { | ||
| 409 | gpio-controller; | ||
| 410 | #gpio-cells = <2>; | ||
| 411 | }; | ||
| 412 | |||
| 413 | gpy1: gpy1 { | ||
| 414 | gpio-controller; | ||
| 415 | #gpio-cells = <2>; | ||
| 416 | }; | ||
| 417 | |||
| 418 | gpy2: gpy2 { | ||
| 419 | gpio-controller; | ||
| 420 | #gpio-cells = <2>; | ||
| 421 | }; | ||
| 422 | |||
| 423 | gpy3: gpy3 { | ||
| 424 | gpio-controller; | ||
| 425 | #gpio-cells = <2>; | ||
| 426 | }; | ||
| 427 | |||
| 428 | gpy4: gpy4 { | ||
| 429 | gpio-controller; | ||
| 430 | #gpio-cells = <2>; | ||
| 431 | }; | ||
| 432 | |||
| 433 | gpy5: gpy5 { | ||
| 434 | gpio-controller; | ||
| 435 | #gpio-cells = <2>; | ||
| 436 | }; | ||
| 437 | |||
| 438 | gpy6: gpy6 { | ||
| 439 | gpio-controller; | ||
| 440 | #gpio-cells = <2>; | ||
| 441 | }; | ||
| 442 | |||
| 443 | gpx0: gpx0 { | ||
| 444 | gpio-controller; | ||
| 445 | #gpio-cells = <2>; | ||
| 446 | |||
| 447 | interrupt-controller; | ||
| 448 | interrupt-parent = <&gic>; | ||
| 449 | interrupts = <0 16 0>, <0 17 0>, <0 18 0>, <0 19 0>, | ||
| 450 | <0 20 0>, <0 21 0>, <0 22 0>, <0 23 0>; | ||
| 451 | #interrupt-cells = <2>; | ||
| 452 | }; | ||
| 453 | |||
| 454 | gpx1: gpx1 { | ||
| 455 | gpio-controller; | ||
| 456 | #gpio-cells = <2>; | ||
| 457 | |||
| 458 | interrupt-controller; | ||
| 459 | interrupt-parent = <&gic>; | ||
| 460 | interrupts = <0 24 0>, <0 25 0>, <0 26 0>, <0 27 0>, | ||
| 461 | <0 28 0>, <0 29 0>, <0 30 0>, <0 31 0>; | ||
| 462 | #interrupt-cells = <2>; | ||
| 463 | }; | ||
| 464 | |||
| 465 | gpx2: gpx2 { | ||
| 466 | gpio-controller; | ||
| 467 | #gpio-cells = <2>; | ||
| 468 | |||
| 469 | interrupt-controller; | ||
| 470 | #interrupt-cells = <2>; | ||
| 471 | }; | ||
| 472 | |||
| 473 | gpx3: gpx3 { | ||
| 474 | gpio-controller; | ||
| 475 | #gpio-cells = <2>; | ||
| 476 | |||
| 477 | interrupt-controller; | ||
| 478 | #interrupt-cells = <2>; | ||
| 479 | }; | ||
| 480 | |||
| 208 | sd0_clk: sd0-clk { | 481 | sd0_clk: sd0-clk { |
| 209 | samsung,pins = "gpk0-0"; | 482 | samsung,pins = "gpk0-0"; |
| 210 | samsung,pin-function = <2>; | 483 | samsung,pin-function = <2>; |
| @@ -438,6 +711,11 @@ | |||
| 438 | }; | 711 | }; |
| 439 | 712 | ||
| 440 | pinctrl@03860000 { | 713 | pinctrl@03860000 { |
| 714 | gpz: gpz { | ||
| 715 | gpio-controller; | ||
| 716 | #gpio-cells = <2>; | ||
| 717 | }; | ||
| 718 | |||
| 441 | i2s0_bus: i2s0-bus { | 719 | i2s0_bus: i2s0-bus { |
| 442 | samsung,pins = "gpz-0", "gpz-1", "gpz-2", "gpz-3", | 720 | samsung,pins = "gpz-0", "gpz-1", "gpz-2", "gpz-3", |
| 443 | "gpz-4", "gpz-5", "gpz-6"; | 721 | "gpz-4", "gpz-5", "gpz-6"; |
diff --git a/arch/arm/boot/dts/exynos4210.dtsi b/arch/arm/boot/dts/exynos4210.dtsi index 214c557eda7f..d877dbe7ac0e 100644 --- a/arch/arm/boot/dts/exynos4210.dtsi +++ b/arch/arm/boot/dts/exynos4210.dtsi | |||
| @@ -46,27 +46,17 @@ | |||
| 46 | compatible = "samsung,pinctrl-exynos4210"; | 46 | compatible = "samsung,pinctrl-exynos4210"; |
| 47 | reg = <0x11400000 0x1000>; | 47 | reg = <0x11400000 0x1000>; |
| 48 | interrupts = <0 47 0>; | 48 | interrupts = <0 47 0>; |
| 49 | interrupt-controller; | ||
| 50 | #interrupt-cells = <2>; | ||
| 51 | }; | 49 | }; |
| 52 | 50 | ||
| 53 | pinctrl_1: pinctrl@11000000 { | 51 | pinctrl_1: pinctrl@11000000 { |
| 54 | compatible = "samsung,pinctrl-exynos4210"; | 52 | compatible = "samsung,pinctrl-exynos4210"; |
| 55 | reg = <0x11000000 0x1000>; | 53 | reg = <0x11000000 0x1000>; |
| 56 | interrupts = <0 46 0>; | 54 | interrupts = <0 46 0>; |
| 57 | interrupt-controller; | ||
| 58 | #interrupt-cells = <2>; | ||
| 59 | 55 | ||
| 60 | wakup_eint: wakeup-interrupt-controller { | 56 | wakup_eint: wakeup-interrupt-controller { |
| 61 | compatible = "samsung,exynos4210-wakeup-eint"; | 57 | compatible = "samsung,exynos4210-wakeup-eint"; |
| 62 | interrupt-parent = <&gic>; | 58 | interrupt-parent = <&gic>; |
| 63 | interrupt-controller; | 59 | interrupts = <0 32 0>; |
| 64 | #interrupt-cells = <2>; | ||
| 65 | interrupts = <0 16 0>, <0 17 0>, <0 18 0>, <0 19 0>, | ||
| 66 | <0 20 0>, <0 21 0>, <0 22 0>, <0 23 0>, | ||
| 67 | <0 24 0>, <0 25 0>, <0 26 0>, <0 27 0>, | ||
| 68 | <0 28 0>, <0 29 0>, <0 30 0>, <0 31 0>, | ||
| 69 | <0 32 0>; | ||
| 70 | }; | 60 | }; |
| 71 | }; | 61 | }; |
| 72 | 62 | ||
| @@ -74,233 +64,4 @@ | |||
| 74 | compatible = "samsung,pinctrl-exynos4210"; | 64 | compatible = "samsung,pinctrl-exynos4210"; |
| 75 | reg = <0x03860000 0x1000>; | 65 | reg = <0x03860000 0x1000>; |
| 76 | }; | 66 | }; |
| 77 | |||
| 78 | gpio-controllers { | ||
| 79 | #address-cells = <1>; | ||
| 80 | #size-cells = <1>; | ||
| 81 | gpio-controller; | ||
| 82 | ranges; | ||
| 83 | |||
| 84 | gpa0: gpio-controller@11400000 { | ||
| 85 | compatible = "samsung,exynos4-gpio"; | ||
| 86 | reg = <0x11400000 0x20>; | ||
| 87 | #gpio-cells = <4>; | ||
| 88 | }; | ||
| 89 | |||
| 90 | gpa1: gpio-controller@11400020 { | ||
| 91 | compatible = "samsung,exynos4-gpio"; | ||
| 92 | reg = <0x11400020 0x20>; | ||
| 93 | #gpio-cells = <4>; | ||
| 94 | }; | ||
| 95 | |||
| 96 | gpb: gpio-controller@11400040 { | ||
| 97 | compatible = "samsung,exynos4-gpio"; | ||
| 98 | reg = <0x11400040 0x20>; | ||
| 99 | #gpio-cells = <4>; | ||
| 100 | }; | ||
| 101 | |||
| 102 | gpc0: gpio-controller@11400060 { | ||
| 103 | compatible = "samsung,exynos4-gpio"; | ||
| 104 | reg = <0x11400060 0x20>; | ||
| 105 | #gpio-cells = <4>; | ||
| 106 | }; | ||
| 107 | |||
| 108 | gpc1: gpio-controller@11400080 { | ||
| 109 | compatible = "samsung,exynos4-gpio"; | ||
| 110 | reg = <0x11400080 0x20>; | ||
| 111 | #gpio-cells = <4>; | ||
| 112 | }; | ||
| 113 | |||
| 114 | gpd0: gpio-controller@114000A0 { | ||
| 115 | compatible = "samsung,exynos4-gpio"; | ||
| 116 | reg = <0x114000A0 0x20>; | ||
| 117 | #gpio-cells = <4>; | ||
| 118 | }; | ||
| 119 | |||
| 120 | gpd1: gpio-controller@114000C0 { | ||
| 121 | compatible = "samsung,exynos4-gpio"; | ||
| 122 | reg = <0x114000C0 0x20>; | ||
| 123 | #gpio-cells = <4>; | ||
| 124 | }; | ||
| 125 | |||
| 126 | gpe0: gpio-controller@114000E0 { | ||
| 127 | compatible = "samsung,exynos4-gpio"; | ||
| 128 | reg = <0x114000E0 0x20>; | ||
| 129 | #gpio-cells = <4>; | ||
| 130 | }; | ||
| 131 | |||
| 132 | gpe1: gpio-controller@11400100 { | ||
| 133 | compatible = "samsung,exynos4-gpio"; | ||
| 134 | reg = <0x11400100 0x20>; | ||
| 135 | #gpio-cells = <4>; | ||
| 136 | }; | ||
| 137 | |||
| 138 | gpe2: gpio-controller@11400120 { | ||
| 139 | compatible = "samsung,exynos4-gpio"; | ||
| 140 | reg = <0x11400120 0x20>; | ||
| 141 | #gpio-cells = <4>; | ||
| 142 | }; | ||
| 143 | |||
| 144 | gpe3: gpio-controller@11400140 { | ||
| 145 | compatible = "samsung,exynos4-gpio"; | ||
| 146 | reg = <0x11400140 0x20>; | ||
| 147 | #gpio-cells = <4>; | ||
| 148 | }; | ||
| 149 | |||
| 150 | gpe4: gpio-controller@11400160 { | ||
| 151 | compatible = "samsung,exynos4-gpio"; | ||
| 152 | reg = <0x11400160 0x20>; | ||
| 153 | #gpio-cells = <4>; | ||
| 154 | }; | ||
| 155 | |||
| 156 | gpf0: gpio-controller@11400180 { | ||
| 157 | compatible = "samsung,exynos4-gpio"; | ||
| 158 | reg = <0x11400180 0x20>; | ||
| 159 | #gpio-cells = <4>; | ||
| 160 | }; | ||
| 161 | |||
| 162 | gpf1: gpio-controller@114001A0 { | ||
| 163 | compatible = "samsung,exynos4-gpio"; | ||
| 164 | reg = <0x114001A0 0x20>; | ||
| 165 | #gpio-cells = <4>; | ||
| 166 | }; | ||
| 167 | |||
| 168 | gpf2: gpio-controller@114001C0 { | ||
| 169 | compatible = "samsung,exynos4-gpio"; | ||
| 170 | reg = <0x114001C0 0x20>; | ||
| 171 | #gpio-cells = <4>; | ||
| 172 | }; | ||
| 173 | |||
| 174 | gpf3: gpio-controller@114001E0 { | ||
| 175 | compatible = "samsung,exynos4-gpio"; | ||
| 176 | reg = <0x114001E0 0x20>; | ||
| 177 | #gpio-cells = <4>; | ||
| 178 | }; | ||
| 179 | |||
| 180 | gpj0: gpio-controller@11000000 { | ||
| 181 | compatible = "samsung,exynos4-gpio"; | ||
| 182 | reg = <0x11000000 0x20>; | ||
| 183 | #gpio-cells = <4>; | ||
| 184 | }; | ||
| 185 | |||
| 186 | gpj1: gpio-controller@11000020 { | ||
| 187 | compatible = "samsung,exynos4-gpio"; | ||
| 188 | reg = <0x11000020 0x20>; | ||
| 189 | #gpio-cells = <4>; | ||
| 190 | }; | ||
| 191 | |||
| 192 | gpk0: gpio-controller@11000040 { | ||
| 193 | compatible = "samsung,exynos4-gpio"; | ||
| 194 | reg = <0x11000040 0x20>; | ||
| 195 | #gpio-cells = <4>; | ||
| 196 | }; | ||
| 197 | |||
| 198 | gpk1: gpio-controller@11000060 { | ||
| 199 | compatible = "samsung,exynos4-gpio"; | ||
| 200 | reg = <0x11000060 0x20>; | ||
| 201 | #gpio-cells = <4>; | ||
| 202 | }; | ||
| 203 | |||
| 204 | gpk2: gpio-controller@11000080 { | ||
| 205 | compatible = "samsung,exynos4-gpio"; | ||
| 206 | reg = <0x11000080 0x20>; | ||
| 207 | #gpio-cells = <4>; | ||
| 208 | }; | ||
| 209 | |||
| 210 | gpk3: gpio-controller@110000A0 { | ||
| 211 | compatible = "samsung,exynos4-gpio"; | ||
| 212 | reg = <0x110000A0 0x20>; | ||
| 213 | #gpio-cells = <4>; | ||
| 214 | }; | ||
| 215 | |||
| 216 | gpl0: gpio-controller@110000C0 { | ||
| 217 | compatible = "samsung,exynos4-gpio"; | ||
| 218 | reg = <0x110000C0 0x20>; | ||
| 219 | #gpio-cells = <4>; | ||
| 220 | }; | ||
| 221 | |||
| 222 | gpl1: gpio-controller@110000E0 { | ||
| 223 | compatible = "samsung,exynos4-gpio"; | ||
| 224 | reg = <0x110000E0 0x20>; | ||
| 225 | #gpio-cells = <4>; | ||
| 226 | }; | ||
| 227 | |||
| 228 | gpl2: gpio-controller@11000100 { | ||
| 229 | compatible = "samsung,exynos4-gpio"; | ||
| 230 | reg = <0x11000100 0x20>; | ||
| 231 | #gpio-cells = <4>; | ||
| 232 | }; | ||
| 233 | |||
| 234 | gpy0: gpio-controller@11000120 { | ||
| 235 | compatible = "samsung,exynos4-gpio"; | ||
| 236 | reg = <0x11000120 0x20>; | ||
| 237 | #gpio-cells = <4>; | ||
| 238 | }; | ||
| 239 | |||
| 240 | gpy1: gpio-controller@11000140 { | ||
| 241 | compatible = "samsung,exynos4-gpio"; | ||
| 242 | reg = <0x11000140 0x20>; | ||
| 243 | #gpio-cells = <4>; | ||
| 244 | }; | ||
| 245 | |||
| 246 | gpy2: gpio-controller@11000160 { | ||
| 247 | compatible = "samsung,exynos4-gpio"; | ||
| 248 | reg = <0x11000160 0x20>; | ||
| 249 | #gpio-cells = <4>; | ||
| 250 | }; | ||
| 251 | |||
| 252 | gpy3: gpio-controller@11000180 { | ||
| 253 | compatible = "samsung,exynos4-gpio"; | ||
| 254 | reg = <0x11000180 0x20>; | ||
| 255 | #gpio-cells = <4>; | ||
| 256 | }; | ||
| 257 | |||
| 258 | gpy4: gpio-controller@110001A0 { | ||
| 259 | compatible = "samsung,exynos4-gpio"; | ||
| 260 | reg = <0x110001A0 0x20>; | ||
| 261 | #gpio-cells = <4>; | ||
| 262 | }; | ||
| 263 | |||
| 264 | gpy5: gpio-controller@110001C0 { | ||
| 265 | compatible = "samsung,exynos4-gpio"; | ||
| 266 | reg = <0x110001C0 0x20>; | ||
| 267 | #gpio-cells = <4>; | ||
| 268 | }; | ||
| 269 | |||
| 270 | gpy6: gpio-controller@110001E0 { | ||
| 271 | compatible = "samsung,exynos4-gpio"; | ||
| 272 | reg = <0x110001E0 0x20>; | ||
| 273 | #gpio-cells = <4>; | ||
| 274 | }; | ||
| 275 | |||
| 276 | gpx0: gpio-controller@11000C00 { | ||
| 277 | compatible = "samsung,exynos4-gpio"; | ||
| 278 | reg = <0x11000C00 0x20>; | ||
| 279 | #gpio-cells = <4>; | ||
| 280 | }; | ||
| 281 | |||
| 282 | gpx1: gpio-controller@11000C20 { | ||
| 283 | compatible = "samsung,exynos4-gpio"; | ||
| 284 | reg = <0x11000C20 0x20>; | ||
| 285 | #gpio-cells = <4>; | ||
| 286 | }; | ||
| 287 | |||
| 288 | gpx2: gpio-controller@11000C40 { | ||
| 289 | compatible = "samsung,exynos4-gpio"; | ||
| 290 | reg = <0x11000C40 0x20>; | ||
| 291 | #gpio-cells = <4>; | ||
| 292 | }; | ||
| 293 | |||
| 294 | gpx3: gpio-controller@11000C60 { | ||
| 295 | compatible = "samsung,exynos4-gpio"; | ||
| 296 | reg = <0x11000C60 0x20>; | ||
| 297 | #gpio-cells = <4>; | ||
| 298 | }; | ||
| 299 | |||
| 300 | gpz: gpio-controller@03860000 { | ||
| 301 | compatible = "samsung,exynos4-gpio"; | ||
| 302 | reg = <0x03860000 0x20>; | ||
| 303 | #gpio-cells = <4>; | ||
| 304 | }; | ||
| 305 | }; | ||
| 306 | }; | 67 | }; |
diff --git a/drivers/pinctrl/pinctrl-exynos.c b/drivers/pinctrl/pinctrl-exynos.c index 21362f48d370..19fab68a9fbf 100644 --- a/drivers/pinctrl/pinctrl-exynos.c +++ b/drivers/pinctrl/pinctrl-exynos.c | |||
| @@ -40,46 +40,46 @@ static const struct of_device_id exynos_wkup_irq_ids[] = { | |||
| 40 | 40 | ||
| 41 | static void exynos_gpio_irq_unmask(struct irq_data *irqd) | 41 | static void exynos_gpio_irq_unmask(struct irq_data *irqd) |
| 42 | { | 42 | { |
| 43 | struct samsung_pinctrl_drv_data *d = irqd->domain->host_data; | 43 | struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd); |
| 44 | struct exynos_geint_data *edata = irq_data_get_irq_handler_data(irqd); | 44 | struct samsung_pinctrl_drv_data *d = bank->drvdata; |
| 45 | unsigned long reg_mask = d->ctrl->geint_mask + edata->eint_offset; | 45 | unsigned long reg_mask = d->ctrl->geint_mask + bank->eint_offset; |
| 46 | unsigned long mask; | 46 | unsigned long mask; |
| 47 | 47 | ||
| 48 | mask = readl(d->virt_base + reg_mask); | 48 | mask = readl(d->virt_base + reg_mask); |
| 49 | mask &= ~(1 << edata->pin); | 49 | mask &= ~(1 << irqd->hwirq); |
| 50 | writel(mask, d->virt_base + reg_mask); | 50 | writel(mask, d->virt_base + reg_mask); |
| 51 | } | 51 | } |
| 52 | 52 | ||
| 53 | static void exynos_gpio_irq_mask(struct irq_data *irqd) | 53 | static void exynos_gpio_irq_mask(struct irq_data *irqd) |
| 54 | { | 54 | { |
| 55 | struct samsung_pinctrl_drv_data *d = irqd->domain->host_data; | 55 | struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd); |
| 56 | struct exynos_geint_data *edata = irq_data_get_irq_handler_data(irqd); | 56 | struct samsung_pinctrl_drv_data *d = bank->drvdata; |
| 57 | unsigned long reg_mask = d->ctrl->geint_mask + edata->eint_offset; | 57 | unsigned long reg_mask = d->ctrl->geint_mask + bank->eint_offset; |
| 58 | unsigned long mask; | 58 | unsigned long mask; |
| 59 | 59 | ||
| 60 | mask = readl(d->virt_base + reg_mask); | 60 | mask = readl(d->virt_base + reg_mask); |
| 61 | mask |= 1 << edata->pin; | 61 | mask |= 1 << irqd->hwirq; |
| 62 | writel(mask, d->virt_base + reg_mask); | 62 | writel(mask, d->virt_base + reg_mask); |
| 63 | } | 63 | } |
| 64 | 64 | ||
| 65 | static void exynos_gpio_irq_ack(struct irq_data *irqd) | 65 | static void exynos_gpio_irq_ack(struct irq_data *irqd) |
| 66 | { | 66 | { |
| 67 | struct samsung_pinctrl_drv_data *d = irqd->domain->host_data; | 67 | struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd); |
| 68 | struct exynos_geint_data *edata = irq_data_get_irq_handler_data(irqd); | 68 | struct samsung_pinctrl_drv_data *d = bank->drvdata; |
| 69 | unsigned long reg_pend = d->ctrl->geint_pend + edata->eint_offset; | 69 | unsigned long reg_pend = d->ctrl->geint_pend + bank->eint_offset; |
| 70 | 70 | ||
| 71 | writel(1 << edata->pin, d->virt_base + reg_pend); | 71 | writel(1 << irqd->hwirq, d->virt_base + reg_pend); |
| 72 | } | 72 | } |
| 73 | 73 | ||
| 74 | static int exynos_gpio_irq_set_type(struct irq_data *irqd, unsigned int type) | 74 | static int exynos_gpio_irq_set_type(struct irq_data *irqd, unsigned int type) |
| 75 | { | 75 | { |
| 76 | struct samsung_pinctrl_drv_data *d = irqd->domain->host_data; | 76 | struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd); |
| 77 | struct samsung_pinctrl_drv_data *d = bank->drvdata; | ||
| 77 | struct samsung_pin_ctrl *ctrl = d->ctrl; | 78 | struct samsung_pin_ctrl *ctrl = d->ctrl; |
| 78 | struct exynos_geint_data *edata = irq_data_get_irq_handler_data(irqd); | 79 | unsigned int pin = irqd->hwirq; |
| 79 | struct samsung_pin_bank *bank = edata->bank; | 80 | unsigned int shift = EXYNOS_EINT_CON_LEN * pin; |
| 80 | unsigned int shift = EXYNOS_EINT_CON_LEN * edata->pin; | ||
| 81 | unsigned int con, trig_type; | 81 | unsigned int con, trig_type; |
| 82 | unsigned long reg_con = ctrl->geint_con + edata->eint_offset; | 82 | unsigned long reg_con = ctrl->geint_con + bank->eint_offset; |
| 83 | unsigned int mask; | 83 | unsigned int mask; |
| 84 | 84 | ||
| 85 | switch (type) { | 85 | switch (type) { |
| @@ -114,7 +114,7 @@ static int exynos_gpio_irq_set_type(struct irq_data *irqd, unsigned int type) | |||
| 114 | writel(con, d->virt_base + reg_con); | 114 | writel(con, d->virt_base + reg_con); |
| 115 | 115 | ||
| 116 | reg_con = bank->pctl_offset; | 116 | reg_con = bank->pctl_offset; |
| 117 | shift = edata->pin * bank->func_width; | 117 | shift = pin * bank->func_width; |
| 118 | mask = (1 << bank->func_width) - 1; | 118 | mask = (1 << bank->func_width) - 1; |
| 119 | 119 | ||
| 120 | con = readl(d->virt_base + reg_con); | 120 | con = readl(d->virt_base + reg_con); |
| @@ -136,82 +136,23 @@ static struct irq_chip exynos_gpio_irq_chip = { | |||
| 136 | .irq_set_type = exynos_gpio_irq_set_type, | 136 | .irq_set_type = exynos_gpio_irq_set_type, |
| 137 | }; | 137 | }; |
| 138 | 138 | ||
| 139 | /* | ||
| 140 | * given a controller-local external gpio interrupt number, prepare the handler | ||
| 141 | * data for it. | ||
| 142 | */ | ||
| 143 | static struct exynos_geint_data *exynos_get_eint_data(irq_hw_number_t hw, | ||
| 144 | struct samsung_pinctrl_drv_data *d) | ||
| 145 | { | ||
| 146 | struct samsung_pin_bank *bank = d->ctrl->pin_banks; | ||
| 147 | struct exynos_geint_data *eint_data; | ||
| 148 | unsigned int nr_banks = d->ctrl->nr_banks, idx; | ||
| 149 | unsigned int irq_base = 0, eint_offset = 0; | ||
| 150 | |||
| 151 | if (hw >= d->ctrl->nr_gint) { | ||
| 152 | dev_err(d->dev, "unsupported ext-gpio interrupt\n"); | ||
| 153 | return NULL; | ||
| 154 | } | ||
| 155 | |||
| 156 | for (idx = 0; idx < nr_banks; idx++, bank++) { | ||
| 157 | if (bank->eint_type != EINT_TYPE_GPIO) | ||
| 158 | continue; | ||
| 159 | if ((hw >= irq_base) && (hw < (irq_base + bank->nr_pins))) | ||
| 160 | break; | ||
| 161 | irq_base += bank->nr_pins; | ||
| 162 | eint_offset += 4; | ||
| 163 | } | ||
| 164 | |||
| 165 | if (idx == nr_banks) { | ||
| 166 | dev_err(d->dev, "pin bank not found for ext-gpio interrupt\n"); | ||
| 167 | return NULL; | ||
| 168 | } | ||
| 169 | |||
| 170 | eint_data = devm_kzalloc(d->dev, sizeof(*eint_data), GFP_KERNEL); | ||
| 171 | if (!eint_data) { | ||
| 172 | dev_err(d->dev, "no memory for eint-gpio data\n"); | ||
| 173 | return NULL; | ||
| 174 | } | ||
| 175 | |||
| 176 | eint_data->bank = bank; | ||
| 177 | eint_data->pin = hw - irq_base; | ||
| 178 | eint_data->eint_offset = eint_offset; | ||
| 179 | return eint_data; | ||
| 180 | } | ||
| 181 | |||
| 182 | static int exynos_gpio_irq_map(struct irq_domain *h, unsigned int virq, | 139 | static int exynos_gpio_irq_map(struct irq_domain *h, unsigned int virq, |
| 183 | irq_hw_number_t hw) | 140 | irq_hw_number_t hw) |
| 184 | { | 141 | { |
| 185 | struct samsung_pinctrl_drv_data *d = h->host_data; | 142 | struct samsung_pin_bank *b = h->host_data; |
| 186 | struct exynos_geint_data *eint_data; | ||
| 187 | |||
| 188 | eint_data = exynos_get_eint_data(hw, d); | ||
| 189 | if (!eint_data) | ||
| 190 | return -EINVAL; | ||
| 191 | 143 | ||
| 192 | irq_set_handler_data(virq, eint_data); | 144 | irq_set_chip_data(virq, b); |
| 193 | irq_set_chip_data(virq, h->host_data); | ||
| 194 | irq_set_chip_and_handler(virq, &exynos_gpio_irq_chip, | 145 | irq_set_chip_and_handler(virq, &exynos_gpio_irq_chip, |
| 195 | handle_level_irq); | 146 | handle_level_irq); |
| 196 | set_irq_flags(virq, IRQF_VALID); | 147 | set_irq_flags(virq, IRQF_VALID); |
| 197 | return 0; | 148 | return 0; |
| 198 | } | 149 | } |
| 199 | 150 | ||
| 200 | static void exynos_gpio_irq_unmap(struct irq_domain *h, unsigned int virq) | ||
| 201 | { | ||
| 202 | struct samsung_pinctrl_drv_data *d = h->host_data; | ||
| 203 | struct exynos_geint_data *eint_data; | ||
| 204 | |||
| 205 | eint_data = irq_get_handler_data(virq); | ||
| 206 | devm_kfree(d->dev, eint_data); | ||
| 207 | } | ||
| 208 | |||
| 209 | /* | 151 | /* |
| 210 | * irq domain callbacks for external gpio interrupt controller. | 152 | * irq domain callbacks for external gpio interrupt controller. |
| 211 | */ | 153 | */ |
| 212 | static const struct irq_domain_ops exynos_gpio_irqd_ops = { | 154 | static const struct irq_domain_ops exynos_gpio_irqd_ops = { |
| 213 | .map = exynos_gpio_irq_map, | 155 | .map = exynos_gpio_irq_map, |
| 214 | .unmap = exynos_gpio_irq_unmap, | ||
| 215 | .xlate = irq_domain_xlate_twocell, | 156 | .xlate = irq_domain_xlate_twocell, |
| 216 | }; | 157 | }; |
| 217 | 158 | ||
| @@ -230,7 +171,7 @@ static irqreturn_t exynos_eint_gpio_irq(int irq, void *data) | |||
| 230 | return IRQ_HANDLED; | 171 | return IRQ_HANDLED; |
| 231 | bank += (group - 1); | 172 | bank += (group - 1); |
| 232 | 173 | ||
| 233 | virq = irq_linear_revmap(d->gpio_irqd, bank->irq_base + pin); | 174 | virq = irq_linear_revmap(bank->irq_domain, pin); |
| 234 | if (!virq) | 175 | if (!virq) |
| 235 | return IRQ_NONE; | 176 | return IRQ_NONE; |
| 236 | generic_handle_irq(virq); | 177 | generic_handle_irq(virq); |
| @@ -243,8 +184,10 @@ static irqreturn_t exynos_eint_gpio_irq(int irq, void *data) | |||
| 243 | */ | 184 | */ |
| 244 | static int exynos_eint_gpio_init(struct samsung_pinctrl_drv_data *d) | 185 | static int exynos_eint_gpio_init(struct samsung_pinctrl_drv_data *d) |
| 245 | { | 186 | { |
| 187 | struct samsung_pin_bank *bank; | ||
| 246 | struct device *dev = d->dev; | 188 | struct device *dev = d->dev; |
| 247 | unsigned int ret; | 189 | unsigned int ret; |
| 190 | unsigned int i; | ||
| 248 | 191 | ||
| 249 | if (!d->irq) { | 192 | if (!d->irq) { |
| 250 | dev_err(dev, "irq number not available\n"); | 193 | dev_err(dev, "irq number not available\n"); |
| @@ -258,11 +201,16 @@ static int exynos_eint_gpio_init(struct samsung_pinctrl_drv_data *d) | |||
| 258 | return -ENXIO; | 201 | return -ENXIO; |
| 259 | } | 202 | } |
| 260 | 203 | ||
| 261 | d->gpio_irqd = irq_domain_add_linear(dev->of_node, d->ctrl->nr_gint, | 204 | bank = d->ctrl->pin_banks; |
| 262 | &exynos_gpio_irqd_ops, d); | 205 | for (i = 0; i < d->ctrl->nr_banks; ++i, ++bank) { |
| 263 | if (!d->gpio_irqd) { | 206 | if (bank->eint_type != EINT_TYPE_GPIO) |
| 264 | dev_err(dev, "gpio irq domain allocation failed\n"); | 207 | continue; |
| 265 | return -ENXIO; | 208 | bank->irq_domain = irq_domain_add_linear(bank->of_node, |
| 209 | bank->nr_pins, &exynos_gpio_irqd_ops, bank); | ||
| 210 | if (!bank->irq_domain) { | ||
| 211 | dev_err(dev, "gpio irq domain add failed\n"); | ||
| 212 | return -ENXIO; | ||
| 213 | } | ||
| 266 | } | 214 | } |
| 267 | 215 | ||
| 268 | return 0; | 216 | return 0; |
| @@ -270,48 +218,46 @@ static int exynos_eint_gpio_init(struct samsung_pinctrl_drv_data *d) | |||
| 270 | 218 | ||
| 271 | static void exynos_wkup_irq_unmask(struct irq_data *irqd) | 219 | static void exynos_wkup_irq_unmask(struct irq_data *irqd) |
| 272 | { | 220 | { |
| 273 | struct samsung_pinctrl_drv_data *d = irq_data_get_irq_chip_data(irqd); | 221 | struct samsung_pin_bank *b = irq_data_get_irq_chip_data(irqd); |
| 274 | unsigned int bank = irqd->hwirq / EXYNOS_EINT_MAX_PER_BANK; | 222 | struct samsung_pinctrl_drv_data *d = b->drvdata; |
| 275 | unsigned int pin = irqd->hwirq & (EXYNOS_EINT_MAX_PER_BANK - 1); | 223 | unsigned long reg_mask = d->ctrl->weint_mask + b->eint_offset; |
| 276 | unsigned long reg_mask = d->ctrl->weint_mask + (bank << 2); | ||
| 277 | unsigned long mask; | 224 | unsigned long mask; |
| 278 | 225 | ||
| 279 | mask = readl(d->virt_base + reg_mask); | 226 | mask = readl(d->virt_base + reg_mask); |
| 280 | mask &= ~(1 << pin); | 227 | mask &= ~(1 << irqd->hwirq); |
| 281 | writel(mask, d->virt_base + reg_mask); | 228 | writel(mask, d->virt_base + reg_mask); |
| 282 | } | 229 | } |
| 283 | 230 | ||
| 284 | static void exynos_wkup_irq_mask(struct irq_data *irqd) | 231 | static void exynos_wkup_irq_mask(struct irq_data *irqd) |
| 285 | { | 232 | { |
| 286 | struct samsung_pinctrl_drv_data *d = irq_data_get_irq_chip_data(irqd); | 233 | struct samsung_pin_bank *b = irq_data_get_irq_chip_data(irqd); |
| 287 | unsigned int bank = irqd->hwirq / EXYNOS_EINT_MAX_PER_BANK; | 234 | struct samsung_pinctrl_drv_data *d = b->drvdata; |
| 288 | unsigned int pin = irqd->hwirq & (EXYNOS_EINT_MAX_PER_BANK - 1); | 235 | unsigned long reg_mask = d->ctrl->weint_mask + b->eint_offset; |
| 289 | unsigned long reg_mask = d->ctrl->weint_mask + (bank << 2); | ||
| 290 | unsigned long mask; | 236 | unsigned long mask; |
| 291 | 237 | ||
| 292 | mask = readl(d->virt_base + reg_mask); | 238 | mask = readl(d->virt_base + reg_mask); |
| 293 | mask |= 1 << pin; | 239 | mask |= 1 << irqd->hwirq; |
| 294 | writel(mask, d->virt_base + reg_mask); | 240 | writel(mask, d->virt_base + reg_mask); |
| 295 | } | 241 | } |
| 296 | 242 | ||
| 297 | static void exynos_wkup_irq_ack(struct irq_data *irqd) | 243 | static void exynos_wkup_irq_ack(struct irq_data *irqd) |
| 298 | { | 244 | { |
| 299 | struct samsung_pinctrl_drv_data *d = irq_data_get_irq_chip_data(irqd); | 245 | struct samsung_pin_bank *b = irq_data_get_irq_chip_data(irqd); |
| 300 | unsigned int bank = irqd->hwirq / EXYNOS_EINT_MAX_PER_BANK; | 246 | struct samsung_pinctrl_drv_data *d = b->drvdata; |
| 301 | unsigned int pin = irqd->hwirq & (EXYNOS_EINT_MAX_PER_BANK - 1); | 247 | unsigned long pend = d->ctrl->weint_pend + b->eint_offset; |
| 302 | unsigned long pend = d->ctrl->weint_pend + (bank << 2); | ||
| 303 | 248 | ||
| 304 | writel(1 << pin, d->virt_base + pend); | 249 | writel(1 << irqd->hwirq, d->virt_base + pend); |
| 305 | } | 250 | } |
| 306 | 251 | ||
| 307 | static int exynos_wkup_irq_set_type(struct irq_data *irqd, unsigned int type) | 252 | static int exynos_wkup_irq_set_type(struct irq_data *irqd, unsigned int type) |
| 308 | { | 253 | { |
| 309 | struct samsung_pinctrl_drv_data *d = irq_data_get_irq_chip_data(irqd); | 254 | struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd); |
| 310 | unsigned int bank = irqd->hwirq / EXYNOS_EINT_MAX_PER_BANK; | 255 | struct samsung_pinctrl_drv_data *d = bank->drvdata; |
| 311 | unsigned int pin = irqd->hwirq & (EXYNOS_EINT_MAX_PER_BANK - 1); | 256 | unsigned int pin = irqd->hwirq; |
| 312 | unsigned long reg_con = d->ctrl->weint_con + (bank << 2); | 257 | unsigned long reg_con = d->ctrl->weint_con + bank->eint_offset; |
| 313 | unsigned long shift = EXYNOS_EINT_CON_LEN * pin; | 258 | unsigned long shift = EXYNOS_EINT_CON_LEN * pin; |
| 314 | unsigned long con, trig_type; | 259 | unsigned long con, trig_type; |
| 260 | unsigned int mask; | ||
| 315 | 261 | ||
| 316 | switch (type) { | 262 | switch (type) { |
| 317 | case IRQ_TYPE_EDGE_RISING: | 263 | case IRQ_TYPE_EDGE_RISING: |
| @@ -343,6 +289,16 @@ static int exynos_wkup_irq_set_type(struct irq_data *irqd, unsigned int type) | |||
| 343 | con &= ~(EXYNOS_EINT_CON_MASK << shift); | 289 | con &= ~(EXYNOS_EINT_CON_MASK << shift); |
| 344 | con |= trig_type << shift; | 290 | con |= trig_type << shift; |
| 345 | writel(con, d->virt_base + reg_con); | 291 | writel(con, d->virt_base + reg_con); |
| 292 | |||
| 293 | reg_con = bank->pctl_offset; | ||
| 294 | shift = pin * bank->func_width; | ||
| 295 | mask = (1 << bank->func_width) - 1; | ||
| 296 | |||
| 297 | con = readl(d->virt_base + reg_con); | ||
| 298 | con &= ~(mask << shift); | ||
| 299 | con |= EXYNOS_EINT_FUNC << shift; | ||
| 300 | writel(con, d->virt_base + reg_con); | ||
| 301 | |||
| 346 | return 0; | 302 | return 0; |
| 347 | } | 303 | } |
| 348 | 304 | ||
| @@ -361,6 +317,7 @@ static struct irq_chip exynos_wkup_irq_chip = { | |||
| 361 | static void exynos_irq_eint0_15(unsigned int irq, struct irq_desc *desc) | 317 | static void exynos_irq_eint0_15(unsigned int irq, struct irq_desc *desc) |
| 362 | { | 318 | { |
| 363 | struct exynos_weint_data *eintd = irq_get_handler_data(irq); | 319 | struct exynos_weint_data *eintd = irq_get_handler_data(irq); |
| 320 | struct samsung_pin_bank *bank = eintd->bank; | ||
| 364 | struct irq_chip *chip = irq_get_chip(irq); | 321 | struct irq_chip *chip = irq_get_chip(irq); |
| 365 | int eint_irq; | 322 | int eint_irq; |
| 366 | 323 | ||
| @@ -370,20 +327,20 @@ static void exynos_irq_eint0_15(unsigned int irq, struct irq_desc *desc) | |||
| 370 | if (chip->irq_ack) | 327 | if (chip->irq_ack) |
| 371 | chip->irq_ack(&desc->irq_data); | 328 | chip->irq_ack(&desc->irq_data); |
| 372 | 329 | ||
| 373 | eint_irq = irq_linear_revmap(eintd->domain, eintd->irq); | 330 | eint_irq = irq_linear_revmap(bank->irq_domain, eintd->irq); |
| 374 | generic_handle_irq(eint_irq); | 331 | generic_handle_irq(eint_irq); |
| 375 | chip->irq_unmask(&desc->irq_data); | 332 | chip->irq_unmask(&desc->irq_data); |
| 376 | chained_irq_exit(chip, desc); | 333 | chained_irq_exit(chip, desc); |
| 377 | } | 334 | } |
| 378 | 335 | ||
| 379 | static inline void exynos_irq_demux_eint(int irq_base, unsigned long pend, | 336 | static inline void exynos_irq_demux_eint(unsigned long pend, |
| 380 | struct irq_domain *domain) | 337 | struct irq_domain *domain) |
| 381 | { | 338 | { |
| 382 | unsigned int irq; | 339 | unsigned int irq; |
| 383 | 340 | ||
| 384 | while (pend) { | 341 | while (pend) { |
| 385 | irq = fls(pend) - 1; | 342 | irq = fls(pend) - 1; |
| 386 | generic_handle_irq(irq_find_mapping(domain, irq_base + irq)); | 343 | generic_handle_irq(irq_find_mapping(domain, irq)); |
| 387 | pend &= ~(1 << irq); | 344 | pend &= ~(1 << irq); |
| 388 | } | 345 | } |
| 389 | } | 346 | } |
| @@ -392,18 +349,22 @@ static inline void exynos_irq_demux_eint(int irq_base, unsigned long pend, | |||
| 392 | static void exynos_irq_demux_eint16_31(unsigned int irq, struct irq_desc *desc) | 349 | static void exynos_irq_demux_eint16_31(unsigned int irq, struct irq_desc *desc) |
| 393 | { | 350 | { |
| 394 | struct irq_chip *chip = irq_get_chip(irq); | 351 | struct irq_chip *chip = irq_get_chip(irq); |
| 395 | struct exynos_weint_data *eintd = irq_get_handler_data(irq); | 352 | struct exynos_muxed_weint_data *eintd = irq_get_handler_data(irq); |
| 396 | struct samsung_pinctrl_drv_data *d = eintd->domain->host_data; | 353 | struct samsung_pinctrl_drv_data *d = eintd->banks[0]->drvdata; |
| 354 | struct samsung_pin_ctrl *ctrl = d->ctrl; | ||
| 397 | unsigned long pend; | 355 | unsigned long pend; |
| 398 | unsigned long mask; | 356 | unsigned long mask; |
| 357 | int i; | ||
| 399 | 358 | ||
| 400 | chained_irq_enter(chip, desc); | 359 | chained_irq_enter(chip, desc); |
| 401 | pend = readl(d->virt_base + d->ctrl->weint_pend + 0x8); | 360 | |
| 402 | mask = readl(d->virt_base + d->ctrl->weint_mask + 0x8); | 361 | for (i = 0; i < eintd->nr_banks; ++i) { |
| 403 | exynos_irq_demux_eint(16, pend & ~mask, eintd->domain); | 362 | struct samsung_pin_bank *b = eintd->banks[i]; |
| 404 | pend = readl(d->virt_base + d->ctrl->weint_pend + 0xC); | 363 | pend = readl(d->virt_base + ctrl->weint_pend + b->eint_offset); |
| 405 | mask = readl(d->virt_base + d->ctrl->weint_mask + 0xC); | 364 | mask = readl(d->virt_base + ctrl->weint_mask + b->eint_offset); |
| 406 | exynos_irq_demux_eint(24, pend & ~mask, eintd->domain); | 365 | exynos_irq_demux_eint(pend & ~mask, b->irq_domain); |
| 366 | } | ||
| 367 | |||
| 407 | chained_irq_exit(chip, desc); | 368 | chained_irq_exit(chip, desc); |
| 408 | } | 369 | } |
| 409 | 370 | ||
| @@ -433,7 +394,11 @@ static int exynos_eint_wkup_init(struct samsung_pinctrl_drv_data *d) | |||
| 433 | struct device *dev = d->dev; | 394 | struct device *dev = d->dev; |
| 434 | struct device_node *wkup_np = NULL; | 395 | struct device_node *wkup_np = NULL; |
| 435 | struct device_node *np; | 396 | struct device_node *np; |
| 397 | struct samsung_pin_bank *bank; | ||
| 436 | struct exynos_weint_data *weint_data; | 398 | struct exynos_weint_data *weint_data; |
| 399 | struct exynos_muxed_weint_data *muxed_data; | ||
| 400 | unsigned int muxed_banks = 0; | ||
| 401 | unsigned int i; | ||
| 437 | int idx, irq; | 402 | int idx, irq; |
| 438 | 403 | ||
| 439 | for_each_child_of_node(dev->of_node, np) { | 404 | for_each_child_of_node(dev->of_node, np) { |
| @@ -445,90 +410,124 @@ static int exynos_eint_wkup_init(struct samsung_pinctrl_drv_data *d) | |||
| 445 | if (!wkup_np) | 410 | if (!wkup_np) |
| 446 | return -ENODEV; | 411 | return -ENODEV; |
| 447 | 412 | ||
| 448 | d->wkup_irqd = irq_domain_add_linear(wkup_np, d->ctrl->nr_wint, | 413 | bank = d->ctrl->pin_banks; |
| 449 | &exynos_wkup_irqd_ops, d); | 414 | for (i = 0; i < d->ctrl->nr_banks; ++i, ++bank) { |
| 450 | if (!d->wkup_irqd) { | 415 | if (bank->eint_type != EINT_TYPE_WKUP) |
| 451 | dev_err(dev, "wakeup irq domain allocation failed\n"); | 416 | continue; |
| 452 | return -ENXIO; | ||
| 453 | } | ||
| 454 | 417 | ||
| 455 | weint_data = devm_kzalloc(dev, sizeof(*weint_data) * 17, GFP_KERNEL); | 418 | bank->irq_domain = irq_domain_add_linear(bank->of_node, |
| 456 | if (!weint_data) { | 419 | bank->nr_pins, &exynos_wkup_irqd_ops, bank); |
| 457 | dev_err(dev, "could not allocate memory for weint_data\n"); | 420 | if (!bank->irq_domain) { |
| 458 | return -ENOMEM; | 421 | dev_err(dev, "wkup irq domain add failed\n"); |
| 459 | } | 422 | return -ENXIO; |
| 423 | } | ||
| 460 | 424 | ||
| 461 | irq = irq_of_parse_and_map(wkup_np, 16); | 425 | if (!of_find_property(bank->of_node, "interrupts", NULL)) { |
| 462 | if (irq) { | 426 | bank->eint_type = EINT_TYPE_WKUP_MUX; |
| 463 | weint_data[16].domain = d->wkup_irqd; | 427 | ++muxed_banks; |
| 464 | irq_set_chained_handler(irq, exynos_irq_demux_eint16_31); | 428 | continue; |
| 465 | irq_set_handler_data(irq, &weint_data[16]); | 429 | } |
| 466 | } else { | ||
| 467 | dev_err(dev, "irq number for EINT16-32 not found\n"); | ||
| 468 | } | ||
| 469 | 430 | ||
| 470 | for (idx = 0; idx < 16; idx++) { | 431 | weint_data = devm_kzalloc(dev, bank->nr_pins |
| 471 | weint_data[idx].domain = d->wkup_irqd; | 432 | * sizeof(*weint_data), GFP_KERNEL); |
| 472 | weint_data[idx].irq = idx; | 433 | if (!weint_data) { |
| 434 | dev_err(dev, "could not allocate memory for weint_data\n"); | ||
| 435 | return -ENOMEM; | ||
| 436 | } | ||
| 473 | 437 | ||
| 474 | irq = irq_of_parse_and_map(wkup_np, idx); | 438 | for (idx = 0; idx < bank->nr_pins; ++idx) { |
| 475 | if (irq) { | 439 | irq = irq_of_parse_and_map(bank->of_node, idx); |
| 440 | if (!irq) { | ||
| 441 | dev_err(dev, "irq number for eint-%s-%d not found\n", | ||
| 442 | bank->name, idx); | ||
| 443 | continue; | ||
| 444 | } | ||
| 445 | weint_data[idx].irq = idx; | ||
| 446 | weint_data[idx].bank = bank; | ||
| 476 | irq_set_handler_data(irq, &weint_data[idx]); | 447 | irq_set_handler_data(irq, &weint_data[idx]); |
| 477 | irq_set_chained_handler(irq, exynos_irq_eint0_15); | 448 | irq_set_chained_handler(irq, exynos_irq_eint0_15); |
| 478 | } else { | ||
| 479 | dev_err(dev, "irq number for eint-%x not found\n", idx); | ||
| 480 | } | 449 | } |
| 481 | } | 450 | } |
| 451 | |||
| 452 | if (!muxed_banks) | ||
| 453 | return 0; | ||
| 454 | |||
| 455 | irq = irq_of_parse_and_map(wkup_np, 0); | ||
| 456 | if (!irq) { | ||
| 457 | dev_err(dev, "irq number for muxed EINTs not found\n"); | ||
| 458 | return 0; | ||
| 459 | } | ||
| 460 | |||
| 461 | muxed_data = devm_kzalloc(dev, sizeof(*muxed_data) | ||
| 462 | + muxed_banks*sizeof(struct samsung_pin_bank *), GFP_KERNEL); | ||
| 463 | if (!muxed_data) { | ||
| 464 | dev_err(dev, "could not allocate memory for muxed_data\n"); | ||
| 465 | return -ENOMEM; | ||
| 466 | } | ||
| 467 | |||
| 468 | irq_set_chained_handler(irq, exynos_irq_demux_eint16_31); | ||
| 469 | irq_set_handler_data(irq, muxed_data); | ||
| 470 | |||
| 471 | bank = d->ctrl->pin_banks; | ||
| 472 | idx = 0; | ||
| 473 | for (i = 0; i < d->ctrl->nr_banks; ++i, ++bank) { | ||
| 474 | if (bank->eint_type != EINT_TYPE_WKUP_MUX) | ||
| 475 | continue; | ||
| 476 | |||
| 477 | muxed_data->banks[idx++] = bank; | ||
| 478 | } | ||
| 479 | muxed_data->nr_banks = muxed_banks; | ||
| 480 | |||
| 482 | return 0; | 481 | return 0; |
| 483 | } | 482 | } |
| 484 | 483 | ||
| 485 | /* pin banks of exynos4210 pin-controller 0 */ | 484 | /* pin banks of exynos4210 pin-controller 0 */ |
| 486 | static struct samsung_pin_bank exynos4210_pin_banks0[] = { | 485 | static struct samsung_pin_bank exynos4210_pin_banks0[] = { |
| 487 | EXYNOS_PIN_BANK_EINTG(0x000, EXYNOS4210_GPIO_A0, "gpa0"), | 486 | EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpa0", 0x00), |
| 488 | EXYNOS_PIN_BANK_EINTG(0x020, EXYNOS4210_GPIO_A1, "gpa1"), | 487 | EXYNOS_PIN_BANK_EINTG(6, 0x020, "gpa1", 0x04), |
| 489 | EXYNOS_PIN_BANK_EINTG(0x040, EXYNOS4210_GPIO_B, "gpb"), | 488 | EXYNOS_PIN_BANK_EINTG(8, 0x040, "gpb", 0x08), |
| 490 | EXYNOS_PIN_BANK_EINTG(0x060, EXYNOS4210_GPIO_C0, "gpc0"), | 489 | EXYNOS_PIN_BANK_EINTG(5, 0x060, "gpc0", 0x0c), |
| 491 | EXYNOS_PIN_BANK_EINTG(0x080, EXYNOS4210_GPIO_C1, "gpc1"), | 490 | EXYNOS_PIN_BANK_EINTG(5, 0x080, "gpc1", 0x10), |
| 492 | EXYNOS_PIN_BANK_EINTG(0x0A0, EXYNOS4210_GPIO_D0, "gpd0"), | 491 | EXYNOS_PIN_BANK_EINTG(4, 0x0A0, "gpd0", 0x14), |
| 493 | EXYNOS_PIN_BANK_EINTG(0x0C0, EXYNOS4210_GPIO_D1, "gpd1"), | 492 | EXYNOS_PIN_BANK_EINTG(4, 0x0C0, "gpd1", 0x18), |
| 494 | EXYNOS_PIN_BANK_EINTG(0x0E0, EXYNOS4210_GPIO_E0, "gpe0"), | 493 | EXYNOS_PIN_BANK_EINTG(5, 0x0E0, "gpe0", 0x1c), |
| 495 | EXYNOS_PIN_BANK_EINTG(0x100, EXYNOS4210_GPIO_E1, "gpe1"), | 494 | EXYNOS_PIN_BANK_EINTG(8, 0x100, "gpe1", 0x20), |
| 496 | EXYNOS_PIN_BANK_EINTG(0x120, EXYNOS4210_GPIO_E2, "gpe2"), | 495 | EXYNOS_PIN_BANK_EINTG(6, 0x120, "gpe2", 0x24), |
| 497 | EXYNOS_PIN_BANK_EINTG(0x140, EXYNOS4210_GPIO_E3, "gpe3"), | 496 | EXYNOS_PIN_BANK_EINTG(8, 0x140, "gpe3", 0x28), |
| 498 | EXYNOS_PIN_BANK_EINTG(0x160, EXYNOS4210_GPIO_E4, "gpe4"), | 497 | EXYNOS_PIN_BANK_EINTG(8, 0x160, "gpe4", 0x2c), |
| 499 | EXYNOS_PIN_BANK_EINTG(0x180, EXYNOS4210_GPIO_F0, "gpf0"), | 498 | EXYNOS_PIN_BANK_EINTG(8, 0x180, "gpf0", 0x30), |
| 500 | EXYNOS_PIN_BANK_EINTG(0x1A0, EXYNOS4210_GPIO_F1, "gpf1"), | 499 | EXYNOS_PIN_BANK_EINTG(8, 0x1A0, "gpf1", 0x34), |
| 501 | EXYNOS_PIN_BANK_EINTG(0x1C0, EXYNOS4210_GPIO_F2, "gpf2"), | 500 | EXYNOS_PIN_BANK_EINTG(8, 0x1C0, "gpf2", 0x38), |
| 502 | EXYNOS_PIN_BANK_EINTG(0x1E0, EXYNOS4210_GPIO_F3, "gpf3"), | 501 | EXYNOS_PIN_BANK_EINTG(6, 0x1E0, "gpf3", 0x3c), |
| 503 | }; | 502 | }; |
| 504 | 503 | ||
| 505 | /* pin banks of exynos4210 pin-controller 1 */ | 504 | /* pin banks of exynos4210 pin-controller 1 */ |
| 506 | static struct samsung_pin_bank exynos4210_pin_banks1[] = { | 505 | static struct samsung_pin_bank exynos4210_pin_banks1[] = { |
| 507 | EXYNOS_PIN_BANK_EINTG(0x000, EXYNOS4210_GPIO_J0, "gpj0"), | 506 | EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpj0", 0x00), |
| 508 | EXYNOS_PIN_BANK_EINTG(0x020, EXYNOS4210_GPIO_J1, "gpj1"), | 507 | EXYNOS_PIN_BANK_EINTG(5, 0x020, "gpj1", 0x04), |
| 509 | EXYNOS_PIN_BANK_EINTG(0x040, EXYNOS4210_GPIO_K0, "gpk0"), | 508 | EXYNOS_PIN_BANK_EINTG(7, 0x040, "gpk0", 0x08), |
| 510 | EXYNOS_PIN_BANK_EINTG(0x060, EXYNOS4210_GPIO_K1, "gpk1"), | 509 | EXYNOS_PIN_BANK_EINTG(7, 0x060, "gpk1", 0x0c), |
| 511 | EXYNOS_PIN_BANK_EINTG(0x080, EXYNOS4210_GPIO_K2, "gpk2"), | 510 | EXYNOS_PIN_BANK_EINTG(7, 0x080, "gpk2", 0x10), |
| 512 | EXYNOS_PIN_BANK_EINTG(0x0A0, EXYNOS4210_GPIO_K3, "gpk3"), | 511 | EXYNOS_PIN_BANK_EINTG(7, 0x0A0, "gpk3", 0x14), |
| 513 | EXYNOS_PIN_BANK_EINTG(0x0C0, EXYNOS4210_GPIO_L0, "gpl0"), | 512 | EXYNOS_PIN_BANK_EINTG(8, 0x0C0, "gpl0", 0x18), |
| 514 | EXYNOS_PIN_BANK_EINTG(0x0E0, EXYNOS4210_GPIO_L1, "gpl1"), | 513 | EXYNOS_PIN_BANK_EINTG(3, 0x0E0, "gpl1", 0x1c), |
| 515 | EXYNOS_PIN_BANK_EINTG(0x100, EXYNOS4210_GPIO_L2, "gpl2"), | 514 | EXYNOS_PIN_BANK_EINTG(8, 0x100, "gpl2", 0x20), |
| 516 | EXYNOS_PIN_BANK_EINTN(0x120, EXYNOS4210_GPIO_Y0, "gpy0"), | 515 | EXYNOS_PIN_BANK_EINTN(6, 0x120, "gpy0"), |
| 517 | EXYNOS_PIN_BANK_EINTN(0x140, EXYNOS4210_GPIO_Y1, "gpy1"), | 516 | EXYNOS_PIN_BANK_EINTN(4, 0x140, "gpy1"), |
| 518 | EXYNOS_PIN_BANK_EINTN(0x160, EXYNOS4210_GPIO_Y2, "gpy2"), | 517 | EXYNOS_PIN_BANK_EINTN(6, 0x160, "gpy2"), |
| 519 | EXYNOS_PIN_BANK_EINTN(0x180, EXYNOS4210_GPIO_Y3, "gpy3"), | 518 | EXYNOS_PIN_BANK_EINTN(8, 0x180, "gpy3"), |
| 520 | EXYNOS_PIN_BANK_EINTN(0x1A0, EXYNOS4210_GPIO_Y4, "gpy4"), | 519 | EXYNOS_PIN_BANK_EINTN(8, 0x1A0, "gpy4"), |
| 521 | EXYNOS_PIN_BANK_EINTN(0x1C0, EXYNOS4210_GPIO_Y5, "gpy5"), | 520 | EXYNOS_PIN_BANK_EINTN(8, 0x1C0, "gpy5"), |
| 522 | EXYNOS_PIN_BANK_EINTN(0x1E0, EXYNOS4210_GPIO_Y6, "gpy6"), | 521 | EXYNOS_PIN_BANK_EINTN(8, 0x1E0, "gpy6"), |
| 523 | EXYNOS_PIN_BANK_EINTN(0xC00, EXYNOS4210_GPIO_X0, "gpx0"), | 522 | EXYNOS_PIN_BANK_EINTW(8, 0xC00, "gpx0", 0x00), |
| 524 | EXYNOS_PIN_BANK_EINTN(0xC20, EXYNOS4210_GPIO_X1, "gpx1"), | 523 | EXYNOS_PIN_BANK_EINTW(8, 0xC20, "gpx1", 0x04), |
| 525 | EXYNOS_PIN_BANK_EINTN(0xC40, EXYNOS4210_GPIO_X2, "gpx2"), | 524 | EXYNOS_PIN_BANK_EINTW(8, 0xC40, "gpx2", 0x08), |
| 526 | EXYNOS_PIN_BANK_EINTN(0xC60, EXYNOS4210_GPIO_X3, "gpx3"), | 525 | EXYNOS_PIN_BANK_EINTW(8, 0xC60, "gpx3", 0x0c), |
| 527 | }; | 526 | }; |
| 528 | 527 | ||
| 529 | /* pin banks of exynos4210 pin-controller 2 */ | 528 | /* pin banks of exynos4210 pin-controller 2 */ |
| 530 | static struct samsung_pin_bank exynos4210_pin_banks2[] = { | 529 | static struct samsung_pin_bank exynos4210_pin_banks2[] = { |
| 531 | EXYNOS_PIN_BANK_EINTN(0x000, EXYNOS4210_GPIO_Z, "gpz"), | 530 | EXYNOS_PIN_BANK_EINTN(7, 0x000, "gpz"), |
| 532 | }; | 531 | }; |
| 533 | 532 | ||
| 534 | /* | 533 | /* |
| @@ -540,9 +539,6 @@ struct samsung_pin_ctrl exynos4210_pin_ctrl[] = { | |||
| 540 | /* pin-controller instance 0 data */ | 539 | /* pin-controller instance 0 data */ |
| 541 | .pin_banks = exynos4210_pin_banks0, | 540 | .pin_banks = exynos4210_pin_banks0, |
| 542 | .nr_banks = ARRAY_SIZE(exynos4210_pin_banks0), | 541 | .nr_banks = ARRAY_SIZE(exynos4210_pin_banks0), |
| 543 | .base = EXYNOS4210_GPIO_A0_START, | ||
| 544 | .nr_pins = EXYNOS4210_GPIOA_NR_PINS, | ||
| 545 | .nr_gint = EXYNOS4210_GPIOA_NR_GINT, | ||
| 546 | .geint_con = EXYNOS_GPIO_ECON_OFFSET, | 542 | .geint_con = EXYNOS_GPIO_ECON_OFFSET, |
| 547 | .geint_mask = EXYNOS_GPIO_EMASK_OFFSET, | 543 | .geint_mask = EXYNOS_GPIO_EMASK_OFFSET, |
| 548 | .geint_pend = EXYNOS_GPIO_EPEND_OFFSET, | 544 | .geint_pend = EXYNOS_GPIO_EPEND_OFFSET, |
| @@ -553,10 +549,6 @@ struct samsung_pin_ctrl exynos4210_pin_ctrl[] = { | |||
| 553 | /* pin-controller instance 1 data */ | 549 | /* pin-controller instance 1 data */ |
| 554 | .pin_banks = exynos4210_pin_banks1, | 550 | .pin_banks = exynos4210_pin_banks1, |
| 555 | .nr_banks = ARRAY_SIZE(exynos4210_pin_banks1), | 551 | .nr_banks = ARRAY_SIZE(exynos4210_pin_banks1), |
| 556 | .base = EXYNOS4210_GPIOA_NR_PINS, | ||
| 557 | .nr_pins = EXYNOS4210_GPIOB_NR_PINS, | ||
| 558 | .nr_gint = EXYNOS4210_GPIOB_NR_GINT, | ||
| 559 | .nr_wint = 32, | ||
| 560 | .geint_con = EXYNOS_GPIO_ECON_OFFSET, | 552 | .geint_con = EXYNOS_GPIO_ECON_OFFSET, |
| 561 | .geint_mask = EXYNOS_GPIO_EMASK_OFFSET, | 553 | .geint_mask = EXYNOS_GPIO_EMASK_OFFSET, |
| 562 | .geint_pend = EXYNOS_GPIO_EPEND_OFFSET, | 554 | .geint_pend = EXYNOS_GPIO_EPEND_OFFSET, |
| @@ -571,9 +563,116 @@ struct samsung_pin_ctrl exynos4210_pin_ctrl[] = { | |||
| 571 | /* pin-controller instance 2 data */ | 563 | /* pin-controller instance 2 data */ |
| 572 | .pin_banks = exynos4210_pin_banks2, | 564 | .pin_banks = exynos4210_pin_banks2, |
| 573 | .nr_banks = ARRAY_SIZE(exynos4210_pin_banks2), | 565 | .nr_banks = ARRAY_SIZE(exynos4210_pin_banks2), |
| 574 | .base = EXYNOS4210_GPIOA_NR_PINS + | ||
| 575 | EXYNOS4210_GPIOB_NR_PINS, | ||
| 576 | .nr_pins = EXYNOS4210_GPIOC_NR_PINS, | ||
| 577 | .label = "exynos4210-gpio-ctrl2", | 566 | .label = "exynos4210-gpio-ctrl2", |
| 578 | }, | 567 | }, |
| 579 | }; | 568 | }; |
| 569 | |||
| 570 | /* pin banks of exynos4x12 pin-controller 0 */ | ||
| 571 | static struct samsung_pin_bank exynos4x12_pin_banks0[] = { | ||
| 572 | EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpa0", 0x00), | ||
| 573 | EXYNOS_PIN_BANK_EINTG(6, 0x020, "gpa1", 0x04), | ||
| 574 | EXYNOS_PIN_BANK_EINTG(8, 0x040, "gpb", 0x08), | ||
| 575 | EXYNOS_PIN_BANK_EINTG(5, 0x060, "gpc0", 0x0c), | ||
| 576 | EXYNOS_PIN_BANK_EINTG(5, 0x080, "gpc1", 0x10), | ||
| 577 | EXYNOS_PIN_BANK_EINTG(4, 0x0A0, "gpd0", 0x14), | ||
| 578 | EXYNOS_PIN_BANK_EINTG(4, 0x0C0, "gpd1", 0x18), | ||
| 579 | EXYNOS_PIN_BANK_EINTG(8, 0x180, "gpf0", 0x30), | ||
| 580 | EXYNOS_PIN_BANK_EINTG(8, 0x1A0, "gpf1", 0x34), | ||
| 581 | EXYNOS_PIN_BANK_EINTG(8, 0x1C0, "gpf2", 0x38), | ||
| 582 | EXYNOS_PIN_BANK_EINTG(6, 0x1E0, "gpf3", 0x3c), | ||
| 583 | EXYNOS_PIN_BANK_EINTG(8, 0x240, "gpj0", 0x40), | ||
| 584 | EXYNOS_PIN_BANK_EINTG(5, 0x260, "gpj1", 0x44), | ||
| 585 | }; | ||
| 586 | |||
| 587 | /* pin banks of exynos4x12 pin-controller 1 */ | ||
| 588 | static struct samsung_pin_bank exynos4x12_pin_banks1[] = { | ||
| 589 | EXYNOS_PIN_BANK_EINTG(7, 0x040, "gpk0", 0x08), | ||
| 590 | EXYNOS_PIN_BANK_EINTG(7, 0x060, "gpk1", 0x0c), | ||
| 591 | EXYNOS_PIN_BANK_EINTG(7, 0x080, "gpk2", 0x10), | ||
| 592 | EXYNOS_PIN_BANK_EINTG(7, 0x0A0, "gpk3", 0x14), | ||
| 593 | EXYNOS_PIN_BANK_EINTG(7, 0x0C0, "gpl0", 0x18), | ||
| 594 | EXYNOS_PIN_BANK_EINTG(2, 0x0E0, "gpl1", 0x1c), | ||
| 595 | EXYNOS_PIN_BANK_EINTG(8, 0x100, "gpl2", 0x20), | ||
| 596 | EXYNOS_PIN_BANK_EINTG(8, 0x260, "gpm0", 0x24), | ||
| 597 | EXYNOS_PIN_BANK_EINTG(7, 0x280, "gpm1", 0x28), | ||
| 598 | EXYNOS_PIN_BANK_EINTG(5, 0x2A0, "gpm2", 0x2c), | ||
| 599 | EXYNOS_PIN_BANK_EINTG(8, 0x2C0, "gpm3", 0x30), | ||
| 600 | EXYNOS_PIN_BANK_EINTG(8, 0x2E0, "gpm4", 0x34), | ||
| 601 | EXYNOS_PIN_BANK_EINTN(6, 0x120, "gpy0"), | ||
| 602 | EXYNOS_PIN_BANK_EINTN(4, 0x140, "gpy1"), | ||
| 603 | EXYNOS_PIN_BANK_EINTN(6, 0x160, "gpy2"), | ||
| 604 | EXYNOS_PIN_BANK_EINTN(8, 0x180, "gpy3"), | ||
| 605 | EXYNOS_PIN_BANK_EINTN(8, 0x1A0, "gpy4"), | ||
| 606 | EXYNOS_PIN_BANK_EINTN(8, 0x1C0, "gpy5"), | ||
| 607 | EXYNOS_PIN_BANK_EINTN(8, 0x1E0, "gpy6"), | ||
| 608 | EXYNOS_PIN_BANK_EINTW(8, 0xC00, "gpx0", 0x00), | ||
| 609 | EXYNOS_PIN_BANK_EINTW(8, 0xC20, "gpx1", 0x04), | ||
| 610 | EXYNOS_PIN_BANK_EINTW(8, 0xC40, "gpx2", 0x08), | ||
| 611 | EXYNOS_PIN_BANK_EINTW(8, 0xC60, "gpx3", 0x0c), | ||
| 612 | }; | ||
| 613 | |||
| 614 | /* pin banks of exynos4x12 pin-controller 2 */ | ||
| 615 | static struct samsung_pin_bank exynos4x12_pin_banks2[] = { | ||
| 616 | EXYNOS_PIN_BANK_EINTG(7, 0x000, "gpz", 0x00), | ||
| 617 | }; | ||
| 618 | |||
| 619 | /* pin banks of exynos4x12 pin-controller 3 */ | ||
| 620 | static struct samsung_pin_bank exynos4x12_pin_banks3[] = { | ||
| 621 | EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpv0", 0x00), | ||
| 622 | EXYNOS_PIN_BANK_EINTG(8, 0x020, "gpv1", 0x04), | ||
| 623 | EXYNOS_PIN_BANK_EINTG(8, 0x040, "gpv2", 0x08), | ||
| 624 | EXYNOS_PIN_BANK_EINTG(8, 0x060, "gpv3", 0x0c), | ||
| 625 | EXYNOS_PIN_BANK_EINTG(2, 0x080, "gpv4", 0x10), | ||
| 626 | }; | ||
| 627 | |||
| 628 | /* | ||
| 629 | * Samsung pinctrl driver data for Exynos4x12 SoC. Exynos4x12 SoC includes | ||
| 630 | * four gpio/pin-mux/pinconfig controllers. | ||
| 631 | */ | ||
| 632 | struct samsung_pin_ctrl exynos4x12_pin_ctrl[] = { | ||
| 633 | { | ||
| 634 | /* pin-controller instance 0 data */ | ||
| 635 | .pin_banks = exynos4x12_pin_banks0, | ||
| 636 | .nr_banks = ARRAY_SIZE(exynos4x12_pin_banks0), | ||
| 637 | .geint_con = EXYNOS_GPIO_ECON_OFFSET, | ||
| 638 | .geint_mask = EXYNOS_GPIO_EMASK_OFFSET, | ||
| 639 | .geint_pend = EXYNOS_GPIO_EPEND_OFFSET, | ||
| 640 | .svc = EXYNOS_SVC_OFFSET, | ||
| 641 | .eint_gpio_init = exynos_eint_gpio_init, | ||
| 642 | .label = "exynos4x12-gpio-ctrl0", | ||
| 643 | }, { | ||
| 644 | /* pin-controller instance 1 data */ | ||
| 645 | .pin_banks = exynos4x12_pin_banks1, | ||
| 646 | .nr_banks = ARRAY_SIZE(exynos4x12_pin_banks1), | ||
| 647 | .geint_con = EXYNOS_GPIO_ECON_OFFSET, | ||
| 648 | .geint_mask = EXYNOS_GPIO_EMASK_OFFSET, | ||
| 649 | .geint_pend = EXYNOS_GPIO_EPEND_OFFSET, | ||
| 650 | .weint_con = EXYNOS_WKUP_ECON_OFFSET, | ||
| 651 | .weint_mask = EXYNOS_WKUP_EMASK_OFFSET, | ||
| 652 | .weint_pend = EXYNOS_WKUP_EPEND_OFFSET, | ||
| 653 | .svc = EXYNOS_SVC_OFFSET, | ||
| 654 | .eint_gpio_init = exynos_eint_gpio_init, | ||
| 655 | .eint_wkup_init = exynos_eint_wkup_init, | ||
| 656 | .label = "exynos4x12-gpio-ctrl1", | ||
| 657 | }, { | ||
| 658 | /* pin-controller instance 2 data */ | ||
| 659 | .pin_banks = exynos4x12_pin_banks2, | ||
| 660 | .nr_banks = ARRAY_SIZE(exynos4x12_pin_banks2), | ||
| 661 | .geint_con = EXYNOS_GPIO_ECON_OFFSET, | ||
| 662 | .geint_mask = EXYNOS_GPIO_EMASK_OFFSET, | ||
| 663 | .geint_pend = EXYNOS_GPIO_EPEND_OFFSET, | ||
| 664 | .svc = EXYNOS_SVC_OFFSET, | ||
| 665 | .eint_gpio_init = exynos_eint_gpio_init, | ||
| 666 | .label = "exynos4x12-gpio-ctrl2", | ||
| 667 | }, { | ||
| 668 | /* pin-controller instance 3 data */ | ||
| 669 | .pin_banks = exynos4x12_pin_banks3, | ||
| 670 | .nr_banks = ARRAY_SIZE(exynos4x12_pin_banks3), | ||
| 671 | .geint_con = EXYNOS_GPIO_ECON_OFFSET, | ||
| 672 | .geint_mask = EXYNOS_GPIO_EMASK_OFFSET, | ||
| 673 | .geint_pend = EXYNOS_GPIO_EPEND_OFFSET, | ||
| 674 | .svc = EXYNOS_SVC_OFFSET, | ||
| 675 | .eint_gpio_init = exynos_eint_gpio_init, | ||
| 676 | .label = "exynos4x12-gpio-ctrl3", | ||
| 677 | }, | ||
| 678 | }; | ||
diff --git a/drivers/pinctrl/pinctrl-exynos.h b/drivers/pinctrl/pinctrl-exynos.h index 31d0a06174e4..0a708890d8b4 100644 --- a/drivers/pinctrl/pinctrl-exynos.h +++ b/drivers/pinctrl/pinctrl-exynos.h | |||
| @@ -17,125 +17,6 @@ | |||
| 17 | * (at your option) any later version. | 17 | * (at your option) any later version. |
| 18 | */ | 18 | */ |
| 19 | 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 | |||
| 60 | enum 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 | |||
| 79 | enum 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 | |||
| 102 | enum 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 */ | 20 | /* External GPIO and wakeup interrupt related definitions */ |
| 140 | #define EXYNOS_GPIO_ECON_OFFSET 0x700 | 21 | #define EXYNOS_GPIO_ECON_OFFSET 0x700 |
| 141 | #define EXYNOS_GPIO_EMASK_OFFSET 0x900 | 22 | #define EXYNOS_GPIO_EMASK_OFFSET 0x900 |
| @@ -165,11 +46,10 @@ enum exynos4210_gpio_xc_start { | |||
| 165 | #define EXYNOS_EINT_MAX_PER_BANK 8 | 46 | #define EXYNOS_EINT_MAX_PER_BANK 8 |
| 166 | #define EXYNOS_EINT_NR_WKUP_EINT | 47 | #define EXYNOS_EINT_NR_WKUP_EINT |
| 167 | 48 | ||
| 168 | #define EXYNOS_PIN_BANK_EINTN(reg, __gpio, id) \ | 49 | #define EXYNOS_PIN_BANK_EINTN(pins, reg, id) \ |
| 169 | { \ | 50 | { \ |
| 170 | .pctl_offset = reg, \ | 51 | .pctl_offset = reg, \ |
| 171 | .pin_base = (__gpio##_START), \ | 52 | .nr_pins = pins, \ |
| 172 | .nr_pins = (__gpio##_NR), \ | ||
| 173 | .func_width = 4, \ | 53 | .func_width = 4, \ |
| 174 | .pud_width = 2, \ | 54 | .pud_width = 2, \ |
| 175 | .drv_width = 2, \ | 55 | .drv_width = 2, \ |
| @@ -179,40 +59,50 @@ enum exynos4210_gpio_xc_start { | |||
| 179 | .name = id \ | 59 | .name = id \ |
| 180 | } | 60 | } |
| 181 | 61 | ||
| 182 | #define EXYNOS_PIN_BANK_EINTG(reg, __gpio, id) \ | 62 | #define EXYNOS_PIN_BANK_EINTG(pins, reg, id, offs) \ |
| 183 | { \ | 63 | { \ |
| 184 | .pctl_offset = reg, \ | 64 | .pctl_offset = reg, \ |
| 185 | .pin_base = (__gpio##_START), \ | 65 | .nr_pins = pins, \ |
| 186 | .nr_pins = (__gpio##_NR), \ | ||
| 187 | .func_width = 4, \ | 66 | .func_width = 4, \ |
| 188 | .pud_width = 2, \ | 67 | .pud_width = 2, \ |
| 189 | .drv_width = 2, \ | 68 | .drv_width = 2, \ |
| 190 | .conpdn_width = 2, \ | 69 | .conpdn_width = 2, \ |
| 191 | .pudpdn_width = 2, \ | 70 | .pudpdn_width = 2, \ |
| 192 | .eint_type = EINT_TYPE_GPIO, \ | 71 | .eint_type = EINT_TYPE_GPIO, \ |
| 193 | .irq_base = (__gpio##_IRQ), \ | 72 | .eint_offset = offs, \ |
| 194 | .name = id \ | 73 | .name = id \ |
| 195 | } | 74 | } |
| 196 | 75 | ||
| 197 | /** | 76 | #define EXYNOS_PIN_BANK_EINTW(pins, reg, id, offs) \ |
| 198 | * struct exynos_geint_data: gpio eint specific data for irq_chip callbacks. | 77 | { \ |
| 199 | * @bank: pin bank from which this gpio interrupt originates. | 78 | .pctl_offset = reg, \ |
| 200 | * @pin: pin number within the bank. | 79 | .nr_pins = pins, \ |
| 201 | * @eint_offset: offset to be added to the con/pend/mask register bank base. | 80 | .func_width = 4, \ |
| 202 | */ | 81 | .pud_width = 2, \ |
| 203 | struct exynos_geint_data { | 82 | .drv_width = 2, \ |
| 204 | struct samsung_pin_bank *bank; | 83 | .eint_type = EINT_TYPE_WKUP, \ |
| 205 | u32 pin; | 84 | .eint_offset = offs, \ |
| 206 | u32 eint_offset; | 85 | .name = id \ |
| 207 | }; | 86 | } |
| 208 | 87 | ||
| 209 | /** | 88 | /** |
| 210 | * struct exynos_weint_data: irq specific data for all the wakeup interrupts | 89 | * struct exynos_weint_data: irq specific data for all the wakeup interrupts |
| 211 | * generated by the external wakeup interrupt controller. | 90 | * generated by the external wakeup interrupt controller. |
| 212 | * @domain: irq domain representing the external wakeup interrupts | ||
| 213 | * @irq: interrupt number within the domain. | 91 | * @irq: interrupt number within the domain. |
| 92 | * @bank: bank responsible for this interrupt | ||
| 214 | */ | 93 | */ |
| 215 | struct exynos_weint_data { | 94 | struct exynos_weint_data { |
| 216 | struct irq_domain *domain; | 95 | unsigned int irq; |
| 217 | u32 irq; | 96 | struct samsung_pin_bank *bank; |
| 97 | }; | ||
| 98 | |||
| 99 | /** | ||
| 100 | * struct exynos_muxed_weint_data: irq specific data for muxed wakeup interrupts | ||
| 101 | * generated by the external wakeup interrupt controller. | ||
| 102 | * @nr_banks: count of banks being part of the mux | ||
| 103 | * @banks: array of banks being part of the mux | ||
| 104 | */ | ||
| 105 | struct exynos_muxed_weint_data { | ||
| 106 | unsigned int nr_banks; | ||
| 107 | struct samsung_pin_bank *banks[]; | ||
| 218 | }; | 108 | }; |
diff --git a/drivers/pinctrl/pinctrl-samsung.c b/drivers/pinctrl/pinctrl-samsung.c index 861cd5f04d5e..81c9896d4f64 100644 --- a/drivers/pinctrl/pinctrl-samsung.c +++ b/drivers/pinctrl/pinctrl-samsung.c | |||
| @@ -26,6 +26,7 @@ | |||
| 26 | #include <linux/slab.h> | 26 | #include <linux/slab.h> |
| 27 | #include <linux/err.h> | 27 | #include <linux/err.h> |
| 28 | #include <linux/gpio.h> | 28 | #include <linux/gpio.h> |
| 29 | #include <linux/irqdomain.h> | ||
| 29 | 30 | ||
| 30 | #include "core.h" | 31 | #include "core.h" |
| 31 | #include "pinctrl-samsung.h" | 32 | #include "pinctrl-samsung.h" |
| @@ -46,6 +47,13 @@ struct pin_config { | |||
| 46 | { "samsung,pin-pud-pdn", PINCFG_TYPE_PUD_PDN }, | 47 | { "samsung,pin-pud-pdn", PINCFG_TYPE_PUD_PDN }, |
| 47 | }; | 48 | }; |
| 48 | 49 | ||
| 50 | static unsigned int pin_base = 0; | ||
| 51 | |||
| 52 | static inline struct samsung_pin_bank *gc_to_pin_bank(struct gpio_chip *gc) | ||
| 53 | { | ||
| 54 | return container_of(gc, struct samsung_pin_bank, gpio_chip); | ||
| 55 | } | ||
| 56 | |||
| 49 | /* check if the selector is a valid pin group selector */ | 57 | /* check if the selector is a valid pin group selector */ |
| 50 | static int samsung_get_group_count(struct pinctrl_dev *pctldev) | 58 | static int samsung_get_group_count(struct pinctrl_dev *pctldev) |
| 51 | { | 59 | { |
| @@ -250,14 +258,12 @@ static int samsung_pinmux_get_groups(struct pinctrl_dev *pctldev, | |||
| 250 | * given a pin number that is local to a pin controller, find out the pin bank | 258 | * 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. | 259 | * and the register base of the pin bank. |
| 252 | */ | 260 | */ |
| 253 | static void pin_to_reg_bank(struct gpio_chip *gc, unsigned pin, | 261 | static void pin_to_reg_bank(struct samsung_pinctrl_drv_data *drvdata, |
| 254 | void __iomem **reg, u32 *offset, | 262 | unsigned pin, void __iomem **reg, u32 *offset, |
| 255 | struct samsung_pin_bank **bank) | 263 | struct samsung_pin_bank **bank) |
| 256 | { | 264 | { |
| 257 | struct samsung_pinctrl_drv_data *drvdata; | ||
| 258 | struct samsung_pin_bank *b; | 265 | struct samsung_pin_bank *b; |
| 259 | 266 | ||
| 260 | drvdata = dev_get_drvdata(gc->dev); | ||
| 261 | b = drvdata->ctrl->pin_banks; | 267 | b = drvdata->ctrl->pin_banks; |
| 262 | 268 | ||
| 263 | while ((pin >= b->pin_base) && | 269 | while ((pin >= b->pin_base) && |
| @@ -292,7 +298,7 @@ static void samsung_pinmux_setup(struct pinctrl_dev *pctldev, unsigned selector, | |||
| 292 | * pin function number in the config register. | 298 | * pin function number in the config register. |
| 293 | */ | 299 | */ |
| 294 | for (cnt = 0; cnt < drvdata->pin_groups[group].num_pins; cnt++) { | 300 | for (cnt = 0; cnt < drvdata->pin_groups[group].num_pins; cnt++) { |
| 295 | pin_to_reg_bank(drvdata->gc, pins[cnt] - drvdata->ctrl->base, | 301 | pin_to_reg_bank(drvdata, pins[cnt] - drvdata->ctrl->base, |
| 296 | ®, &pin_offset, &bank); | 302 | ®, &pin_offset, &bank); |
| 297 | mask = (1 << bank->func_width) - 1; | 303 | mask = (1 << bank->func_width) - 1; |
| 298 | shift = pin_offset * bank->func_width; | 304 | shift = pin_offset * bank->func_width; |
| @@ -329,10 +335,16 @@ static int samsung_pinmux_gpio_set_direction(struct pinctrl_dev *pctldev, | |||
| 329 | struct pinctrl_gpio_range *range, unsigned offset, bool input) | 335 | struct pinctrl_gpio_range *range, unsigned offset, bool input) |
| 330 | { | 336 | { |
| 331 | struct samsung_pin_bank *bank; | 337 | struct samsung_pin_bank *bank; |
| 338 | struct samsung_pinctrl_drv_data *drvdata; | ||
| 332 | void __iomem *reg; | 339 | void __iomem *reg; |
| 333 | u32 data, pin_offset, mask, shift; | 340 | u32 data, pin_offset, mask, shift; |
| 334 | 341 | ||
| 335 | pin_to_reg_bank(range->gc, offset, ®, &pin_offset, &bank); | 342 | bank = gc_to_pin_bank(range->gc); |
| 343 | drvdata = pinctrl_dev_get_drvdata(pctldev); | ||
| 344 | |||
| 345 | pin_offset = offset - bank->pin_base; | ||
| 346 | reg = drvdata->virt_base + bank->pctl_offset; | ||
| 347 | |||
| 336 | mask = (1 << bank->func_width) - 1; | 348 | mask = (1 << bank->func_width) - 1; |
| 337 | shift = pin_offset * bank->func_width; | 349 | shift = pin_offset * bank->func_width; |
| 338 | 350 | ||
| @@ -366,7 +378,7 @@ static int samsung_pinconf_rw(struct pinctrl_dev *pctldev, unsigned int pin, | |||
| 366 | u32 cfg_value, cfg_reg; | 378 | u32 cfg_value, cfg_reg; |
| 367 | 379 | ||
| 368 | drvdata = pinctrl_dev_get_drvdata(pctldev); | 380 | drvdata = pinctrl_dev_get_drvdata(pctldev); |
| 369 | pin_to_reg_bank(drvdata->gc, pin - drvdata->ctrl->base, ®_base, | 381 | pin_to_reg_bank(drvdata, pin - drvdata->ctrl->base, ®_base, |
| 370 | &pin_offset, &bank); | 382 | &pin_offset, &bank); |
| 371 | 383 | ||
| 372 | switch (cfg_type) { | 384 | switch (cfg_type) { |
| @@ -391,6 +403,9 @@ static int samsung_pinconf_rw(struct pinctrl_dev *pctldev, unsigned int pin, | |||
| 391 | return -EINVAL; | 403 | return -EINVAL; |
| 392 | } | 404 | } |
| 393 | 405 | ||
| 406 | if (!width) | ||
| 407 | return -EINVAL; | ||
| 408 | |||
| 394 | mask = (1 << width) - 1; | 409 | mask = (1 << width) - 1; |
| 395 | shift = pin_offset * width; | 410 | shift = pin_offset * width; |
| 396 | data = readl(reg_base + cfg_reg); | 411 | data = readl(reg_base + cfg_reg); |
| @@ -463,14 +478,16 @@ static struct pinconf_ops samsung_pinconf_ops = { | |||
| 463 | /* gpiolib gpio_set callback function */ | 478 | /* gpiolib gpio_set callback function */ |
| 464 | static void samsung_gpio_set(struct gpio_chip *gc, unsigned offset, int value) | 479 | static void samsung_gpio_set(struct gpio_chip *gc, unsigned offset, int value) |
| 465 | { | 480 | { |
| 481 | struct samsung_pin_bank *bank = gc_to_pin_bank(gc); | ||
| 466 | void __iomem *reg; | 482 | void __iomem *reg; |
| 467 | u32 pin_offset, data; | 483 | u32 data; |
| 484 | |||
| 485 | reg = bank->drvdata->virt_base + bank->pctl_offset; | ||
| 468 | 486 | ||
| 469 | pin_to_reg_bank(gc, offset, ®, &pin_offset, NULL); | ||
| 470 | data = readl(reg + DAT_REG); | 487 | data = readl(reg + DAT_REG); |
| 471 | data &= ~(1 << pin_offset); | 488 | data &= ~(1 << offset); |
| 472 | if (value) | 489 | if (value) |
| 473 | data |= 1 << pin_offset; | 490 | data |= 1 << offset; |
| 474 | writel(data, reg + DAT_REG); | 491 | writel(data, reg + DAT_REG); |
| 475 | } | 492 | } |
| 476 | 493 | ||
| @@ -478,11 +495,13 @@ static void samsung_gpio_set(struct gpio_chip *gc, unsigned offset, int value) | |||
| 478 | static int samsung_gpio_get(struct gpio_chip *gc, unsigned offset) | 495 | static int samsung_gpio_get(struct gpio_chip *gc, unsigned offset) |
| 479 | { | 496 | { |
| 480 | void __iomem *reg; | 497 | void __iomem *reg; |
| 481 | u32 pin_offset, data; | 498 | u32 data; |
| 499 | struct samsung_pin_bank *bank = gc_to_pin_bank(gc); | ||
| 500 | |||
| 501 | reg = bank->drvdata->virt_base + bank->pctl_offset; | ||
| 482 | 502 | ||
| 483 | pin_to_reg_bank(gc, offset, ®, &pin_offset, NULL); | ||
| 484 | data = readl(reg + DAT_REG); | 503 | data = readl(reg + DAT_REG); |
| 485 | data >>= pin_offset; | 504 | data >>= offset; |
| 486 | data &= 1; | 505 | data &= 1; |
| 487 | return data; | 506 | return data; |
| 488 | } | 507 | } |
| @@ -510,6 +529,23 @@ static int samsung_gpio_direction_output(struct gpio_chip *gc, unsigned offset, | |||
| 510 | } | 529 | } |
| 511 | 530 | ||
| 512 | /* | 531 | /* |
| 532 | * gpiolib gpio_to_irq callback function. Creates a mapping between a GPIO pin | ||
| 533 | * and a virtual IRQ, if not already present. | ||
| 534 | */ | ||
| 535 | static int samsung_gpio_to_irq(struct gpio_chip *gc, unsigned offset) | ||
| 536 | { | ||
| 537 | struct samsung_pin_bank *bank = gc_to_pin_bank(gc); | ||
| 538 | unsigned int virq; | ||
| 539 | |||
| 540 | if (!bank->irq_domain) | ||
| 541 | return -ENXIO; | ||
| 542 | |||
| 543 | virq = irq_create_mapping(bank->irq_domain, offset); | ||
| 544 | |||
| 545 | return (virq) ? : -ENXIO; | ||
| 546 | } | ||
| 547 | |||
| 548 | /* | ||
| 513 | * Parse the pin names listed in the 'samsung,pins' property and convert it | 549 | * 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. | 550 | * into a list of gpio numbers are create a pin group from it. |
| 515 | */ | 551 | */ |
| @@ -597,7 +633,7 @@ static int __devinit samsung_pinctrl_parse_dt(struct platform_device *pdev, | |||
| 597 | */ | 633 | */ |
| 598 | for_each_child_of_node(dev_np, cfg_np) { | 634 | for_each_child_of_node(dev_np, cfg_np) { |
| 599 | u32 function; | 635 | u32 function; |
| 600 | if (of_find_property(cfg_np, "interrupt-controller", NULL)) | 636 | if (!of_find_property(cfg_np, "samsung,pins", NULL)) |
| 601 | continue; | 637 | continue; |
| 602 | 638 | ||
| 603 | ret = samsung_pinctrl_parse_dt_pins(pdev, cfg_np, | 639 | ret = samsung_pinctrl_parse_dt_pins(pdev, cfg_np, |
| @@ -712,12 +748,16 @@ static int __devinit samsung_pinctrl_register(struct platform_device *pdev, | |||
| 712 | return -EINVAL; | 748 | return -EINVAL; |
| 713 | } | 749 | } |
| 714 | 750 | ||
| 715 | drvdata->grange.name = "samsung-pctrl-gpio-range"; | 751 | for (bank = 0; bank < drvdata->ctrl->nr_banks; ++bank) { |
| 716 | drvdata->grange.id = 0; | 752 | pin_bank = &drvdata->ctrl->pin_banks[bank]; |
| 717 | drvdata->grange.base = drvdata->ctrl->base; | 753 | pin_bank->grange.name = pin_bank->name; |
| 718 | drvdata->grange.npins = drvdata->ctrl->nr_pins; | 754 | pin_bank->grange.id = bank; |
| 719 | drvdata->grange.gc = drvdata->gc; | 755 | pin_bank->grange.pin_base = pin_bank->pin_base; |
| 720 | pinctrl_add_gpio_range(drvdata->pctl_dev, &drvdata->grange); | 756 | pin_bank->grange.base = pin_bank->gpio_chip.base; |
| 757 | pin_bank->grange.npins = pin_bank->gpio_chip.ngpio; | ||
| 758 | pin_bank->grange.gc = &pin_bank->gpio_chip; | ||
| 759 | pinctrl_add_gpio_range(drvdata->pctl_dev, &pin_bank->grange); | ||
| 760 | } | ||
| 721 | 761 | ||
| 722 | ret = samsung_pinctrl_parse_dt(pdev, drvdata); | 762 | ret = samsung_pinctrl_parse_dt(pdev, drvdata); |
| 723 | if (ret) { | 763 | if (ret) { |
| @@ -728,68 +768,117 @@ static int __devinit samsung_pinctrl_register(struct platform_device *pdev, | |||
| 728 | return 0; | 768 | return 0; |
| 729 | } | 769 | } |
| 730 | 770 | ||
| 771 | static const struct gpio_chip samsung_gpiolib_chip = { | ||
| 772 | .set = samsung_gpio_set, | ||
| 773 | .get = samsung_gpio_get, | ||
| 774 | .direction_input = samsung_gpio_direction_input, | ||
| 775 | .direction_output = samsung_gpio_direction_output, | ||
| 776 | .to_irq = samsung_gpio_to_irq, | ||
| 777 | .owner = THIS_MODULE, | ||
| 778 | }; | ||
| 779 | |||
| 731 | /* register the gpiolib interface with the gpiolib subsystem */ | 780 | /* register the gpiolib interface with the gpiolib subsystem */ |
| 732 | static int __devinit samsung_gpiolib_register(struct platform_device *pdev, | 781 | static int __devinit samsung_gpiolib_register(struct platform_device *pdev, |
| 733 | struct samsung_pinctrl_drv_data *drvdata) | 782 | struct samsung_pinctrl_drv_data *drvdata) |
| 734 | { | 783 | { |
| 784 | struct samsung_pin_ctrl *ctrl = drvdata->ctrl; | ||
| 785 | struct samsung_pin_bank *bank = ctrl->pin_banks; | ||
| 735 | struct gpio_chip *gc; | 786 | struct gpio_chip *gc; |
| 736 | int ret; | 787 | int ret; |
| 737 | 788 | int i; | |
| 738 | gc = devm_kzalloc(&pdev->dev, sizeof(*gc), GFP_KERNEL); | 789 | |
| 739 | if (!gc) { | 790 | for (i = 0; i < ctrl->nr_banks; ++i, ++bank) { |
| 740 | dev_err(&pdev->dev, "mem alloc for gpio_chip failed\n"); | 791 | bank->gpio_chip = samsung_gpiolib_chip; |
| 741 | return -ENOMEM; | 792 | |
| 742 | } | 793 | gc = &bank->gpio_chip; |
| 743 | 794 | gc->base = ctrl->base + bank->pin_base; | |
| 744 | drvdata->gc = gc; | 795 | gc->ngpio = bank->nr_pins; |
| 745 | gc->base = drvdata->ctrl->base; | 796 | gc->dev = &pdev->dev; |
| 746 | gc->ngpio = drvdata->ctrl->nr_pins; | 797 | gc->of_node = bank->of_node; |
| 747 | gc->dev = &pdev->dev; | 798 | gc->label = bank->name; |
| 748 | gc->set = samsung_gpio_set; | 799 | |
| 749 | gc->get = samsung_gpio_get; | 800 | ret = gpiochip_add(gc); |
| 750 | gc->direction_input = samsung_gpio_direction_input; | 801 | if (ret) { |
| 751 | gc->direction_output = samsung_gpio_direction_output; | 802 | dev_err(&pdev->dev, "failed to register gpio_chip %s, error code: %d\n", |
| 752 | gc->label = drvdata->ctrl->label; | 803 | gc->label, ret); |
| 753 | gc->owner = THIS_MODULE; | 804 | goto fail; |
| 754 | ret = gpiochip_add(gc); | 805 | } |
| 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 | } | 806 | } |
| 760 | 807 | ||
| 761 | return 0; | 808 | return 0; |
| 809 | |||
| 810 | fail: | ||
| 811 | for (--i, --bank; i >= 0; --i, --bank) | ||
| 812 | if (gpiochip_remove(&bank->gpio_chip)) | ||
| 813 | dev_err(&pdev->dev, "gpio chip %s remove failed\n", | ||
| 814 | bank->gpio_chip.label); | ||
| 815 | return ret; | ||
| 762 | } | 816 | } |
| 763 | 817 | ||
| 764 | /* unregister the gpiolib interface with the gpiolib subsystem */ | 818 | /* unregister the gpiolib interface with the gpiolib subsystem */ |
| 765 | static int __devinit samsung_gpiolib_unregister(struct platform_device *pdev, | 819 | static int __devinit samsung_gpiolib_unregister(struct platform_device *pdev, |
| 766 | struct samsung_pinctrl_drv_data *drvdata) | 820 | struct samsung_pinctrl_drv_data *drvdata) |
| 767 | { | 821 | { |
| 768 | int ret = gpiochip_remove(drvdata->gc); | 822 | struct samsung_pin_ctrl *ctrl = drvdata->ctrl; |
| 769 | if (ret) { | 823 | struct samsung_pin_bank *bank = ctrl->pin_banks; |
| 824 | int ret = 0; | ||
| 825 | int i; | ||
| 826 | |||
| 827 | for (i = 0; !ret && i < ctrl->nr_banks; ++i, ++bank) | ||
| 828 | ret = gpiochip_remove(&bank->gpio_chip); | ||
| 829 | |||
| 830 | if (ret) | ||
| 770 | dev_err(&pdev->dev, "gpio chip remove failed\n"); | 831 | dev_err(&pdev->dev, "gpio chip remove failed\n"); |
| 771 | return ret; | 832 | |
| 772 | } | 833 | return ret; |
| 773 | return 0; | ||
| 774 | } | 834 | } |
| 775 | 835 | ||
| 776 | static const struct of_device_id samsung_pinctrl_dt_match[]; | 836 | static const struct of_device_id samsung_pinctrl_dt_match[]; |
| 777 | 837 | ||
| 778 | /* retrieve the soc specific data */ | 838 | /* retrieve the soc specific data */ |
| 779 | static struct samsung_pin_ctrl *samsung_pinctrl_get_soc_data( | 839 | static struct samsung_pin_ctrl *samsung_pinctrl_get_soc_data( |
| 840 | struct samsung_pinctrl_drv_data *d, | ||
| 780 | struct platform_device *pdev) | 841 | struct platform_device *pdev) |
| 781 | { | 842 | { |
| 782 | int id; | 843 | int id; |
| 783 | const struct of_device_id *match; | 844 | const struct of_device_id *match; |
| 784 | const struct device_node *node = pdev->dev.of_node; | 845 | struct device_node *node = pdev->dev.of_node; |
| 846 | struct device_node *np; | ||
| 847 | struct samsung_pin_ctrl *ctrl; | ||
| 848 | struct samsung_pin_bank *bank; | ||
| 849 | int i; | ||
| 785 | 850 | ||
| 786 | id = of_alias_get_id(pdev->dev.of_node, "pinctrl"); | 851 | id = of_alias_get_id(node, "pinctrl"); |
| 787 | if (id < 0) { | 852 | if (id < 0) { |
| 788 | dev_err(&pdev->dev, "failed to get alias id\n"); | 853 | dev_err(&pdev->dev, "failed to get alias id\n"); |
| 789 | return NULL; | 854 | return NULL; |
| 790 | } | 855 | } |
| 791 | match = of_match_node(samsung_pinctrl_dt_match, node); | 856 | match = of_match_node(samsung_pinctrl_dt_match, node); |
| 792 | return (struct samsung_pin_ctrl *)match->data + id; | 857 | ctrl = (struct samsung_pin_ctrl *)match->data + id; |
| 858 | |||
| 859 | bank = ctrl->pin_banks; | ||
| 860 | for (i = 0; i < ctrl->nr_banks; ++i, ++bank) { | ||
| 861 | bank->drvdata = d; | ||
| 862 | bank->pin_base = ctrl->nr_pins; | ||
| 863 | ctrl->nr_pins += bank->nr_pins; | ||
| 864 | } | ||
| 865 | |||
| 866 | for_each_child_of_node(node, np) { | ||
| 867 | if (!of_find_property(np, "gpio-controller", NULL)) | ||
| 868 | continue; | ||
| 869 | bank = ctrl->pin_banks; | ||
| 870 | for (i = 0; i < ctrl->nr_banks; ++i, ++bank) { | ||
| 871 | if (!strcmp(bank->name, np->name)) { | ||
| 872 | bank->of_node = np; | ||
| 873 | break; | ||
| 874 | } | ||
| 875 | } | ||
| 876 | } | ||
| 877 | |||
| 878 | ctrl->base = pin_base; | ||
| 879 | pin_base += ctrl->nr_pins; | ||
| 880 | |||
| 881 | return ctrl; | ||
| 793 | } | 882 | } |
| 794 | 883 | ||
| 795 | static int __devinit samsung_pinctrl_probe(struct platform_device *pdev) | 884 | static int __devinit samsung_pinctrl_probe(struct platform_device *pdev) |
| @@ -805,18 +894,18 @@ static int __devinit samsung_pinctrl_probe(struct platform_device *pdev) | |||
| 805 | return -ENODEV; | 894 | return -ENODEV; |
| 806 | } | 895 | } |
| 807 | 896 | ||
| 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); | 897 | drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL); |
| 815 | if (!drvdata) { | 898 | if (!drvdata) { |
| 816 | dev_err(dev, "failed to allocate memory for driver's " | 899 | dev_err(dev, "failed to allocate memory for driver's " |
| 817 | "private data\n"); | 900 | "private data\n"); |
| 818 | return -ENOMEM; | 901 | return -ENOMEM; |
| 819 | } | 902 | } |
| 903 | |||
| 904 | ctrl = samsung_pinctrl_get_soc_data(drvdata, pdev); | ||
| 905 | if (!ctrl) { | ||
| 906 | dev_err(&pdev->dev, "driver data not available\n"); | ||
| 907 | return -EINVAL; | ||
| 908 | } | ||
| 820 | drvdata->ctrl = ctrl; | 909 | drvdata->ctrl = ctrl; |
| 821 | drvdata->dev = dev; | 910 | drvdata->dev = dev; |
| 822 | 911 | ||
| @@ -858,6 +947,8 @@ static int __devinit samsung_pinctrl_probe(struct platform_device *pdev) | |||
| 858 | static const struct of_device_id samsung_pinctrl_dt_match[] = { | 947 | static const struct of_device_id samsung_pinctrl_dt_match[] = { |
| 859 | { .compatible = "samsung,pinctrl-exynos4210", | 948 | { .compatible = "samsung,pinctrl-exynos4210", |
| 860 | .data = (void *)exynos4210_pin_ctrl }, | 949 | .data = (void *)exynos4210_pin_ctrl }, |
| 950 | { .compatible = "samsung,pinctrl-exynos4x12", | ||
| 951 | .data = (void *)exynos4x12_pin_ctrl }, | ||
| 861 | {}, | 952 | {}, |
| 862 | }; | 953 | }; |
| 863 | MODULE_DEVICE_TABLE(of, samsung_pinctrl_dt_match); | 954 | MODULE_DEVICE_TABLE(of, samsung_pinctrl_dt_match); |
diff --git a/drivers/pinctrl/pinctrl-samsung.h b/drivers/pinctrl/pinctrl-samsung.h index b8956934cda6..5addfd16e3cc 100644 --- a/drivers/pinctrl/pinctrl-samsung.h +++ b/drivers/pinctrl/pinctrl-samsung.h | |||
| @@ -23,6 +23,8 @@ | |||
| 23 | #include <linux/pinctrl/consumer.h> | 23 | #include <linux/pinctrl/consumer.h> |
| 24 | #include <linux/pinctrl/machine.h> | 24 | #include <linux/pinctrl/machine.h> |
| 25 | 25 | ||
| 26 | #include <linux/gpio.h> | ||
| 27 | |||
| 26 | /* register offsets within a pin bank */ | 28 | /* register offsets within a pin bank */ |
| 27 | #define DAT_REG 0x4 | 29 | #define DAT_REG 0x4 |
| 28 | #define PUD_REG 0x8 | 30 | #define PUD_REG 0x8 |
| @@ -64,6 +66,7 @@ enum pincfg_type { | |||
| 64 | * @EINT_TYPE_NONE: bank does not support external interrupts | 66 | * @EINT_TYPE_NONE: bank does not support external interrupts |
| 65 | * @EINT_TYPE_GPIO: bank supportes external gpio interrupts | 67 | * @EINT_TYPE_GPIO: bank supportes external gpio interrupts |
| 66 | * @EINT_TYPE_WKUP: bank supportes external wakeup interrupts | 68 | * @EINT_TYPE_WKUP: bank supportes external wakeup interrupts |
| 69 | * @EINT_TYPE_WKUP_MUX: bank supports multiplexed external wakeup interrupts | ||
| 67 | * | 70 | * |
| 68 | * Samsung GPIO controller groups all the available pins into banks. The pins | 71 | * 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 | 72 | * in a pin bank can support external gpio interrupts or external wakeup |
| @@ -76,6 +79,7 @@ enum eint_type { | |||
| 76 | EINT_TYPE_NONE, | 79 | EINT_TYPE_NONE, |
| 77 | EINT_TYPE_GPIO, | 80 | EINT_TYPE_GPIO, |
| 78 | EINT_TYPE_WKUP, | 81 | EINT_TYPE_WKUP, |
| 82 | EINT_TYPE_WKUP_MUX, | ||
| 79 | }; | 83 | }; |
| 80 | 84 | ||
| 81 | /* maximum length of a pin in pin descriptor (example: "gpa0-0") */ | 85 | /* maximum length of a pin in pin descriptor (example: "gpa0-0") */ |
| @@ -109,8 +113,12 @@ struct samsung_pinctrl_drv_data; | |||
| 109 | * @conpdn_width: width of the sleep mode function selector bin field. | 113 | * @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. | 114 | * @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. | 115 | * @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. | 116 | * @name: name to be prefixed for each pin in this pin bank. |
| 117 | * @of_node: OF node of the bank. | ||
| 118 | * @drvdata: link to controller driver data | ||
| 119 | * @irq_domain: IRQ domain of the bank. | ||
| 120 | * @gpio_chip: GPIO chip of the bank. | ||
| 121 | * @grange: linux gpio pin range supported by this bank. | ||
| 114 | */ | 122 | */ |
| 115 | struct samsung_pin_bank { | 123 | struct samsung_pin_bank { |
| 116 | u32 pctl_offset; | 124 | u32 pctl_offset; |
| @@ -122,8 +130,13 @@ struct samsung_pin_bank { | |||
| 122 | u8 conpdn_width; | 130 | u8 conpdn_width; |
| 123 | u8 pudpdn_width; | 131 | u8 pudpdn_width; |
| 124 | enum eint_type eint_type; | 132 | enum eint_type eint_type; |
| 125 | u32 irq_base; | 133 | u32 eint_offset; |
| 126 | char *name; | 134 | char *name; |
| 135 | struct device_node *of_node; | ||
| 136 | struct samsung_pinctrl_drv_data *drvdata; | ||
| 137 | struct irq_domain *irq_domain; | ||
| 138 | struct gpio_chip gpio_chip; | ||
| 139 | struct pinctrl_gpio_range grange; | ||
| 127 | }; | 140 | }; |
| 128 | 141 | ||
| 129 | /** | 142 | /** |
| @@ -132,8 +145,6 @@ struct samsung_pin_bank { | |||
| 132 | * @nr_banks: number of pin banks. | 145 | * @nr_banks: number of pin banks. |
| 133 | * @base: starting system wide pin number. | 146 | * @base: starting system wide pin number. |
| 134 | * @nr_pins: number of pins supported by the controller. | 147 | * @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. | 148 | * @geint_con: offset of the ext-gpio controller registers. |
| 138 | * @geint_mask: offset of the ext-gpio interrupt mask registers. | 149 | * @geint_mask: offset of the ext-gpio interrupt mask registers. |
| 139 | * @geint_pend: offset of the ext-gpio interrupt pending registers. | 150 | * @geint_pend: offset of the ext-gpio interrupt pending registers. |
| @@ -153,8 +164,6 @@ struct samsung_pin_ctrl { | |||
| 153 | 164 | ||
| 154 | u32 base; | 165 | u32 base; |
| 155 | u32 nr_pins; | 166 | u32 nr_pins; |
| 156 | u32 nr_gint; | ||
| 157 | u32 nr_wint; | ||
| 158 | 167 | ||
| 159 | u32 geint_con; | 168 | u32 geint_con; |
| 160 | u32 geint_mask; | 169 | u32 geint_mask; |
| @@ -183,8 +192,6 @@ struct samsung_pin_ctrl { | |||
| 183 | * @nr_groups: number of such pin groups. | 192 | * @nr_groups: number of such pin groups. |
| 184 | * @pmx_functions: list of pin functions available to the driver. | 193 | * @pmx_functions: list of pin functions available to the driver. |
| 185 | * @nr_function: number of such pin functions. | 194 | * @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 | */ | 195 | */ |
| 189 | struct samsung_pinctrl_drv_data { | 196 | struct samsung_pinctrl_drv_data { |
| 190 | void __iomem *virt_base; | 197 | void __iomem *virt_base; |
| @@ -199,12 +206,6 @@ struct samsung_pinctrl_drv_data { | |||
| 199 | unsigned int nr_groups; | 206 | unsigned int nr_groups; |
| 200 | const struct samsung_pmx_func *pmx_functions; | 207 | const struct samsung_pmx_func *pmx_functions; |
| 201 | unsigned int nr_functions; | 208 | 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 | }; |
| 209 | 210 | ||
| 210 | /** | 211 | /** |
| @@ -235,5 +236,6 @@ struct samsung_pmx_func { | |||
| 235 | 236 | ||
| 236 | /* list of all exported SoC specific data */ | 237 | /* list of all exported SoC specific data */ |
| 237 | extern struct samsung_pin_ctrl exynos4210_pin_ctrl[]; | 238 | extern struct samsung_pin_ctrl exynos4210_pin_ctrl[]; |
| 239 | extern struct samsung_pin_ctrl exynos4x12_pin_ctrl[]; | ||
| 238 | 240 | ||
| 239 | #endif /* __PINCTRL_SAMSUNG_H */ | 241 | #endif /* __PINCTRL_SAMSUNG_H */ |
