5fefece493e3fef040b3d1f4939a62df0a85a4ad
[openwrt/openwrt.git] / target / linux / gemini / patches-4.14 / 0011-pinctrl-gemini-Support-drive-strength-setting.patch
1 From f147cf49ef39f5e87d5df9ef1fab52683bc75c63 Mon Sep 17 00:00:00 2001
2 From: Linus Walleij <linus.walleij@linaro.org>
3 Date: Sat, 2 Dec 2017 12:23:09 +0100
4 Subject: [PATCH 11/31] pinctrl: gemini: Support drive strength setting
5
6 The Gemini pin controller can set drive strength for a few
7 select groups of pins (not individually). Implement this
8 for GMAC0 and 1 (ethernet ports), IDE and PCI.
9
10 Cc: devicetree@vger.kernel.org
11 Reviewed-by: Rob Herring <robh@kernel.org>
12 Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
13 ---
14 .../bindings/pinctrl/cortina,gemini-pinctrl.txt | 3 +
15 drivers/pinctrl/pinctrl-gemini.c | 81 ++++++++++++++++++++++
16 2 files changed, 84 insertions(+)
17
18 --- a/Documentation/devicetree/bindings/pinctrl/cortina,gemini-pinctrl.txt
19 +++ b/Documentation/devicetree/bindings/pinctrl/cortina,gemini-pinctrl.txt
20 @@ -17,6 +17,9 @@ and generic pin config nodes.
21
22 Supported configurations:
23 - skew-delay is supported on the Ethernet pins
24 +- drive-strength with 4, 8, 12 or 16 mA as argument is supported for
25 + entire groups on the groups "idegrp", "gmii_gmac0_grp", "gmii_gmac1_grp"
26 + and "pcigrp".
27
28 Example:
29
30 --- a/drivers/pinctrl/pinctrl-gemini.c
31 +++ b/drivers/pinctrl/pinctrl-gemini.c
32 @@ -67,6 +67,9 @@ struct gemini_pmx {
33 * elements in .pins so we can iterate over that array
34 * @mask: bits to clear to enable this when doing pin muxing
35 * @value: bits to set to enable this when doing pin muxing
36 + * @driving_mask: bitmask for the IO Pad driving register for this
37 + * group, if it supports altering the driving strength of
38 + * its lines.
39 */
40 struct gemini_pin_group {
41 const char *name;
42 @@ -74,12 +77,14 @@ struct gemini_pin_group {
43 const unsigned int num_pins;
44 u32 mask;
45 u32 value;
46 + u32 driving_mask;
47 };
48
49 /* Some straight-forward control registers */
50 #define GLOBAL_WORD_ID 0x00
51 #define GLOBAL_STATUS 0x04
52 #define GLOBAL_STATUS_FLPIN BIT(20)
53 +#define GLOBAL_IODRIVE 0x10
54 #define GLOBAL_GMAC_CTRL_SKEW 0x1c
55 #define GLOBAL_GMAC0_DATA_SKEW 0x20
56 #define GLOBAL_GMAC1_DATA_SKEW 0x24
57 @@ -738,6 +743,7 @@ static const struct gemini_pin_group gem
58 /* Conflict with all flash usage */
59 .value = IDE_PADS_ENABLE | NAND_PADS_DISABLE |
60 PFLASH_PADS_DISABLE | SFLASH_PADS_DISABLE,
61 + .driving_mask = GENMASK(21, 20),
62 },
63 {
64 .name = "satagrp",
65 @@ -753,6 +759,7 @@ static const struct gemini_pin_group gem
66 .name = "gmii_gmac0_grp",
67 .pins = gmii_gmac0_3512_pins,
68 .num_pins = ARRAY_SIZE(gmii_gmac0_3512_pins),
69 + .driving_mask = GENMASK(17, 16),
70 },
71 {
72 .name = "gmii_gmac1_grp",
73 @@ -760,6 +767,7 @@ static const struct gemini_pin_group gem
74 .num_pins = ARRAY_SIZE(gmii_gmac1_3512_pins),
75 /* Bring out RGMII on the GMAC1 pins */
76 .value = GEMINI_GMAC_IOSEL_GMAC0_GMAC1_RGMII,
77 + .driving_mask = GENMASK(19, 18),
78 },
79 {
80 .name = "pcigrp",
81 @@ -767,6 +775,7 @@ static const struct gemini_pin_group gem
82 .num_pins = ARRAY_SIZE(pci_3512_pins),
83 /* Conflict only with GPIO2 */
84 .value = PCI_PADS_ENABLE | PCI_CLK_PAD_ENABLE,
85 + .driving_mask = GENMASK(23, 22),
86 },
87 {
88 .name = "lpcgrp",
89 @@ -1671,6 +1680,7 @@ static const struct gemini_pin_group gem
90 /* Conflict with all flash usage */
91 .value = IDE_PADS_ENABLE | NAND_PADS_DISABLE |
92 PFLASH_PADS_DISABLE | SFLASH_PADS_DISABLE,
93 + .driving_mask = GENMASK(21, 20),
94 },
95 {
96 .name = "satagrp",
97 @@ -1686,6 +1696,7 @@ static const struct gemini_pin_group gem
98 .name = "gmii_gmac0_grp",
99 .pins = gmii_gmac0_3516_pins,
100 .num_pins = ARRAY_SIZE(gmii_gmac0_3516_pins),
101 + .driving_mask = GENMASK(17, 16),
102 },
103 {
104 .name = "gmii_gmac1_grp",
105 @@ -1693,6 +1704,7 @@ static const struct gemini_pin_group gem
106 .num_pins = ARRAY_SIZE(gmii_gmac1_3516_pins),
107 /* Bring out RGMII on the GMAC1 pins */
108 .value = GEMINI_GMAC_IOSEL_GMAC0_GMAC1_RGMII,
109 + .driving_mask = GENMASK(19, 18),
110 },
111 {
112 .name = "pcigrp",
113 @@ -1700,6 +1712,7 @@ static const struct gemini_pin_group gem
114 .num_pins = ARRAY_SIZE(pci_3516_pins),
115 /* Conflict only with GPIO2 */
116 .value = PCI_PADS_ENABLE | PCI_CLK_PAD_ENABLE,
117 + .driving_mask = GENMASK(23, 22),
118 },
119 {
120 .name = "lpcgrp",
121 @@ -2394,9 +2407,77 @@ static int gemini_pinconf_set(struct pin
122 return ret;
123 }
124
125 +static int gemini_pinconf_group_set(struct pinctrl_dev *pctldev,
126 + unsigned selector,
127 + unsigned long *configs,
128 + unsigned num_configs)
129 +{
130 + struct gemini_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
131 + const struct gemini_pin_group *grp = NULL;
132 + enum pin_config_param param;
133 + u32 arg;
134 + u32 val;
135 + int i;
136 +
137 + if (pmx->is_3512)
138 + grp = &gemini_3512_pin_groups[selector];
139 + if (pmx->is_3516)
140 + grp = &gemini_3516_pin_groups[selector];
141 +
142 + /* First figure out if this group supports configs */
143 + if (!grp->driving_mask) {
144 + dev_err(pmx->dev, "pin config group \"%s\" does "
145 + "not support drive strength setting\n",
146 + grp->name);
147 + return -EINVAL;
148 + }
149 +
150 + for (i = 0; i < num_configs; i++) {
151 + param = pinconf_to_config_param(configs[i]);
152 + arg = pinconf_to_config_argument(configs[i]);
153 +
154 + switch (param) {
155 + case PIN_CONFIG_DRIVE_STRENGTH:
156 + switch (arg) {
157 + case 4:
158 + val = 0;
159 + break;
160 + case 8:
161 + val = 1;
162 + break;
163 + case 12:
164 + val = 2;
165 + break;
166 + case 16:
167 + val = 3;
168 + break;
169 + default:
170 + dev_err(pmx->dev,
171 + "invalid drive strength %d mA\n",
172 + arg);
173 + return -ENOTSUPP;
174 + }
175 + val <<= (ffs(grp->driving_mask) - 1);
176 + regmap_update_bits(pmx->map, GLOBAL_IODRIVE,
177 + grp->driving_mask,
178 + val);
179 + dev_info(pmx->dev,
180 + "set group %s to %d mA drive strength mask %08x val %08x\n",
181 + grp->name, arg, grp->driving_mask, val);
182 + break;
183 + default:
184 + dev_err(pmx->dev, "invalid config param %04x\n", param);
185 + return -ENOTSUPP;
186 + }
187 + }
188 +
189 + return 0;
190 +}
191 +
192 static const struct pinconf_ops gemini_pinconf_ops = {
193 .pin_config_get = gemini_pinconf_get,
194 .pin_config_set = gemini_pinconf_set,
195 + .pin_config_group_set = gemini_pinconf_group_set,
196 .is_generic = true,
197 };
198