| .. | .. |
|---|
| 42 | 42 | * struct pcs_func_vals - mux function register offset and value pair |
|---|
| 43 | 43 | * @reg: register virtual address |
|---|
| 44 | 44 | * @val: register value |
|---|
| 45 | + * @mask: mask |
|---|
| 45 | 46 | */ |
|---|
| 46 | 47 | struct pcs_func_vals { |
|---|
| 47 | 48 | void __iomem *reg; |
|---|
| .. | .. |
|---|
| 83 | 84 | * @nvals: number of entries in vals array |
|---|
| 84 | 85 | * @pgnames: array of pingroup names the function uses |
|---|
| 85 | 86 | * @npgnames: number of pingroup names the function uses |
|---|
| 87 | + * @conf: array of pin configurations |
|---|
| 88 | + * @nconfs: number of pin configurations available |
|---|
| 86 | 89 | * @node: list node |
|---|
| 87 | 90 | */ |
|---|
| 88 | 91 | struct pcs_function { |
|---|
| .. | .. |
|---|
| 267 | 270 | writel(val, reg); |
|---|
| 268 | 271 | } |
|---|
| 269 | 272 | |
|---|
| 273 | +static unsigned int pcs_pin_reg_offset_get(struct pcs_device *pcs, |
|---|
| 274 | + unsigned int pin) |
|---|
| 275 | +{ |
|---|
| 276 | + unsigned int mux_bytes = pcs->width / BITS_PER_BYTE; |
|---|
| 277 | + |
|---|
| 278 | + if (pcs->bits_per_mux) { |
|---|
| 279 | + unsigned int pin_offset_bytes; |
|---|
| 280 | + |
|---|
| 281 | + pin_offset_bytes = (pcs->bits_per_pin * pin) / BITS_PER_BYTE; |
|---|
| 282 | + return (pin_offset_bytes / mux_bytes) * mux_bytes; |
|---|
| 283 | + } |
|---|
| 284 | + |
|---|
| 285 | + return pin * mux_bytes; |
|---|
| 286 | +} |
|---|
| 287 | + |
|---|
| 288 | +static unsigned int pcs_pin_shift_reg_get(struct pcs_device *pcs, |
|---|
| 289 | + unsigned int pin) |
|---|
| 290 | +{ |
|---|
| 291 | + return (pin % (pcs->width / pcs->bits_per_pin)) * pcs->bits_per_pin; |
|---|
| 292 | +} |
|---|
| 293 | + |
|---|
| 270 | 294 | static void pcs_pin_dbg_show(struct pinctrl_dev *pctldev, |
|---|
| 271 | 295 | struct seq_file *s, |
|---|
| 272 | 296 | unsigned pin) |
|---|
| 273 | 297 | { |
|---|
| 274 | 298 | struct pcs_device *pcs; |
|---|
| 275 | | - unsigned val, mux_bytes; |
|---|
| 299 | + unsigned int val; |
|---|
| 276 | 300 | unsigned long offset; |
|---|
| 277 | 301 | size_t pa; |
|---|
| 278 | 302 | |
|---|
| 279 | 303 | pcs = pinctrl_dev_get_drvdata(pctldev); |
|---|
| 280 | 304 | |
|---|
| 281 | | - mux_bytes = pcs->width / BITS_PER_BYTE; |
|---|
| 282 | | - offset = pin * mux_bytes; |
|---|
| 305 | + offset = pcs_pin_reg_offset_get(pcs, pin); |
|---|
| 283 | 306 | val = pcs->read(pcs->base + offset); |
|---|
| 307 | + |
|---|
| 308 | + if (pcs->bits_per_mux) |
|---|
| 309 | + val &= pcs->fmask << pcs_pin_shift_reg_get(pcs, pin); |
|---|
| 310 | + |
|---|
| 284 | 311 | pa = pcs->res->start + offset; |
|---|
| 285 | 312 | |
|---|
| 286 | 313 | seq_printf(s, "%zx %08x %s ", pa, val, DRIVER_NAME); |
|---|
| .. | .. |
|---|
| 345 | 372 | if (!pcs->fmask) |
|---|
| 346 | 373 | return 0; |
|---|
| 347 | 374 | function = pinmux_generic_get_function(pctldev, fselector); |
|---|
| 375 | + if (!function) |
|---|
| 376 | + return -EINVAL; |
|---|
| 348 | 377 | func = function->data; |
|---|
| 349 | 378 | if (!func) |
|---|
| 350 | 379 | return -EINVAL; |
|---|
| .. | .. |
|---|
| 381 | 410 | struct pcs_device *pcs = pinctrl_dev_get_drvdata(pctldev); |
|---|
| 382 | 411 | struct pcs_gpiofunc_range *frange = NULL; |
|---|
| 383 | 412 | struct list_head *pos, *tmp; |
|---|
| 384 | | - int mux_bytes = 0; |
|---|
| 385 | 413 | unsigned data; |
|---|
| 386 | 414 | |
|---|
| 387 | 415 | /* If function mask is null, return directly. */ |
|---|
| .. | .. |
|---|
| 389 | 417 | return -ENOTSUPP; |
|---|
| 390 | 418 | |
|---|
| 391 | 419 | list_for_each_safe(pos, tmp, &pcs->gpiofuncs) { |
|---|
| 420 | + u32 offset; |
|---|
| 421 | + |
|---|
| 392 | 422 | frange = list_entry(pos, struct pcs_gpiofunc_range, node); |
|---|
| 393 | 423 | if (pin >= frange->offset + frange->npins |
|---|
| 394 | 424 | || pin < frange->offset) |
|---|
| 395 | 425 | continue; |
|---|
| 396 | | - mux_bytes = pcs->width / BITS_PER_BYTE; |
|---|
| 426 | + |
|---|
| 427 | + offset = pcs_pin_reg_offset_get(pcs, pin); |
|---|
| 397 | 428 | |
|---|
| 398 | 429 | if (pcs->bits_per_mux) { |
|---|
| 399 | | - int byte_num, offset, pin_shift; |
|---|
| 400 | | - |
|---|
| 401 | | - byte_num = (pcs->bits_per_pin * pin) / BITS_PER_BYTE; |
|---|
| 402 | | - offset = (byte_num / mux_bytes) * mux_bytes; |
|---|
| 403 | | - pin_shift = pin % (pcs->width / pcs->bits_per_pin) * |
|---|
| 404 | | - pcs->bits_per_pin; |
|---|
| 430 | + int pin_shift = pcs_pin_shift_reg_get(pcs, pin); |
|---|
| 405 | 431 | |
|---|
| 406 | 432 | data = pcs->read(pcs->base + offset); |
|---|
| 407 | 433 | data &= ~(pcs->fmask << pin_shift); |
|---|
| 408 | 434 | data |= frange->gpiofunc << pin_shift; |
|---|
| 409 | 435 | pcs->write(data, pcs->base + offset); |
|---|
| 410 | 436 | } else { |
|---|
| 411 | | - data = pcs->read(pcs->base + pin * mux_bytes); |
|---|
| 437 | + data = pcs->read(pcs->base + offset); |
|---|
| 412 | 438 | data &= ~pcs->fmask; |
|---|
| 413 | 439 | data |= frange->gpiofunc; |
|---|
| 414 | | - pcs->write(data, pcs->base + pin * mux_bytes); |
|---|
| 440 | + pcs->write(data, pcs->base + offset); |
|---|
| 415 | 441 | } |
|---|
| 416 | 442 | break; |
|---|
| 417 | 443 | } |
|---|
| .. | .. |
|---|
| 560 | 586 | case PIN_CONFIG_BIAS_PULL_UP: |
|---|
| 561 | 587 | if (arg) |
|---|
| 562 | 588 | pcs_pinconf_clear_bias(pctldev, pin); |
|---|
| 563 | | - /* fall through */ |
|---|
| 589 | + fallthrough; |
|---|
| 564 | 590 | case PIN_CONFIG_INPUT_SCHMITT_ENABLE: |
|---|
| 565 | 591 | data &= ~func->conf[i].mask; |
|---|
| 566 | 592 | if (arg) |
|---|
| .. | .. |
|---|
| 654 | 680 | * @pcs: pcs driver instance |
|---|
| 655 | 681 | * @offset: register offset from base |
|---|
| 656 | 682 | */ |
|---|
| 657 | | -static int pcs_add_pin(struct pcs_device *pcs, unsigned offset, |
|---|
| 658 | | - unsigned pin_pos) |
|---|
| 683 | +static int pcs_add_pin(struct pcs_device *pcs, unsigned int offset) |
|---|
| 659 | 684 | { |
|---|
| 660 | 685 | struct pcs_soc_data *pcs_soc = &pcs->socdata; |
|---|
| 661 | 686 | struct pinctrl_pin_desc *pin; |
|---|
| .. | .. |
|---|
| 703 | 728 | |
|---|
| 704 | 729 | mux_bytes = pcs->width / BITS_PER_BYTE; |
|---|
| 705 | 730 | |
|---|
| 706 | | - if (pcs->bits_per_mux) { |
|---|
| 731 | + if (pcs->bits_per_mux && pcs->fmask) { |
|---|
| 707 | 732 | pcs->bits_per_pin = fls(pcs->fmask); |
|---|
| 708 | 733 | nr_pins = (pcs->size * BITS_PER_BYTE) / pcs->bits_per_pin; |
|---|
| 709 | 734 | num_pins_in_register = pcs->width / pcs->bits_per_pin; |
|---|
| .. | .. |
|---|
| 724 | 749 | for (i = 0; i < pcs->desc.npins; i++) { |
|---|
| 725 | 750 | unsigned offset; |
|---|
| 726 | 751 | int res; |
|---|
| 727 | | - int byte_num; |
|---|
| 728 | | - int pin_pos = 0; |
|---|
| 729 | 752 | |
|---|
| 730 | | - if (pcs->bits_per_mux) { |
|---|
| 731 | | - byte_num = (pcs->bits_per_pin * i) / BITS_PER_BYTE; |
|---|
| 732 | | - offset = (byte_num / mux_bytes) * mux_bytes; |
|---|
| 733 | | - pin_pos = i % num_pins_in_register; |
|---|
| 734 | | - } else { |
|---|
| 735 | | - offset = i * mux_bytes; |
|---|
| 736 | | - } |
|---|
| 737 | | - res = pcs_add_pin(pcs, offset, pin_pos); |
|---|
| 753 | + offset = pcs_pin_reg_offset_get(pcs, i); |
|---|
| 754 | + res = pcs_add_pin(pcs, offset); |
|---|
| 738 | 755 | if (res < 0) { |
|---|
| 739 | 756 | dev_err(pcs->dev, "error adding pins: %i\n", res); |
|---|
| 740 | 757 | return res; |
|---|
| .. | .. |
|---|
| 958 | 975 | } |
|---|
| 959 | 976 | |
|---|
| 960 | 977 | /** |
|---|
| 961 | | - * smux_parse_one_pinctrl_entry() - parses a device tree mux entry |
|---|
| 962 | | - * @pctldev: pin controller device |
|---|
| 978 | + * pcs_parse_one_pinctrl_entry() - parses a device tree mux entry |
|---|
| 963 | 979 | * @pcs: pinctrl driver instance |
|---|
| 964 | 980 | * @np: device node of the mux entry |
|---|
| 965 | 981 | * @map: map entry |
|---|
| .. | .. |
|---|
| 1011 | 1027 | if (res) |
|---|
| 1012 | 1028 | return res; |
|---|
| 1013 | 1029 | |
|---|
| 1014 | | - if (pinctrl_spec.args_count < 2) { |
|---|
| 1030 | + if (pinctrl_spec.args_count < 2 || pinctrl_spec.args_count > 3) { |
|---|
| 1015 | 1031 | dev_err(pcs->dev, "invalid args_count for spec: %i\n", |
|---|
| 1016 | 1032 | pinctrl_spec.args_count); |
|---|
| 1017 | 1033 | break; |
|---|
| 1018 | 1034 | } |
|---|
| 1019 | 1035 | |
|---|
| 1020 | | - /* Index plus one value cell */ |
|---|
| 1021 | 1036 | offset = pinctrl_spec.args[0]; |
|---|
| 1022 | 1037 | vals[found].reg = pcs->base + offset; |
|---|
| 1023 | | - vals[found].val = pinctrl_spec.args[1]; |
|---|
| 1024 | 1038 | |
|---|
| 1025 | | - dev_dbg(pcs->dev, "%s index: 0x%x value: 0x%x\n", |
|---|
| 1026 | | - pinctrl_spec.np->name, offset, pinctrl_spec.args[1]); |
|---|
| 1039 | + switch (pinctrl_spec.args_count) { |
|---|
| 1040 | + case 2: |
|---|
| 1041 | + vals[found].val = pinctrl_spec.args[1]; |
|---|
| 1042 | + break; |
|---|
| 1043 | + case 3: |
|---|
| 1044 | + vals[found].val = (pinctrl_spec.args[1] | pinctrl_spec.args[2]); |
|---|
| 1045 | + break; |
|---|
| 1046 | + } |
|---|
| 1047 | + |
|---|
| 1048 | + dev_dbg(pcs->dev, "%pOFn index: 0x%x value: 0x%x\n", |
|---|
| 1049 | + pinctrl_spec.np, offset, vals[found].val); |
|---|
| 1027 | 1050 | |
|---|
| 1028 | 1051 | pin = pcs_get_pin_by_offset(pcs, offset); |
|---|
| 1029 | 1052 | if (pin < 0) { |
|---|
| 1030 | 1053 | dev_err(pcs->dev, |
|---|
| 1031 | | - "could not add functions for %s %ux\n", |
|---|
| 1032 | | - np->name, offset); |
|---|
| 1054 | + "could not add functions for %pOFn %ux\n", |
|---|
| 1055 | + np, offset); |
|---|
| 1033 | 1056 | break; |
|---|
| 1034 | 1057 | } |
|---|
| 1035 | 1058 | pins[found++] = pin; |
|---|
| .. | .. |
|---|
| 1138 | 1161 | val = pinctrl_spec.args[1]; |
|---|
| 1139 | 1162 | mask = pinctrl_spec.args[2]; |
|---|
| 1140 | 1163 | |
|---|
| 1141 | | - dev_dbg(pcs->dev, "%s index: 0x%x value: 0x%x mask: 0x%x\n", |
|---|
| 1142 | | - pinctrl_spec.np->name, offset, val, mask); |
|---|
| 1164 | + dev_dbg(pcs->dev, "%pOFn index: 0x%x value: 0x%x mask: 0x%x\n", |
|---|
| 1165 | + pinctrl_spec.np, offset, val, mask); |
|---|
| 1143 | 1166 | |
|---|
| 1144 | 1167 | /* Parse pins in each row from LSB */ |
|---|
| 1145 | 1168 | while (mask) { |
|---|
| .. | .. |
|---|
| 1151 | 1174 | |
|---|
| 1152 | 1175 | if ((mask & mask_pos) == 0) { |
|---|
| 1153 | 1176 | dev_err(pcs->dev, |
|---|
| 1154 | | - "Invalid mask for %s at 0x%x\n", |
|---|
| 1155 | | - np->name, offset); |
|---|
| 1177 | + "Invalid mask for %pOFn at 0x%x\n", |
|---|
| 1178 | + np, offset); |
|---|
| 1156 | 1179 | break; |
|---|
| 1157 | 1180 | } |
|---|
| 1158 | 1181 | |
|---|
| .. | .. |
|---|
| 1160 | 1183 | |
|---|
| 1161 | 1184 | if (submask != mask_pos) { |
|---|
| 1162 | 1185 | dev_warn(pcs->dev, |
|---|
| 1163 | | - "Invalid submask 0x%x for %s at 0x%x\n", |
|---|
| 1164 | | - submask, np->name, offset); |
|---|
| 1186 | + "Invalid submask 0x%x for %pOFn at 0x%x\n", |
|---|
| 1187 | + submask, np, offset); |
|---|
| 1165 | 1188 | continue; |
|---|
| 1166 | 1189 | } |
|---|
| 1167 | 1190 | |
|---|
| .. | .. |
|---|
| 1172 | 1195 | pin = pcs_get_pin_by_offset(pcs, offset); |
|---|
| 1173 | 1196 | if (pin < 0) { |
|---|
| 1174 | 1197 | dev_err(pcs->dev, |
|---|
| 1175 | | - "could not add functions for %s %ux\n", |
|---|
| 1176 | | - np->name, offset); |
|---|
| 1198 | + "could not add functions for %pOFn %ux\n", |
|---|
| 1199 | + np, offset); |
|---|
| 1177 | 1200 | break; |
|---|
| 1178 | 1201 | } |
|---|
| 1179 | 1202 | pins[found++] = pin + pin_num_from_lsb; |
|---|
| .. | .. |
|---|
| 1258 | 1281 | ret = pcs_parse_bits_in_pinctrl_entry(pcs, np_config, map, |
|---|
| 1259 | 1282 | num_maps, pgnames); |
|---|
| 1260 | 1283 | if (ret < 0) { |
|---|
| 1261 | | - dev_err(pcs->dev, "no pins entries for %s\n", |
|---|
| 1262 | | - np_config->name); |
|---|
| 1284 | + dev_err(pcs->dev, "no pins entries for %pOFn\n", |
|---|
| 1285 | + np_config); |
|---|
| 1263 | 1286 | goto free_pgnames; |
|---|
| 1264 | 1287 | } |
|---|
| 1265 | 1288 | } else { |
|---|
| 1266 | 1289 | ret = pcs_parse_one_pinctrl_entry(pcs, np_config, map, |
|---|
| 1267 | 1290 | num_maps, pgnames); |
|---|
| 1268 | 1291 | if (ret < 0) { |
|---|
| 1269 | | - dev_err(pcs->dev, "no pins entries for %s\n", |
|---|
| 1270 | | - np_config->name); |
|---|
| 1292 | + dev_err(pcs->dev, "no pins entries for %pOFn\n", |
|---|
| 1293 | + np_config); |
|---|
| 1271 | 1294 | goto free_pgnames; |
|---|
| 1272 | 1295 | } |
|---|
| 1273 | 1296 | } |
|---|
| .. | .. |
|---|
| 1347 | 1370 | } |
|---|
| 1348 | 1371 | return ret; |
|---|
| 1349 | 1372 | } |
|---|
| 1373 | + |
|---|
| 1350 | 1374 | /** |
|---|
| 1375 | + * struct pcs_interrupt |
|---|
| 1351 | 1376 | * @reg: virtual address of interrupt register |
|---|
| 1352 | 1377 | * @hwirq: hardware irq number |
|---|
| 1353 | 1378 | * @irq: virtual irq number |
|---|
| .. | .. |
|---|
| 1362 | 1387 | |
|---|
| 1363 | 1388 | /** |
|---|
| 1364 | 1389 | * pcs_irq_set() - enables or disables an interrupt |
|---|
| 1390 | + * @pcs_soc: SoC specific settings |
|---|
| 1391 | + * @irq: interrupt |
|---|
| 1392 | + * @enable: enable or disable the interrupt |
|---|
| 1365 | 1393 | * |
|---|
| 1366 | 1394 | * Note that this currently assumes one interrupt per pinctrl |
|---|
| 1367 | 1395 | * register that is typically used for wake-up events. |
|---|
| .. | .. |
|---|
| 1442 | 1470 | |
|---|
| 1443 | 1471 | /** |
|---|
| 1444 | 1472 | * pcs_irq_handle() - common interrupt handler |
|---|
| 1445 | | - * @pcs_irq: interrupt data |
|---|
| 1473 | + * @pcs_soc: SoC specific settings |
|---|
| 1446 | 1474 | * |
|---|
| 1447 | 1475 | * Note that this currently assumes we have one interrupt bit per |
|---|
| 1448 | 1476 | * mux register. This interrupt is typically used for wake-up events. |
|---|
| .. | .. |
|---|
| 1490 | 1518 | |
|---|
| 1491 | 1519 | /** |
|---|
| 1492 | 1520 | * pcs_irq_handle() - handler for the dedicated chained interrupt case |
|---|
| 1493 | | - * @irq: interrupt |
|---|
| 1494 | 1521 | * @desc: interrupt descriptor |
|---|
| 1495 | 1522 | * |
|---|
| 1496 | 1523 | * Use this if you have a separate interrupt for each |
|---|