summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorManjunathappa, Prakash <prakash.pm@ti.com>2013-05-21 10:08:00 -0400
committerLinus Walleij <linus.walleij@linaro.org>2013-06-16 05:56:52 -0400
commit4e7e8017a80e1810100c9b416b86e3baef900285 (patch)
tree98f812edd3f0c787a5ac04c6b0304dce5bffd00f
parentac844b62713045557c834c8d5fe2863b8bbaf124 (diff)
pinctrl: pinctrl-single: enhance to configure multiple pins of different modules
Add support to configure multiple pins in each register, existing implementation added by [1] does not support full fledge multiple pin configuration in single register, reports a pin clash when different modules configure different bits of same register. The issue reported and discussed here http://www.spinics.net/lists/arm-kernel/msg235213.html With pinctrl-single,bits-per-mux property specified, use function-mask property to find out number pins to configure. Allocate and register pin control functions based sub mask. Tested on da850/omap-l138 EVM. does not support variable submask for pins. does not support pinconf. [1] "pinctrl: pinctrl-single: Add pinctrl-single,bits type of mux" (9e605cb68a21d5704839a192a46ebcf387773704), Signed-off-by: Manjunathappa, Prakash <prakash.pm@ti.com> Reported-by: Lad, Prabhakar <prabhakar.csengg@gmail.com> Tested-by: Lad, Prabhakar <prabhakar.csengg@gmail.com> Acked-by: Haojian Zhuang <haojian.zhuang@gmail.com> Acked-by: Tony Lindgren <tony@atomide.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
-rw-r--r--Documentation/devicetree/bindings/pinctrl/pinctrl-single.txt3
-rw-r--r--drivers/pinctrl/pinctrl-single.c198
2 files changed, 167 insertions, 34 deletions
diff --git a/Documentation/devicetree/bindings/pinctrl/pinctrl-single.txt b/Documentation/devicetree/bindings/pinctrl/pinctrl-single.txt
index 08f0c3d01575..5a02e30dd262 100644
--- a/Documentation/devicetree/bindings/pinctrl/pinctrl-single.txt
+++ b/Documentation/devicetree/bindings/pinctrl/pinctrl-single.txt
@@ -18,7 +18,8 @@ Optional properties:
18 pin functions is ignored 18 pin functions is ignored
19 19
20- pinctrl-single,bit-per-mux : boolean to indicate that one register controls 20- pinctrl-single,bit-per-mux : boolean to indicate that one register controls
21 more than one pin 21 more than one pin, for which "pinctrl-single,function-mask" property specifies
22 position mask of pin.
22 23
23- pinctrl-single,drive-strength : array of value that are used to configure 24- pinctrl-single,drive-strength : array of value that are used to configure
24 drive strength in the pinmux register. They're value of drive strength 25 drive strength in the pinmux register. They're value of drive strength
diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c
index b9fa04618601..9a1ea65014d7 100644
--- a/drivers/pinctrl/pinctrl-single.c
+++ b/drivers/pinctrl/pinctrl-single.c
@@ -163,6 +163,7 @@ struct pcs_name {
163 * @foff: value to turn mux off 163 * @foff: value to turn mux off
164 * @fmax: max number of functions in fmask 164 * @fmax: max number of functions in fmask
165 * @is_pinconf: whether supports pinconf 165 * @is_pinconf: whether supports pinconf
166 * @bits_per_pin:number of bits per pin
166 * @names: array of register names for pins 167 * @names: array of register names for pins
167 * @pins: physical pins on the SoC 168 * @pins: physical pins on the SoC
168 * @pgtree: pingroup index radix tree 169 * @pgtree: pingroup index radix tree
@@ -190,6 +191,7 @@ struct pcs_device {
190 unsigned fmax; 191 unsigned fmax;
191 bool bits_per_mux; 192 bool bits_per_mux;
192 bool is_pinconf; 193 bool is_pinconf;
194 unsigned bits_per_pin;
193 struct pcs_name *names; 195 struct pcs_name *names;
194 struct pcs_data pins; 196 struct pcs_data pins;
195 struct radix_tree_root pgtree; 197 struct radix_tree_root pgtree;
@@ -431,10 +433,11 @@ static int pcs_enable(struct pinctrl_dev *pctldev, unsigned fselector,
431 433
432 vals = &func->vals[i]; 434 vals = &func->vals[i];
433 val = pcs->read(vals->reg); 435 val = pcs->read(vals->reg);
434 if (!vals->mask) 436
435 mask = pcs->fmask; 437 if (pcs->bits_per_mux)
438 mask = vals->mask;
436 else 439 else
437 mask = pcs->fmask & vals->mask; 440 mask = pcs->fmask;
438 441
439 val &= ~mask; 442 val &= ~mask;
440 val |= (vals->val & mask); 443 val |= (vals->val & mask);
@@ -779,7 +782,13 @@ static int pcs_allocate_pin_table(struct pcs_device *pcs)
779 int mux_bytes, nr_pins, i; 782 int mux_bytes, nr_pins, i;
780 783
781 mux_bytes = pcs->width / BITS_PER_BYTE; 784 mux_bytes = pcs->width / BITS_PER_BYTE;
782 nr_pins = pcs->size / mux_bytes; 785
786 if (pcs->bits_per_mux) {
787 pcs->bits_per_pin = fls(pcs->fmask);
788 nr_pins = (pcs->size * BITS_PER_BYTE) / pcs->bits_per_pin;
789 } else {
790 nr_pins = pcs->size / mux_bytes;
791 }
783 792
784 dev_dbg(pcs->dev, "allocating %i pins\n", nr_pins); 793 dev_dbg(pcs->dev, "allocating %i pins\n", nr_pins);
785 pcs->pins.pa = devm_kzalloc(pcs->dev, 794 pcs->pins.pa = devm_kzalloc(pcs->dev,
@@ -800,8 +809,14 @@ static int pcs_allocate_pin_table(struct pcs_device *pcs)
800 for (i = 0; i < pcs->desc.npins; i++) { 809 for (i = 0; i < pcs->desc.npins; i++) {
801 unsigned offset; 810 unsigned offset;
802 int res; 811 int res;
812 int byte_num;
803 813
804 offset = i * mux_bytes; 814 if (pcs->bits_per_mux) {
815 byte_num = (pcs->bits_per_pin * i) / BITS_PER_BYTE;
816 offset = (byte_num / mux_bytes) * mux_bytes;
817 } else {
818 offset = i * mux_bytes;
819 }
805 res = pcs_add_pin(pcs, offset); 820 res = pcs_add_pin(pcs, offset);
806 if (res < 0) { 821 if (res < 0) {
807 dev_err(pcs->dev, "error adding pins: %i\n", res); 822 dev_err(pcs->dev, "error adding pins: %i\n", res);
@@ -919,7 +934,10 @@ static int pcs_get_pin_by_offset(struct pcs_device *pcs, unsigned offset)
919 return -EINVAL; 934 return -EINVAL;
920 } 935 }
921 936
922 index = offset / (pcs->width / BITS_PER_BYTE); 937 if (pcs->bits_per_mux)
938 index = (offset * BITS_PER_BYTE) / pcs->bits_per_pin;
939 else
940 index = offset / (pcs->width / BITS_PER_BYTE);
923 941
924 return index; 942 return index;
925} 943}
@@ -1097,29 +1115,18 @@ static int pcs_parse_one_pinctrl_entry(struct pcs_device *pcs,
1097{ 1115{
1098 struct pcs_func_vals *vals; 1116 struct pcs_func_vals *vals;
1099 const __be32 *mux; 1117 const __be32 *mux;
1100 int size, params, rows, *pins, index = 0, found = 0, res = -ENOMEM; 1118 int size, rows, *pins, index = 0, found = 0, res = -ENOMEM;
1101 struct pcs_function *function; 1119 struct pcs_function *function;
1102 1120
1103 if (pcs->bits_per_mux) { 1121 mux = of_get_property(np, PCS_MUX_PINS_NAME, &size);
1104 params = 3; 1122 if ((!mux) || (size < sizeof(*mux) * 2)) {
1105 mux = of_get_property(np, PCS_MUX_BITS_NAME, &size); 1123 dev_err(pcs->dev, "bad data for mux %s\n",
1106 } else { 1124 np->name);
1107 params = 2;
1108 mux = of_get_property(np, PCS_MUX_PINS_NAME, &size);
1109 }
1110
1111 if (!mux) {
1112 dev_err(pcs->dev, "no valid property for %s\n", np->name);
1113 return -EINVAL;
1114 }
1115
1116 if (size < (sizeof(*mux) * params)) {
1117 dev_err(pcs->dev, "bad data for %s\n", np->name);
1118 return -EINVAL; 1125 return -EINVAL;
1119 } 1126 }
1120 1127
1121 size /= sizeof(*mux); /* Number of elements in array */ 1128 size /= sizeof(*mux); /* Number of elements in array */
1122 rows = size / params; 1129 rows = size / 2;
1123 1130
1124 vals = devm_kzalloc(pcs->dev, sizeof(*vals) * rows, GFP_KERNEL); 1131 vals = devm_kzalloc(pcs->dev, sizeof(*vals) * rows, GFP_KERNEL);
1125 if (!vals) 1132 if (!vals)
@@ -1137,10 +1144,6 @@ static int pcs_parse_one_pinctrl_entry(struct pcs_device *pcs,
1137 val = be32_to_cpup(mux + index++); 1144 val = be32_to_cpup(mux + index++);
1138 vals[found].reg = pcs->base + offset; 1145 vals[found].reg = pcs->base + offset;
1139 vals[found].val = val; 1146 vals[found].val = val;
1140 if (params == 3) {
1141 val = be32_to_cpup(mux + index++);
1142 vals[found].mask = val;
1143 }
1144 1147
1145 pin = pcs_get_pin_by_offset(pcs, offset); 1148 pin = pcs_get_pin_by_offset(pcs, offset);
1146 if (pin < 0) { 1149 if (pin < 0) {
@@ -1189,6 +1192,125 @@ free_vals:
1189 1192
1190 return res; 1193 return res;
1191} 1194}
1195
1196#define PARAMS_FOR_BITS_PER_MUX 3
1197
1198static int pcs_parse_bits_in_pinctrl_entry(struct pcs_device *pcs,
1199 struct device_node *np,
1200 struct pinctrl_map **map,
1201 unsigned *num_maps,
1202 const char **pgnames)
1203{
1204 struct pcs_func_vals *vals;
1205 const __be32 *mux;
1206 int size, rows, *pins, index = 0, found = 0, res = -ENOMEM;
1207 int npins_in_row;
1208 struct pcs_function *function;
1209
1210 mux = of_get_property(np, PCS_MUX_BITS_NAME, &size);
1211
1212 if (!mux) {
1213 dev_err(pcs->dev, "no valid property for %s\n", np->name);
1214 return -EINVAL;
1215 }
1216
1217 if (size < (sizeof(*mux) * PARAMS_FOR_BITS_PER_MUX)) {
1218 dev_err(pcs->dev, "bad data for %s\n", np->name);
1219 return -EINVAL;
1220 }
1221
1222 /* Number of elements in array */
1223 size /= sizeof(*mux);
1224
1225 rows = size / PARAMS_FOR_BITS_PER_MUX;
1226 npins_in_row = pcs->width / pcs->bits_per_pin;
1227
1228 vals = devm_kzalloc(pcs->dev, sizeof(*vals) * rows * npins_in_row,
1229 GFP_KERNEL);
1230 if (!vals)
1231 return -ENOMEM;
1232
1233 pins = devm_kzalloc(pcs->dev, sizeof(*pins) * rows * npins_in_row,
1234 GFP_KERNEL);
1235 if (!pins)
1236 goto free_vals;
1237
1238 while (index < size) {
1239 unsigned offset, val;
1240 unsigned mask, bit_pos, val_pos, mask_pos, submask;
1241 unsigned pin_num_from_lsb;
1242 int pin;
1243
1244 offset = be32_to_cpup(mux + index++);
1245 val = be32_to_cpup(mux + index++);
1246 mask = be32_to_cpup(mux + index++);
1247
1248 /* Parse pins in each row from LSB */
1249 while (mask) {
1250 bit_pos = ffs(mask);
1251 pin_num_from_lsb = bit_pos / pcs->bits_per_pin;
1252 mask_pos = ((pcs->fmask) << (bit_pos - 1));
1253 val_pos = val & mask_pos;
1254 submask = mask & mask_pos;
1255 mask &= ~mask_pos;
1256
1257 if (submask != mask_pos) {
1258 dev_warn(pcs->dev,
1259 "Invalid submask 0x%x for %s at 0x%x\n",
1260 submask, np->name, offset);
1261 continue;
1262 }
1263
1264 vals[found].mask = submask;
1265 vals[found].reg = pcs->base + offset;
1266 vals[found].val = val_pos;
1267
1268 pin = pcs_get_pin_by_offset(pcs, offset);
1269 if (pin < 0) {
1270 dev_err(pcs->dev,
1271 "could not add functions for %s %ux\n",
1272 np->name, offset);
1273 break;
1274 }
1275 pins[found++] = pin + pin_num_from_lsb;
1276 }
1277 }
1278
1279 pgnames[0] = np->name;
1280 function = pcs_add_function(pcs, np, np->name, vals, found, pgnames, 1);
1281 if (!function)
1282 goto free_pins;
1283
1284 res = pcs_add_pingroup(pcs, np, np->name, pins, found);
1285 if (res < 0)
1286 goto free_function;
1287
1288 (*map)->type = PIN_MAP_TYPE_MUX_GROUP;
1289 (*map)->data.mux.group = np->name;
1290 (*map)->data.mux.function = np->name;
1291
1292 if (pcs->is_pinconf) {
1293 dev_err(pcs->dev, "pinconf not supported\n");
1294 goto free_pingroups;
1295 }
1296
1297 *num_maps = 1;
1298 return 0;
1299
1300free_pingroups:
1301 pcs_free_pingroups(pcs);
1302 *num_maps = 1;
1303free_function:
1304 pcs_remove_function(pcs, function);
1305
1306free_pins:
1307 devm_kfree(pcs->dev, pins);
1308
1309free_vals:
1310 devm_kfree(pcs->dev, vals);
1311
1312 return res;
1313}
1192/** 1314/**
1193 * pcs_dt_node_to_map() - allocates and parses pinctrl maps 1315 * pcs_dt_node_to_map() - allocates and parses pinctrl maps
1194 * @pctldev: pinctrl instance 1316 * @pctldev: pinctrl instance
@@ -1219,12 +1341,22 @@ static int pcs_dt_node_to_map(struct pinctrl_dev *pctldev,
1219 goto free_map; 1341 goto free_map;
1220 } 1342 }
1221 1343
1222 ret = pcs_parse_one_pinctrl_entry(pcs, np_config, map, num_maps, 1344 if (pcs->bits_per_mux) {
1223 pgnames); 1345 ret = pcs_parse_bits_in_pinctrl_entry(pcs, np_config, map,
1224 if (ret < 0) { 1346 num_maps, pgnames);
1225 dev_err(pcs->dev, "no pins entries for %s\n", 1347 if (ret < 0) {
1226 np_config->name); 1348 dev_err(pcs->dev, "no pins entries for %s\n",
1227 goto free_pgnames; 1349 np_config->name);
1350 goto free_pgnames;
1351 }
1352 } else {
1353 ret = pcs_parse_one_pinctrl_entry(pcs, np_config, map,
1354 num_maps, pgnames);
1355 if (ret < 0) {
1356 dev_err(pcs->dev, "no pins entries for %s\n",
1357 np_config->name);
1358 goto free_pgnames;
1359 }
1228 } 1360 }
1229 1361
1230 return 0; 1362 return 0;