diff options
Diffstat (limited to 'drivers/pinctrl/pinctrl-single.c')
-rw-r--r-- | drivers/pinctrl/pinctrl-single.c | 242 |
1 files changed, 203 insertions, 39 deletions
diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c index b9fa04618601..6866548fab31 100644 --- a/drivers/pinctrl/pinctrl-single.c +++ b/drivers/pinctrl/pinctrl-single.c | |||
@@ -30,7 +30,7 @@ | |||
30 | #define DRIVER_NAME "pinctrl-single" | 30 | #define DRIVER_NAME "pinctrl-single" |
31 | #define PCS_MUX_PINS_NAME "pinctrl-single,pins" | 31 | #define PCS_MUX_PINS_NAME "pinctrl-single,pins" |
32 | #define PCS_MUX_BITS_NAME "pinctrl-single,bits" | 32 | #define PCS_MUX_BITS_NAME "pinctrl-single,bits" |
33 | #define PCS_REG_NAME_LEN ((sizeof(unsigned long) * 2) + 1) | 33 | #define PCS_REG_NAME_LEN ((sizeof(unsigned long) * 2) + 3) |
34 | #define PCS_OFF_DISABLED ~0U | 34 | #define PCS_OFF_DISABLED ~0U |
35 | 35 | ||
36 | /** | 36 | /** |
@@ -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); |
@@ -741,7 +744,8 @@ static const struct pinconf_ops pcs_pinconf_ops = { | |||
741 | * @pcs: pcs driver instance | 744 | * @pcs: pcs driver instance |
742 | * @offset: register offset from base | 745 | * @offset: register offset from base |
743 | */ | 746 | */ |
744 | static int pcs_add_pin(struct pcs_device *pcs, unsigned offset) | 747 | static int pcs_add_pin(struct pcs_device *pcs, unsigned offset, |
748 | unsigned pin_pos) | ||
745 | { | 749 | { |
746 | struct pinctrl_pin_desc *pin; | 750 | struct pinctrl_pin_desc *pin; |
747 | struct pcs_name *pn; | 751 | struct pcs_name *pn; |
@@ -756,8 +760,8 @@ static int pcs_add_pin(struct pcs_device *pcs, unsigned offset) | |||
756 | 760 | ||
757 | pin = &pcs->pins.pa[i]; | 761 | pin = &pcs->pins.pa[i]; |
758 | pn = &pcs->names[i]; | 762 | pn = &pcs->names[i]; |
759 | sprintf(pn->name, "%lx", | 763 | sprintf(pn->name, "%lx.%d", |
760 | (unsigned long)pcs->res->start + offset); | 764 | (unsigned long)pcs->res->start + offset, pin_pos); |
761 | pin->name = pn->name; | 765 | pin->name = pn->name; |
762 | pin->number = i; | 766 | pin->number = i; |
763 | pcs->pins.cur++; | 767 | pcs->pins.cur++; |
@@ -777,9 +781,17 @@ static int pcs_add_pin(struct pcs_device *pcs, unsigned offset) | |||
777 | static int pcs_allocate_pin_table(struct pcs_device *pcs) | 781 | static int pcs_allocate_pin_table(struct pcs_device *pcs) |
778 | { | 782 | { |
779 | int mux_bytes, nr_pins, i; | 783 | int mux_bytes, nr_pins, i; |
784 | int num_pins_in_register = 0; | ||
780 | 785 | ||
781 | mux_bytes = pcs->width / BITS_PER_BYTE; | 786 | mux_bytes = pcs->width / BITS_PER_BYTE; |
782 | nr_pins = pcs->size / mux_bytes; | 787 | |
788 | if (pcs->bits_per_mux) { | ||
789 | pcs->bits_per_pin = fls(pcs->fmask); | ||
790 | nr_pins = (pcs->size * BITS_PER_BYTE) / pcs->bits_per_pin; | ||
791 | num_pins_in_register = pcs->width / pcs->bits_per_pin; | ||
792 | } else { | ||
793 | nr_pins = pcs->size / mux_bytes; | ||
794 | } | ||
783 | 795 | ||
784 | dev_dbg(pcs->dev, "allocating %i pins\n", nr_pins); | 796 | dev_dbg(pcs->dev, "allocating %i pins\n", nr_pins); |
785 | pcs->pins.pa = devm_kzalloc(pcs->dev, | 797 | pcs->pins.pa = devm_kzalloc(pcs->dev, |
@@ -800,9 +812,17 @@ static int pcs_allocate_pin_table(struct pcs_device *pcs) | |||
800 | for (i = 0; i < pcs->desc.npins; i++) { | 812 | for (i = 0; i < pcs->desc.npins; i++) { |
801 | unsigned offset; | 813 | unsigned offset; |
802 | int res; | 814 | int res; |
803 | 815 | int byte_num; | |
804 | offset = i * mux_bytes; | 816 | int pin_pos = 0; |
805 | res = pcs_add_pin(pcs, offset); | 817 | |
818 | if (pcs->bits_per_mux) { | ||
819 | byte_num = (pcs->bits_per_pin * i) / BITS_PER_BYTE; | ||
820 | offset = (byte_num / mux_bytes) * mux_bytes; | ||
821 | pin_pos = i % num_pins_in_register; | ||
822 | } else { | ||
823 | offset = i * mux_bytes; | ||
824 | } | ||
825 | res = pcs_add_pin(pcs, offset, pin_pos); | ||
806 | if (res < 0) { | 826 | if (res < 0) { |
807 | dev_err(pcs->dev, "error adding pins: %i\n", res); | 827 | dev_err(pcs->dev, "error adding pins: %i\n", res); |
808 | return res; | 828 | return res; |
@@ -919,7 +939,10 @@ static int pcs_get_pin_by_offset(struct pcs_device *pcs, unsigned offset) | |||
919 | return -EINVAL; | 939 | return -EINVAL; |
920 | } | 940 | } |
921 | 941 | ||
922 | index = offset / (pcs->width / BITS_PER_BYTE); | 942 | if (pcs->bits_per_mux) |
943 | index = (offset * BITS_PER_BYTE) / pcs->bits_per_pin; | ||
944 | else | ||
945 | index = offset / (pcs->width / BITS_PER_BYTE); | ||
923 | 946 | ||
924 | return index; | 947 | return index; |
925 | } | 948 | } |
@@ -1097,29 +1120,18 @@ static int pcs_parse_one_pinctrl_entry(struct pcs_device *pcs, | |||
1097 | { | 1120 | { |
1098 | struct pcs_func_vals *vals; | 1121 | struct pcs_func_vals *vals; |
1099 | const __be32 *mux; | 1122 | const __be32 *mux; |
1100 | int size, params, rows, *pins, index = 0, found = 0, res = -ENOMEM; | 1123 | int size, rows, *pins, index = 0, found = 0, res = -ENOMEM; |
1101 | struct pcs_function *function; | 1124 | struct pcs_function *function; |
1102 | 1125 | ||
1103 | if (pcs->bits_per_mux) { | 1126 | mux = of_get_property(np, PCS_MUX_PINS_NAME, &size); |
1104 | params = 3; | 1127 | if ((!mux) || (size < sizeof(*mux) * 2)) { |
1105 | mux = of_get_property(np, PCS_MUX_BITS_NAME, &size); | 1128 | dev_err(pcs->dev, "bad data for mux %s\n", |
1106 | } else { | 1129 | 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; | 1130 | return -EINVAL; |
1119 | } | 1131 | } |
1120 | 1132 | ||
1121 | size /= sizeof(*mux); /* Number of elements in array */ | 1133 | size /= sizeof(*mux); /* Number of elements in array */ |
1122 | rows = size / params; | 1134 | rows = size / 2; |
1123 | 1135 | ||
1124 | vals = devm_kzalloc(pcs->dev, sizeof(*vals) * rows, GFP_KERNEL); | 1136 | vals = devm_kzalloc(pcs->dev, sizeof(*vals) * rows, GFP_KERNEL); |
1125 | if (!vals) | 1137 | if (!vals) |
@@ -1137,10 +1149,6 @@ static int pcs_parse_one_pinctrl_entry(struct pcs_device *pcs, | |||
1137 | val = be32_to_cpup(mux + index++); | 1149 | val = be32_to_cpup(mux + index++); |
1138 | vals[found].reg = pcs->base + offset; | 1150 | vals[found].reg = pcs->base + offset; |
1139 | vals[found].val = val; | 1151 | vals[found].val = val; |
1140 | if (params == 3) { | ||
1141 | val = be32_to_cpup(mux + index++); | ||
1142 | vals[found].mask = val; | ||
1143 | } | ||
1144 | 1152 | ||
1145 | pin = pcs_get_pin_by_offset(pcs, offset); | 1153 | pin = pcs_get_pin_by_offset(pcs, offset); |
1146 | if (pin < 0) { | 1154 | if (pin < 0) { |
@@ -1189,6 +1197,125 @@ free_vals: | |||
1189 | 1197 | ||
1190 | return res; | 1198 | return res; |
1191 | } | 1199 | } |
1200 | |||
1201 | #define PARAMS_FOR_BITS_PER_MUX 3 | ||
1202 | |||
1203 | static int pcs_parse_bits_in_pinctrl_entry(struct pcs_device *pcs, | ||
1204 | struct device_node *np, | ||
1205 | struct pinctrl_map **map, | ||
1206 | unsigned *num_maps, | ||
1207 | const char **pgnames) | ||
1208 | { | ||
1209 | struct pcs_func_vals *vals; | ||
1210 | const __be32 *mux; | ||
1211 | int size, rows, *pins, index = 0, found = 0, res = -ENOMEM; | ||
1212 | int npins_in_row; | ||
1213 | struct pcs_function *function; | ||
1214 | |||
1215 | mux = of_get_property(np, PCS_MUX_BITS_NAME, &size); | ||
1216 | |||
1217 | if (!mux) { | ||
1218 | dev_err(pcs->dev, "no valid property for %s\n", np->name); | ||
1219 | return -EINVAL; | ||
1220 | } | ||
1221 | |||
1222 | if (size < (sizeof(*mux) * PARAMS_FOR_BITS_PER_MUX)) { | ||
1223 | dev_err(pcs->dev, "bad data for %s\n", np->name); | ||
1224 | return -EINVAL; | ||
1225 | } | ||
1226 | |||
1227 | /* Number of elements in array */ | ||
1228 | size /= sizeof(*mux); | ||
1229 | |||
1230 | rows = size / PARAMS_FOR_BITS_PER_MUX; | ||
1231 | npins_in_row = pcs->width / pcs->bits_per_pin; | ||
1232 | |||
1233 | vals = devm_kzalloc(pcs->dev, sizeof(*vals) * rows * npins_in_row, | ||
1234 | GFP_KERNEL); | ||
1235 | if (!vals) | ||
1236 | return -ENOMEM; | ||
1237 | |||
1238 | pins = devm_kzalloc(pcs->dev, sizeof(*pins) * rows * npins_in_row, | ||
1239 | GFP_KERNEL); | ||
1240 | if (!pins) | ||
1241 | goto free_vals; | ||
1242 | |||
1243 | while (index < size) { | ||
1244 | unsigned offset, val; | ||
1245 | unsigned mask, bit_pos, val_pos, mask_pos, submask; | ||
1246 | unsigned pin_num_from_lsb; | ||
1247 | int pin; | ||
1248 | |||
1249 | offset = be32_to_cpup(mux + index++); | ||
1250 | val = be32_to_cpup(mux + index++); | ||
1251 | mask = be32_to_cpup(mux + index++); | ||
1252 | |||
1253 | /* Parse pins in each row from LSB */ | ||
1254 | while (mask) { | ||
1255 | bit_pos = ffs(mask); | ||
1256 | pin_num_from_lsb = bit_pos / pcs->bits_per_pin; | ||
1257 | mask_pos = ((pcs->fmask) << (bit_pos - 1)); | ||
1258 | val_pos = val & mask_pos; | ||
1259 | submask = mask & mask_pos; | ||
1260 | mask &= ~mask_pos; | ||
1261 | |||
1262 | if (submask != mask_pos) { | ||
1263 | dev_warn(pcs->dev, | ||
1264 | "Invalid submask 0x%x for %s at 0x%x\n", | ||
1265 | submask, np->name, offset); | ||
1266 | continue; | ||
1267 | } | ||
1268 | |||
1269 | vals[found].mask = submask; | ||
1270 | vals[found].reg = pcs->base + offset; | ||
1271 | vals[found].val = val_pos; | ||
1272 | |||
1273 | pin = pcs_get_pin_by_offset(pcs, offset); | ||
1274 | if (pin < 0) { | ||
1275 | dev_err(pcs->dev, | ||
1276 | "could not add functions for %s %ux\n", | ||
1277 | np->name, offset); | ||
1278 | break; | ||
1279 | } | ||
1280 | pins[found++] = pin + pin_num_from_lsb; | ||
1281 | } | ||
1282 | } | ||
1283 | |||
1284 | pgnames[0] = np->name; | ||
1285 | function = pcs_add_function(pcs, np, np->name, vals, found, pgnames, 1); | ||
1286 | if (!function) | ||
1287 | goto free_pins; | ||
1288 | |||
1289 | res = pcs_add_pingroup(pcs, np, np->name, pins, found); | ||
1290 | if (res < 0) | ||
1291 | goto free_function; | ||
1292 | |||
1293 | (*map)->type = PIN_MAP_TYPE_MUX_GROUP; | ||
1294 | (*map)->data.mux.group = np->name; | ||
1295 | (*map)->data.mux.function = np->name; | ||
1296 | |||
1297 | if (pcs->is_pinconf) { | ||
1298 | dev_err(pcs->dev, "pinconf not supported\n"); | ||
1299 | goto free_pingroups; | ||
1300 | } | ||
1301 | |||
1302 | *num_maps = 1; | ||
1303 | return 0; | ||
1304 | |||
1305 | free_pingroups: | ||
1306 | pcs_free_pingroups(pcs); | ||
1307 | *num_maps = 1; | ||
1308 | free_function: | ||
1309 | pcs_remove_function(pcs, function); | ||
1310 | |||
1311 | free_pins: | ||
1312 | devm_kfree(pcs->dev, pins); | ||
1313 | |||
1314 | free_vals: | ||
1315 | devm_kfree(pcs->dev, vals); | ||
1316 | |||
1317 | return res; | ||
1318 | } | ||
1192 | /** | 1319 | /** |
1193 | * pcs_dt_node_to_map() - allocates and parses pinctrl maps | 1320 | * pcs_dt_node_to_map() - allocates and parses pinctrl maps |
1194 | * @pctldev: pinctrl instance | 1321 | * @pctldev: pinctrl instance |
@@ -1219,12 +1346,22 @@ static int pcs_dt_node_to_map(struct pinctrl_dev *pctldev, | |||
1219 | goto free_map; | 1346 | goto free_map; |
1220 | } | 1347 | } |
1221 | 1348 | ||
1222 | ret = pcs_parse_one_pinctrl_entry(pcs, np_config, map, num_maps, | 1349 | if (pcs->bits_per_mux) { |
1223 | pgnames); | 1350 | ret = pcs_parse_bits_in_pinctrl_entry(pcs, np_config, map, |
1224 | if (ret < 0) { | 1351 | num_maps, pgnames); |
1225 | dev_err(pcs->dev, "no pins entries for %s\n", | 1352 | if (ret < 0) { |
1226 | np_config->name); | 1353 | dev_err(pcs->dev, "no pins entries for %s\n", |
1227 | goto free_pgnames; | 1354 | np_config->name); |
1355 | goto free_pgnames; | ||
1356 | } | ||
1357 | } else { | ||
1358 | ret = pcs_parse_one_pinctrl_entry(pcs, np_config, map, | ||
1359 | num_maps, pgnames); | ||
1360 | if (ret < 0) { | ||
1361 | dev_err(pcs->dev, "no pins entries for %s\n", | ||
1362 | np_config->name); | ||
1363 | goto free_pgnames; | ||
1364 | } | ||
1228 | } | 1365 | } |
1229 | 1366 | ||
1230 | return 0; | 1367 | return 0; |
@@ -1346,6 +1483,29 @@ static int pcs_add_gpio_func(struct device_node *node, struct pcs_device *pcs) | |||
1346 | return ret; | 1483 | return ret; |
1347 | } | 1484 | } |
1348 | 1485 | ||
1486 | static int pinctrl_single_suspend(struct platform_device *pdev, | ||
1487 | pm_message_t state) | ||
1488 | { | ||
1489 | struct pcs_device *pcs; | ||
1490 | |||
1491 | pcs = platform_get_drvdata(pdev); | ||
1492 | if (!pcs) | ||
1493 | return -EINVAL; | ||
1494 | |||
1495 | return pinctrl_force_sleep(pcs->pctl); | ||
1496 | } | ||
1497 | |||
1498 | static int pinctrl_single_resume(struct platform_device *pdev) | ||
1499 | { | ||
1500 | struct pcs_device *pcs; | ||
1501 | |||
1502 | pcs = platform_get_drvdata(pdev); | ||
1503 | if (!pcs) | ||
1504 | return -EINVAL; | ||
1505 | |||
1506 | return pinctrl_force_default(pcs->pctl); | ||
1507 | } | ||
1508 | |||
1349 | static int pcs_probe(struct platform_device *pdev) | 1509 | static int pcs_probe(struct platform_device *pdev) |
1350 | { | 1510 | { |
1351 | struct device_node *np = pdev->dev.of_node; | 1511 | struct device_node *np = pdev->dev.of_node; |
@@ -1494,6 +1654,10 @@ static struct platform_driver pcs_driver = { | |||
1494 | .name = DRIVER_NAME, | 1654 | .name = DRIVER_NAME, |
1495 | .of_match_table = pcs_of_match, | 1655 | .of_match_table = pcs_of_match, |
1496 | }, | 1656 | }, |
1657 | #ifdef CONFIG_PM | ||
1658 | .suspend = pinctrl_single_suspend, | ||
1659 | .resume = pinctrl_single_resume, | ||
1660 | #endif | ||
1497 | }; | 1661 | }; |
1498 | 1662 | ||
1499 | module_platform_driver(pcs_driver); | 1663 | module_platform_driver(pcs_driver); |