diff options
-rw-r--r-- | Documentation/devicetree/bindings/pinctrl/pinctrl-single.txt | 41 | ||||
-rw-r--r-- | drivers/pinctrl/pinctrl-single.c | 46 |
2 files changed, 74 insertions, 13 deletions
diff --git a/Documentation/devicetree/bindings/pinctrl/pinctrl-single.txt b/Documentation/devicetree/bindings/pinctrl/pinctrl-single.txt index 5187f0dd8b28..2c81e45f1374 100644 --- a/Documentation/devicetree/bindings/pinctrl/pinctrl-single.txt +++ b/Documentation/devicetree/bindings/pinctrl/pinctrl-single.txt | |||
@@ -14,10 +14,12 @@ Optional properties: | |||
14 | - pinctrl-single,function-off : function off mode for disabled state if | 14 | - pinctrl-single,function-off : function off mode for disabled state if |
15 | available and same for all registers; if not specified, disabling of | 15 | available and same for all registers; if not specified, disabling of |
16 | pin functions is ignored | 16 | pin functions is ignored |
17 | - pinctrl-single,bit-per-mux : boolean to indicate that one register controls | ||
18 | more than one pin | ||
17 | 19 | ||
18 | This driver assumes that there is only one register for each pin, | 20 | This driver assumes that there is only one register for each pin (unless the |
19 | and uses the common pinctrl bindings as specified in the pinctrl-bindings.txt | 21 | pinctrl-single,bit-per-mux is set), and uses the common pinctrl bindings as |
20 | document in this directory. | 22 | specified in the pinctrl-bindings.txt document in this directory. |
21 | 23 | ||
22 | The pin configuration nodes for pinctrl-single are specified as pinctrl | 24 | The pin configuration nodes for pinctrl-single are specified as pinctrl |
23 | register offset and value pairs using pinctrl-single,pins. Only the bits | 25 | register offset and value pairs using pinctrl-single,pins. Only the bits |
@@ -31,6 +33,15 @@ device pinctrl register, and 0x118 contains the desired value of the | |||
31 | pinctrl register. See the device example and static board pins example | 33 | pinctrl register. See the device example and static board pins example |
32 | below for more information. | 34 | below for more information. |
33 | 35 | ||
36 | In case when one register changes more than one pin's mux the | ||
37 | pinctrl-single,bits need to be used which takes three parameters: | ||
38 | |||
39 | pinctrl-single,bits = <0xdc 0x18, 0xff>; | ||
40 | |||
41 | Where 0xdc is the offset from the pinctrl register base address for the | ||
42 | device pinctrl register, 0x18 is the desired value, and 0xff is the sub mask to | ||
43 | be used when applying this change to the register. | ||
44 | |||
34 | Example: | 45 | Example: |
35 | 46 | ||
36 | /* SoC common file */ | 47 | /* SoC common file */ |
@@ -55,6 +66,15 @@ pmx_wkup: pinmux@4a31e040 { | |||
55 | pinctrl-single,function-mask = <0xffff>; | 66 | pinctrl-single,function-mask = <0xffff>; |
56 | }; | 67 | }; |
57 | 68 | ||
69 | control_devconf0: pinmux@48002274 { | ||
70 | compatible = "pinctrl-single"; | ||
71 | reg = <0x48002274 4>; /* Single register */ | ||
72 | #address-cells = <1>; | ||
73 | #size-cells = <0>; | ||
74 | pinctrl-single,bit-per-mux; | ||
75 | pinctrl-single,register-width = <32>; | ||
76 | pinctrl-single,function-mask = <0x5F>; | ||
77 | }; | ||
58 | 78 | ||
59 | /* board specific .dts file */ | 79 | /* board specific .dts file */ |
60 | 80 | ||
@@ -87,6 +107,21 @@ pmx_wkup: pinmux@4a31e040 { | |||
87 | }; | 107 | }; |
88 | }; | 108 | }; |
89 | 109 | ||
110 | &control_devconf0 { | ||
111 | mcbsp1_pins: pinmux_mcbsp1_pins { | ||
112 | pinctrl-single,bits = < | ||
113 | 0x00 0x18 0x18 /* FSR/CLKR signal from FSX/CLKX pin */ | ||
114 | >; | ||
115 | }; | ||
116 | |||
117 | mcbsp2_clks_pins: pinmux_mcbsp2_clks_pins { | ||
118 | pinctrl-single,bits = < | ||
119 | 0x00 0x40 0x40 /* McBSP2 CLKS from McBSP_CLKS pin */ | ||
120 | >; | ||
121 | }; | ||
122 | |||
123 | }; | ||
124 | |||
90 | &uart2 { | 125 | &uart2 { |
91 | pinctrl-names = "default"; | 126 | pinctrl-names = "default"; |
92 | pinctrl-0 = <&uart2_pins>; | 127 | pinctrl-0 = <&uart2_pins>; |
diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c index 35086310b81d..aabecfa507b4 100644 --- a/drivers/pinctrl/pinctrl-single.c +++ b/drivers/pinctrl/pinctrl-single.c | |||
@@ -26,7 +26,8 @@ | |||
26 | #include "core.h" | 26 | #include "core.h" |
27 | 27 | ||
28 | #define DRIVER_NAME "pinctrl-single" | 28 | #define DRIVER_NAME "pinctrl-single" |
29 | #define PCS_MUX_NAME "pinctrl-single,pins" | 29 | #define PCS_MUX_PINS_NAME "pinctrl-single,pins" |
30 | #define PCS_MUX_BITS_NAME "pinctrl-single,bits" | ||
30 | #define PCS_REG_NAME_LEN ((sizeof(unsigned long) * 2) + 1) | 31 | #define PCS_REG_NAME_LEN ((sizeof(unsigned long) * 2) + 1) |
31 | #define PCS_OFF_DISABLED ~0U | 32 | #define PCS_OFF_DISABLED ~0U |
32 | 33 | ||
@@ -54,6 +55,7 @@ struct pcs_pingroup { | |||
54 | struct pcs_func_vals { | 55 | struct pcs_func_vals { |
55 | void __iomem *reg; | 56 | void __iomem *reg; |
56 | unsigned val; | 57 | unsigned val; |
58 | unsigned mask; | ||
57 | }; | 59 | }; |
58 | 60 | ||
59 | /** | 61 | /** |
@@ -139,6 +141,7 @@ struct pcs_device { | |||
139 | unsigned fshift; | 141 | unsigned fshift; |
140 | unsigned foff; | 142 | unsigned foff; |
141 | unsigned fmax; | 143 | unsigned fmax; |
144 | bool bits_per_mux; | ||
142 | struct pcs_name *names; | 145 | struct pcs_name *names; |
143 | struct pcs_data pins; | 146 | struct pcs_data pins; |
144 | struct radix_tree_root pgtree; | 147 | struct radix_tree_root pgtree; |
@@ -332,12 +335,17 @@ static int pcs_enable(struct pinctrl_dev *pctldev, unsigned fselector, | |||
332 | 335 | ||
333 | for (i = 0; i < func->nvals; i++) { | 336 | for (i = 0; i < func->nvals; i++) { |
334 | struct pcs_func_vals *vals; | 337 | struct pcs_func_vals *vals; |
335 | unsigned val; | 338 | unsigned val, mask; |
336 | 339 | ||
337 | vals = &func->vals[i]; | 340 | vals = &func->vals[i]; |
338 | val = pcs->read(vals->reg); | 341 | val = pcs->read(vals->reg); |
339 | val &= ~pcs->fmask; | 342 | if (!vals->mask) |
340 | val |= (vals->val & pcs->fmask); | 343 | mask = pcs->fmask; |
344 | else | ||
345 | mask = pcs->fmask & vals->mask; | ||
346 | |||
347 | val &= ~mask; | ||
348 | val |= (vals->val & mask); | ||
341 | pcs->write(val, vals->reg); | 349 | pcs->write(val, vals->reg); |
342 | } | 350 | } |
343 | 351 | ||
@@ -657,18 +665,29 @@ static int pcs_parse_one_pinctrl_entry(struct pcs_device *pcs, | |||
657 | { | 665 | { |
658 | struct pcs_func_vals *vals; | 666 | struct pcs_func_vals *vals; |
659 | const __be32 *mux; | 667 | const __be32 *mux; |
660 | int size, rows, *pins, index = 0, found = 0, res = -ENOMEM; | 668 | int size, params, rows, *pins, index = 0, found = 0, res = -ENOMEM; |
661 | struct pcs_function *function; | 669 | struct pcs_function *function; |
662 | 670 | ||
663 | mux = of_get_property(np, PCS_MUX_NAME, &size); | 671 | if (pcs->bits_per_mux) { |
664 | if ((!mux) || (size < sizeof(*mux) * 2)) { | 672 | params = 3; |
665 | dev_err(pcs->dev, "bad data for mux %s\n", | 673 | mux = of_get_property(np, PCS_MUX_BITS_NAME, &size); |
666 | np->name); | 674 | } else { |
675 | params = 2; | ||
676 | mux = of_get_property(np, PCS_MUX_PINS_NAME, &size); | ||
677 | } | ||
678 | |||
679 | if (!mux) { | ||
680 | dev_err(pcs->dev, "no valid property for %s\n", np->name); | ||
681 | return -EINVAL; | ||
682 | } | ||
683 | |||
684 | if (size < (sizeof(*mux) * params)) { | ||
685 | dev_err(pcs->dev, "bad data for %s\n", np->name); | ||
667 | return -EINVAL; | 686 | return -EINVAL; |
668 | } | 687 | } |
669 | 688 | ||
670 | size /= sizeof(*mux); /* Number of elements in array */ | 689 | size /= sizeof(*mux); /* Number of elements in array */ |
671 | rows = size / 2; /* Each row is a key value pair */ | 690 | rows = size / params; |
672 | 691 | ||
673 | vals = devm_kzalloc(pcs->dev, sizeof(*vals) * rows, GFP_KERNEL); | 692 | vals = devm_kzalloc(pcs->dev, sizeof(*vals) * rows, GFP_KERNEL); |
674 | if (!vals) | 693 | if (!vals) |
@@ -686,6 +705,10 @@ static int pcs_parse_one_pinctrl_entry(struct pcs_device *pcs, | |||
686 | val = be32_to_cpup(mux + index++); | 705 | val = be32_to_cpup(mux + index++); |
687 | vals[found].reg = pcs->base + offset; | 706 | vals[found].reg = pcs->base + offset; |
688 | vals[found].val = val; | 707 | vals[found].val = val; |
708 | if (params == 3) { | ||
709 | val = be32_to_cpup(mux + index++); | ||
710 | vals[found].mask = val; | ||
711 | } | ||
689 | 712 | ||
690 | pin = pcs_get_pin_by_offset(pcs, offset); | 713 | pin = pcs_get_pin_by_offset(pcs, offset); |
691 | if (pin < 0) { | 714 | if (pin < 0) { |
@@ -883,6 +906,9 @@ static int __devinit pcs_probe(struct platform_device *pdev) | |||
883 | if (ret) | 906 | if (ret) |
884 | pcs->foff = PCS_OFF_DISABLED; | 907 | pcs->foff = PCS_OFF_DISABLED; |
885 | 908 | ||
909 | pcs->bits_per_mux = of_property_read_bool(np, | ||
910 | "pinctrl-single,bit-per-mux"); | ||
911 | |||
886 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 912 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
887 | if (!res) { | 913 | if (!res) { |
888 | dev_err(pcs->dev, "could not get resource\n"); | 914 | dev_err(pcs->dev, "could not get resource\n"); |