Hi AngeloGioacchino, Thank you for the patch! Perhaps something to improve:
[auto build test WARNING on pm/linux-next] [also build test WARNING on robh/for-next linux/master linus/master v5.11-rc2 next-20210108] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch] url: https://github.com/0day-ci/linux/commits/AngeloGioacchino-Del-Regno/Enable-CPRh-3-4-CPU-Scaling-on-various-QCOM-SoCs/20210110-021002 base: https://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git linux-next config: arm64-allyesconfig (attached as .config) compiler: aarch64-linux-gcc (GCC) 9.3.0 reproduce (this is a W=1 build): wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # https://github.com/0day-ci/linux/commit/f7b151e3b7c4b04b3333508e6ff13738de070041 git remote add linux-review https://github.com/0day-ci/linux git fetch --no-tags linux-review AngeloGioacchino-Del-Regno/Enable-CPRh-3-4-CPU-Scaling-on-various-QCOM-SoCs/20210110-021002 git checkout f7b151e3b7c4b04b3333508e6ff13738de070041 # save the attached .config to linux build tree COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross ARCH=arm64 If you fix the issue, kindly add following tag as appropriate Reported-by: kernel test robot <l...@intel.com> All warnings (new ones prefixed by >>): drivers/soc/qcom/cpr3.c: In function 'cpr3_corner_init': >> drivers/soc/qcom/cpr3.c:1673:17: warning: variable 'min_quot_val' set but >> not used [-Wunused-but-set-variable] 1673 | int ring_osc, min_quot_val; | ^~~~~~~~~~~~ >> drivers/soc/qcom/cpr3.c:1316:7: warning: variable 'apply_scaling' set but >> not used [-Wunused-but-set-variable] 1316 | bool apply_scaling; | ^~~~~~~~~~~~~ vim +/min_quot_val +1673 drivers/soc/qcom/cpr3.c 1284 1285 /** 1286 * cpr3_corner_init - Calculate and set-up corners for the CPR HW 1287 * @thread: Structure holding CPR thread-specific parameters 1288 * 1289 * This function calculates all the corner parameters by comparing 1290 * and interpolating the values read from the various set-points 1291 * read from the fuses (also called "fuse corners") to generate and 1292 * program to the CPR a lookup table that describes each voltage 1293 * step, mapped to a performance level (or corner number). 1294 * 1295 * It also programs other essential parameters on the CPR and - if 1296 * we are dealing with CPR-Hardened, it will also enable the internal 1297 * interface between the Operating State Manager (OSM) and the CPRh 1298 * in order to achieve CPU DVFS. 1299 * 1300 * Returns: Zero for success, negative number on error 1301 */ 1302 static int cpr3_corner_init(struct cpr_thread *thread) 1303 { 1304 struct cpr_drv *drv = thread->drv; 1305 const struct cpr_desc *desc = drv->desc; 1306 const struct cpr_thread_desc *tdesc = thread->desc; 1307 const struct cpr_fuse *fuses = thread->cpr_fuses; 1308 int i, ret, total_corners, extra_corners, level, scaling = 0; 1309 unsigned int fnum, fc; 1310 const char *quot_offset; 1311 const struct fuse_corner_data *fdata; 1312 struct fuse_corner *fuse, *prev_fuse; 1313 struct corner *corner, *prev_corner, *end; 1314 struct corner_data *cdata; 1315 struct dev_pm_opp *opp; 1316 bool apply_scaling; 1317 unsigned long freq; 1318 u32 ring_osc_mask = CPR3_RO_MASK, min_quotient = U32_MAX; 1319 1320 corner = thread->corners; 1321 prev_corner = &thread->corners[0]; 1322 end = &corner[thread->num_corners - 1]; 1323 1324 cdata = devm_kcalloc(drv->dev, 1325 thread->num_corners + drv->extra_corners, 1326 sizeof(struct corner_data), 1327 GFP_KERNEL); 1328 if (!cdata) 1329 return -ENOMEM; 1330 1331 for (level = 1; level <= thread->num_corners; level++) { 1332 opp = dev_pm_opp_find_level_exact(&thread->pd.dev, level); 1333 if (IS_ERR(opp)) 1334 return -EINVAL; 1335 1336 /* 1337 * If there is only one specified qcom,opp-fuse-level, then 1338 * it is assumed that this only one is global and valid for 1339 * all IDs, so try to get the specific one but, on failure, 1340 * go for the global one. 1341 */ 1342 fc = cpr_get_fuse_corner(opp, thread->id); 1343 if (fc == 0) { 1344 fc = cpr_get_fuse_corner(opp, 0); 1345 if (fc == 0) { 1346 dev_err(drv->dev, 1347 "qcom,opp-fuse-level is missing!\n"); 1348 dev_pm_opp_put(opp); 1349 return -EINVAL; 1350 } 1351 } 1352 fnum = fc - 1; 1353 1354 freq = cpr_get_opp_hz_for_req(opp, thread->attached_cpu_dev); 1355 if (!freq) { 1356 thread->num_corners = max(level - 1, 0); 1357 end = &thread->corners[thread->num_corners - 1]; 1358 break; 1359 } 1360 1361 /* 1362 * If any post-vadj (open/closed loop) is not specified, then 1363 * it's zero, meaning that it is not required for this corner. 1364 */ 1365 cpr_get_corner_post_vadj(opp, thread->id, 1366 &cdata[level - 1].oloop_vadj, 1367 &cdata[level - 1].cloop_vadj); 1368 cdata[level - 1].fuse_corner = fnum; 1369 cdata[level - 1].freq = freq; 1370 1371 fuse = &thread->fuse_corners[fnum]; 1372 dev_dbg(drv->dev, "freq: %lu level: %u fuse level: %u\n", 1373 freq, dev_pm_opp_get_level(opp) - 1, fnum); 1374 if (freq > fuse->max_freq) 1375 fuse->max_freq = freq; 1376 dev_pm_opp_put(opp); 1377 1378 /* 1379 * Make sure that the frequencies in the table are in ascending 1380 * order, as this is critical for the algorithm to work. 1381 */ 1382 if (cdata[level - 2].freq > freq) { 1383 dev_err(drv->dev, 1384 "Frequency table not in ascending order.\n"); 1385 return -EINVAL; 1386 } 1387 } 1388 1389 if (thread->num_corners < 2) { 1390 dev_err(drv->dev, "need at least 2 OPPs to use CPR\n"); 1391 return -EINVAL; 1392 } 1393 1394 /* 1395 * Get the quotient adjustment scaling factor, according to: 1396 * 1397 * scaling = min(1000 * (QUOT(corner_N) - QUOT(corner_N-1)) 1398 * / (freq(corner_N) - freq(corner_N-1)), max_factor) 1399 * 1400 * QUOT(corner_N): quotient read from fuse for fuse corner N 1401 * QUOT(corner_N-1): quotient read from fuse for fuse corner (N - 1) 1402 * freq(corner_N): max frequency in MHz supported by fuse corner N 1403 * freq(corner_N-1): max frequency in MHz supported by fuse corner 1404 * (N - 1) 1405 * 1406 * Then walk through the corners mapped to each fuse corner 1407 * and calculate the quotient adjustment for each one using the 1408 * following formula: 1409 * 1410 * quot_adjust = (freq_max - freq_corner) * scaling / 1000 1411 * 1412 * freq_max: max frequency in MHz supported by the fuse corner 1413 * freq_corner: frequency in MHz corresponding to the corner 1414 * scaling: calculated from above equation 1415 * 1416 * 1417 * + + 1418 * | v | 1419 * q | f c o | f c 1420 * u | c l | c 1421 * o | f t | f 1422 * t | c a | c 1423 * | c f g | c f 1424 * | e | 1425 * +--------------- +---------------- 1426 * 0 1 2 3 4 5 6 0 1 2 3 4 5 6 1427 * corner corner 1428 * 1429 * c = corner 1430 * f = fuse corner 1431 * 1432 */ 1433 for (apply_scaling = false, i = 0; corner <= end; corner++, i++) { 1434 unsigned long freq_diff_mhz; 1435 int ro_fac, vadj, prev_quot; 1436 1437 fnum = cdata[i].fuse_corner; 1438 fdata = &tdesc->fuse_corner_data[fnum]; 1439 quot_offset = fuses[fnum].quotient_offset; 1440 fuse = &thread->fuse_corners[fnum]; 1441 ring_osc_mask &= (u16)(~BIT(fuse->ring_osc_idx)); 1442 if (fnum) 1443 prev_fuse = &thread->fuse_corners[fnum - 1]; 1444 else 1445 prev_fuse = NULL; 1446 1447 corner->fuse_corner = fuse; 1448 corner->freq = cdata[i].freq; 1449 corner->uV = fuse->uV; 1450 1451 if (prev_fuse) { 1452 if (prev_fuse->ring_osc_idx == fuse->ring_osc_idx) 1453 quot_offset = NULL; 1454 1455 scaling = cpr_calculate_scaling(quot_offset, drv->dev, 1456 fdata, corner); 1457 if (scaling < 0) 1458 return scaling; 1459 1460 freq_diff_mhz = fuse->max_freq - corner->freq; 1461 do_div(freq_diff_mhz, 1000000); /* now in MHz */ 1462 1463 corner->quot_adjust = scaling * freq_diff_mhz; 1464 do_div(corner->quot_adjust, 1000); 1465 1466 /* Fine-tune QUOT (closed-loop) based on fixed values */ 1467 ro_fac = cpr_get_ro_factor(tdesc, fnum, fuse->ring_osc_idx); 1468 vadj = cdata[i].cloop_vadj; 1469 corner->quot_adjust -= cpr3_adjust_quot(ro_fac, vadj); 1470 dev_vdbg(drv->dev, 1471 "Quot fine-tuning to %d for post-vadj=%d\n", 1472 corner->quot_adjust, vadj); 1473 1474 /* 1475 * Make sure that we scale (up) monotonically. 1476 * P.S.: Fuse quots can never be descending. 1477 */ 1478 prev_quot = prev_corner->fuse_corner->quot; 1479 prev_quot -= prev_corner->quot_adjust; 1480 if (fuse->quot - corner->quot_adjust < prev_quot) { 1481 int new_adj = prev_corner->fuse_corner->quot; 1482 new_adj -= fuse->quot; 1483 dev_vdbg(drv->dev, 1484 "Monotonic increase forced: %d->%d\n", 1485 corner->quot_adjust, new_adj); 1486 corner->quot_adjust = new_adj; 1487 } 1488 1489 corner->uV = cpr_interpolate(corner, 1490 drv->vreg_step, fdata); 1491 } else if (corner->freq == fuse->max_freq) { 1492 /* This is a fuse corner; don't scale anything */ 1493 apply_scaling = false; 1494 } 1495 /* Negative fuse quotients are nonsense. */ 1496 if (fuse->quot < corner->quot_adjust) 1497 return -EINVAL; 1498 1499 min_quotient = min(min_quotient, 1500 (u32)(fuse->quot - corner->quot_adjust)); 1501 1502 /* Fine-tune voltages (open-loop) based on fixed values */ 1503 corner->uV += cdata[i].oloop_vadj; 1504 dev_dbg(drv->dev, 1505 "Voltage fine-tuning to %d for post-vadj=%d\n", 1506 corner->uV, cdata[i].oloop_vadj); 1507 1508 corner->max_uV = fuse->max_uV; 1509 corner->min_uV = fuse->min_uV; 1510 corner->uV = clamp(corner->uV, corner->min_uV, corner->max_uV); 1511 dev_vdbg(drv->dev, "Clamped after interpolation: [%d %d %d]\n", 1512 corner->min_uV, corner->uV, corner->max_uV); 1513 1514 /* Make sure that we scale monotonically here, too. */ 1515 if (corner->uV < prev_corner->uV) 1516 corner->uV = prev_corner->uV; 1517 1518 corner->last_uV = corner->uV; 1519 1520 /* Reduce the ceiling voltage if needed */ 1521 if (desc->reduce_to_corner_uV && corner->uV < corner->max_uV) 1522 corner->max_uV = corner->uV; 1523 else if (desc->reduce_to_fuse_uV && fuse->uV < corner->max_uV) 1524 corner->max_uV = max(corner->min_uV, fuse->uV); 1525 1526 corner->min_uV = max(corner->max_uV - fdata->range_uV, 1527 corner->min_uV); 1528 1529 /* 1530 * Adjust per-corner floor and ceiling voltages so that 1531 * they do not overlap the memory Array Power Mux (APM) 1532 * nor the Memory Accelerator (MEM-ACC) threshold voltages. 1533 */ 1534 if (desc->apm_threshold) 1535 cpr3_restrict_corner(corner, desc->apm_threshold, 1536 desc->apm_hysteresis, 1537 drv->vreg_step); 1538 if (desc->mem_acc_threshold) 1539 cpr3_restrict_corner(corner, desc->mem_acc_threshold, 1540 0, drv->vreg_step); 1541 1542 prev_corner = corner; 1543 dev_dbg(drv->dev, "corner %d: [%d %d %d] scaling %d quot %d\n", i, 1544 corner->min_uV, corner->uV, corner->max_uV, scaling, 1545 fuse->quot - corner->quot_adjust); 1546 } 1547 1548 /* Additional setup for CPRh only */ 1549 if (desc->cpr_type < CTRL_TYPE_CPRH) 1550 return 0; 1551 1552 /* If the OPPs can't be adjusted, programming the CPRh is useless */ 1553 ret = cprh_corner_adjust_opps(thread); 1554 if (ret) { 1555 dev_err(drv->dev, "Cannot adjust CPU OPP voltages: %d\n", ret); 1556 return ret; 1557 } 1558 1559 total_corners = thread->num_corners; 1560 extra_corners = drv->extra_corners; 1561 1562 /* If the APM extra corner exists, add it now. */ 1563 if (desc->apm_crossover && desc->apm_threshold && extra_corners) { 1564 /* Program the APM crossover corner on the CPR-Hardened */ 1565 thread->corners[total_corners].uV = desc->apm_crossover; 1566 thread->corners[total_corners].min_uV = desc->apm_crossover; 1567 thread->corners[total_corners].max_uV = desc->apm_crossover; 1568 thread->corners[total_corners].is_open_loop = true; 1569 1570 /* 1571 * Also add and disable an opp with zero frequency: other 1572 * drivers will need to know what is the APM *threshold* 1573 * voltage. 1574 */ 1575 ret = dev_pm_opp_add(thread->attached_cpu_dev, 0, 1576 desc->apm_threshold); 1577 if (ret) 1578 return ret; 1579 1580 ret = dev_pm_opp_disable(thread->attached_cpu_dev, 0); 1581 if (ret) 1582 return ret; 1583 1584 dev_dbg(drv->dev, "corner %d (APM): [%d %d %d] Open-Loop\n", 1585 total_corners, desc->apm_crossover, 1586 desc->apm_crossover, desc->apm_crossover); 1587 1588 total_corners++; 1589 extra_corners--; 1590 } 1591 1592 if (desc->mem_acc_threshold && extra_corners) { 1593 /* Program the Memory Accelerator threshold corner to CPRh */ 1594 thread->corners[total_corners].uV = desc->mem_acc_threshold; 1595 thread->corners[total_corners].min_uV = desc->mem_acc_threshold; 1596 thread->corners[total_corners].max_uV = desc->mem_acc_threshold; 1597 thread->corners[total_corners].is_open_loop = true; 1598 1599 /* 1600 * Add and disable an opp with zero frequency: other 1601 * drivers will also need to know about any mem-acc 1602 * threshold to respect. 1603 */ 1604 ret = dev_pm_opp_add(thread->attached_cpu_dev, 1, 1605 desc->mem_acc_threshold); 1606 if (ret) 1607 return ret; 1608 1609 ret = dev_pm_opp_disable(thread->attached_cpu_dev, 1); 1610 if (ret) 1611 return ret; 1612 1613 dev_dbg(drv->dev, "corner %d (MEMACC): [%d %d %d] Open-Loop\n", 1614 total_corners, desc->mem_acc_threshold, 1615 desc->mem_acc_threshold, desc->mem_acc_threshold); 1616 1617 total_corners++; 1618 extra_corners--; 1619 } 1620 1621 /* 1622 * If there are any extra corners left, it means that even though we 1623 * expect to fill in both APM and MEM-ACC crossovers, one couldn't 1624 * satisfy requirements, which means that the specified parameters 1625 * are wrong: in this case, inform the user and bail out, otherwise 1626 * if we go on writing the (invalid) table to the CPR-Hardened, the 1627 * hardware (in this case, the CPU) will surely freeze and crash. 1628 */ 1629 if (unlikely(extra_corners)) { 1630 dev_err(drv->dev, "APM/MEM-ACC corners: bad parameters.\n"); 1631 return -EINVAL; 1632 } 1633 /* Reassign extra_corners, as we have to exclude delta_quot for them */ 1634 extra_corners = drv->extra_corners; 1635 1636 /* Disable the interface between OSM and CPRh */ 1637 cpr_masked_write(thread, drv->reg_ctl, 1638 CPRH_CTL_OSM_ENABLED, 0); 1639 1640 /* Program the GCNT before unmasking ring oscillator(s) */ 1641 for (i = 0; i < CPR3_RO_COUNT; i++) { 1642 if (!(ring_osc_mask & BIT(i))) { 1643 cpr_write(thread, CPR3_REG_GCNT(i), drv->gcnt); 1644 dev_vdbg(drv->dev, "RO%d gcnt=%d\n", i, drv->gcnt); 1645 } 1646 } 1647 1648 /* 1649 * Unmask the ring oscillator(s) that we're going to use: it seems 1650 * to be mandatory to do this *before* sending the rest of the 1651 * CPRhardened specific configuration. 1652 */ 1653 dev_dbg(drv->dev, 1654 "Unmasking ring oscillators with mask 0x%x\n", ring_osc_mask); 1655 cpr_write(thread, CPR3_REG_RO_MASK(tdesc->hw_tid), ring_osc_mask); 1656 1657 /* Setup minimum quotients for ring oscillators */ 1658 for (i = 0; i < CPR3_RO_COUNT; i++) { 1659 u32 tgt_quot_reg = CPR3_REG_TARGET_QUOT(tdesc->hw_tid, i); 1660 u32 tgt_quot_val = 0; 1661 1662 if (!(ring_osc_mask & BIT(i))) 1663 tgt_quot_val = min_quotient; 1664 1665 cpr_write(thread, tgt_quot_reg, tgt_quot_val); 1666 dev_vdbg(drv->dev, 1667 "Programmed min quotient %u for Ring Oscillator %d\n", 1668 tgt_quot_val, tgt_quot_reg); 1669 } 1670 1671 for (i = 0; i < total_corners; i++) { 1672 int volt_oloop_steps, volt_floor_steps, delta_quot_steps; > 1673 int ring_osc, min_quot_val; 1674 u32 val; 1675 1676 fnum = cdata[i].fuse_corner; 1677 fuse = &thread->fuse_corners[fnum]; 1678 1679 val = thread->corners[i].uV - desc->cpr_base_voltage; 1680 volt_oloop_steps = DIV_ROUND_UP(val, drv->vreg_step); 1681 1682 val = thread->corners[i].min_uV - desc->cpr_base_voltage; 1683 volt_floor_steps = DIV_ROUND_UP(val, drv->vreg_step); 1684 1685 if (i >= (total_corners - extra_corners)) { 1686 delta_quot_steps = 0; 1687 min_quot_val = 0; 1688 } else { 1689 min_quot_val = min_quotient; 1690 val = fuse->quot - thread->corners[i].quot_adjust; 1691 val -= min_quotient; 1692 delta_quot_steps = DIV_ROUND_UP(val, 1693 CPRH_DELTA_QUOT_STEP_FACTOR); 1694 } 1695 1696 /* 1697 * If we are accessing corners that are not used as 1698 * an active DCVS set-point, then always select RO 0 1699 * and zero out the delta quotient. 1700 */ 1701 if (i >= thread->num_corners) { 1702 ring_osc = 0; 1703 delta_quot_steps = 0; 1704 } else { 1705 ring_osc = fuse->ring_osc_idx; 1706 } 1707 1708 if (volt_oloop_steps > CPRH_CORNER_INIT_VOLTAGE_MAX_VALUE || 1709 volt_floor_steps > CPRH_CORNER_FLOOR_VOLTAGE_MAX_VALUE || 1710 delta_quot_steps > CPRH_CORNER_QUOT_DELTA_MAX_VALUE) { 1711 dev_err(drv->dev, 1712 "Invalid cfg: oloop=%d, floor=%d, delta=%d\n", 1713 volt_oloop_steps, volt_floor_steps, 1714 delta_quot_steps); 1715 return -EINVAL; 1716 } 1717 /* Green light: Go, Go, Go! */ 1718 1719 /* Set number of open-loop steps */ 1720 val = volt_oloop_steps << CPRH_CORNER_INIT_VOLTAGE_SHIFT; 1721 val &= CPRH_CORNER_INIT_VOLTAGE_MASK; 1722 1723 /* Set number of floor voltage steps */ 1724 val |= (volt_floor_steps << CPRH_CORNER_FLOOR_VOLTAGE_SHIFT) & 1725 CPRH_CORNER_FLOOR_VOLTAGE_MASK; 1726 1727 /* Set number of target quotient delta steps */ 1728 val |= (delta_quot_steps << CPRH_CORNER_QUOT_DELTA_SHIFT) & 1729 CPRH_CORNER_QUOT_DELTA_MASK; 1730 1731 /* Select ring oscillator for this corner */ 1732 val |= (ring_osc << CPRH_CORNER_RO_SEL_SHIFT) & 1733 CPRH_CORNER_RO_SEL_MASK; 1734 1735 /* Open loop corner is usually APM/ACC crossover */ 1736 if (thread->corners[i].is_open_loop) { 1737 dev_dbg(drv->dev, 1738 "Disabling Closed-Loop on corner %d\n", i); 1739 val |= CPRH_CORNER_CPR_CL_DISABLE; 1740 } 1741 cpr_write(thread, CPRH_REG_CORNER(drv, tdesc->hw_tid, i), val); 1742 1743 dev_dbg(drv->dev, 1744 "steps [%d]: open-loop %d, floor %d, delta_quot %d\n", 1745 i, volt_oloop_steps, volt_floor_steps, 1746 delta_quot_steps); 1747 } 1748 1749 /* YAY! Setup is done! Enable the internal loop to start CPR. */ 1750 cpr_masked_write(thread, CPR3_REG_CPR_CTL, 1751 CPR3_CPR_CTL_LOOP_EN_MASK, 1752 CPR3_CPR_CTL_LOOP_EN_MASK); 1753 1754 /* 1755 * Make sure that all the writes go through before enabling 1756 * internal communication between the OSM and the CPRh 1757 * controllers, otherwise there is a high risk of hardware 1758 * lockups due to under-voltage for the selected CPU clock. 1759 * 1760 * Please note that the CPR-hardened gets set-up in Linux but 1761 * then gets actually used in firmware (and only by the OSM); 1762 * after handing it off we will have no more control on it, 1763 * hence the only way to get things up properly for sure here 1764 * is a write barrier. 1765 */ 1766 wmb(); 1767 1768 /* Enable the interface between OSM and CPRh */ 1769 cpr_masked_write(thread, drv->reg_ctl, 1770 CPRH_CTL_OSM_ENABLED, 1771 CPRH_CTL_OSM_ENABLED); 1772 1773 /* On success, free cdata manually */ 1774 devm_kfree(drv->dev, cdata); 1775 return 0; 1776 } 1777 --- 0-DAY CI Kernel Test Service, Intel Corporation https://lists.01.org/hyperkitty/list/kbuild-...@lists.01.org
.config.gz
Description: application/gzip